Mercurial Hosting > luan
diff src/luan/interp/LuaParser.java @ 32:c3eab5a3ce3c
implement closures
git-svn-id: https://luan-java.googlecode.com/svn/trunk@33 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Fri, 14 Dec 2012 05:40:35 +0000 |
parents | 5cf15507d77e |
children | 8793c71ad47a |
line wrap: on
line diff
--- a/src/luan/interp/LuaParser.java Thu Dec 13 02:50:04 2012 +0000 +++ b/src/luan/interp/LuaParser.java Fri Dec 14 05:40:35 2012 +0000 @@ -29,12 +29,46 @@ int stackSize = 0; int loops = 0; boolean isVarArg = false; + final List<String> upValueSymbols = new ArrayList<String>(); + final List<UpValue.Getter> upValueGetters = new ArrayList<UpValue.Getter>(); Frame(Frame parent) { this.parent = parent; } + + int stackIndex(String name) { + int i = symbols.size(); + while( --i >= 0 ) { + if( symbols.get(i).equals(name) ) + return i; + } + return -1; + } + + int upValueIndex(String name) { + int i = upValueSymbols.size(); + while( --i >= 0 ) { + if( upValueSymbols.get(i).equals(name) ) + return i; + } + if( parent==null ) + return -1; + i = parent.stackIndex(name); + if( i != -1 ) { + upValueGetters.add(new UpValue.StackGetter(i)); + } else { + i = parent.upValueIndex(name); + if( i == -1 ) + return -1; + upValueGetters.add(new UpValue.NestedGetter(i)); + } + upValueSymbols.add(name); + return upValueSymbols.size() - 1; + } } + static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; + int nEquals; int parens = 0; Frame frame = new Frame(null); @@ -76,14 +110,8 @@ return true; } - int index(String name) { - List<String> symbols = frame.symbols; - int i = symbols.size(); - while( --i >= 0 ) { - if( symbols.get(i).equals(name) ) - return i; - } - return -1; + int stackIndex(String name) { + return frame.stackIndex(name); } boolean popSymbols(int n) { @@ -94,6 +122,10 @@ return true; } + int upValueIndex(String name) { + return frame.upValueIndex(name); + } + boolean incLoops() { frame.loops++; return true; @@ -104,6 +136,9 @@ return true; } + Chunk newChunk() { + return new Chunk( (Stmt)pop(), frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); + } Rule Target() { return Sequence( @@ -114,7 +149,7 @@ action( frame.isVarArg = true ), Block(), EOI, - push( new Chunk( (Stmt)pop(), frame.stackSize, 0, frame.isVarArg ) ) + push( newChunk() ) ) ) ); @@ -386,20 +421,19 @@ if( obj2==null ) return false; Object obj1 = pop(); - if( obj1==null ) { - String name = (String)obj2; - int index = index(name); - if( index == -1 ) { - push( new SetTableEntry( EnvExpr.INSTANCE, new ConstExpr(name) ) ); - } else { - push( new SetLocalVar(index) ); - } - } else { + if( obj1!=null ) { Expr key = expr(obj2); Expr table = expr(obj1); - push( new SetTableEntry(table,key) ); + return push( new SetTableEntry(table,key) ); } - return true; + String name = (String)obj2; + int index = stackIndex(name); + if( index != -1 ) + return push( new SetLocalVar(index) ); + index = upValueIndex(name); + if( index != -1 ) + return push( new SetUpVar(index) ); + return push( new SetTableEntry( EnvExpr.INSTANCE, new ConstExpr(name) ) ); } Rule Expr() { @@ -515,7 +549,7 @@ ) ), ')', decParens(), Spaces(), Block(), Keyword("end"), - push( new Chunk( (Stmt)pop(), frame.stackSize, symbolsSize(), frame.isVarArg ) ), + push( newChunk() ), action( frame = frame.parent ) ); } @@ -617,16 +651,16 @@ if( obj2==null ) return true; Object obj1 = pop(); - if( obj1==null ) { - String name = (String)obj2; - int index = index(name); - if( index == -1 ) { - return push( new GetExpr( EnvExpr.INSTANCE, new ConstExpr(name) ) ); - } else { - return push( new GetLocalVar(index) ); - } - } - return push( new GetExpr( expr(obj1), expr(obj2) ) ); + if( obj1 != null ) + return push( new GetExpr( expr(obj1), expr(obj2) ) ); + String name = (String)obj2; + int index = stackIndex(name); + if( index != -1 ) + return push( new GetLocalVar(index) ); + index = upValueIndex(name); + if( index != -1 ) + return push( new GetUpVar(index) ); + return push( new GetExpr( EnvExpr.INSTANCE, new ConstExpr(name) ) ); } // function should be on top of the stack