Mercurial Hosting > luan
changeset 19:a7c13c6017f7
add GenericForStmt
git-svn-id: https://luan-java.googlecode.com/svn/trunk@20 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Sun, 02 Dec 2012 10:08:24 +0000 |
parents | 3971113699b8 |
children | d85510d92eee |
files | src/luan/CmdLine.java src/luan/LuaTable.java src/luan/interp/GenericForStmt.java src/luan/interp/LuaParser.java src/luan/interp/SetStmt.java src/luan/lib/BasicLib.java |
diffstat | 6 files changed, 151 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/CmdLine.java Sun Dec 02 07:00:44 2012 +0000 +++ b/src/luan/CmdLine.java Sun Dec 02 10:08:24 2012 +0000 @@ -30,7 +30,8 @@ LuaFunction fn = BasicLib.loadFile(file); fn.call(lua); } catch(LuaException e) { - System.out.println(e.getMessage()); +// System.out.println(e.getMessage()); + e.printStackTrace(); return; } }
--- a/src/luan/LuaTable.java Sun Dec 02 07:00:44 2012 +0000 +++ b/src/luan/LuaTable.java Sun Dec 02 10:08:24 2012 +0000 @@ -5,7 +5,7 @@ public class LuaTable { - private final Map<Object,Object> map = new HashMap<Object,Object>(); + public final Map<Object,Object> map = new HashMap<Object,Object>(); @Override public String toString() { return "table: " + Integer.toHexString(hashCode());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/interp/GenericForStmt.java Sun Dec 02 10:08:24 2012 +0000 @@ -0,0 +1,42 @@ +package luan.interp; + +import luan.Lua; +import luan.LuaState; +import luan.LuaException; +import luan.LuaFunction; + + +final class GenericForStmt implements Stmt { + private final int iVars; + private final int nVars; + private final Expr iterExpr; + private final Stmt block; + + GenericForStmt(int iVars,int nVars,Expr iterExpr,Stmt block) { + this.iVars = iVars; + this.nVars = nVars; + this.iterExpr = iterExpr; + this.block = block; + } + + @Override public void eval(LuaState lua) throws LuaException { + LuaFunction iter = Lua.checkFunction( iterExpr.eval(lua) ); + Object[] stack = lua.stack(); + try { + while(true) { + Object[] vals = iter.call(lua); + if( vals.length==0 || vals[0]==null ) + break; + for( int i=0; i<nVars; i++ ) { + stack[iVars+i] = i < vals.length ? vals[i] : null; + } + block.eval(lua); + } + } finally { + for( int i=iVars; i<iVars+nVars; i++ ) { + stack[i] = null; + } + } + } + +}
--- a/src/luan/interp/LuaParser.java Sun Dec 02 07:00:44 2012 +0000 +++ b/src/luan/interp/LuaParser.java Sun Dec 02 10:08:24 2012 +0000 @@ -45,13 +45,19 @@ int index(String name) { int i = symbols.size(); while( --i >= 0 ) { -System.out.println("index ["+name+"] ["+symbols.get(i)+"] "+symbols.get(i).equals(name)); if( symbols.get(i).equals(name) ) return i; } return -1; } + boolean popSymbols(int n) { + while( n-- > 0 ) { + symbols.remove(symbols.size()-1); + } + return true; + } + public Rule Target() { return Sequence( Spaces(), @@ -71,28 +77,27 @@ Rule Block() { Var<List<Stmt>> stmts = new Var<List<Stmt>>(new ArrayList<Stmt>()); - Var<Integer> stackCount = new Var<Integer>(0); + Var<Integer> stackStart = new Var<Integer>(symbols.size()); return Sequence( - Optional( Stmt(stmts,stackCount) ), + Optional( Stmt(stmts) ), ZeroOrMore( StmtSep(), - Optional( Stmt(stmts,stackCount) ) + Optional( Stmt(stmts) ) ), - push( newBlock(stmts.get(),stackCount.get()) ) + push( newBlock(stmts.get(),stackStart.get()) ) ); } - Stmt newBlock(List<Stmt> stmts,int stackN) { + Stmt newBlock(List<Stmt> stmts,int stackStart) { if( stackSize < symbols.size() ) stackSize = symbols.size(); - for( int i=0; i<stackN; i++ ) { - symbols.remove(symbols.size()-1); // pop - } + int stackEnd = symbols.size(); + popSymbols( stackEnd - stackStart ); if( stmts.isEmpty() ) return Stmt.EMPTY; - if( stmts.size()==1 && stackN==0 ) + if( stmts.size()==1 && stackStart==stackEnd ) return stmts.get(0); - return new Block( stmts.toArray(new Stmt[0]), symbols.size(), symbols.size()+stackN ); + return new Block( stmts.toArray(new Stmt[0]), stackStart, stackEnd ); } Rule StmtSep() { @@ -112,11 +117,12 @@ return FirstOf("\r\n", '\r', '\n'); } - Rule Stmt(Var<List<Stmt>> stmts,Var<Integer> stackCount) { + Rule Stmt(Var<List<Stmt>> stmts) { return FirstOf( - LocalStmt(stmts,stackCount), + LocalStmt(stmts), Sequence( FirstOf( + GenericForStmt(), NumericForStmt(), DoStmt(), WhileStmt(), @@ -130,6 +136,15 @@ ); } + Rule GenericForStmt() { + Var<Integer> stackStart = new Var<Integer>(symbols.size()); + return Sequence( + Keyword("for"), NameList(), Keyword("in"), Expr(), Keyword("do"), Block(), Keyword("end"), + push( new GenericForStmt( stackStart.get(), symbols.size() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ), + popSymbols( symbols.size() - stackStart.get() ) + ); + } + Rule NumericForStmt() { return Sequence( Keyword("for"), Name(), '=', Spaces(), Expr(), ',', Spaces(), Expr(), @@ -142,7 +157,7 @@ symbols.add( (String)pop(3) ), // add "for" var to symbols Keyword("do"), Block(), Keyword("end"), push( new NumericForStmt( symbols.size()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ), - action( symbols.remove(symbols.size()-1) ) // pop + popSymbols(1) ); } @@ -152,37 +167,33 @@ ); } - Rule LocalStmt(Var<List<Stmt>> stmts,Var<Integer> stackCount) { - Var<List<String>> names = new Var<List<String>>(new ArrayList<String>()); + Rule LocalStmt(Var<List<Stmt>> stmts) { + Var<Integer> stackStart = new Var<Integer>(symbols.size()); return Sequence( - Keyword("local"), - Name(), - newName(names.get(),stackCount), - ZeroOrMore( - ',', Spaces(), Name(), - newName(names.get(),stackCount) - ), + Keyword("local"), NameList(), Optional( - '=', Spaces(), - ExpList(), - stmts.get().add( newSetLocalStmt(names.get()) ) + '=', Spaces(), ExpList(), + stmts.get().add( newSetLocalStmt(stackStart.get()) ) ) ); } - boolean newName(List<String> names,Var<Integer> stackCount) { - String name = (String)pop(); - names.add(name); - symbols.add(name); - stackCount.set( stackCount.get() + 1 ); - return true; + Rule NameList() { + return Sequence( + Name(), + symbols.add( (String)pop() ), + ZeroOrMore( + ',', Spaces(), Name(), + symbols.add( (String)pop() ) + ) + ); } - SetStmt newSetLocalStmt(List<String> names) { + SetStmt newSetLocalStmt(int stackStart) { Expressions values = (Expressions)pop(); - SetLocalVar[] vars = new SetLocalVar[names.size()]; + SetLocalVar[] vars = new SetLocalVar[symbols.size()-stackStart]; for( int i=0; i<vars.length; i++ ) { - vars[i] = new SetLocalVar(index(names.get(i))); + vars[i] = new SetLocalVar(stackStart+i); } return new SetStmt( vars, values ); }
--- a/src/luan/interp/SetStmt.java Sun Dec 02 07:00:44 2012 +0000 +++ b/src/luan/interp/SetStmt.java Sun Dec 02 10:08:24 2012 +0000 @@ -17,9 +17,8 @@ @Override public void eval(LuaState lua) throws LuaException { final Object[] vals = expressions.eval(lua); for( int i=0; i<vars.length; i++ ) { - Settable var = vars[i]; Object val = i < vals.length ? vals[i] : null; - var.set(lua,val); + vars[i].set(lua,val); } }
--- a/src/luan/lib/BasicLib.java Sun Dec 02 07:00:44 2012 +0000 +++ b/src/luan/lib/BasicLib.java Sun Dec 02 10:08:24 2012 +0000 @@ -2,6 +2,9 @@ import java.io.FileReader; import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.Map; import org.parboiled.Parboiled; import org.parboiled.errors.ErrorUtils; import org.parboiled.parserunners.ReportingParseRunner; @@ -10,6 +13,7 @@ import luan.Lua; import luan.LuaState; import luan.LuaTable; +import luan.LuaNumber; import luan.LuaFunction; import luan.LuaJavaFunction; import luan.LuaException; @@ -24,6 +28,10 @@ LuaTable t = lua.env(); add( t, "print", new Object[0].getClass() ); add( t, "type", Object.class ); + add( t, "load", String.class ); + add( t, "loadFile", String.class ); + add( t, "pairs", LuaTable.class ); + add( t, "ipairs", LuaTable.class ); } private static void add(LuaTable t,String method,Class<?>... parameterTypes) { @@ -86,4 +94,55 @@ return load(readFile(fileName)); } + private static class TableIter { + private final Iterator<Map.Entry<Object,Object>> iter; + + TableIter(LuaTable t) { + this.iter = t.map.entrySet().iterator(); + } + + public Object[] next() { + if( !iter.hasNext() ) + return LuaFunction.EMPTY_RTN; + Map.Entry<Object,Object> entry = iter.next(); + return new Object[]{entry.getKey(),entry.getValue()}; + } + } + + public static LuaFunction pairs(LuaTable t) { + try { + TableIter ti = new TableIter(t); + Method m = TableIter.class.getMethod("next"); + m.setAccessible(true); + return new LuaJavaFunction(m,ti); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + private static class ArrayIter { + private final LuaTable t; + private double i = 0.0; + + ArrayIter(LuaTable t) { + this.t = t; + } + + public Object[] next() { + LuaNumber n = new LuaNumber(++i); + Object val = t.get(n); + return val==null ? LuaFunction.EMPTY_RTN : new Object[]{n,val}; + } + } + + public static LuaFunction ipairs(LuaTable t) { + try { + ArrayIter ai = new ArrayIter(t); + Method m = ArrayIter.class.getMethod("next"); + m.setAccessible(true); + return new LuaJavaFunction(m,ai); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + } }