Mercurial Hosting > luan
changeset 166:4eaee12f6c65
move luan/interp to impl
git-svn-id: https://luan-java.googlecode.com/svn/trunk@167 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Sun, 22 Jun 2014 04:17:38 +0000 |
parents | 94bbc4cbc106 |
children | 4c0131c2b650 |
files | src/luan/LuanState.java src/luan/impl/AddExpr.java src/luan/impl/AndExpr.java src/luan/impl/BinaryOpExpr.java src/luan/impl/Block.java src/luan/impl/BreakException.java src/luan/impl/BreakStmt.java src/luan/impl/Closure.java src/luan/impl/Code.java src/luan/impl/CodeImpl.java src/luan/impl/ConcatExpr.java src/luan/impl/ConstExpr.java src/luan/impl/DivExpr.java src/luan/impl/EqExpr.java src/luan/impl/ExpList.java src/luan/impl/Expr.java src/luan/impl/Expressions.java src/luan/impl/ExpressionsExpr.java src/luan/impl/ExpressionsStmt.java src/luan/impl/FnCall.java src/luan/impl/FnDef.java src/luan/impl/ForStmt.java src/luan/impl/GetLocalVar.java src/luan/impl/GetUpVar.java src/luan/impl/IfStmt.java src/luan/impl/IndexExpr.java src/luan/impl/LeExpr.java src/luan/impl/LenExpr.java src/luan/impl/LtExpr.java src/luan/impl/LuanCompiler.java src/luan/impl/LuanParser.java src/luan/impl/LuanStateImpl.java src/luan/impl/ModExpr.java src/luan/impl/MulExpr.java src/luan/impl/NotExpr.java src/luan/impl/OrExpr.java src/luan/impl/ParseException.java src/luan/impl/Parser.java src/luan/impl/PowExpr.java src/luan/impl/RepeatStmt.java src/luan/impl/ReturnException.java src/luan/impl/ReturnStmt.java src/luan/impl/SetLocalVar.java src/luan/impl/SetStmt.java src/luan/impl/SetTableEntry.java src/luan/impl/SetUpVar.java src/luan/impl/Settable.java src/luan/impl/Stmt.java src/luan/impl/SubExpr.java src/luan/impl/TableExpr.java src/luan/impl/TryStmt.java src/luan/impl/UnaryOpExpr.java src/luan/impl/UnmExpr.java src/luan/impl/UpValue.java src/luan/impl/VarArgs.java src/luan/impl/WhileStmt.java src/luan/interp/AddExpr.java src/luan/interp/AndExpr.java src/luan/interp/BinaryOpExpr.java src/luan/interp/Block.java src/luan/interp/BreakException.java src/luan/interp/BreakStmt.java src/luan/interp/Closure.java src/luan/interp/Code.java src/luan/interp/CodeImpl.java src/luan/interp/ConcatExpr.java src/luan/interp/ConstExpr.java src/luan/interp/DivExpr.java src/luan/interp/EqExpr.java src/luan/interp/ExpList.java src/luan/interp/Expr.java src/luan/interp/Expressions.java src/luan/interp/ExpressionsExpr.java src/luan/interp/ExpressionsStmt.java src/luan/interp/FnCall.java src/luan/interp/FnDef.java src/luan/interp/ForStmt.java src/luan/interp/GetLocalVar.java src/luan/interp/GetUpVar.java src/luan/interp/IfStmt.java src/luan/interp/IndexExpr.java src/luan/interp/LeExpr.java src/luan/interp/LenExpr.java src/luan/interp/LtExpr.java src/luan/interp/LuanCompiler.java src/luan/interp/LuanParser.java src/luan/interp/LuanStateImpl.java src/luan/interp/ModExpr.java src/luan/interp/MulExpr.java src/luan/interp/NotExpr.java src/luan/interp/OrExpr.java src/luan/interp/ParseException.java src/luan/interp/Parser.java src/luan/interp/PowExpr.java src/luan/interp/RepeatStmt.java src/luan/interp/ReturnException.java src/luan/interp/ReturnStmt.java src/luan/interp/SetLocalVar.java src/luan/interp/SetStmt.java src/luan/interp/SetTableEntry.java src/luan/interp/SetUpVar.java src/luan/interp/Settable.java src/luan/interp/Stmt.java src/luan/interp/SubExpr.java src/luan/interp/TableExpr.java src/luan/interp/TryStmt.java src/luan/interp/UnaryOpExpr.java src/luan/interp/UnmExpr.java src/luan/interp/UpValue.java src/luan/interp/VarArgs.java src/luan/interp/WhileStmt.java src/luan/lib/BasicLib.java |
diffstat | 112 files changed, 3162 insertions(+), 3162 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/LuanState.java Sun Jun 22 04:10:59 2014 +0000 +++ b/src/luan/LuanState.java Sun Jun 22 04:17:38 2014 +0000 @@ -6,7 +6,7 @@ import java.util.ArrayList; import java.util.Map; import java.util.LinkedHashMap; -import luan.interp.LuanCompiler; +import luan.impl.LuanCompiler; import luan.lib.BasicLib; import luan.lib.PackageLib; import luan.lib.JavaLib;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/AddExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,23 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class AddExpr extends BinaryOpExpr { + + AddExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + Number n1 = Luan.toNumber(o1); + Number n2 = Luan.toNumber(o2); + if( n1 != null && n2 != null ) + return n1.doubleValue() + n2.doubleValue(); + return arithmetic(luan,"__add",o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/AndExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,18 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class AndExpr extends BinaryOpExpr { + + AndExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object v1 = op1.eval(luan); + return !Luan.toBoolean(v1) ? v1 : op2.eval(luan); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/BinaryOpExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,24 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanTable; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; + + +abstract class BinaryOpExpr extends CodeImpl implements Expr { + final Expr op1; + final Expr op2; + + BinaryOpExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se); + this.op1 = op1; + this.op2 = op2; + } + + Object arithmetic(LuanStateImpl luan,String op,Object o1,Object o2) throws LuanException { + return luan.bit(se()).arithmetic("__mod",o1,o2); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Block.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,29 @@ +package luan.impl; + +import luan.LuanException; + + +final class Block implements Stmt { + final Stmt[] stmts; + private final int stackStart; + private final int stackEnd; + + Block(Stmt[] stmts,int stackStart,int stackEnd) { + if( stmts.length==0 ) + throw new RuntimeException("empty block"); + this.stmts = stmts; + this.stackStart = stackStart; + this.stackEnd = stackEnd; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + try { + for( Stmt stmt : stmts ) { + stmt.eval(luan); + } + } finally { + luan.stackClear(stackStart,stackEnd); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/BreakException.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,4 @@ +package luan.impl; + + +final class BreakException extends RuntimeException {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/BreakStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,9 @@ +package luan.impl; + + +final class BreakStmt implements Stmt { + + @Override public void eval(LuanStateImpl luan) { + throw new BreakException(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Closure.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,79 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanState; +import luan.LuanElement; +import luan.LuanException; +import luan.DeepCloner; +import luan.DeepCloneable; + + +final class Closure extends LuanFunction implements DeepCloneable<Closure> { + private final FnDef fnDef; + private UpValue[] upValues; + + Closure(LuanStateImpl luan,FnDef fnDef) throws LuanException { + this.fnDef = fnDef; + UpValue.Getter[] upValueGetters = fnDef.upValueGetters; + upValues = new UpValue[upValueGetters.length]; + for( int i=0; i<upValues.length; i++ ) { + upValues[i] = upValueGetters[i].get(luan); + } + } + + private Closure(Closure c) { + this.fnDef = c.fnDef; + } + + @Override public Closure shallowClone() { + return new Closure(this); + } + + @Override public void deepenClone(Closure clone,DeepCloner cloner) { + clone.upValues = cloner.deepClone(upValues); + } + + UpValue[] upValues() { + return upValues; + } + + @Override public Object call(LuanState luan,Object[] args) throws LuanException { + return call(this,(LuanStateImpl)luan,args); + } + + private static Object call(Closure closure,LuanStateImpl luan,Object[] args) throws LuanException { + while(true) { + FnDef fnDef = closure.fnDef; + Object[] varArgs = null; + if( fnDef.isVarArg ) { + if( args.length > fnDef.numArgs ) { + varArgs = new Object[ args.length - fnDef.numArgs ]; + for( int i=0; i<varArgs.length; i++ ) { + varArgs[i] = args[fnDef.numArgs+i]; + } + } else { + varArgs = LuanFunction.NOTHING; + } + } + Object[] stack = luan.newFrame(closure,fnDef.stackSize,varArgs); + final int n = Math.min(args.length,fnDef.numArgs); + for( int i=0; i<n; i++ ) { + stack[i] = args[i]; + } + Object returnValues; + try { + fnDef.block.eval(luan); + } catch(ReturnException e) { + } finally { + returnValues = luan.returnValues; + closure = luan.tailFn; + luan.popFrame(); + } + if( closure == null ) + return returnValues; + args = Luan.array(returnValues); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Code.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,8 @@ +package luan.impl; + +import luan.LuanSource; + + +interface Code { + public LuanSource.Element se(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/CodeImpl.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,16 @@ +package luan.impl; + +import luan.LuanSource; + + +class CodeImpl implements Code { + final LuanSource.Element se; + + CodeImpl(LuanSource.Element se) { + this.se = se; + } + + @Override public final LuanSource.Element se() { + return se; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ConcatExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,31 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; + + +final class ConcatExpr extends BinaryOpExpr { + + ConcatExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + String s1 = luan.bit(op1.se()).toString(o1); + String s2 = luan.bit(op2.se()).toString(o2); +/* + if( s1 != null && s2 != null ) + return s1 + s2; + LuanFunction fn = luan.getBinHandler(se,"__concat",o1,o2); + if( fn != null ) + return Luan.first(luan.call(fn,se,"__concat",o1,o2)); + String type = s1==null ? Luan.type(o1) : Luan.type(o2); + throw new LuanException( luan, se, "attempt to concatenate a " + type + " value" ); +*/ + return s1 + s2; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ConstExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,25 @@ +package luan.impl; + +import luan.LuanSource; + + +final class ConstExpr extends CodeImpl implements Expr { + private final Object obj; + + ConstExpr(Object obj) { + this(null,obj); + } + + ConstExpr(LuanSource.Element se,Object obj) { + super(se); + this.obj = obj; + } + + @Override public Object eval(LuanStateImpl luan) { + return obj; + } + + @Override public String toString() { + return "(ConstExpr "+obj+")"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/DivExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,23 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class DivExpr extends BinaryOpExpr { + + DivExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + Number n1 = Luan.toNumber(o1); + Number n2 = Luan.toNumber(o2); + if( n1 != null && n2 != null ) + return n1.doubleValue() / n2.doubleValue(); + return arithmetic(luan,"__div",o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/EqExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,40 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanTable; +import luan.LuanException; +import luan.LuanSource; +import luan.LuanBit; + + +final class EqExpr extends BinaryOpExpr { + + EqExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + if( o1 == o2 || o1 != null && o1.equals(o2) ) + return true; + if( o1 instanceof Number && o2 instanceof Number ) { + Number n1 = (Number)o1; + Number n2 = (Number)o2; + return n1.doubleValue() == n2.doubleValue(); + } + if( o1==null || o2==null || !o1.getClass().equals(o2.getClass()) ) + return false; + LuanTable mt1 = luan.getMetatable(o1); + LuanTable mt2 = luan.getMetatable(o2); + if( mt1==null || mt2==null ) + return false; + Object f = mt1.get("__eq"); + if( f == null || !f.equals(mt2.get("__eq")) ) + return null; + LuanBit bit = luan.bit(se); + LuanFunction fn = bit.checkFunction(f); + return Luan.toBoolean( Luan.first(bit.call(fn,"__eq",new Object[]{o1,o2})) ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ExpList.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,96 @@ +package luan.impl; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import luan.LuanException; +import luan.LuanSource; +import luan.LuanFunction; +import luan.Luan; + + +final class ExpList { + + static final Expressions emptyExpList = new Expressions() { + + @Override public Object[] eval(LuanStateImpl luan) { + return LuanFunction.NOTHING; + } + + @Override public LuanSource.Element se() { + return null; + } + }; + + static Expr[] toArray(List<Expressions> list) { + Expr[] a = new Expr[list.size()]; + for( int i=0; i<a.length; i++ ) { + Expressions exprs = list.get(i); + if( exprs instanceof Expr ) { + a[i] = (Expr)exprs; + } else { + a[i] = new ExpressionsExpr(exprs); + } + } + return a; + } + + static Expressions build(List<Expressions> list) { + switch(list.size()) { + case 0: + return emptyExpList; + case 1: + return list.get(0); + default: + if( list.get(list.size()-1) instanceof Expr ) { + return new ExprList1( toArray(list) ); + } else { + Expressions last = list.remove(list.size()-1); + return new ExprList2( toArray(list), last ); + } + } + } + + private static class ExprList1 implements Expressions { + private final Expr[] exprs; + + private ExprList1(Expr[] exprs) { + this.exprs = exprs; + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object[] a = new Object[exprs.length]; + for( int i=0; i<exprs.length; i++ ) { + a[i] = exprs[i].eval(luan); + } + return a; + } + + @Override public LuanSource.Element se() { + return new LuanSource.Element(exprs[0].se().source,exprs[0].se().start,exprs[exprs.length-1].se().end); + } + } + + private static class ExprList2 implements Expressions { + private final Expr[] exprs; + private final Expressions last; + + private ExprList2(Expr[] exprs,Expressions last) { + this.exprs = exprs; + this.last = last; + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + List<Object> list = new ArrayList<Object>(); + for( Expr expr : exprs ) { + list.add( expr.eval(luan) ); + } + list.addAll( Arrays.asList(Luan.array( last.eval(luan) )) ); + return list.toArray(); + } + + @Override public LuanSource.Element se() { + return new LuanSource.Element(exprs[0].se().source,exprs[0].se().start,last.se().end); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Expr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,6 @@ +package luan.impl; + +import luan.LuanException; + + +interface Expr extends Expressions {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Expressions.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,8 @@ +package luan.impl; + +import luan.LuanException; + + +interface Expressions extends Code { + public Object eval(LuanStateImpl luan) throws LuanException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ExpressionsExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,24 @@ +package luan.impl; + +import java.util.List; +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class ExpressionsExpr implements Expr { + private final Expressions expressions; + + ExpressionsExpr(Expressions expressions) { + this.expressions = expressions; + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + return Luan.first( expressions.eval(luan) ); + } + + public LuanSource.Element se() { + return expressions.se(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ExpressionsStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,17 @@ +package luan.impl; + +import luan.LuanException; + + +final class ExpressionsStmt implements Stmt { + private final Expressions expressions; + + ExpressionsStmt(Expressions expressions) { + this.expressions = expressions; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + expressions.eval(luan); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/FnCall.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,39 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; + + +final class FnCall extends CodeImpl implements Expressions { + final Expr fnExpr; + final Expressions args; + final String fnName; + + FnCall(LuanSource.Element se,Expr fnExpr,Expressions args) { + super(se); + this.fnExpr = fnExpr; + this.args = args; + this.fnName = fnExpr.se().text(); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + return call( luan, fnExpr.eval(luan) ); + } + + private Object call(LuanStateImpl luan,Object o) throws LuanException { + if( o instanceof LuanFunction ) { + LuanFunction fn = (LuanFunction)o; + return luan.bit(se).call( fn, fnName, Luan.array(args.eval(luan)) ); + } + Object h = luan.getHandler("__call",o); + if( h != null ) + return call(luan,h); + throw luan.bit(fnExpr.se()).exception( "attempt to call '"+fnExpr.se().text()+"' (a " + Luan.type(o) + " value)" ); + } + + @Override public String toString() { + return "(FnCall "+fnName+" "+fnExpr+" "+args+")"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/FnDef.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,42 @@ +package luan.impl; + +import luan.LuanException; +import luan.LuanSource; + + +final class FnDef extends CodeImpl implements Expr { + final Stmt block; + final int stackSize; + final int numArgs; + final boolean isVarArg; + final UpValue.Getter[] upValueGetters; + + FnDef(LuanSource.Element se,Stmt block,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) { + super(se); + this.block = block; + this.stackSize = stackSize; + this.numArgs = numArgs; + this.isVarArg = isVarArg; + this.upValueGetters = upValueGetters; + fixReturns(block); + } + + private static void fixReturns(Stmt stmt) { + if( stmt instanceof ReturnStmt ) { + ReturnStmt rs = (ReturnStmt)stmt; + rs.throwReturnException = false; + } else if( stmt instanceof Block ) { + Block b = (Block)stmt; + fixReturns( b.stmts[b.stmts.length-1] ); + } else if( stmt instanceof IfStmt ) { + IfStmt is = (IfStmt)stmt; + fixReturns( is.thenStmt ); + fixReturns( is.elseStmt ); + } + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + return new Closure(luan,this); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ForStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,54 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanFunction; +import luan.LuanSource; +import luan.LuanBit; + + +final class ForStmt extends CodeImpl implements Stmt { + private final int iVars; + private final int nVars; + private final Expr iterExpr; + private final Stmt block; + + ForStmt(LuanSource.Element se,int iVars,int nVars,Expr iterExpr,Stmt block) { + super(se); + this.iVars = iVars; + this.nVars = nVars; + this.iterExpr = iterExpr; + this.block = block; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + LuanFunction iter = luan.bit(se).checkFunction( iterExpr.eval(luan) ); + LuanBit bit = luan.bit(iterExpr.se()); + String name = iterExpr.se().text(); + try { + while(true) { + Object vals = bit.call(iter,name,LuanFunction.NOTHING); + if( vals==null ) + break; + if( vals instanceof Object[] ) { + Object[] a = (Object[])vals; + if( a.length==0 ) + break; + for( int i=0; i<nVars; i++ ) { + luan.stackSet( iVars+i, i < a.length ? a[i] : null ); + } + } else { + luan.stackSet( iVars, vals ); + for( int i=1; i<nVars; i++ ) { + luan.stackSet( iVars+i, null ); + } + } + block.eval(luan); + } + } catch(BreakException e) { + } finally { + luan.stackClear(iVars,iVars+nVars); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/GetLocalVar.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,17 @@ +package luan.impl; + +import luan.LuanSource; + + +final class GetLocalVar extends CodeImpl implements Expr { + private final int index; + + GetLocalVar(LuanSource.Element se,int index) { + super(se); + this.index = index; + } + + @Override public Object eval(LuanStateImpl luan) { + return luan.stackGet(index); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/GetUpVar.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,17 @@ +package luan.impl; + +import luan.LuanSource; + + +final class GetUpVar extends CodeImpl implements Expr { + private final int index; + + GetUpVar(LuanSource.Element se,int index) { + super(se); + this.index = index; + } + + @Override public Object eval(LuanStateImpl luan) { + return luan.closure().upValues()[index].get(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/IfStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,27 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class IfStmt extends CodeImpl implements Stmt { + private final Expr cnd; + final Stmt thenStmt; + final Stmt elseStmt; + + IfStmt(LuanSource.Element se,Expr cnd,Stmt thenStmt,Stmt elseStmt) { + super(se); + this.cnd = cnd; + this.thenStmt = thenStmt; + this.elseStmt = elseStmt; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + if( luan.bit(se).checkBoolean( cnd.eval(luan) ) ) { + thenStmt.eval(luan); + } else { + elseStmt.eval(luan); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/IndexExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,41 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanTable; +import luan.LuanFunction; +import luan.LuanSource; + + +final class IndexExpr extends BinaryOpExpr { + + IndexExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + return index(luan,op1.eval(luan),op2.eval(luan)); + } + + private Object index(LuanStateImpl luan,Object t,Object key) throws LuanException { + Object h; + if( t instanceof LuanTable ) { + LuanTable tbl = (LuanTable)t; + Object value = tbl.get(key); + if( value != null ) + return value; + h = luan.getHandler("__index",t); + if( h==null ) + return null; + } else { + h = luan.getHandler("__index",t); + if( h==null ) + throw luan.bit(op1.se()).exception( "attempt to index '"+op1.se().text()+"' (a " + Luan.type(t) + " value)" ); + } + if( h instanceof LuanFunction ) { + LuanFunction fn = (LuanFunction)h; + return Luan.first(luan.bit(se).call(fn,"__index",new Object[]{t,key})); + } + return index(luan,h,key); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/LeExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,38 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; +import luan.LuanBit; + + +final class LeExpr extends BinaryOpExpr { + + LeExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + if( o1 instanceof Number && o2 instanceof Number ) { + Number n1 = (Number)o1; + Number n2 = (Number)o2; + return n1.doubleValue() <= n2.doubleValue(); + } + if( o1 instanceof String && o2 instanceof String ) { + String s1 = (String)o1; + String s2 = (String)o2; + return s1.compareTo(s2) <= 0; + } + LuanBit bit = luan.bit(se); + LuanFunction fn = bit.getBinHandler("__le",o1,o2); + if( fn != null ) + return Luan.toBoolean( Luan.first(bit.call(fn,"__le",new Object[]{o1,o2})) ); + fn = bit.getBinHandler("__lt",o1,o2); + if( fn != null ) + return !Luan.toBoolean( Luan.first(bit.call(fn,"__lt",new Object[]{o2,o1})) ); + throw bit.exception( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/LenExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,37 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanTable; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; +import luan.LuanBit; + + +final class LenExpr extends UnaryOpExpr { + + LenExpr(LuanSource.Element se,Expr op) { + super(se,op); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o = op.eval(luan); + if( o instanceof String ) { + String s = (String)o; + return s.length(); + } + if( o instanceof byte[] ) { + byte[] a = (byte[])o; + return a.length; + } + LuanBit bit = luan.bit(se); + LuanFunction fn = bit.getHandlerFunction("__len",o); + if( fn != null ) + return Luan.first(bit.call(fn,"__len",new Object[]{o})); + if( o instanceof LuanTable ) { + LuanTable t = (LuanTable)o; + return t.length(); + } + throw bit.exception( "attempt to get length of a " + Luan.type(o) + " value" ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/LtExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,20 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; + + +final class LtExpr extends BinaryOpExpr { + + LtExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + return luan.bit(se).isLessThan(o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/LuanCompiler.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,55 @@ +package luan.impl; + +import luan.LuanFunction; +import luan.LuanState; +import luan.LuanException; +import luan.LuanSource; +import luan.LuanElement; +import luan.LuanTable; +import java.util.Map; + + +public final class LuanCompiler { + private LuanCompiler() {} // never + + public static LuanFunction compile(LuanState luan,LuanSource src,LuanTable env,boolean allowExpr) throws LuanException { + UpValue.Getter envGetter = env!=null ? new UpValue.ValueGetter(env) : new UpValue.EnvGetter(); + LuanParser parser = new LuanParser(src,envGetter); + for( Map.Entry<Object,Object> entry : luan.global() ) { + Object key = entry.getKey(); + if( key instanceof String ) + parser.addVar( (String)key, entry.getValue() ); + } + FnDef fnDef = parse(luan,parser,allowExpr); + if( env != null ) + return new Closure((LuanStateImpl)luan,fnDef); + final Closure c = new Closure((LuanStateImpl)luan,fnDef); + return new LuanFunction() { + @Override public Object call(LuanState luan,Object[] args) throws LuanException { + Object rtn = c.call(luan,args); + if( rtn instanceof Object[] && ((Object[])rtn).length==0 ) + rtn = c.upValues()[0].get(); + return rtn; + } + }; + } + + private static FnDef parse(LuanState luan,LuanParser parser,boolean allowExpr) throws LuanException { + try { + if( allowExpr ) { + FnDef fnDef = parser.Expression(); + if( fnDef != null ) + return fnDef; + } + return parser.RequiredModule(); + } catch(ParseException e) { +//e.printStackTrace(); + LuanElement le = new LuanSource.CompilerElement(parser.source); + throw luan.bit(le).exception( e.getFancyMessage() ); + } + } + + public static LuanState newLuanState() { + return new LuanStateImpl(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/LuanParser.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,1360 @@ +package luan.impl; + +import java.util.Set; +import java.util.HashSet; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import java.util.Scanner; +import luan.Luan; +import luan.LuanState; +import luan.LuanSource; + + +final class LuanParser { + + private static final class Frame { + final Frame parent; + final List<String> symbols = new ArrayList<String>(); + 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(UpValue.Getter envGetter) { + this.parent = null; + upValueSymbols.add(_ENV); + upValueGetters.add(envGetter); + } + + Frame(Frame parent) { + this.parent = parent; + if( upValueIndex(_ENV) != 0 ) + throw new RuntimeException(); + } + + 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; + } + + void addUpValueGetter(String name,UpValue.Getter upValueGetter) { + upValueSymbols.add(name); + upValueGetters.add(upValueGetter); + } + } + + private static class In { + static final In NOTHING = new In(false,false); + + final boolean parens; + final boolean template; + + private In(boolean parens,boolean template) { + this.parens = parens; + this.template = template; + } + + In parens() { + return parens ? this : new In(true,template); + } + + In template() { + return template ? this : new In(parens,true); + } + } + + private static final String _ENV = "_ENV"; + private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; + + final LuanSource source; + private Frame frame; + private final Parser parser; + private final boolean interactive; + + LuanParser(LuanSource source,UpValue.Getter envGetter) { + this.source = source; + this.frame = new Frame(envGetter); + this.parser = new Parser(source); + this.interactive = envGetter instanceof UpValue.ValueGetter; + } + + void addVar(String name,Object value) { + frame.addUpValueGetter(name,new UpValue.ValueGetter(value)); + } + + private LuanSource.Element se(int start) { + return new LuanSource.Element(source,start,parser.currentIndex()); + } + + private List<String> symbols() { + return frame.symbols; + } + + private int symbolsSize() { + return frame.symbols.size(); + } + + private void addSymbol(String name) { + frame.symbols.add(name); + if( frame.stackSize < symbolsSize() ) + frame.stackSize = symbolsSize(); + } + + private void addSymbols(List<String> names) { + frame.symbols.addAll(names); + if( frame.stackSize < symbolsSize() ) + frame.stackSize = symbolsSize(); + } + + private int stackIndex(String name) { + return frame.stackIndex(name); + } + + private void popSymbols(int n) { + List<String> symbols = frame.symbols; + while( n-- > 0 ) { + symbols.remove(symbols.size()-1); + } + } + + private int upValueIndex(String name) { + return frame.upValueIndex(name); + } + + private void incLoops() { + frame.loops++; + } + + private void decLoops() { + frame.loops--; + } + + private <T> T required(T t) throws ParseException { + if( t==null ) + throw parser.exception(); + return t; + } + + private <T> T required(T t,String msg) throws ParseException { + if( t==null ) + throw parser.exception(msg); + return t; + } + + private static Expr expr(Expressions exprs) { + if( exprs instanceof Expr ) + return (Expr)exprs; + return new ExpressionsExpr(exprs); + } + + private FnDef newFnDef(int start,Stmt stmt) { + return new FnDef( se(start), stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); + } + + FnDef Expression() throws ParseException { + Spaces(In.NOTHING); + int start = parser.begin(); + Expressions expr = Expr(In.NOTHING); + if( expr != null && parser.endOfInput() ) { + Stmt stmt = new ReturnStmt( se(start), expr ); + return parser.success(newFnDef(start,stmt)); + } + return parser.failure(null); + } + + FnDef RequiredModule() throws ParseException { + Spaces(In.NOTHING); + int start = parser.begin(); + frame.isVarArg = true; + Stmt stmt = RequiredBlock(); + if( parser.endOfInput() ) + return parser.success(newFnDef(start,stmt)); + throw parser.exception(); + } + + private Stmt RequiredBlock() throws ParseException { + List<Stmt> stmts = new ArrayList<Stmt>(); + int stackStart = symbolsSize(); + Stmt(stmts); + while( StmtSep(stmts) ) { + Spaces(In.NOTHING); + Stmt(stmts); + } + int stackEnd = symbolsSize(); + popSymbols( stackEnd - stackStart ); + if( stmts.isEmpty() ) + return Stmt.EMPTY; + if( stmts.size()==1 && stackStart==stackEnd ) + return stmts.get(0); + return new Block( stmts.toArray(new Stmt[0]), stackStart, stackEnd ); + } + + private boolean StmtSep(List<Stmt> stmts) throws ParseException { + parser.begin(); + if( parser.match( ';' ) ) + return parser.success(); + if( parser.match( "--" ) ) { + while( parser.noneOf("\r\n") ); + } + if( EndOfLine() ) + return parser.success(); + parser.rollback(); + Stmt stmt = TemplateStmt(); + if( stmt != null ) { + stmts.add(stmt); + return parser.success(); + } + return parser.failure(); + } + + private boolean EndOfLine() { + return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); + } + + private void Stmt(List<Stmt> stmts) throws ParseException { + if( LocalStmt(stmts) ) + return; + Stmt stmt; + if( (stmt=ReturnStmt()) != null + || (stmt=FunctionStmt()) != null + || (stmt=LocalFunctionStmt()) != null + || (stmt=ImportStmt()) != null + || (stmt=BreakStmt()) != null + || (stmt=ForStmt()) != null + || (stmt=TryStmt()) != null + || (stmt=DoStmt()) != null + || (stmt=WhileStmt()) != null + || (stmt=FunctionStmt()) != null + || (stmt=RepeatStmt()) != null + || (stmt=IfStmt()) != null + || (stmt=SetStmt()) != null + || (stmt=ExpressionsStmt()) != null + ) { + stmts.add(stmt); + } + } + + private Stmt TemplateStmt() throws ParseException { + int start = parser.currentIndex(); + Expressions exp = TemplateExpressions(In.NOTHING); + if( exp == null ) + return null; + Expr fnExp = (Expr)nameVar(start,"Io").expr(); + fnExp = new IndexExpr( se(start), fnExp, new ConstExpr("stdout") ); + fnExp = new IndexExpr( se(start), fnExp, new ConstExpr("write") ); + FnCall fnCall = new FnCall( se(start), fnExp, exp ); + return new ExpressionsStmt(fnCall); + } + + private Expressions TemplateExpressions(In in) throws ParseException { + if( in.template ) + return null; + int start = parser.begin(); + if( !parser.match( "%>" ) ) + return parser.failure(null); + EndOfLine(); + In inTemplate = in.template(); + List<Expressions> builder = new ArrayList<Expressions>(); + while(true) { + if( parser.match( "<%=" ) ) { + Spaces(inTemplate); + builder.add( RequiredExpr(inTemplate) ); + RequiredMatch( "%>" ); + } else if( parser.match( "<%" ) ) { + Spaces(inTemplate); + return parser.success(ExpList.build(builder)); + } else { + int i = parser.currentIndex(); + do { + if( parser.match( "%>" ) ) + throw parser.exception("'%>' unexpected"); + if( !parser.anyChar() ) + throw parser.exception("Unclosed template expression"); + } while( !parser.test( "<%" ) ); + String match = parser.textFrom(i); + builder.add( new ConstExpr(match) ); + } + } + } + + private Stmt ReturnStmt() throws ParseException { + int start = parser.begin(); + if( !Keyword("return",In.NOTHING) ) + return parser.failure(null); + Expressions exprs = ExpList(In.NOTHING); + if( exprs==null ) + exprs = ExpList.emptyExpList; + return parser.success( new ReturnStmt(se(start),exprs) ); + } + + private Stmt FunctionStmt() throws ParseException { + parser.begin(); + if( !Keyword("function",In.NOTHING) ) + return parser.failure(null); + + int start = parser.currentIndex(); + Var var = nameVar(start,RequiredName(In.NOTHING)); + while( parser.match( '.' ) ) { + Spaces(In.NOTHING); + var = indexVar( start, expr(var.expr()), NameExpr(In.NOTHING) ); + } + Settable fnName = var.settable(); + + FnDef fnDef = RequiredFunction(In.NOTHING); + return parser.success( new SetStmt(fnName,fnDef) ); + } + + private Stmt LocalFunctionStmt() throws ParseException { + parser.begin(); + if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) + return parser.failure(null); + String name = RequiredName(In.NOTHING); + addSymbol( name ); + FnDef fnDef = RequiredFunction(In.NOTHING); + return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) ); + } + + private Stmt ImportStmt() throws ParseException { + int start = parser.begin(); + if( !Keyword("import",In.NOTHING) ) + return parser.failure(null); + Expr importExpr = (Expr)nameVar(start,"require").expr(); + String modName = StringLiteral(In.NOTHING); + if( modName==null ) + return parser.failure(null); + String varName = modName.substring(modName.lastIndexOf('.')+1); + LuanSource.Element se = se(start); + FnCall require = new FnCall( se, importExpr, new ConstExpr(modName) ); + Settable settable; + if( interactive ) { + settable = nameVar(se,varName).settable(); + } else { + addSymbol( varName ); + settable = new SetLocalVar(symbolsSize()-1); + } + return parser.success( new SetStmt( settable, expr(require) ) ); + } + + private Stmt BreakStmt() throws ParseException { + parser.begin(); + if( !Keyword("break",In.NOTHING) ) + return parser.failure(null); + if( frame.loops <= 0 ) + throw parser.exception("'break' outside of loop"); + return parser.success( new BreakStmt() ); + } + + private Stmt ForStmt() throws ParseException { + int start = parser.begin(); + int stackStart = symbolsSize(); + if( !Keyword("for",In.NOTHING) ) + return parser.failure(null); + List<String> names = RequiredNameList(In.NOTHING); + if( !Keyword("in",In.NOTHING) ) + return parser.failure(null); + Expr expr = expr(RequiredExpr(In.NOTHING)); + RequiredKeyword("do",In.NOTHING); + addSymbols(names); + Stmt loop = RequiredLoopBlock(); + RequiredKeyword("end",In.NOTHING); + Stmt stmt = new ForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop ); + popSymbols( symbolsSize() - stackStart ); + return parser.success(stmt); + } + + private Stmt TryStmt() throws ParseException { + parser.begin(); + if( !Keyword("try",In.NOTHING) ) + return parser.failure(null); + Stmt tryBlock = RequiredBlock(); + RequiredKeyword("catch",In.NOTHING); + String name = RequiredName(In.NOTHING); + addSymbol(name); + RequiredKeyword("do",In.NOTHING); + Stmt catchBlock = RequiredBlock(); + RequiredKeyword("end",In.NOTHING); + Stmt stmt = new TryStmt( tryBlock, symbolsSize()-1, catchBlock ); + popSymbols(1); + return parser.success(stmt); + } + + private Stmt DoStmt() throws ParseException { + parser.begin(); + if( !Keyword("do",In.NOTHING) ) + return parser.failure(null); + Stmt stmt = RequiredBlock(); + RequiredKeyword("end",In.NOTHING); + return parser.success(stmt); + } + + private boolean LocalStmt(List<Stmt> stmts) throws ParseException { + parser.begin(); + if( !Keyword("local",In.NOTHING) ) + return parser.failure(); + List<String> names = NameList(In.NOTHING); + if( names==null ) + return parser.failure(); + if( parser.match( '=' ) ) { + Spaces(In.NOTHING); + Expressions values = ExpList(In.NOTHING); + if( values==null ) + throw parser.exception("Expressions expected"); + SetLocalVar[] vars = new SetLocalVar[names.size()]; + int stackStart = symbolsSize(); + for( int i=0; i<vars.length; i++ ) { + vars[i] = new SetLocalVar(stackStart+i); + } + stmts.add( new SetStmt( vars, values ) ); + } + addSymbols(names); + return parser.success(); + } + + private List<String> RequiredNameList(In in) throws ParseException { + parser.begin(); + List<String> names = NameList(in); + if( names==null ) + throw parser.exception("Name expected"); + return parser.success(names); + } + + private List<String> NameList(In in) throws ParseException { + String name = Name(in); + if( name==null ) + return null; + List<String> names = new ArrayList<String>(); + names.add(name); + while( (name=anotherName(in)) != null ) { + names.add(name); + } + return names; + } + + private String anotherName(In in) throws ParseException { + parser.begin(); + if( !parser.match( ',' ) ) + return parser.failure(null); + Spaces(in); + String name = Name(in); + if( name==null ) + return parser.failure(null); + return parser.success(name); + } + + private Stmt WhileStmt() throws ParseException { + int start = parser.begin(); + if( !Keyword("while",In.NOTHING) ) + return parser.failure(null); + Expr cnd = expr(RequiredExpr(In.NOTHING)); + RequiredKeyword("do",In.NOTHING); + Stmt loop = RequiredLoopBlock(); + RequiredKeyword("end",In.NOTHING); + return parser.success( new WhileStmt(se(start),cnd,loop) ); + } + + private Stmt RepeatStmt() throws ParseException { + int start = parser.begin(); + if( !Keyword("repeat",In.NOTHING) ) + return parser.failure(null); + Stmt loop = RequiredLoopBlock(); + RequiredKeyword("until",In.NOTHING); + Expr cnd = expr(RequiredExpr(In.NOTHING)); + return parser.success( new RepeatStmt(se(start),loop,cnd) ); + } + + private Stmt RequiredLoopBlock() throws ParseException { + incLoops(); + Stmt stmt = RequiredBlock(); + decLoops(); + return stmt; + } + + private Stmt IfStmt() throws ParseException { + parser.begin(); + if( !Keyword("if",In.NOTHING) ) + return parser.failure(null); + return parser.success( IfStmt2() ); + } + + private Stmt IfStmt2() throws ParseException { + int start = parser.currentIndex(); + Expr cnd = expr(RequiredExpr(In.NOTHING)); + RequiredKeyword("then",In.NOTHING); + Stmt thenBlock = RequiredBlock(); + Stmt elseBlock; + if( Keyword("elseif",In.NOTHING) ) { + elseBlock = IfStmt2(); + } else { + elseBlock = Keyword("else",In.NOTHING) ? RequiredBlock() : Stmt.EMPTY; + RequiredKeyword("end",In.NOTHING); + } + return new IfStmt(se(start),cnd,thenBlock,elseBlock); + } + + private Stmt SetStmt() throws ParseException { + parser.begin(); + List<Settable> vars = new ArrayList<Settable>(); + Settable s = SettableVar(); + if( s == null ) + return parser.failure(null); + vars.add(s); + while( parser.match( ',' ) ) { + Spaces(In.NOTHING); + s = SettableVar(); + if( s == null ) + return parser.failure(null); + vars.add(s); + } + if( !parser.match( '=' ) ) + return parser.failure(null); + Spaces(In.NOTHING); + Expressions values = ExpList(In.NOTHING); + if( values==null ) + throw parser.exception("Expressions expected"); + return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); + } + + private Stmt ExpressionsStmt() throws ParseException { + parser.begin(); + Expressions exp = Expr(In.NOTHING); + if( exp instanceof FnCall || exp instanceof AndExpr || exp instanceof OrExpr ) + return parser.success( new ExpressionsStmt(exp) ); + return parser.failure(null); + } + + private Settable SettableVar() throws ParseException { + int start = parser.begin(); + Var var = VarZ(In.NOTHING); + if( var==null ) + return parser.failure(null); + return parser.success( var.settable() ); + } + + private Expressions RequiredExpr(In in) throws ParseException { + parser.begin(); + return parser.success(required(Expr(in),"Bad expression")); + } + + private Expressions Expr(In in) throws ParseException { + parser.begin(); + Expressions exp; + return (exp = VarArgs(in)) != null + || (exp = OrExpr(in)) != null + ? parser.success(exp) + : parser.failure((Expressions)null) + ; + } + + private Expressions OrExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = AndExpr(in); + if( exp==null ) + return parser.failure(null); + while( Keyword("or",in) ) { + exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(in))) ); + } + return parser.success(exp); + } + + private Expressions AndExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = RelExpr(in); + if( exp==null ) + return parser.failure(null); + while( Keyword("and",in) ) { + exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(in))) ); + } + return parser.success(exp); + } + + private Expressions RelExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = ConcatExpr(in); + if( exp==null ) + return parser.failure(null); + while(true) { + if( parser.match("==") ) { + Spaces(in); + exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); + } else if( parser.match("~=") ) { + Spaces(in); + exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ) ); + } else if( parser.match("<=") ) { + Spaces(in); + exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); + } else if( parser.match(">=") ) { + Spaces(in); + exp = new LeExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) ); + } else if( parser.match("<") ) { + Spaces(in); + exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); + } else if( parser.match(">") ) { + Spaces(in); + exp = new LtExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) ); + } else + break; + } + return parser.success(exp); + } + + private Expressions ConcatExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = SumExpr(in); + if( exp==null ) + return parser.failure(null); + if( parser.match("..") ) { + Spaces(in); + exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); + } + return parser.success(exp); + } + + private Expressions SumExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = TermExpr(in); + if( exp==null ) + return parser.failure(null); + while(true) { + if( parser.match('+') ) { + Spaces(in); + exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(in))) ); + } else if( Minus() ) { + Spaces(in); + exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(in))) ); + } else + break; + } + return parser.success(exp); + } + + private boolean Minus() { + parser.begin(); + return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); + } + + private Expressions TermExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = UnaryExpr(in); + if( exp==null ) + return parser.failure(null); + while(true) { + if( parser.match('*') ) { + Spaces(in); + exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); + } else if( parser.match('/') ) { + Spaces(in); + exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); + } else if( Mod() ) { + Spaces(in); + exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); + } else + break; + } + return parser.success(exp); + } + + private boolean Mod() { + parser.begin(); + return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure(); + } + + private Expressions UnaryExpr(In in) throws ParseException { + int start = parser.begin(); + if( parser.match('#') ) { + Spaces(in); + return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(in))) ) ); + } + if( Minus() ) { + Spaces(in); + return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(in))) ) ); + } + if( Keyword("not",in) ) { + Spaces(in); + return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(in))) ) ); + } + Expressions exp = PowExpr(in); + if( exp==null ) + return parser.failure(null); + return parser.success(exp); + } + + private Expressions PowExpr(In in) throws ParseException { + int start = parser.begin(); + Expressions exp = SingleExpr(in); + if( exp==null ) + return parser.failure(null); + if( parser.match('^') ) { + Spaces(in); + exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(in))) ); + } + return parser.success(exp); + } + + private Expressions SingleExpr(In in) throws ParseException { + parser.begin(); + Expressions exp; + exp = FunctionExpr(in); + if( exp != null ) + return parser.success(exp); + exp = TableExpr(in); + if( exp != null ) + return parser.success(exp); + exp = VarExp(in); + if( exp != null ) + return parser.success(exp); + exp = Literal(in); + if( exp != null ) + return parser.success(exp); + return parser.failure(null); + } + + private Expr FunctionExpr(In in) throws ParseException { + if( !Keyword("function",in) ) + return null; + return RequiredFunction(in); + } + + private FnDef RequiredFunction(In in) throws ParseException { + int start = parser.begin(); + RequiredMatch('('); + In inParens = in.parens(); + Spaces(inParens); + frame = new Frame(frame); + List<String> names = NameList(in); + if( names != null ) { + addSymbols(names); + if( parser.match(',') ) { + Spaces(inParens); + if( !parser.match("...") ) + throw parser.exception(); + frame.isVarArg = true; + } + } else if( parser.match("...") ) { + Spaces(inParens); + frame.isVarArg = true; + } + RequiredMatch(')'); + Spaces(in); + Stmt block = RequiredBlock(); + RequiredKeyword("end",in); + FnDef fnDef = newFnDef(start,block); + frame = frame.parent; + return parser.success(fnDef); + } + + private VarArgs VarArgs(In in) throws ParseException { + int start = parser.begin(); + if( !frame.isVarArg || !parser.match("...") ) + return parser.failure(null); + Spaces(in); + return parser.success( new VarArgs(se(start)) ); + } + + private Expr TableExpr(In in) throws ParseException { + int start = parser.begin(); + if( !parser.match('{') ) + return parser.failure(null); + In inParens = in.parens(); + Spaces(inParens); + List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>(); + List<Expressions> builder = new ArrayList<Expressions>(); + while( Field(fields,builder,in) && FieldSep(inParens) ); + Spaces(inParens); + if( !parser.match('}') ) + throw parser.exception("Expected table element or '}'"); + return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), ExpList.build(builder) ) ); + } + + private boolean FieldSep(In in) throws ParseException { + if( !parser.anyOf(",;") ) + return false; + Spaces(in); + return true; + } + + private boolean Field(List<TableExpr.Field> fields,List<Expressions> builder,In in) throws ParseException { + parser.begin(); + Expr exp = SubExpr(in); + if( exp==null ) + exp = NameExpr(in); + if( exp!=null && parser.match('=') ) { + Spaces(in); + fields.add( new TableExpr.Field( exp, required(expr(Expr(in))) ) ); + return parser.success(); + } + parser.rollback(); + Expressions exprs = Expr(in); + if( exprs != null ) { + builder.add(exprs); + return parser.success(); + } + return parser.failure(); + } + + private Expressions VarExp(In in) throws ParseException { + Var var = VarZ(in); + return var==null ? null : var.expr(); + } + + private Var VarZ(In in) throws ParseException { + int start = parser.begin(); + Var var = VarStart(in); + if( var==null ) + return parser.failure(null); + Var var2; + while( (var2=Var2(in,start,var.expr())) != null ) { + var = var2; + } + return parser.success(var); + } + + private Var Var2(In in,int start,Expressions exp1) throws ParseException { + parser.begin(); + Var var = VarExt(in,start,exp1); + if( var != null ) + return parser.success(var); + if( parser.match("->") ) { + Spaces(in); + List<Expressions> builder = new ArrayList<Expressions>(); + builder.add(exp1); + Expr exp2 = expr(RequiredVarExpB(in)); + FnCall fnCall = required(Args( in, start, exp2, builder )); + return parser.success(exprVar(fnCall)); + } + FnCall fnCall = Args( in, start, expr(exp1), new ArrayList<Expressions>() ); + if( fnCall != null ) + return parser.success(exprVar(fnCall)); + return parser.failure(null); + } + + private Expressions RequiredVarExpB(In in) throws ParseException { + int start = parser.begin(); + Var var = required(VarStart(in)); + Var var2; + while( (var2=VarExt(in,start,var.expr())) != null ) { + var = var2; + } + return parser.success(var.expr()); + } + + private Var VarExt(In in,int start,Expressions exp1) throws ParseException { + parser.begin(); + Expr exp2 = SubExpr(in); + if( exp2 != null ) + return parser.success(indexVar(start,expr(exp1),exp2)); + if( parser.match('.') ) { + Spaces(in); + exp2 = NameExpr(in); + if( exp2!=null ) + return parser.success(indexVar(start,expr(exp1),exp2)); + } + return parser.failure(null); + } + + private Var VarStart(In in) throws ParseException { + int start = parser.begin(); + if( parser.match('(') ) { + In inParens = in.parens(); + Spaces(inParens); + Expr exp = expr(RequiredExpr(inParens)); + RequiredMatch(')'); + Spaces(in); + return parser.success(exprVar(exp)); + } + String name = Name(in); + if( name != null ) + return parser.success(nameVar(start,name)); + return parser.failure(null); + } + + private Expr env() { + int index = stackIndex(_ENV); + if( index != -1 ) + return new GetLocalVar(null,index); + index = upValueIndex(_ENV); + if( index != -1 ) + return new GetUpVar(null,index); + throw new RuntimeException("_ENV not found"); + } + + private interface Var { + public Expressions expr(); + public Settable settable(); + } + + private Var nameVar(final int start,final String name) { + return nameVar(se(start),name); + } + + private Var nameVar(final LuanSource.Element se,final String name) { + return new Var() { + + public Expr expr() { + int index = stackIndex(name); + if( index != -1 ) + return new GetLocalVar(se,index); + index = upValueIndex(name); + if( index != -1 ) + return new GetUpVar(se,index); + return new IndexExpr( se, env(), new ConstExpr(name) ); + } + + public Settable settable() { + int index = stackIndex(name); + if( index != -1 ) + return new SetLocalVar(index); + index = upValueIndex(name); + if( index != -1 ) + return new SetUpVar(index); + return new SetTableEntry( se, env(), new ConstExpr(name) ); + } + }; + } + + private Var exprVar(final Expressions expr) { + return new Var() { + + public Expressions expr() { + return expr; + } + + public Settable settable() { + return null; + } + }; + } + + private Var indexVar(final int start,final Expr table,final Expr key) { + return new Var() { + + public Expr expr() { + return new IndexExpr( se(start), table, key ); + } + + public Settable settable() { + return new SetTableEntry(se(start),table,key); + } + }; + } + + private FnCall Args(In in,int start,Expr fn,List<Expressions> builder) throws ParseException { + parser.begin(); + return args(in,builder) + ? parser.success( new FnCall( se(start), fn, ExpList.build(builder) ) ) + : parser.failure((FnCall)null); + } + + private boolean args(In in,List<Expressions> builder) throws ParseException { + if( parser.match('(') ) { + In inParens = in.parens(); + Spaces(inParens); + ExpList(inParens,builder); // optional + if( !parser.match(')') ) + throw parser.exception("Expression or ')' expected"); + Spaces(in); + return true; + } + Expr exp = TableExpr(in); + if( exp != null ) { + builder.add(exp); + return true; + } + String s = StringLiteral(in); + if( s != null ) { + builder.add( new ConstExpr(s) ); + return true; + } + Expressions exps = TemplateExpressions(in); + if( exps != null ) { + builder.add(exps); + return true; + } + return false; + } + + private Expressions ExpList(In in) throws ParseException { + List<Expressions> builder = new ArrayList<Expressions>(); + return ExpList(in,builder) ? ExpList.build(builder) : null; + } + + private boolean ExpList(In in,List<Expressions> builder) throws ParseException { + parser.begin(); + Expressions exp = TemplateExpressions(in); + if( exp != null ) { + builder.add(exp); + return parser.success(); + } + exp = Expr(in); + if( exp==null ) + return parser.failure(); + builder.add(exp); + while( parser.match(',') ) { + Spaces(in); + exp = TemplateExpressions(in); + if( exp != null ) { + builder.add(exp); + return parser.success(); + } + builder.add( RequiredExpr(in) ); + } + return parser.success(); + } + + private Expr SubExpr(In in) throws ParseException { + parser.begin(); + if( !parser.match('[') ) + return parser.failure(null); + In inParens = in.parens(); + Spaces(inParens); + Expr exp = expr(RequiredExpr(inParens)); + RequiredMatch(']'); + Spaces(in); + return parser.success(exp); + } + + private Expr NameExpr(In in) throws ParseException { + String name = Name(in); + return name==null ? null : new ConstExpr(name); + } + + private String RequiredName(In in) throws ParseException { + parser.begin(); + String name = Name(in); + if( name==null ) + throw parser.exception("Name expected"); + return parser.success(name); + } + + private String Name(In in) throws ParseException { + int start = parser.begin(); + if( !NameFirstChar() ) + return parser.failure(null); + while( NameChar() ); + String match = parser.textFrom(start); + if( keywords.contains(match) ) + return parser.failure(null); + Spaces(in); + return parser.success(match); + } + + private boolean NameChar() { + return NameFirstChar() || Digit(); + } + + private boolean NameFirstChar() { + return parser.inCharRange('a', 'z') || parser.inCharRange('A', 'Z') || parser.match('_'); + } + + private void RequiredMatch(char c) throws ParseException { + if( !parser.match(c) ) + throw parser.exception("'"+c+"' expected"); + } + + private void RequiredMatch(String s) throws ParseException { + if( !parser.match(s) ) + throw parser.exception("'"+s+"' expected"); + } + + private void RequiredKeyword(String keyword,In in) throws ParseException { + if( !Keyword(keyword,in) ) + throw parser.exception("'"+keyword+"' expected"); + } + + private boolean Keyword(String keyword,In in) throws ParseException { + parser.begin(); + if( !parser.match(keyword) || NameChar() ) + return parser.failure(); + Spaces(in); + return parser.success(); + } + + private static final Set<String> keywords = new HashSet<String>(Arrays.asList( + "and", + "break", + "catch", + "do", + "else", + "elseif", + "end", + "false", + "for", + "function", + "goto", + "if", + "import", + "in", + "local", + "nil", + "not", + "or", + "repeat", + "return", + "then", + "true", + "try", + "until", + "while" + )); + + private Expr Literal(In in) throws ParseException { + if( NilLiteral(in) ) + return new ConstExpr(null); + Boolean b = BooleanLiteral(in); + if( b != null ) + return new ConstExpr(b); + Number n = NumberLiteral(in); + if( n != null ) + return new ConstExpr(n); + String s = StringLiteral(in); + if( s != null ) + return new ConstExpr(s); + return null; + } + + private boolean NilLiteral(In in) throws ParseException { + return Keyword("nil",in); + } + + private Boolean BooleanLiteral(In in) throws ParseException { + if( Keyword("true",in) ) + return true; + if( Keyword("false",in) ) + return false; + return null; + } + + private Number NumberLiteral(In in) throws ParseException { + parser.begin(); + Number n; + if( parser.matchIgnoreCase("0x") ) { + n = HexNumber(); + } else { + n = DecNumber(); + } + if( n==null || NameChar() ) + return parser.failure(null); + Spaces(in); + return parser.success(n); + } + + private Number DecNumber() { + int start = parser.begin(); + if( Int() ) { + if( parser.match('.') ) + Int(); // optional + } else if( parser.match('.') && Int() ) { + // ok + } else + return parser.failure(null); + Exponent(); // optional + return parser.success(Double.valueOf(parser.textFrom(start))); + } + + private boolean Exponent() { + parser.begin(); + if( !parser.matchIgnoreCase("e") ) + return parser.failure(); + parser.anyOf("+-"); // optional + if( !Int() ) + return parser.failure(); + return parser.success(); + } + + private boolean Int() { + if( !Digit() ) + return false; + while( Digit() ); + return true; + } + + private boolean Digit() { + return parser.inCharRange('0', '9'); + } + + private Number HexNumber() { + int start = parser.begin(); + double n; + if( HexInt() ) { + n = (double)Long.parseLong(parser.textFrom(start),16); + if( parser.match('.') ) { + start = parser.currentIndex(); + if( HexInt() ) { + String dec = parser.textFrom(start); + n += (double)Long.parseLong(dec,16) / Math.pow(16,dec.length()); + } + } + } else if( parser.match('.') && HexInt() ) { + String dec = parser.textFrom(start+1); + n = (double)Long.parseLong(dec,16) / Math.pow(16,dec.length()); + } else { + return parser.failure(null); + } + if( parser.matchIgnoreCase("p") ) { + parser.anyOf("+-"); // optional + start = parser.currentIndex(); + if( !HexInt() ) + return parser.failure(null); + n *= Math.pow(2,(double)Long.parseLong(parser.textFrom(start))); + } + return parser.success(Double.valueOf(n)); + } + + private boolean HexInt() { + if( !HexDigit() ) + return false; + while( HexDigit() ); + return true; + } + + + private boolean HexDigit() { + return Digit() || parser.anyOf("abcdefABCDEF"); + } + + private String StringLiteral(In in) throws ParseException { + String s; + if( (s=QuotedString('"'))==null + && (s=QuotedString('\''))==null + && (s=LongString())==null + ) + return null; + Spaces(in); + return s; + } + + private String LongString() throws ParseException { + parser.begin(); + if( !parser.match('[') ) + return parser.failure(null); + int start = parser.currentIndex(); + while( parser.match('=') ); + int nEquals = parser.currentIndex() - start; + if( !parser.match('[') ) + return parser.failure(null); + EndOfLine(); + start = parser.currentIndex(); + while( !LongBracketsEnd(nEquals) ) { + if( !parser.anyChar() ) + throw parser.exception("Unclosed long string"); + } + String s = parser.text.substring( start, parser.currentIndex() - nEquals - 2 ); + return parser.success(s); + } + + private String QuotedString(char quote) throws ParseException { + parser.begin(); + if( !parser.match(quote) ) + return parser.failure(null); + StringBuilder buf = new StringBuilder(); + while( !parser.match(quote) ) { + Character c = EscSeq(); + if( c != null ) { + buf.append(c); + } else { + if( !parser.anyChar() ) + throw parser.exception("Unclosed string"); + buf.append(parser.lastChar()); + } + } + return parser.success(buf.toString()); + } + + private Character EscSeq() { + parser.begin(); + if( !parser.match('\\') ) + return parser.failure(null); + if( parser.match('a') ) return parser.success('\u0007'); + if( parser.match('b') ) return parser.success('\b'); + if( parser.match('f') ) return parser.success('\f'); + if( parser.match('n') ) return parser.success('\n'); + if( parser.match('r') ) return parser.success('\r'); + if( parser.match('t') ) return parser.success('\t'); + if( parser.match('v') ) return parser.success('\u000b'); + if( parser.match('\\') ) return parser.success('\\'); + if( parser.match('"') ) return parser.success('"'); + if( parser.match('\'') ) return parser.success('\''); + int start = parser.currentIndex(); + if( parser.match('x') && HexDigit() && HexDigit() ) + return parser.success((char)Integer.parseInt(parser.textFrom(start+1),16)); + if( Digit() ) { + if( Digit() ) Digit(); // optional + return parser.success((char)Integer.parseInt(parser.textFrom(start))); + } + return parser.failure(null); + } + + private void Spaces(In in) throws ParseException { + while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || in.parens && NewLine() ); + } + + private boolean ContinueOnNextLine() { + parser.begin(); + return parser.match('\\') && EndOfLine() ? parser.success() : parser.failure(); + } + + private boolean NewLine() { + if( !EndOfLine() ) + return false; + if( parser.match("--") ) { + while( parser.noneOf("\r\n") ); + } + return true; + } + + private boolean Comment() throws ParseException { + parser.begin(); + if( !parser.match("--[") ) + return parser.failure(); + int start = parser.currentIndex(); + while( parser.match('=') ); + int nEquals = parser.currentIndex() - start; + if( !parser.match('[') ) + return parser.failure(); + while( !LongBracketsEnd(nEquals) ) { + if( !parser.anyChar() ) + throw parser.exception("Unclosed comment"); + } + return parser.success(); + } + + private boolean LongBracketsEnd(int nEquals) { + parser.begin(); + if( !parser.match(']') ) + return parser.failure(); + while( nEquals-- > 0 ) { + if( !parser.match('=') ) + return parser.failure(); + } + if( !parser.match(']') ) + return parser.failure(); + return parser.success(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/LuanStateImpl.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,137 @@ +package luan.impl; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import luan.Luan; +import luan.LuanState; +import luan.LuanTable; +import luan.LuanFunction; +import luan.MetatableGetter; +import luan.LuanException; +import luan.LuanElement; +import luan.DeepCloner; + + +final class LuanStateImpl extends LuanState { + + private static class Frame { + final Frame previousFrame; + final Closure closure; + final Object[] stack; + final Object[] varArgs; + UpValue[] downValues = null; + + Frame( Frame previousFrame, Closure closure, int stackSize, Object[] varArgs) { + this.previousFrame = previousFrame; + this.closure = closure; + this.stack = new Object[stackSize]; + this.varArgs = varArgs; + } + + void stackClear(int start,int end) { + if( downValues != null ) { + for( int i=start; i<end; i++ ) { + UpValue downValue = downValues[i]; + if( downValue != null ) { + downValue.close(); + downValues[i] = null; + } + } + } + for( int i=start; i<end; i++ ) { + stack[i] = null; + } + } + + UpValue getUpValue(int index) { + if( downValues==null ) + downValues = new UpValue[stack.length]; + if( downValues[index] == null ) + downValues[index] = new UpValue(stack,index); + return downValues[index]; + } + } + + private Frame frame = null; + Object returnValues; + Closure tailFn; + Map<UpValue.EnvGetter,UpValue> envs = new HashMap<UpValue.EnvGetter,UpValue>(); + + LuanStateImpl() {} + + private LuanStateImpl(LuanStateImpl luan) { + super(luan); + } + + @Override public LuanState shallowClone() { +// if( frame != null ) +// throw new IllegalStateException("frame isn't null"); + return new LuanStateImpl(this); + } + + @Override public void deepenClone(LuanState clone,DeepCloner cloner) { + super.deepenClone(clone,cloner); + LuanStateImpl cloneImpl = (LuanStateImpl)clone; + cloneImpl.envs = new HashMap<UpValue.EnvGetter,UpValue>(); + for( Map.Entry<UpValue.EnvGetter,UpValue> entry : envs.entrySet() ) { + cloneImpl.envs.put( entry.getKey(), cloner.deepClone(entry.getValue()) ); + } + } + + // returns stack + Object[] newFrame(Closure closure, int stackSize, Object[] varArgs) { + returnValues = LuanFunction.NOTHING; + tailFn = null; + frame = new Frame(frame,closure,stackSize,varArgs); + return frame.stack; + } + + void popFrame() { + returnValues = LuanFunction.NOTHING; + tailFn = null; + frame = frame.previousFrame; + } + + Object stackGet(int index) { + return frame.stack[index]; + } + + void stackSet(int index,Object value) { + frame.stack[index] = value; + } + + void stackClear(int start,int end) { + frame.stackClear(start,end); + } + + Object[] varArgs() { + return frame.varArgs; + } + + Closure closure() { + return frame.closure; + } + + UpValue getUpValue(int index) { + return frame.getUpValue(index); + } + + UpValue getUpValue(UpValue.EnvGetter getter) throws LuanException { + UpValue uv = envs.get(getter); + if( uv == null ) { + LuanTable env = new LuanTable(); + uv = new UpValue(env); + envs.put(getter,uv); + } + return uv; + } + + @Override public LuanTable currentEnvironment() { + if( frame==null ) + return null; + return (LuanTable)frame.closure.upValues()[0].get(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ModExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,23 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class ModExpr extends BinaryOpExpr { + + ModExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + Number n1 = Luan.toNumber(o1); + Number n2 = Luan.toNumber(o2); + if( n1 != null && n2 != null ) + return n1.doubleValue() % n2.doubleValue(); + return arithmetic(luan,"__mod",o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/MulExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,23 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class MulExpr extends BinaryOpExpr { + + MulExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + Number n1 = Luan.toNumber(o1); + Number n2 = Luan.toNumber(o2); + if( n1 != null && n2 != null ) + return n1.doubleValue() * n2.doubleValue(); + return arithmetic(luan,"__mul",o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/NotExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,17 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class NotExpr extends UnaryOpExpr { + + NotExpr(LuanSource.Element se,Expr op) { + super(se,op); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + return !Luan.toBoolean(op.eval(luan)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/OrExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,18 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class OrExpr extends BinaryOpExpr { + + OrExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object v1 = op1.eval(luan); + return Luan.toBoolean(v1) ? v1 : op2.eval(luan); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ParseException.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,55 @@ +package luan.impl; + +import luan.LuanSource; + + +public final class ParseException extends Exception { + public final LuanSource src; + public final int iCurrent; + public final int iHigh; + + ParseException(String msg,LuanSource src,int iCurrent,int iHigh) { + super(msg); + this.src = src; + this.iCurrent = iCurrent; + this.iHigh = iHigh; +//System.out.println("iCurrent = "+iCurrent); +//System.out.println("iHigh = "+iHigh); + } + + private class Location { + final int line; + final int pos; + + Location(int index) { + int line = 0; + int i = -1; + while(true) { + int j = src.text.indexOf('\n',i+1); + if( j == -1 || j >= index ) + break; + i = j; + line++; + } + this.line = line; + this.pos = index - i - 1; + } + } + + private String[] lines() { + return src.text.split("\n",-1); + } + + public String getFancyMessage() { + Location loc = new Location(iCurrent); + String line = lines()[loc.line]; + String msg = getMessage() + " (line " + (loc.line+1) + ", pos " + (loc.pos+1) + ") in " + src.name + "\n"; + StringBuilder sb = new StringBuilder(msg); + sb.append( line + "\n" ); + for( int i=0; i<loc.pos; i++ ) { + sb.append( line.charAt(i)=='\t' ? '\t' : ' ' ); + } + sb.append("^\n"); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Parser.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,152 @@ +package luan.impl; + +import luan.LuanSource; + + +final class Parser { + private final LuanSource src; + public final String text; + private final int len; + private int[] stack = new int[256]; + private int frame = 0; + private int iHigh; + + public Parser(LuanSource src) { + this.src = src; + this.text = src.text; + this.len = text.length(); + } + + private int i() { + return stack[frame]; + } + + private void i(int i) { + stack[frame] += i; + if( iHigh < stack[frame] ) + iHigh = stack[frame]; + } + + public int begin() { + frame++; + if( frame == stack.length ) { + int[] a = new int[2*frame]; + System.arraycopy(stack,0,a,0,frame); + stack = a; + } + stack[frame] = stack[frame-1]; + return i(); + } + + public void rollback() { + stack[frame] = stack[frame-1]; + } + + public <T> T success(T t) { + success(); + return t; + } + + public boolean success() { + frame--; + stack[frame] = stack[frame+1]; + return true; + } + + public <T> T failure(T t) { + failure(); + return t; + } + + public boolean failure() { + frame--; + return false; + } + + public ParseException exception(String msg) { + return new ParseException(msg,src,i(),iHigh); + } + + public ParseException exception() { + return exception("Invalid input"); + } + + public int currentIndex() { + return i(); + } + + public char lastChar() { + return text.charAt(i()-1); + } + + public char currentChar() { + return text.charAt(i()); + } + + public boolean endOfInput() { + return i() >= len; + } + + public boolean match(char c) { + if( endOfInput() || text.charAt(i()) != c ) + return false; + i(1); + return true; + } + + public boolean match(String s) { + int n = s.length(); + if( !text.regionMatches(i(),s,0,n) ) + return false; + i(n); + return true; + } + + public boolean matchIgnoreCase(String s) { + int n = s.length(); + if( !text.regionMatches(true,i(),s,0,n) ) + return false; + i(n); + return true; + } + + public boolean anyOf(String s) { + if( endOfInput() || s.indexOf(text.charAt(i())) == -1 ) + return false; + i(1); + return true; + } + + public boolean noneOf(String s) { + if( endOfInput() || s.indexOf(text.charAt(i())) != -1 ) + return false; + i(1); + return true; + } + + public boolean inCharRange(char cLow, char cHigh) { + if( endOfInput() ) + return false; + char c = text.charAt(i()); + if( !(cLow <= c && c <= cHigh) ) + return false; + i(1); + return true; + } + + public boolean anyChar() { + if( endOfInput() ) + return false; + i(1); + return true; + } + + public boolean test(String s) { + return text.regionMatches(i(),s,0,s.length()); + } + + public String textFrom(int start) { + return text.substring(start,i()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/PowExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,23 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class PowExpr extends BinaryOpExpr { + + PowExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + Number n1 = Luan.toNumber(o1); + Number n2 = Luan.toNumber(o2); + if( n1 != null && n2 != null ) + return Math.pow( n1.doubleValue(), n2.doubleValue() ); + return arithmetic(luan,"__pow",o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/RepeatStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,25 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class RepeatStmt extends CodeImpl implements Stmt { + private final Stmt doStmt; + private final Expr cnd; + + RepeatStmt(LuanSource.Element se,Stmt doStmt,Expr cnd) { + super(se); + this.doStmt = doStmt; + this.cnd = cnd; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + try { + do { + doStmt.eval(luan); + } while( !luan.bit(se).checkBoolean( cnd.eval(luan) ) ); + } catch(BreakException e) {} + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ReturnException.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,4 @@ +package luan.impl; + + +final class ReturnException extends RuntimeException {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/ReturnStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,39 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanFunction; +import luan.LuanSource; + + +final class ReturnStmt extends CodeImpl implements Stmt { + private final Expressions expressions; + private final Expr tailFnExpr; + boolean throwReturnException = true; + + ReturnStmt(LuanSource.Element se,Expressions expressions) { + super(se); + if( expressions instanceof FnCall ) { // tail call + FnCall fnCall = (FnCall)expressions; + this.expressions = fnCall.args; + this.tailFnExpr = fnCall.fnExpr; + } else { + this.expressions = expressions; + this.tailFnExpr = null; + } + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + luan.returnValues = expressions.eval(luan); + if( tailFnExpr != null ) { + LuanFunction tailFn = luan.bit(se).checkFunction( tailFnExpr.eval(luan) ); + if( tailFn instanceof Closure ) { + luan.tailFn = (Closure)tailFn; + } else { + luan.returnValues = luan.bit(tailFnExpr.se()).call(tailFn,tailFnExpr.se().text(),Luan.array(luan.returnValues)); + } + } + if( throwReturnException ) + throw new ReturnException(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/SetLocalVar.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,14 @@ +package luan.impl; + + +final class SetLocalVar implements Settable { + private final int index; + + SetLocalVar(int index) { + this.index = index; + } + + @Override public void set(LuanStateImpl luan,Object value) { + luan.stackSet( index, value ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/SetStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,36 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; + + +final class SetStmt implements Stmt { + private final Settable[] vars; + private final Expressions expressions; + + SetStmt(Settable var,Expr expr) { + this( new Settable[]{var}, expr ); + } + + SetStmt(Settable[] vars,Expressions expressions) { + this.vars = vars; + this.expressions = expressions; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + final Object obj = expressions.eval(luan); + if( obj instanceof Object[] ) { + Object[] vals = (Object[])obj; + for( int i=0; i<vars.length; i++ ) { + Object val = i < vals.length ? vals[i] : null; + vars[i].set(luan,val); + } + } else { + vars[0].set(luan,obj); + for( int i=1; i<vars.length; i++ ) { + vars[i].set(luan,null); + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/SetTableEntry.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,48 @@ +package luan.impl; + +import luan.LuanException; +import luan.LuanTable; +import luan.Luan; +import luan.LuanFunction; +import luan.LuanSource; + + +final class SetTableEntry extends CodeImpl implements Settable { + private final Expr tableExpr; + private final Expr keyExpr; + + SetTableEntry(LuanSource.Element se,Expr tableExpr,Expr keyExpr) { + super(se); + this.tableExpr = tableExpr; + this.keyExpr = keyExpr; + } + + @Override public void set(LuanStateImpl luan,Object value) throws LuanException { + newindex( luan, tableExpr.eval(luan), keyExpr.eval(luan), value ); + } + + private void newindex(LuanStateImpl luan,Object t,Object key,Object value) throws LuanException { + Object h; + if( t instanceof LuanTable ) { + LuanTable table = (LuanTable)t; + Object old = table.put(key,value); + if( old != null ) + return; + h = luan.getHandler("__newindex",t); + if( h==null ) + return; + table.put(key,old); + } else { + h = luan.getHandler("__newindex",t); + if( h==null ) + throw luan.bit(se).exception( "attempt to index a " + Luan.type(t) + " value" ); + } + if( h instanceof LuanFunction ) { + LuanFunction fn = (LuanFunction)h; + luan.bit(se).call(fn,"__newindex",new Object[]{t,key,value}); + return; + } + newindex(luan,h,key,value); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/SetUpVar.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,14 @@ +package luan.impl; + + +final class SetUpVar implements Settable { + private final int index; + + SetUpVar(int index) { + this.index = index; + } + + @Override public void set(LuanStateImpl luan,Object value) { + luan.closure().upValues()[index].set(value); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Settable.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,8 @@ +package luan.impl; + +import luan.LuanException; + + +interface Settable { + public void set(LuanStateImpl luan,Object value) throws LuanException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/Stmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,12 @@ +package luan.impl; + +import luan.LuanException; + + +interface Stmt { + public void eval(LuanStateImpl luan) throws LuanException; + + static final Stmt EMPTY = new Stmt() { + @Override public void eval(LuanStateImpl luan) {} + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/SubExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,23 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class SubExpr extends BinaryOpExpr { + + SubExpr(LuanSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o1 = op1.eval(luan); + Object o2 = op2.eval(luan); + Number n1 = Luan.toNumber(o1); + Number n2 = Luan.toNumber(o2); + if( n1 != null && n2 != null ) + return n1.doubleValue() - n2.doubleValue(); + return arithmetic(luan,"__sub",o1,o2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/TableExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,45 @@ +package luan.impl; + +import luan.LuanException; +import luan.LuanTable; +import luan.LuanSource; + + +final class TableExpr extends CodeImpl implements Expr { + + static class Field { + final Expr key; + final Expr value; + + Field(Expr key,Expr value) { + this.key = key; + this.value = value; + } + } + + private final Field[] fields; + private final Expressions expressions; + + TableExpr(LuanSource.Element se,Field[] fields,Expressions expressions) { + super(se); + this.fields = fields; + this.expressions = expressions; + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + LuanTable table = new LuanTable(); + for( Field field : fields ) { + table.put( field.key.eval(luan), field.value.eval(luan) ); + } + Object obj = expressions.eval(luan); + if( obj instanceof Object[] ) { + Object[] a = (Object[])obj; + for( int i=0; i<a.length; i++ ) { + table.put( i+1, a[i] ); + } + } else { + table.put( 1, obj ); + } + return table; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/TryStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,30 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; + + +final class TryStmt implements Stmt { + private final Stmt tryBlock; + private final int iExceptionVar; + private final Stmt catchBlock; + + TryStmt(Stmt tryBlock,int iExceptionVar,Stmt catchBlock) { + this.tryBlock = tryBlock; + this.iExceptionVar = iExceptionVar; + this.catchBlock = catchBlock; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + try { + tryBlock.eval(luan); + } catch(LuanException e) { + try { + luan.stackSet( iExceptionVar, e ); + catchBlock.eval(luan); + } finally { + luan.stackClear(iExceptionVar,iExceptionVar+1); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/UnaryOpExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,13 @@ +package luan.impl; + +import luan.LuanSource; + + +abstract class UnaryOpExpr extends CodeImpl implements Expr { + final Expr op; + + UnaryOpExpr(LuanSource.Element se,Expr op) { + super(se); + this.op = op; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/UnmExpr.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,29 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanSource; +import luan.LuanBit; + + +// unary minus +final class UnmExpr extends UnaryOpExpr { + + UnmExpr(LuanSource.Element se,Expr op) { + super(se,op); + } + + @Override public Object eval(LuanStateImpl luan) throws LuanException { + Object o = op.eval(luan); + Number n = Luan.toNumber(o); + if( n != null ) + return -n.doubleValue(); + LuanBit bit = luan.bit(se); + LuanFunction fn = bit.getHandlerFunction("__unm",o); + if( fn != null ) { + return Luan.first(bit.call(fn,"__unm",new Object[]{o})); + } + throw bit.exception("attempt to perform arithmetic on a "+Luan.type(o)+" value"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/UpValue.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,105 @@ +package luan.impl; + +import luan.DeepCloner; +import luan.DeepCloneable; +import luan.LuanException; + + +final class UpValue implements DeepCloneable<UpValue> { + private Object[] stack; + private int index; + private boolean isClosed = false; + private Object value; + + UpValue(Object[] stack,int index) { + this.stack = stack; + this.index = index; + } + + UpValue(Object value) { + this.value = value; + this.isClosed = true; + } + + private UpValue() {} + + @Override public UpValue shallowClone() { + return new UpValue(); + } + + @Override public void deepenClone(UpValue clone,DeepCloner cloner) { + clone.isClosed = isClosed; + if( isClosed ) { + clone.value = cloner.get(value); + } else { + clone.stack = cloner.deepClone(stack); + clone.index = index; + } + } + + Object get() { + return isClosed ? value : stack[index]; + } + + void set(Object value) { + if( isClosed ) { + this.value = value; + } else { + stack[index] = value; + } + } + + void close() { + value = stack[index]; + isClosed = true; + stack = null; + } + + static interface Getter { + public UpValue get(LuanStateImpl luan) throws LuanException; + } + + static final class StackGetter implements Getter { + private final int index; + + StackGetter(int index) { + this.index = index; + } + + public UpValue get(LuanStateImpl luan) { + return luan.getUpValue(index); + } + } + + static final class NestedGetter implements Getter { + private final int index; + + NestedGetter(int index) { + this.index = index; + } + + public UpValue get(LuanStateImpl luan) { + return luan.closure().upValues()[index]; + } + } + + static final class EnvGetter implements Getter { + + public UpValue get(LuanStateImpl luan) throws LuanException { + return luan.getUpValue(this); + } + } + + static final class ValueGetter implements Getter { + private final UpValue upValue; + + ValueGetter(Object value) { + this.upValue = new UpValue(value); + } + + public UpValue get(LuanStateImpl luan) { + return upValue; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/VarArgs.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,15 @@ +package luan.impl; + +import luan.LuanSource; + + +final class VarArgs extends CodeImpl implements Expressions { + + VarArgs(LuanSource.Element se) { + super(se); + } + + @Override public Object[] eval(LuanStateImpl luan) { + return luan.varArgs(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/impl/WhileStmt.java Sun Jun 22 04:17:38 2014 +0000 @@ -0,0 +1,25 @@ +package luan.impl; + +import luan.Luan; +import luan.LuanException; +import luan.LuanSource; + + +final class WhileStmt extends CodeImpl implements Stmt { + private final Expr cnd; + private final Stmt doStmt; + + WhileStmt(LuanSource.Element se,Expr cnd,Stmt doStmt) { + super(se); + this.cnd = cnd; + this.doStmt = doStmt; + } + + @Override public void eval(LuanStateImpl luan) throws LuanException { + try { + while( luan.bit(se).checkBoolean( cnd.eval(luan) ) ) { + doStmt.eval(luan); + } + } catch(BreakException e) {} + } +}
--- a/src/luan/interp/AddExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class AddExpr extends BinaryOpExpr { - - AddExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - Number n1 = Luan.toNumber(o1); - Number n2 = Luan.toNumber(o2); - if( n1 != null && n2 != null ) - return n1.doubleValue() + n2.doubleValue(); - return arithmetic(luan,"__add",o1,o2); - } -}
--- a/src/luan/interp/AndExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class AndExpr extends BinaryOpExpr { - - AndExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object v1 = op1.eval(luan); - return !Luan.toBoolean(v1) ? v1 : op2.eval(luan); - } -}
--- a/src/luan/interp/BinaryOpExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanTable; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; - - -abstract class BinaryOpExpr extends CodeImpl implements Expr { - final Expr op1; - final Expr op2; - - BinaryOpExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se); - this.op1 = op1; - this.op2 = op2; - } - - Object arithmetic(LuanStateImpl luan,String op,Object o1,Object o2) throws LuanException { - return luan.bit(se()).arithmetic("__mod",o1,o2); - } - -}
--- a/src/luan/interp/Block.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package luan.interp; - -import luan.LuanException; - - -final class Block implements Stmt { - final Stmt[] stmts; - private final int stackStart; - private final int stackEnd; - - Block(Stmt[] stmts,int stackStart,int stackEnd) { - if( stmts.length==0 ) - throw new RuntimeException("empty block"); - this.stmts = stmts; - this.stackStart = stackStart; - this.stackEnd = stackEnd; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - try { - for( Stmt stmt : stmts ) { - stmt.eval(luan); - } - } finally { - luan.stackClear(stackStart,stackEnd); - } - } - -}
--- a/src/luan/interp/BreakException.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -package luan.interp; - - -final class BreakException extends RuntimeException {}
--- a/src/luan/interp/BreakStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -package luan.interp; - - -final class BreakStmt implements Stmt { - - @Override public void eval(LuanStateImpl luan) { - throw new BreakException(); - } -}
--- a/src/luan/interp/Closure.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanState; -import luan.LuanElement; -import luan.LuanException; -import luan.DeepCloner; -import luan.DeepCloneable; - - -final class Closure extends LuanFunction implements DeepCloneable<Closure> { - private final FnDef fnDef; - private UpValue[] upValues; - - Closure(LuanStateImpl luan,FnDef fnDef) throws LuanException { - this.fnDef = fnDef; - UpValue.Getter[] upValueGetters = fnDef.upValueGetters; - upValues = new UpValue[upValueGetters.length]; - for( int i=0; i<upValues.length; i++ ) { - upValues[i] = upValueGetters[i].get(luan); - } - } - - private Closure(Closure c) { - this.fnDef = c.fnDef; - } - - @Override public Closure shallowClone() { - return new Closure(this); - } - - @Override public void deepenClone(Closure clone,DeepCloner cloner) { - clone.upValues = cloner.deepClone(upValues); - } - - UpValue[] upValues() { - return upValues; - } - - @Override public Object call(LuanState luan,Object[] args) throws LuanException { - return call(this,(LuanStateImpl)luan,args); - } - - private static Object call(Closure closure,LuanStateImpl luan,Object[] args) throws LuanException { - while(true) { - FnDef fnDef = closure.fnDef; - Object[] varArgs = null; - if( fnDef.isVarArg ) { - if( args.length > fnDef.numArgs ) { - varArgs = new Object[ args.length - fnDef.numArgs ]; - for( int i=0; i<varArgs.length; i++ ) { - varArgs[i] = args[fnDef.numArgs+i]; - } - } else { - varArgs = LuanFunction.NOTHING; - } - } - Object[] stack = luan.newFrame(closure,fnDef.stackSize,varArgs); - final int n = Math.min(args.length,fnDef.numArgs); - for( int i=0; i<n; i++ ) { - stack[i] = args[i]; - } - Object returnValues; - try { - fnDef.block.eval(luan); - } catch(ReturnException e) { - } finally { - returnValues = luan.returnValues; - closure = luan.tailFn; - luan.popFrame(); - } - if( closure == null ) - return returnValues; - args = Luan.array(returnValues); - } - } - -}
--- a/src/luan/interp/Code.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -interface Code { - public LuanSource.Element se(); -}
--- a/src/luan/interp/CodeImpl.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -class CodeImpl implements Code { - final LuanSource.Element se; - - CodeImpl(LuanSource.Element se) { - this.se = se; - } - - @Override public final LuanSource.Element se() { - return se; - } -}
--- a/src/luan/interp/ConcatExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; - - -final class ConcatExpr extends BinaryOpExpr { - - ConcatExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - String s1 = luan.bit(op1.se()).toString(o1); - String s2 = luan.bit(op2.se()).toString(o2); -/* - if( s1 != null && s2 != null ) - return s1 + s2; - LuanFunction fn = luan.getBinHandler(se,"__concat",o1,o2); - if( fn != null ) - return Luan.first(luan.call(fn,se,"__concat",o1,o2)); - String type = s1==null ? Luan.type(o1) : Luan.type(o2); - throw new LuanException( luan, se, "attempt to concatenate a " + type + " value" ); -*/ - return s1 + s2; - } -}
--- a/src/luan/interp/ConstExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -final class ConstExpr extends CodeImpl implements Expr { - private final Object obj; - - ConstExpr(Object obj) { - this(null,obj); - } - - ConstExpr(LuanSource.Element se,Object obj) { - super(se); - this.obj = obj; - } - - @Override public Object eval(LuanStateImpl luan) { - return obj; - } - - @Override public String toString() { - return "(ConstExpr "+obj+")"; - } -}
--- a/src/luan/interp/DivExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class DivExpr extends BinaryOpExpr { - - DivExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - Number n1 = Luan.toNumber(o1); - Number n2 = Luan.toNumber(o2); - if( n1 != null && n2 != null ) - return n1.doubleValue() / n2.doubleValue(); - return arithmetic(luan,"__div",o1,o2); - } -}
--- a/src/luan/interp/EqExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanTable; -import luan.LuanException; -import luan.LuanSource; -import luan.LuanBit; - - -final class EqExpr extends BinaryOpExpr { - - EqExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - if( o1 == o2 || o1 != null && o1.equals(o2) ) - return true; - if( o1 instanceof Number && o2 instanceof Number ) { - Number n1 = (Number)o1; - Number n2 = (Number)o2; - return n1.doubleValue() == n2.doubleValue(); - } - if( o1==null || o2==null || !o1.getClass().equals(o2.getClass()) ) - return false; - LuanTable mt1 = luan.getMetatable(o1); - LuanTable mt2 = luan.getMetatable(o2); - if( mt1==null || mt2==null ) - return false; - Object f = mt1.get("__eq"); - if( f == null || !f.equals(mt2.get("__eq")) ) - return null; - LuanBit bit = luan.bit(se); - LuanFunction fn = bit.checkFunction(f); - return Luan.toBoolean( Luan.first(bit.call(fn,"__eq",new Object[]{o1,o2})) ); - } -}
--- a/src/luan/interp/ExpList.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -package luan.interp; - -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import luan.LuanException; -import luan.LuanSource; -import luan.LuanFunction; -import luan.Luan; - - -final class ExpList { - - static final Expressions emptyExpList = new Expressions() { - - @Override public Object[] eval(LuanStateImpl luan) { - return LuanFunction.NOTHING; - } - - @Override public LuanSource.Element se() { - return null; - } - }; - - static Expr[] toArray(List<Expressions> list) { - Expr[] a = new Expr[list.size()]; - for( int i=0; i<a.length; i++ ) { - Expressions exprs = list.get(i); - if( exprs instanceof Expr ) { - a[i] = (Expr)exprs; - } else { - a[i] = new ExpressionsExpr(exprs); - } - } - return a; - } - - static Expressions build(List<Expressions> list) { - switch(list.size()) { - case 0: - return emptyExpList; - case 1: - return list.get(0); - default: - if( list.get(list.size()-1) instanceof Expr ) { - return new ExprList1( toArray(list) ); - } else { - Expressions last = list.remove(list.size()-1); - return new ExprList2( toArray(list), last ); - } - } - } - - private static class ExprList1 implements Expressions { - private final Expr[] exprs; - - private ExprList1(Expr[] exprs) { - this.exprs = exprs; - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object[] a = new Object[exprs.length]; - for( int i=0; i<exprs.length; i++ ) { - a[i] = exprs[i].eval(luan); - } - return a; - } - - @Override public LuanSource.Element se() { - return new LuanSource.Element(exprs[0].se().source,exprs[0].se().start,exprs[exprs.length-1].se().end); - } - } - - private static class ExprList2 implements Expressions { - private final Expr[] exprs; - private final Expressions last; - - private ExprList2(Expr[] exprs,Expressions last) { - this.exprs = exprs; - this.last = last; - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - List<Object> list = new ArrayList<Object>(); - for( Expr expr : exprs ) { - list.add( expr.eval(luan) ); - } - list.addAll( Arrays.asList(Luan.array( last.eval(luan) )) ); - return list.toArray(); - } - - @Override public LuanSource.Element se() { - return new LuanSource.Element(exprs[0].se().source,exprs[0].se().start,last.se().end); - } - } -}
--- a/src/luan/interp/Expr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -package luan.interp; - -import luan.LuanException; - - -interface Expr extends Expressions {}
--- a/src/luan/interp/Expressions.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -package luan.interp; - -import luan.LuanException; - - -interface Expressions extends Code { - public Object eval(LuanStateImpl luan) throws LuanException; -}
--- a/src/luan/interp/ExpressionsExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package luan.interp; - -import java.util.List; -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class ExpressionsExpr implements Expr { - private final Expressions expressions; - - ExpressionsExpr(Expressions expressions) { - this.expressions = expressions; - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - return Luan.first( expressions.eval(luan) ); - } - - public LuanSource.Element se() { - return expressions.se(); - } - -}
--- a/src/luan/interp/ExpressionsStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package luan.interp; - -import luan.LuanException; - - -final class ExpressionsStmt implements Stmt { - private final Expressions expressions; - - ExpressionsStmt(Expressions expressions) { - this.expressions = expressions; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - expressions.eval(luan); - } - -}
--- a/src/luan/interp/FnCall.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; - - -final class FnCall extends CodeImpl implements Expressions { - final Expr fnExpr; - final Expressions args; - final String fnName; - - FnCall(LuanSource.Element se,Expr fnExpr,Expressions args) { - super(se); - this.fnExpr = fnExpr; - this.args = args; - this.fnName = fnExpr.se().text(); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - return call( luan, fnExpr.eval(luan) ); - } - - private Object call(LuanStateImpl luan,Object o) throws LuanException { - if( o instanceof LuanFunction ) { - LuanFunction fn = (LuanFunction)o; - return luan.bit(se).call( fn, fnName, Luan.array(args.eval(luan)) ); - } - Object h = luan.getHandler("__call",o); - if( h != null ) - return call(luan,h); - throw luan.bit(fnExpr.se()).exception( "attempt to call '"+fnExpr.se().text()+"' (a " + Luan.type(o) + " value)" ); - } - - @Override public String toString() { - return "(FnCall "+fnName+" "+fnExpr+" "+args+")"; - } -}
--- a/src/luan/interp/FnDef.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -package luan.interp; - -import luan.LuanException; -import luan.LuanSource; - - -final class FnDef extends CodeImpl implements Expr { - final Stmt block; - final int stackSize; - final int numArgs; - final boolean isVarArg; - final UpValue.Getter[] upValueGetters; - - FnDef(LuanSource.Element se,Stmt block,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) { - super(se); - this.block = block; - this.stackSize = stackSize; - this.numArgs = numArgs; - this.isVarArg = isVarArg; - this.upValueGetters = upValueGetters; - fixReturns(block); - } - - private static void fixReturns(Stmt stmt) { - if( stmt instanceof ReturnStmt ) { - ReturnStmt rs = (ReturnStmt)stmt; - rs.throwReturnException = false; - } else if( stmt instanceof Block ) { - Block b = (Block)stmt; - fixReturns( b.stmts[b.stmts.length-1] ); - } else if( stmt instanceof IfStmt ) { - IfStmt is = (IfStmt)stmt; - fixReturns( is.thenStmt ); - fixReturns( is.elseStmt ); - } - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - return new Closure(luan,this); - } - -}
--- a/src/luan/interp/ForStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanFunction; -import luan.LuanSource; -import luan.LuanBit; - - -final class ForStmt extends CodeImpl implements Stmt { - private final int iVars; - private final int nVars; - private final Expr iterExpr; - private final Stmt block; - - ForStmt(LuanSource.Element se,int iVars,int nVars,Expr iterExpr,Stmt block) { - super(se); - this.iVars = iVars; - this.nVars = nVars; - this.iterExpr = iterExpr; - this.block = block; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - LuanFunction iter = luan.bit(se).checkFunction( iterExpr.eval(luan) ); - LuanBit bit = luan.bit(iterExpr.se()); - String name = iterExpr.se().text(); - try { - while(true) { - Object vals = bit.call(iter,name,LuanFunction.NOTHING); - if( vals==null ) - break; - if( vals instanceof Object[] ) { - Object[] a = (Object[])vals; - if( a.length==0 ) - break; - for( int i=0; i<nVars; i++ ) { - luan.stackSet( iVars+i, i < a.length ? a[i] : null ); - } - } else { - luan.stackSet( iVars, vals ); - for( int i=1; i<nVars; i++ ) { - luan.stackSet( iVars+i, null ); - } - } - block.eval(luan); - } - } catch(BreakException e) { - } finally { - luan.stackClear(iVars,iVars+nVars); - } - } - -}
--- a/src/luan/interp/GetLocalVar.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -final class GetLocalVar extends CodeImpl implements Expr { - private final int index; - - GetLocalVar(LuanSource.Element se,int index) { - super(se); - this.index = index; - } - - @Override public Object eval(LuanStateImpl luan) { - return luan.stackGet(index); - } -}
--- a/src/luan/interp/GetUpVar.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -final class GetUpVar extends CodeImpl implements Expr { - private final int index; - - GetUpVar(LuanSource.Element se,int index) { - super(se); - this.index = index; - } - - @Override public Object eval(LuanStateImpl luan) { - return luan.closure().upValues()[index].get(); - } -}
--- a/src/luan/interp/IfStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class IfStmt extends CodeImpl implements Stmt { - private final Expr cnd; - final Stmt thenStmt; - final Stmt elseStmt; - - IfStmt(LuanSource.Element se,Expr cnd,Stmt thenStmt,Stmt elseStmt) { - super(se); - this.cnd = cnd; - this.thenStmt = thenStmt; - this.elseStmt = elseStmt; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - if( luan.bit(se).checkBoolean( cnd.eval(luan) ) ) { - thenStmt.eval(luan); - } else { - elseStmt.eval(luan); - } - } -}
--- a/src/luan/interp/IndexExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanTable; -import luan.LuanFunction; -import luan.LuanSource; - - -final class IndexExpr extends BinaryOpExpr { - - IndexExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - return index(luan,op1.eval(luan),op2.eval(luan)); - } - - private Object index(LuanStateImpl luan,Object t,Object key) throws LuanException { - Object h; - if( t instanceof LuanTable ) { - LuanTable tbl = (LuanTable)t; - Object value = tbl.get(key); - if( value != null ) - return value; - h = luan.getHandler("__index",t); - if( h==null ) - return null; - } else { - h = luan.getHandler("__index",t); - if( h==null ) - throw luan.bit(op1.se()).exception( "attempt to index '"+op1.se().text()+"' (a " + Luan.type(t) + " value)" ); - } - if( h instanceof LuanFunction ) { - LuanFunction fn = (LuanFunction)h; - return Luan.first(luan.bit(se).call(fn,"__index",new Object[]{t,key})); - } - return index(luan,h,key); - } -}
--- a/src/luan/interp/LeExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; -import luan.LuanBit; - - -final class LeExpr extends BinaryOpExpr { - - LeExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - if( o1 instanceof Number && o2 instanceof Number ) { - Number n1 = (Number)o1; - Number n2 = (Number)o2; - return n1.doubleValue() <= n2.doubleValue(); - } - if( o1 instanceof String && o2 instanceof String ) { - String s1 = (String)o1; - String s2 = (String)o2; - return s1.compareTo(s2) <= 0; - } - LuanBit bit = luan.bit(se); - LuanFunction fn = bit.getBinHandler("__le",o1,o2); - if( fn != null ) - return Luan.toBoolean( Luan.first(bit.call(fn,"__le",new Object[]{o1,o2})) ); - fn = bit.getBinHandler("__lt",o1,o2); - if( fn != null ) - return !Luan.toBoolean( Luan.first(bit.call(fn,"__lt",new Object[]{o2,o1})) ); - throw bit.exception( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); - } -}
--- a/src/luan/interp/LenExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanTable; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; -import luan.LuanBit; - - -final class LenExpr extends UnaryOpExpr { - - LenExpr(LuanSource.Element se,Expr op) { - super(se,op); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o = op.eval(luan); - if( o instanceof String ) { - String s = (String)o; - return s.length(); - } - if( o instanceof byte[] ) { - byte[] a = (byte[])o; - return a.length; - } - LuanBit bit = luan.bit(se); - LuanFunction fn = bit.getHandlerFunction("__len",o); - if( fn != null ) - return Luan.first(bit.call(fn,"__len",new Object[]{o})); - if( o instanceof LuanTable ) { - LuanTable t = (LuanTable)o; - return t.length(); - } - throw bit.exception( "attempt to get length of a " + Luan.type(o) + " value" ); - } -}
--- a/src/luan/interp/LtExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; - - -final class LtExpr extends BinaryOpExpr { - - LtExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - return luan.bit(se).isLessThan(o1,o2); - } -}
--- a/src/luan/interp/LuanCompiler.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -package luan.interp; - -import luan.LuanFunction; -import luan.LuanState; -import luan.LuanException; -import luan.LuanSource; -import luan.LuanElement; -import luan.LuanTable; -import java.util.Map; - - -public final class LuanCompiler { - private LuanCompiler() {} // never - - public static LuanFunction compile(LuanState luan,LuanSource src,LuanTable env,boolean allowExpr) throws LuanException { - UpValue.Getter envGetter = env!=null ? new UpValue.ValueGetter(env) : new UpValue.EnvGetter(); - LuanParser parser = new LuanParser(src,envGetter); - for( Map.Entry<Object,Object> entry : luan.global() ) { - Object key = entry.getKey(); - if( key instanceof String ) - parser.addVar( (String)key, entry.getValue() ); - } - FnDef fnDef = parse(luan,parser,allowExpr); - if( env != null ) - return new Closure((LuanStateImpl)luan,fnDef); - final Closure c = new Closure((LuanStateImpl)luan,fnDef); - return new LuanFunction() { - @Override public Object call(LuanState luan,Object[] args) throws LuanException { - Object rtn = c.call(luan,args); - if( rtn instanceof Object[] && ((Object[])rtn).length==0 ) - rtn = c.upValues()[0].get(); - return rtn; - } - }; - } - - private static FnDef parse(LuanState luan,LuanParser parser,boolean allowExpr) throws LuanException { - try { - if( allowExpr ) { - FnDef fnDef = parser.Expression(); - if( fnDef != null ) - return fnDef; - } - return parser.RequiredModule(); - } catch(ParseException e) { -//e.printStackTrace(); - LuanElement le = new LuanSource.CompilerElement(parser.source); - throw luan.bit(le).exception( e.getFancyMessage() ); - } - } - - public static LuanState newLuanState() { - return new LuanStateImpl(); - } -}
--- a/src/luan/interp/LuanParser.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1360 +0,0 @@ -package luan.interp; - -import java.util.Set; -import java.util.HashSet; -import java.util.Arrays; -import java.util.List; -import java.util.ArrayList; -import java.util.Scanner; -import luan.Luan; -import luan.LuanState; -import luan.LuanSource; - - -final class LuanParser { - - private static final class Frame { - final Frame parent; - final List<String> symbols = new ArrayList<String>(); - 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(UpValue.Getter envGetter) { - this.parent = null; - upValueSymbols.add(_ENV); - upValueGetters.add(envGetter); - } - - Frame(Frame parent) { - this.parent = parent; - if( upValueIndex(_ENV) != 0 ) - throw new RuntimeException(); - } - - 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; - } - - void addUpValueGetter(String name,UpValue.Getter upValueGetter) { - upValueSymbols.add(name); - upValueGetters.add(upValueGetter); - } - } - - private static class In { - static final In NOTHING = new In(false,false); - - final boolean parens; - final boolean template; - - private In(boolean parens,boolean template) { - this.parens = parens; - this.template = template; - } - - In parens() { - return parens ? this : new In(true,template); - } - - In template() { - return template ? this : new In(parens,true); - } - } - - private static final String _ENV = "_ENV"; - private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; - - final LuanSource source; - private Frame frame; - private final Parser parser; - private final boolean interactive; - - LuanParser(LuanSource source,UpValue.Getter envGetter) { - this.source = source; - this.frame = new Frame(envGetter); - this.parser = new Parser(source); - this.interactive = envGetter instanceof UpValue.ValueGetter; - } - - void addVar(String name,Object value) { - frame.addUpValueGetter(name,new UpValue.ValueGetter(value)); - } - - private LuanSource.Element se(int start) { - return new LuanSource.Element(source,start,parser.currentIndex()); - } - - private List<String> symbols() { - return frame.symbols; - } - - private int symbolsSize() { - return frame.symbols.size(); - } - - private void addSymbol(String name) { - frame.symbols.add(name); - if( frame.stackSize < symbolsSize() ) - frame.stackSize = symbolsSize(); - } - - private void addSymbols(List<String> names) { - frame.symbols.addAll(names); - if( frame.stackSize < symbolsSize() ) - frame.stackSize = symbolsSize(); - } - - private int stackIndex(String name) { - return frame.stackIndex(name); - } - - private void popSymbols(int n) { - List<String> symbols = frame.symbols; - while( n-- > 0 ) { - symbols.remove(symbols.size()-1); - } - } - - private int upValueIndex(String name) { - return frame.upValueIndex(name); - } - - private void incLoops() { - frame.loops++; - } - - private void decLoops() { - frame.loops--; - } - - private <T> T required(T t) throws ParseException { - if( t==null ) - throw parser.exception(); - return t; - } - - private <T> T required(T t,String msg) throws ParseException { - if( t==null ) - throw parser.exception(msg); - return t; - } - - private static Expr expr(Expressions exprs) { - if( exprs instanceof Expr ) - return (Expr)exprs; - return new ExpressionsExpr(exprs); - } - - private FnDef newFnDef(int start,Stmt stmt) { - return new FnDef( se(start), stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); - } - - FnDef Expression() throws ParseException { - Spaces(In.NOTHING); - int start = parser.begin(); - Expressions expr = Expr(In.NOTHING); - if( expr != null && parser.endOfInput() ) { - Stmt stmt = new ReturnStmt( se(start), expr ); - return parser.success(newFnDef(start,stmt)); - } - return parser.failure(null); - } - - FnDef RequiredModule() throws ParseException { - Spaces(In.NOTHING); - int start = parser.begin(); - frame.isVarArg = true; - Stmt stmt = RequiredBlock(); - if( parser.endOfInput() ) - return parser.success(newFnDef(start,stmt)); - throw parser.exception(); - } - - private Stmt RequiredBlock() throws ParseException { - List<Stmt> stmts = new ArrayList<Stmt>(); - int stackStart = symbolsSize(); - Stmt(stmts); - while( StmtSep(stmts) ) { - Spaces(In.NOTHING); - Stmt(stmts); - } - int stackEnd = symbolsSize(); - popSymbols( stackEnd - stackStart ); - if( stmts.isEmpty() ) - return Stmt.EMPTY; - if( stmts.size()==1 && stackStart==stackEnd ) - return stmts.get(0); - return new Block( stmts.toArray(new Stmt[0]), stackStart, stackEnd ); - } - - private boolean StmtSep(List<Stmt> stmts) throws ParseException { - parser.begin(); - if( parser.match( ';' ) ) - return parser.success(); - if( parser.match( "--" ) ) { - while( parser.noneOf("\r\n") ); - } - if( EndOfLine() ) - return parser.success(); - parser.rollback(); - Stmt stmt = TemplateStmt(); - if( stmt != null ) { - stmts.add(stmt); - return parser.success(); - } - return parser.failure(); - } - - private boolean EndOfLine() { - return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); - } - - private void Stmt(List<Stmt> stmts) throws ParseException { - if( LocalStmt(stmts) ) - return; - Stmt stmt; - if( (stmt=ReturnStmt()) != null - || (stmt=FunctionStmt()) != null - || (stmt=LocalFunctionStmt()) != null - || (stmt=ImportStmt()) != null - || (stmt=BreakStmt()) != null - || (stmt=ForStmt()) != null - || (stmt=TryStmt()) != null - || (stmt=DoStmt()) != null - || (stmt=WhileStmt()) != null - || (stmt=FunctionStmt()) != null - || (stmt=RepeatStmt()) != null - || (stmt=IfStmt()) != null - || (stmt=SetStmt()) != null - || (stmt=ExpressionsStmt()) != null - ) { - stmts.add(stmt); - } - } - - private Stmt TemplateStmt() throws ParseException { - int start = parser.currentIndex(); - Expressions exp = TemplateExpressions(In.NOTHING); - if( exp == null ) - return null; - Expr fnExp = (Expr)nameVar(start,"Io").expr(); - fnExp = new IndexExpr( se(start), fnExp, new ConstExpr("stdout") ); - fnExp = new IndexExpr( se(start), fnExp, new ConstExpr("write") ); - FnCall fnCall = new FnCall( se(start), fnExp, exp ); - return new ExpressionsStmt(fnCall); - } - - private Expressions TemplateExpressions(In in) throws ParseException { - if( in.template ) - return null; - int start = parser.begin(); - if( !parser.match( "%>" ) ) - return parser.failure(null); - EndOfLine(); - In inTemplate = in.template(); - List<Expressions> builder = new ArrayList<Expressions>(); - while(true) { - if( parser.match( "<%=" ) ) { - Spaces(inTemplate); - builder.add( RequiredExpr(inTemplate) ); - RequiredMatch( "%>" ); - } else if( parser.match( "<%" ) ) { - Spaces(inTemplate); - return parser.success(ExpList.build(builder)); - } else { - int i = parser.currentIndex(); - do { - if( parser.match( "%>" ) ) - throw parser.exception("'%>' unexpected"); - if( !parser.anyChar() ) - throw parser.exception("Unclosed template expression"); - } while( !parser.test( "<%" ) ); - String match = parser.textFrom(i); - builder.add( new ConstExpr(match) ); - } - } - } - - private Stmt ReturnStmt() throws ParseException { - int start = parser.begin(); - if( !Keyword("return",In.NOTHING) ) - return parser.failure(null); - Expressions exprs = ExpList(In.NOTHING); - if( exprs==null ) - exprs = ExpList.emptyExpList; - return parser.success( new ReturnStmt(se(start),exprs) ); - } - - private Stmt FunctionStmt() throws ParseException { - parser.begin(); - if( !Keyword("function",In.NOTHING) ) - return parser.failure(null); - - int start = parser.currentIndex(); - Var var = nameVar(start,RequiredName(In.NOTHING)); - while( parser.match( '.' ) ) { - Spaces(In.NOTHING); - var = indexVar( start, expr(var.expr()), NameExpr(In.NOTHING) ); - } - Settable fnName = var.settable(); - - FnDef fnDef = RequiredFunction(In.NOTHING); - return parser.success( new SetStmt(fnName,fnDef) ); - } - - private Stmt LocalFunctionStmt() throws ParseException { - parser.begin(); - if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) - return parser.failure(null); - String name = RequiredName(In.NOTHING); - addSymbol( name ); - FnDef fnDef = RequiredFunction(In.NOTHING); - return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) ); - } - - private Stmt ImportStmt() throws ParseException { - int start = parser.begin(); - if( !Keyword("import",In.NOTHING) ) - return parser.failure(null); - Expr importExpr = (Expr)nameVar(start,"require").expr(); - String modName = StringLiteral(In.NOTHING); - if( modName==null ) - return parser.failure(null); - String varName = modName.substring(modName.lastIndexOf('.')+1); - LuanSource.Element se = se(start); - FnCall require = new FnCall( se, importExpr, new ConstExpr(modName) ); - Settable settable; - if( interactive ) { - settable = nameVar(se,varName).settable(); - } else { - addSymbol( varName ); - settable = new SetLocalVar(symbolsSize()-1); - } - return parser.success( new SetStmt( settable, expr(require) ) ); - } - - private Stmt BreakStmt() throws ParseException { - parser.begin(); - if( !Keyword("break",In.NOTHING) ) - return parser.failure(null); - if( frame.loops <= 0 ) - throw parser.exception("'break' outside of loop"); - return parser.success( new BreakStmt() ); - } - - private Stmt ForStmt() throws ParseException { - int start = parser.begin(); - int stackStart = symbolsSize(); - if( !Keyword("for",In.NOTHING) ) - return parser.failure(null); - List<String> names = RequiredNameList(In.NOTHING); - if( !Keyword("in",In.NOTHING) ) - return parser.failure(null); - Expr expr = expr(RequiredExpr(In.NOTHING)); - RequiredKeyword("do",In.NOTHING); - addSymbols(names); - Stmt loop = RequiredLoopBlock(); - RequiredKeyword("end",In.NOTHING); - Stmt stmt = new ForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop ); - popSymbols( symbolsSize() - stackStart ); - return parser.success(stmt); - } - - private Stmt TryStmt() throws ParseException { - parser.begin(); - if( !Keyword("try",In.NOTHING) ) - return parser.failure(null); - Stmt tryBlock = RequiredBlock(); - RequiredKeyword("catch",In.NOTHING); - String name = RequiredName(In.NOTHING); - addSymbol(name); - RequiredKeyword("do",In.NOTHING); - Stmt catchBlock = RequiredBlock(); - RequiredKeyword("end",In.NOTHING); - Stmt stmt = new TryStmt( tryBlock, symbolsSize()-1, catchBlock ); - popSymbols(1); - return parser.success(stmt); - } - - private Stmt DoStmt() throws ParseException { - parser.begin(); - if( !Keyword("do",In.NOTHING) ) - return parser.failure(null); - Stmt stmt = RequiredBlock(); - RequiredKeyword("end",In.NOTHING); - return parser.success(stmt); - } - - private boolean LocalStmt(List<Stmt> stmts) throws ParseException { - parser.begin(); - if( !Keyword("local",In.NOTHING) ) - return parser.failure(); - List<String> names = NameList(In.NOTHING); - if( names==null ) - return parser.failure(); - if( parser.match( '=' ) ) { - Spaces(In.NOTHING); - Expressions values = ExpList(In.NOTHING); - if( values==null ) - throw parser.exception("Expressions expected"); - SetLocalVar[] vars = new SetLocalVar[names.size()]; - int stackStart = symbolsSize(); - for( int i=0; i<vars.length; i++ ) { - vars[i] = new SetLocalVar(stackStart+i); - } - stmts.add( new SetStmt( vars, values ) ); - } - addSymbols(names); - return parser.success(); - } - - private List<String> RequiredNameList(In in) throws ParseException { - parser.begin(); - List<String> names = NameList(in); - if( names==null ) - throw parser.exception("Name expected"); - return parser.success(names); - } - - private List<String> NameList(In in) throws ParseException { - String name = Name(in); - if( name==null ) - return null; - List<String> names = new ArrayList<String>(); - names.add(name); - while( (name=anotherName(in)) != null ) { - names.add(name); - } - return names; - } - - private String anotherName(In in) throws ParseException { - parser.begin(); - if( !parser.match( ',' ) ) - return parser.failure(null); - Spaces(in); - String name = Name(in); - if( name==null ) - return parser.failure(null); - return parser.success(name); - } - - private Stmt WhileStmt() throws ParseException { - int start = parser.begin(); - if( !Keyword("while",In.NOTHING) ) - return parser.failure(null); - Expr cnd = expr(RequiredExpr(In.NOTHING)); - RequiredKeyword("do",In.NOTHING); - Stmt loop = RequiredLoopBlock(); - RequiredKeyword("end",In.NOTHING); - return parser.success( new WhileStmt(se(start),cnd,loop) ); - } - - private Stmt RepeatStmt() throws ParseException { - int start = parser.begin(); - if( !Keyword("repeat",In.NOTHING) ) - return parser.failure(null); - Stmt loop = RequiredLoopBlock(); - RequiredKeyword("until",In.NOTHING); - Expr cnd = expr(RequiredExpr(In.NOTHING)); - return parser.success( new RepeatStmt(se(start),loop,cnd) ); - } - - private Stmt RequiredLoopBlock() throws ParseException { - incLoops(); - Stmt stmt = RequiredBlock(); - decLoops(); - return stmt; - } - - private Stmt IfStmt() throws ParseException { - parser.begin(); - if( !Keyword("if",In.NOTHING) ) - return parser.failure(null); - return parser.success( IfStmt2() ); - } - - private Stmt IfStmt2() throws ParseException { - int start = parser.currentIndex(); - Expr cnd = expr(RequiredExpr(In.NOTHING)); - RequiredKeyword("then",In.NOTHING); - Stmt thenBlock = RequiredBlock(); - Stmt elseBlock; - if( Keyword("elseif",In.NOTHING) ) { - elseBlock = IfStmt2(); - } else { - elseBlock = Keyword("else",In.NOTHING) ? RequiredBlock() : Stmt.EMPTY; - RequiredKeyword("end",In.NOTHING); - } - return new IfStmt(se(start),cnd,thenBlock,elseBlock); - } - - private Stmt SetStmt() throws ParseException { - parser.begin(); - List<Settable> vars = new ArrayList<Settable>(); - Settable s = SettableVar(); - if( s == null ) - return parser.failure(null); - vars.add(s); - while( parser.match( ',' ) ) { - Spaces(In.NOTHING); - s = SettableVar(); - if( s == null ) - return parser.failure(null); - vars.add(s); - } - if( !parser.match( '=' ) ) - return parser.failure(null); - Spaces(In.NOTHING); - Expressions values = ExpList(In.NOTHING); - if( values==null ) - throw parser.exception("Expressions expected"); - return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); - } - - private Stmt ExpressionsStmt() throws ParseException { - parser.begin(); - Expressions exp = Expr(In.NOTHING); - if( exp instanceof FnCall || exp instanceof AndExpr || exp instanceof OrExpr ) - return parser.success( new ExpressionsStmt(exp) ); - return parser.failure(null); - } - - private Settable SettableVar() throws ParseException { - int start = parser.begin(); - Var var = VarZ(In.NOTHING); - if( var==null ) - return parser.failure(null); - return parser.success( var.settable() ); - } - - private Expressions RequiredExpr(In in) throws ParseException { - parser.begin(); - return parser.success(required(Expr(in),"Bad expression")); - } - - private Expressions Expr(In in) throws ParseException { - parser.begin(); - Expressions exp; - return (exp = VarArgs(in)) != null - || (exp = OrExpr(in)) != null - ? parser.success(exp) - : parser.failure((Expressions)null) - ; - } - - private Expressions OrExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = AndExpr(in); - if( exp==null ) - return parser.failure(null); - while( Keyword("or",in) ) { - exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(in))) ); - } - return parser.success(exp); - } - - private Expressions AndExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = RelExpr(in); - if( exp==null ) - return parser.failure(null); - while( Keyword("and",in) ) { - exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(in))) ); - } - return parser.success(exp); - } - - private Expressions RelExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = ConcatExpr(in); - if( exp==null ) - return parser.failure(null); - while(true) { - if( parser.match("==") ) { - Spaces(in); - exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); - } else if( parser.match("~=") ) { - Spaces(in); - exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ) ); - } else if( parser.match("<=") ) { - Spaces(in); - exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); - } else if( parser.match(">=") ) { - Spaces(in); - exp = new LeExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) ); - } else if( parser.match("<") ) { - Spaces(in); - exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); - } else if( parser.match(">") ) { - Spaces(in); - exp = new LtExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) ); - } else - break; - } - return parser.success(exp); - } - - private Expressions ConcatExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = SumExpr(in); - if( exp==null ) - return parser.failure(null); - if( parser.match("..") ) { - Spaces(in); - exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); - } - return parser.success(exp); - } - - private Expressions SumExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = TermExpr(in); - if( exp==null ) - return parser.failure(null); - while(true) { - if( parser.match('+') ) { - Spaces(in); - exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(in))) ); - } else if( Minus() ) { - Spaces(in); - exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(in))) ); - } else - break; - } - return parser.success(exp); - } - - private boolean Minus() { - parser.begin(); - return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); - } - - private Expressions TermExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = UnaryExpr(in); - if( exp==null ) - return parser.failure(null); - while(true) { - if( parser.match('*') ) { - Spaces(in); - exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); - } else if( parser.match('/') ) { - Spaces(in); - exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); - } else if( Mod() ) { - Spaces(in); - exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); - } else - break; - } - return parser.success(exp); - } - - private boolean Mod() { - parser.begin(); - return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure(); - } - - private Expressions UnaryExpr(In in) throws ParseException { - int start = parser.begin(); - if( parser.match('#') ) { - Spaces(in); - return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(in))) ) ); - } - if( Minus() ) { - Spaces(in); - return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(in))) ) ); - } - if( Keyword("not",in) ) { - Spaces(in); - return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(in))) ) ); - } - Expressions exp = PowExpr(in); - if( exp==null ) - return parser.failure(null); - return parser.success(exp); - } - - private Expressions PowExpr(In in) throws ParseException { - int start = parser.begin(); - Expressions exp = SingleExpr(in); - if( exp==null ) - return parser.failure(null); - if( parser.match('^') ) { - Spaces(in); - exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(in))) ); - } - return parser.success(exp); - } - - private Expressions SingleExpr(In in) throws ParseException { - parser.begin(); - Expressions exp; - exp = FunctionExpr(in); - if( exp != null ) - return parser.success(exp); - exp = TableExpr(in); - if( exp != null ) - return parser.success(exp); - exp = VarExp(in); - if( exp != null ) - return parser.success(exp); - exp = Literal(in); - if( exp != null ) - return parser.success(exp); - return parser.failure(null); - } - - private Expr FunctionExpr(In in) throws ParseException { - if( !Keyword("function",in) ) - return null; - return RequiredFunction(in); - } - - private FnDef RequiredFunction(In in) throws ParseException { - int start = parser.begin(); - RequiredMatch('('); - In inParens = in.parens(); - Spaces(inParens); - frame = new Frame(frame); - List<String> names = NameList(in); - if( names != null ) { - addSymbols(names); - if( parser.match(',') ) { - Spaces(inParens); - if( !parser.match("...") ) - throw parser.exception(); - frame.isVarArg = true; - } - } else if( parser.match("...") ) { - Spaces(inParens); - frame.isVarArg = true; - } - RequiredMatch(')'); - Spaces(in); - Stmt block = RequiredBlock(); - RequiredKeyword("end",in); - FnDef fnDef = newFnDef(start,block); - frame = frame.parent; - return parser.success(fnDef); - } - - private VarArgs VarArgs(In in) throws ParseException { - int start = parser.begin(); - if( !frame.isVarArg || !parser.match("...") ) - return parser.failure(null); - Spaces(in); - return parser.success( new VarArgs(se(start)) ); - } - - private Expr TableExpr(In in) throws ParseException { - int start = parser.begin(); - if( !parser.match('{') ) - return parser.failure(null); - In inParens = in.parens(); - Spaces(inParens); - List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>(); - List<Expressions> builder = new ArrayList<Expressions>(); - while( Field(fields,builder,in) && FieldSep(inParens) ); - Spaces(inParens); - if( !parser.match('}') ) - throw parser.exception("Expected table element or '}'"); - return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), ExpList.build(builder) ) ); - } - - private boolean FieldSep(In in) throws ParseException { - if( !parser.anyOf(",;") ) - return false; - Spaces(in); - return true; - } - - private boolean Field(List<TableExpr.Field> fields,List<Expressions> builder,In in) throws ParseException { - parser.begin(); - Expr exp = SubExpr(in); - if( exp==null ) - exp = NameExpr(in); - if( exp!=null && parser.match('=') ) { - Spaces(in); - fields.add( new TableExpr.Field( exp, required(expr(Expr(in))) ) ); - return parser.success(); - } - parser.rollback(); - Expressions exprs = Expr(in); - if( exprs != null ) { - builder.add(exprs); - return parser.success(); - } - return parser.failure(); - } - - private Expressions VarExp(In in) throws ParseException { - Var var = VarZ(in); - return var==null ? null : var.expr(); - } - - private Var VarZ(In in) throws ParseException { - int start = parser.begin(); - Var var = VarStart(in); - if( var==null ) - return parser.failure(null); - Var var2; - while( (var2=Var2(in,start,var.expr())) != null ) { - var = var2; - } - return parser.success(var); - } - - private Var Var2(In in,int start,Expressions exp1) throws ParseException { - parser.begin(); - Var var = VarExt(in,start,exp1); - if( var != null ) - return parser.success(var); - if( parser.match("->") ) { - Spaces(in); - List<Expressions> builder = new ArrayList<Expressions>(); - builder.add(exp1); - Expr exp2 = expr(RequiredVarExpB(in)); - FnCall fnCall = required(Args( in, start, exp2, builder )); - return parser.success(exprVar(fnCall)); - } - FnCall fnCall = Args( in, start, expr(exp1), new ArrayList<Expressions>() ); - if( fnCall != null ) - return parser.success(exprVar(fnCall)); - return parser.failure(null); - } - - private Expressions RequiredVarExpB(In in) throws ParseException { - int start = parser.begin(); - Var var = required(VarStart(in)); - Var var2; - while( (var2=VarExt(in,start,var.expr())) != null ) { - var = var2; - } - return parser.success(var.expr()); - } - - private Var VarExt(In in,int start,Expressions exp1) throws ParseException { - parser.begin(); - Expr exp2 = SubExpr(in); - if( exp2 != null ) - return parser.success(indexVar(start,expr(exp1),exp2)); - if( parser.match('.') ) { - Spaces(in); - exp2 = NameExpr(in); - if( exp2!=null ) - return parser.success(indexVar(start,expr(exp1),exp2)); - } - return parser.failure(null); - } - - private Var VarStart(In in) throws ParseException { - int start = parser.begin(); - if( parser.match('(') ) { - In inParens = in.parens(); - Spaces(inParens); - Expr exp = expr(RequiredExpr(inParens)); - RequiredMatch(')'); - Spaces(in); - return parser.success(exprVar(exp)); - } - String name = Name(in); - if( name != null ) - return parser.success(nameVar(start,name)); - return parser.failure(null); - } - - private Expr env() { - int index = stackIndex(_ENV); - if( index != -1 ) - return new GetLocalVar(null,index); - index = upValueIndex(_ENV); - if( index != -1 ) - return new GetUpVar(null,index); - throw new RuntimeException("_ENV not found"); - } - - private interface Var { - public Expressions expr(); - public Settable settable(); - } - - private Var nameVar(final int start,final String name) { - return nameVar(se(start),name); - } - - private Var nameVar(final LuanSource.Element se,final String name) { - return new Var() { - - public Expr expr() { - int index = stackIndex(name); - if( index != -1 ) - return new GetLocalVar(se,index); - index = upValueIndex(name); - if( index != -1 ) - return new GetUpVar(se,index); - return new IndexExpr( se, env(), new ConstExpr(name) ); - } - - public Settable settable() { - int index = stackIndex(name); - if( index != -1 ) - return new SetLocalVar(index); - index = upValueIndex(name); - if( index != -1 ) - return new SetUpVar(index); - return new SetTableEntry( se, env(), new ConstExpr(name) ); - } - }; - } - - private Var exprVar(final Expressions expr) { - return new Var() { - - public Expressions expr() { - return expr; - } - - public Settable settable() { - return null; - } - }; - } - - private Var indexVar(final int start,final Expr table,final Expr key) { - return new Var() { - - public Expr expr() { - return new IndexExpr( se(start), table, key ); - } - - public Settable settable() { - return new SetTableEntry(se(start),table,key); - } - }; - } - - private FnCall Args(In in,int start,Expr fn,List<Expressions> builder) throws ParseException { - parser.begin(); - return args(in,builder) - ? parser.success( new FnCall( se(start), fn, ExpList.build(builder) ) ) - : parser.failure((FnCall)null); - } - - private boolean args(In in,List<Expressions> builder) throws ParseException { - if( parser.match('(') ) { - In inParens = in.parens(); - Spaces(inParens); - ExpList(inParens,builder); // optional - if( !parser.match(')') ) - throw parser.exception("Expression or ')' expected"); - Spaces(in); - return true; - } - Expr exp = TableExpr(in); - if( exp != null ) { - builder.add(exp); - return true; - } - String s = StringLiteral(in); - if( s != null ) { - builder.add( new ConstExpr(s) ); - return true; - } - Expressions exps = TemplateExpressions(in); - if( exps != null ) { - builder.add(exps); - return true; - } - return false; - } - - private Expressions ExpList(In in) throws ParseException { - List<Expressions> builder = new ArrayList<Expressions>(); - return ExpList(in,builder) ? ExpList.build(builder) : null; - } - - private boolean ExpList(In in,List<Expressions> builder) throws ParseException { - parser.begin(); - Expressions exp = TemplateExpressions(in); - if( exp != null ) { - builder.add(exp); - return parser.success(); - } - exp = Expr(in); - if( exp==null ) - return parser.failure(); - builder.add(exp); - while( parser.match(',') ) { - Spaces(in); - exp = TemplateExpressions(in); - if( exp != null ) { - builder.add(exp); - return parser.success(); - } - builder.add( RequiredExpr(in) ); - } - return parser.success(); - } - - private Expr SubExpr(In in) throws ParseException { - parser.begin(); - if( !parser.match('[') ) - return parser.failure(null); - In inParens = in.parens(); - Spaces(inParens); - Expr exp = expr(RequiredExpr(inParens)); - RequiredMatch(']'); - Spaces(in); - return parser.success(exp); - } - - private Expr NameExpr(In in) throws ParseException { - String name = Name(in); - return name==null ? null : new ConstExpr(name); - } - - private String RequiredName(In in) throws ParseException { - parser.begin(); - String name = Name(in); - if( name==null ) - throw parser.exception("Name expected"); - return parser.success(name); - } - - private String Name(In in) throws ParseException { - int start = parser.begin(); - if( !NameFirstChar() ) - return parser.failure(null); - while( NameChar() ); - String match = parser.textFrom(start); - if( keywords.contains(match) ) - return parser.failure(null); - Spaces(in); - return parser.success(match); - } - - private boolean NameChar() { - return NameFirstChar() || Digit(); - } - - private boolean NameFirstChar() { - return parser.inCharRange('a', 'z') || parser.inCharRange('A', 'Z') || parser.match('_'); - } - - private void RequiredMatch(char c) throws ParseException { - if( !parser.match(c) ) - throw parser.exception("'"+c+"' expected"); - } - - private void RequiredMatch(String s) throws ParseException { - if( !parser.match(s) ) - throw parser.exception("'"+s+"' expected"); - } - - private void RequiredKeyword(String keyword,In in) throws ParseException { - if( !Keyword(keyword,in) ) - throw parser.exception("'"+keyword+"' expected"); - } - - private boolean Keyword(String keyword,In in) throws ParseException { - parser.begin(); - if( !parser.match(keyword) || NameChar() ) - return parser.failure(); - Spaces(in); - return parser.success(); - } - - private static final Set<String> keywords = new HashSet<String>(Arrays.asList( - "and", - "break", - "catch", - "do", - "else", - "elseif", - "end", - "false", - "for", - "function", - "goto", - "if", - "import", - "in", - "local", - "nil", - "not", - "or", - "repeat", - "return", - "then", - "true", - "try", - "until", - "while" - )); - - private Expr Literal(In in) throws ParseException { - if( NilLiteral(in) ) - return new ConstExpr(null); - Boolean b = BooleanLiteral(in); - if( b != null ) - return new ConstExpr(b); - Number n = NumberLiteral(in); - if( n != null ) - return new ConstExpr(n); - String s = StringLiteral(in); - if( s != null ) - return new ConstExpr(s); - return null; - } - - private boolean NilLiteral(In in) throws ParseException { - return Keyword("nil",in); - } - - private Boolean BooleanLiteral(In in) throws ParseException { - if( Keyword("true",in) ) - return true; - if( Keyword("false",in) ) - return false; - return null; - } - - private Number NumberLiteral(In in) throws ParseException { - parser.begin(); - Number n; - if( parser.matchIgnoreCase("0x") ) { - n = HexNumber(); - } else { - n = DecNumber(); - } - if( n==null || NameChar() ) - return parser.failure(null); - Spaces(in); - return parser.success(n); - } - - private Number DecNumber() { - int start = parser.begin(); - if( Int() ) { - if( parser.match('.') ) - Int(); // optional - } else if( parser.match('.') && Int() ) { - // ok - } else - return parser.failure(null); - Exponent(); // optional - return parser.success(Double.valueOf(parser.textFrom(start))); - } - - private boolean Exponent() { - parser.begin(); - if( !parser.matchIgnoreCase("e") ) - return parser.failure(); - parser.anyOf("+-"); // optional - if( !Int() ) - return parser.failure(); - return parser.success(); - } - - private boolean Int() { - if( !Digit() ) - return false; - while( Digit() ); - return true; - } - - private boolean Digit() { - return parser.inCharRange('0', '9'); - } - - private Number HexNumber() { - int start = parser.begin(); - double n; - if( HexInt() ) { - n = (double)Long.parseLong(parser.textFrom(start),16); - if( parser.match('.') ) { - start = parser.currentIndex(); - if( HexInt() ) { - String dec = parser.textFrom(start); - n += (double)Long.parseLong(dec,16) / Math.pow(16,dec.length()); - } - } - } else if( parser.match('.') && HexInt() ) { - String dec = parser.textFrom(start+1); - n = (double)Long.parseLong(dec,16) / Math.pow(16,dec.length()); - } else { - return parser.failure(null); - } - if( parser.matchIgnoreCase("p") ) { - parser.anyOf("+-"); // optional - start = parser.currentIndex(); - if( !HexInt() ) - return parser.failure(null); - n *= Math.pow(2,(double)Long.parseLong(parser.textFrom(start))); - } - return parser.success(Double.valueOf(n)); - } - - private boolean HexInt() { - if( !HexDigit() ) - return false; - while( HexDigit() ); - return true; - } - - - private boolean HexDigit() { - return Digit() || parser.anyOf("abcdefABCDEF"); - } - - private String StringLiteral(In in) throws ParseException { - String s; - if( (s=QuotedString('"'))==null - && (s=QuotedString('\''))==null - && (s=LongString())==null - ) - return null; - Spaces(in); - return s; - } - - private String LongString() throws ParseException { - parser.begin(); - if( !parser.match('[') ) - return parser.failure(null); - int start = parser.currentIndex(); - while( parser.match('=') ); - int nEquals = parser.currentIndex() - start; - if( !parser.match('[') ) - return parser.failure(null); - EndOfLine(); - start = parser.currentIndex(); - while( !LongBracketsEnd(nEquals) ) { - if( !parser.anyChar() ) - throw parser.exception("Unclosed long string"); - } - String s = parser.text.substring( start, parser.currentIndex() - nEquals - 2 ); - return parser.success(s); - } - - private String QuotedString(char quote) throws ParseException { - parser.begin(); - if( !parser.match(quote) ) - return parser.failure(null); - StringBuilder buf = new StringBuilder(); - while( !parser.match(quote) ) { - Character c = EscSeq(); - if( c != null ) { - buf.append(c); - } else { - if( !parser.anyChar() ) - throw parser.exception("Unclosed string"); - buf.append(parser.lastChar()); - } - } - return parser.success(buf.toString()); - } - - private Character EscSeq() { - parser.begin(); - if( !parser.match('\\') ) - return parser.failure(null); - if( parser.match('a') ) return parser.success('\u0007'); - if( parser.match('b') ) return parser.success('\b'); - if( parser.match('f') ) return parser.success('\f'); - if( parser.match('n') ) return parser.success('\n'); - if( parser.match('r') ) return parser.success('\r'); - if( parser.match('t') ) return parser.success('\t'); - if( parser.match('v') ) return parser.success('\u000b'); - if( parser.match('\\') ) return parser.success('\\'); - if( parser.match('"') ) return parser.success('"'); - if( parser.match('\'') ) return parser.success('\''); - int start = parser.currentIndex(); - if( parser.match('x') && HexDigit() && HexDigit() ) - return parser.success((char)Integer.parseInt(parser.textFrom(start+1),16)); - if( Digit() ) { - if( Digit() ) Digit(); // optional - return parser.success((char)Integer.parseInt(parser.textFrom(start))); - } - return parser.failure(null); - } - - private void Spaces(In in) throws ParseException { - while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || in.parens && NewLine() ); - } - - private boolean ContinueOnNextLine() { - parser.begin(); - return parser.match('\\') && EndOfLine() ? parser.success() : parser.failure(); - } - - private boolean NewLine() { - if( !EndOfLine() ) - return false; - if( parser.match("--") ) { - while( parser.noneOf("\r\n") ); - } - return true; - } - - private boolean Comment() throws ParseException { - parser.begin(); - if( !parser.match("--[") ) - return parser.failure(); - int start = parser.currentIndex(); - while( parser.match('=') ); - int nEquals = parser.currentIndex() - start; - if( !parser.match('[') ) - return parser.failure(); - while( !LongBracketsEnd(nEquals) ) { - if( !parser.anyChar() ) - throw parser.exception("Unclosed comment"); - } - return parser.success(); - } - - private boolean LongBracketsEnd(int nEquals) { - parser.begin(); - if( !parser.match(']') ) - return parser.failure(); - while( nEquals-- > 0 ) { - if( !parser.match('=') ) - return parser.failure(); - } - if( !parser.match(']') ) - return parser.failure(); - return parser.success(); - } - -}
--- a/src/luan/interp/LuanStateImpl.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -package luan.interp; - -import java.util.List; -import java.util.ArrayList; -import java.util.Map; -import java.util.HashMap; -import luan.Luan; -import luan.LuanState; -import luan.LuanTable; -import luan.LuanFunction; -import luan.MetatableGetter; -import luan.LuanException; -import luan.LuanElement; -import luan.DeepCloner; - - -final class LuanStateImpl extends LuanState { - - private static class Frame { - final Frame previousFrame; - final Closure closure; - final Object[] stack; - final Object[] varArgs; - UpValue[] downValues = null; - - Frame( Frame previousFrame, Closure closure, int stackSize, Object[] varArgs) { - this.previousFrame = previousFrame; - this.closure = closure; - this.stack = new Object[stackSize]; - this.varArgs = varArgs; - } - - void stackClear(int start,int end) { - if( downValues != null ) { - for( int i=start; i<end; i++ ) { - UpValue downValue = downValues[i]; - if( downValue != null ) { - downValue.close(); - downValues[i] = null; - } - } - } - for( int i=start; i<end; i++ ) { - stack[i] = null; - } - } - - UpValue getUpValue(int index) { - if( downValues==null ) - downValues = new UpValue[stack.length]; - if( downValues[index] == null ) - downValues[index] = new UpValue(stack,index); - return downValues[index]; - } - } - - private Frame frame = null; - Object returnValues; - Closure tailFn; - Map<UpValue.EnvGetter,UpValue> envs = new HashMap<UpValue.EnvGetter,UpValue>(); - - LuanStateImpl() {} - - private LuanStateImpl(LuanStateImpl luan) { - super(luan); - } - - @Override public LuanState shallowClone() { -// if( frame != null ) -// throw new IllegalStateException("frame isn't null"); - return new LuanStateImpl(this); - } - - @Override public void deepenClone(LuanState clone,DeepCloner cloner) { - super.deepenClone(clone,cloner); - LuanStateImpl cloneImpl = (LuanStateImpl)clone; - cloneImpl.envs = new HashMap<UpValue.EnvGetter,UpValue>(); - for( Map.Entry<UpValue.EnvGetter,UpValue> entry : envs.entrySet() ) { - cloneImpl.envs.put( entry.getKey(), cloner.deepClone(entry.getValue()) ); - } - } - - // returns stack - Object[] newFrame(Closure closure, int stackSize, Object[] varArgs) { - returnValues = LuanFunction.NOTHING; - tailFn = null; - frame = new Frame(frame,closure,stackSize,varArgs); - return frame.stack; - } - - void popFrame() { - returnValues = LuanFunction.NOTHING; - tailFn = null; - frame = frame.previousFrame; - } - - Object stackGet(int index) { - return frame.stack[index]; - } - - void stackSet(int index,Object value) { - frame.stack[index] = value; - } - - void stackClear(int start,int end) { - frame.stackClear(start,end); - } - - Object[] varArgs() { - return frame.varArgs; - } - - Closure closure() { - return frame.closure; - } - - UpValue getUpValue(int index) { - return frame.getUpValue(index); - } - - UpValue getUpValue(UpValue.EnvGetter getter) throws LuanException { - UpValue uv = envs.get(getter); - if( uv == null ) { - LuanTable env = new LuanTable(); - uv = new UpValue(env); - envs.put(getter,uv); - } - return uv; - } - - @Override public LuanTable currentEnvironment() { - if( frame==null ) - return null; - return (LuanTable)frame.closure.upValues()[0].get(); - } - -}
--- a/src/luan/interp/ModExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class ModExpr extends BinaryOpExpr { - - ModExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - Number n1 = Luan.toNumber(o1); - Number n2 = Luan.toNumber(o2); - if( n1 != null && n2 != null ) - return n1.doubleValue() % n2.doubleValue(); - return arithmetic(luan,"__mod",o1,o2); - } -}
--- a/src/luan/interp/MulExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class MulExpr extends BinaryOpExpr { - - MulExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - Number n1 = Luan.toNumber(o1); - Number n2 = Luan.toNumber(o2); - if( n1 != null && n2 != null ) - return n1.doubleValue() * n2.doubleValue(); - return arithmetic(luan,"__mul",o1,o2); - } -}
--- a/src/luan/interp/NotExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class NotExpr extends UnaryOpExpr { - - NotExpr(LuanSource.Element se,Expr op) { - super(se,op); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - return !Luan.toBoolean(op.eval(luan)); - } -}
--- a/src/luan/interp/OrExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class OrExpr extends BinaryOpExpr { - - OrExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object v1 = op1.eval(luan); - return Luan.toBoolean(v1) ? v1 : op2.eval(luan); - } -}
--- a/src/luan/interp/ParseException.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -public final class ParseException extends Exception { - public final LuanSource src; - public final int iCurrent; - public final int iHigh; - - ParseException(String msg,LuanSource src,int iCurrent,int iHigh) { - super(msg); - this.src = src; - this.iCurrent = iCurrent; - this.iHigh = iHigh; -//System.out.println("iCurrent = "+iCurrent); -//System.out.println("iHigh = "+iHigh); - } - - private class Location { - final int line; - final int pos; - - Location(int index) { - int line = 0; - int i = -1; - while(true) { - int j = src.text.indexOf('\n',i+1); - if( j == -1 || j >= index ) - break; - i = j; - line++; - } - this.line = line; - this.pos = index - i - 1; - } - } - - private String[] lines() { - return src.text.split("\n",-1); - } - - public String getFancyMessage() { - Location loc = new Location(iCurrent); - String line = lines()[loc.line]; - String msg = getMessage() + " (line " + (loc.line+1) + ", pos " + (loc.pos+1) + ") in " + src.name + "\n"; - StringBuilder sb = new StringBuilder(msg); - sb.append( line + "\n" ); - for( int i=0; i<loc.pos; i++ ) { - sb.append( line.charAt(i)=='\t' ? '\t' : ' ' ); - } - sb.append("^\n"); - return sb.toString(); - } -}
--- a/src/luan/interp/Parser.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -final class Parser { - private final LuanSource src; - public final String text; - private final int len; - private int[] stack = new int[256]; - private int frame = 0; - private int iHigh; - - public Parser(LuanSource src) { - this.src = src; - this.text = src.text; - this.len = text.length(); - } - - private int i() { - return stack[frame]; - } - - private void i(int i) { - stack[frame] += i; - if( iHigh < stack[frame] ) - iHigh = stack[frame]; - } - - public int begin() { - frame++; - if( frame == stack.length ) { - int[] a = new int[2*frame]; - System.arraycopy(stack,0,a,0,frame); - stack = a; - } - stack[frame] = stack[frame-1]; - return i(); - } - - public void rollback() { - stack[frame] = stack[frame-1]; - } - - public <T> T success(T t) { - success(); - return t; - } - - public boolean success() { - frame--; - stack[frame] = stack[frame+1]; - return true; - } - - public <T> T failure(T t) { - failure(); - return t; - } - - public boolean failure() { - frame--; - return false; - } - - public ParseException exception(String msg) { - return new ParseException(msg,src,i(),iHigh); - } - - public ParseException exception() { - return exception("Invalid input"); - } - - public int currentIndex() { - return i(); - } - - public char lastChar() { - return text.charAt(i()-1); - } - - public char currentChar() { - return text.charAt(i()); - } - - public boolean endOfInput() { - return i() >= len; - } - - public boolean match(char c) { - if( endOfInput() || text.charAt(i()) != c ) - return false; - i(1); - return true; - } - - public boolean match(String s) { - int n = s.length(); - if( !text.regionMatches(i(),s,0,n) ) - return false; - i(n); - return true; - } - - public boolean matchIgnoreCase(String s) { - int n = s.length(); - if( !text.regionMatches(true,i(),s,0,n) ) - return false; - i(n); - return true; - } - - public boolean anyOf(String s) { - if( endOfInput() || s.indexOf(text.charAt(i())) == -1 ) - return false; - i(1); - return true; - } - - public boolean noneOf(String s) { - if( endOfInput() || s.indexOf(text.charAt(i())) != -1 ) - return false; - i(1); - return true; - } - - public boolean inCharRange(char cLow, char cHigh) { - if( endOfInput() ) - return false; - char c = text.charAt(i()); - if( !(cLow <= c && c <= cHigh) ) - return false; - i(1); - return true; - } - - public boolean anyChar() { - if( endOfInput() ) - return false; - i(1); - return true; - } - - public boolean test(String s) { - return text.regionMatches(i(),s,0,s.length()); - } - - public String textFrom(int start) { - return text.substring(start,i()); - } - -}
--- a/src/luan/interp/PowExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class PowExpr extends BinaryOpExpr { - - PowExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - Number n1 = Luan.toNumber(o1); - Number n2 = Luan.toNumber(o2); - if( n1 != null && n2 != null ) - return Math.pow( n1.doubleValue(), n2.doubleValue() ); - return arithmetic(luan,"__pow",o1,o2); - } -}
--- a/src/luan/interp/RepeatStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class RepeatStmt extends CodeImpl implements Stmt { - private final Stmt doStmt; - private final Expr cnd; - - RepeatStmt(LuanSource.Element se,Stmt doStmt,Expr cnd) { - super(se); - this.doStmt = doStmt; - this.cnd = cnd; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - try { - do { - doStmt.eval(luan); - } while( !luan.bit(se).checkBoolean( cnd.eval(luan) ) ); - } catch(BreakException e) {} - } -}
--- a/src/luan/interp/ReturnException.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -package luan.interp; - - -final class ReturnException extends RuntimeException {}
--- a/src/luan/interp/ReturnStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanFunction; -import luan.LuanSource; - - -final class ReturnStmt extends CodeImpl implements Stmt { - private final Expressions expressions; - private final Expr tailFnExpr; - boolean throwReturnException = true; - - ReturnStmt(LuanSource.Element se,Expressions expressions) { - super(se); - if( expressions instanceof FnCall ) { // tail call - FnCall fnCall = (FnCall)expressions; - this.expressions = fnCall.args; - this.tailFnExpr = fnCall.fnExpr; - } else { - this.expressions = expressions; - this.tailFnExpr = null; - } - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - luan.returnValues = expressions.eval(luan); - if( tailFnExpr != null ) { - LuanFunction tailFn = luan.bit(se).checkFunction( tailFnExpr.eval(luan) ); - if( tailFn instanceof Closure ) { - luan.tailFn = (Closure)tailFn; - } else { - luan.returnValues = luan.bit(tailFnExpr.se()).call(tailFn,tailFnExpr.se().text(),Luan.array(luan.returnValues)); - } - } - if( throwReturnException ) - throw new ReturnException(); - } -}
--- a/src/luan/interp/SetLocalVar.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -package luan.interp; - - -final class SetLocalVar implements Settable { - private final int index; - - SetLocalVar(int index) { - this.index = index; - } - - @Override public void set(LuanStateImpl luan,Object value) { - luan.stackSet( index, value ); - } -}
--- a/src/luan/interp/SetStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; - - -final class SetStmt implements Stmt { - private final Settable[] vars; - private final Expressions expressions; - - SetStmt(Settable var,Expr expr) { - this( new Settable[]{var}, expr ); - } - - SetStmt(Settable[] vars,Expressions expressions) { - this.vars = vars; - this.expressions = expressions; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - final Object obj = expressions.eval(luan); - if( obj instanceof Object[] ) { - Object[] vals = (Object[])obj; - for( int i=0; i<vars.length; i++ ) { - Object val = i < vals.length ? vals[i] : null; - vars[i].set(luan,val); - } - } else { - vars[0].set(luan,obj); - for( int i=1; i<vars.length; i++ ) { - vars[i].set(luan,null); - } - } - } - -}
--- a/src/luan/interp/SetTableEntry.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -package luan.interp; - -import luan.LuanException; -import luan.LuanTable; -import luan.Luan; -import luan.LuanFunction; -import luan.LuanSource; - - -final class SetTableEntry extends CodeImpl implements Settable { - private final Expr tableExpr; - private final Expr keyExpr; - - SetTableEntry(LuanSource.Element se,Expr tableExpr,Expr keyExpr) { - super(se); - this.tableExpr = tableExpr; - this.keyExpr = keyExpr; - } - - @Override public void set(LuanStateImpl luan,Object value) throws LuanException { - newindex( luan, tableExpr.eval(luan), keyExpr.eval(luan), value ); - } - - private void newindex(LuanStateImpl luan,Object t,Object key,Object value) throws LuanException { - Object h; - if( t instanceof LuanTable ) { - LuanTable table = (LuanTable)t; - Object old = table.put(key,value); - if( old != null ) - return; - h = luan.getHandler("__newindex",t); - if( h==null ) - return; - table.put(key,old); - } else { - h = luan.getHandler("__newindex",t); - if( h==null ) - throw luan.bit(se).exception( "attempt to index a " + Luan.type(t) + " value" ); - } - if( h instanceof LuanFunction ) { - LuanFunction fn = (LuanFunction)h; - luan.bit(se).call(fn,"__newindex",new Object[]{t,key,value}); - return; - } - newindex(luan,h,key,value); - } - -}
--- a/src/luan/interp/SetUpVar.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -package luan.interp; - - -final class SetUpVar implements Settable { - private final int index; - - SetUpVar(int index) { - this.index = index; - } - - @Override public void set(LuanStateImpl luan,Object value) { - luan.closure().upValues()[index].set(value); - } -}
--- a/src/luan/interp/Settable.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -package luan.interp; - -import luan.LuanException; - - -interface Settable { - public void set(LuanStateImpl luan,Object value) throws LuanException; -}
--- a/src/luan/interp/Stmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package luan.interp; - -import luan.LuanException; - - -interface Stmt { - public void eval(LuanStateImpl luan) throws LuanException; - - static final Stmt EMPTY = new Stmt() { - @Override public void eval(LuanStateImpl luan) {} - }; -}
--- a/src/luan/interp/SubExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class SubExpr extends BinaryOpExpr { - - SubExpr(LuanSource.Element se,Expr op1,Expr op2) { - super(se,op1,op2); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o1 = op1.eval(luan); - Object o2 = op2.eval(luan); - Number n1 = Luan.toNumber(o1); - Number n2 = Luan.toNumber(o2); - if( n1 != null && n2 != null ) - return n1.doubleValue() - n2.doubleValue(); - return arithmetic(luan,"__sub",o1,o2); - } -}
--- a/src/luan/interp/TableExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -package luan.interp; - -import luan.LuanException; -import luan.LuanTable; -import luan.LuanSource; - - -final class TableExpr extends CodeImpl implements Expr { - - static class Field { - final Expr key; - final Expr value; - - Field(Expr key,Expr value) { - this.key = key; - this.value = value; - } - } - - private final Field[] fields; - private final Expressions expressions; - - TableExpr(LuanSource.Element se,Field[] fields,Expressions expressions) { - super(se); - this.fields = fields; - this.expressions = expressions; - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - LuanTable table = new LuanTable(); - for( Field field : fields ) { - table.put( field.key.eval(luan), field.value.eval(luan) ); - } - Object obj = expressions.eval(luan); - if( obj instanceof Object[] ) { - Object[] a = (Object[])obj; - for( int i=0; i<a.length; i++ ) { - table.put( i+1, a[i] ); - } - } else { - table.put( 1, obj ); - } - return table; - } -}
--- a/src/luan/interp/TryStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; - - -final class TryStmt implements Stmt { - private final Stmt tryBlock; - private final int iExceptionVar; - private final Stmt catchBlock; - - TryStmt(Stmt tryBlock,int iExceptionVar,Stmt catchBlock) { - this.tryBlock = tryBlock; - this.iExceptionVar = iExceptionVar; - this.catchBlock = catchBlock; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - try { - tryBlock.eval(luan); - } catch(LuanException e) { - try { - luan.stackSet( iExceptionVar, e ); - catchBlock.eval(luan); - } finally { - luan.stackClear(iExceptionVar,iExceptionVar+1); - } - } - } -}
--- a/src/luan/interp/UnaryOpExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -abstract class UnaryOpExpr extends CodeImpl implements Expr { - final Expr op; - - UnaryOpExpr(LuanSource.Element se,Expr op) { - super(se); - this.op = op; - } -}
--- a/src/luan/interp/UnmExpr.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanSource; -import luan.LuanBit; - - -// unary minus -final class UnmExpr extends UnaryOpExpr { - - UnmExpr(LuanSource.Element se,Expr op) { - super(se,op); - } - - @Override public Object eval(LuanStateImpl luan) throws LuanException { - Object o = op.eval(luan); - Number n = Luan.toNumber(o); - if( n != null ) - return -n.doubleValue(); - LuanBit bit = luan.bit(se); - LuanFunction fn = bit.getHandlerFunction("__unm",o); - if( fn != null ) { - return Luan.first(bit.call(fn,"__unm",new Object[]{o})); - } - throw bit.exception("attempt to perform arithmetic on a "+Luan.type(o)+" value"); - } -}
--- a/src/luan/interp/UpValue.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -package luan.interp; - -import luan.DeepCloner; -import luan.DeepCloneable; -import luan.LuanException; - - -final class UpValue implements DeepCloneable<UpValue> { - private Object[] stack; - private int index; - private boolean isClosed = false; - private Object value; - - UpValue(Object[] stack,int index) { - this.stack = stack; - this.index = index; - } - - UpValue(Object value) { - this.value = value; - this.isClosed = true; - } - - private UpValue() {} - - @Override public UpValue shallowClone() { - return new UpValue(); - } - - @Override public void deepenClone(UpValue clone,DeepCloner cloner) { - clone.isClosed = isClosed; - if( isClosed ) { - clone.value = cloner.get(value); - } else { - clone.stack = cloner.deepClone(stack); - clone.index = index; - } - } - - Object get() { - return isClosed ? value : stack[index]; - } - - void set(Object value) { - if( isClosed ) { - this.value = value; - } else { - stack[index] = value; - } - } - - void close() { - value = stack[index]; - isClosed = true; - stack = null; - } - - static interface Getter { - public UpValue get(LuanStateImpl luan) throws LuanException; - } - - static final class StackGetter implements Getter { - private final int index; - - StackGetter(int index) { - this.index = index; - } - - public UpValue get(LuanStateImpl luan) { - return luan.getUpValue(index); - } - } - - static final class NestedGetter implements Getter { - private final int index; - - NestedGetter(int index) { - this.index = index; - } - - public UpValue get(LuanStateImpl luan) { - return luan.closure().upValues()[index]; - } - } - - static final class EnvGetter implements Getter { - - public UpValue get(LuanStateImpl luan) throws LuanException { - return luan.getUpValue(this); - } - } - - static final class ValueGetter implements Getter { - private final UpValue upValue; - - ValueGetter(Object value) { - this.upValue = new UpValue(value); - } - - public UpValue get(LuanStateImpl luan) { - return upValue; - } - } - -}
--- a/src/luan/interp/VarArgs.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package luan.interp; - -import luan.LuanSource; - - -final class VarArgs extends CodeImpl implements Expressions { - - VarArgs(LuanSource.Element se) { - super(se); - } - - @Override public Object[] eval(LuanStateImpl luan) { - return luan.varArgs(); - } -}
--- a/src/luan/interp/WhileStmt.java Sun Jun 22 04:10:59 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -package luan.interp; - -import luan.Luan; -import luan.LuanException; -import luan.LuanSource; - - -final class WhileStmt extends CodeImpl implements Stmt { - private final Expr cnd; - private final Stmt doStmt; - - WhileStmt(LuanSource.Element se,Expr cnd,Stmt doStmt) { - super(se); - this.cnd = cnd; - this.doStmt = doStmt; - } - - @Override public void eval(LuanStateImpl luan) throws LuanException { - try { - while( luan.bit(se).checkBoolean( cnd.eval(luan) ) ) { - doStmt.eval(luan); - } - } catch(BreakException e) {} - } -}
--- a/src/luan/lib/BasicLib.java Sun Jun 22 04:10:59 2014 +0000 +++ b/src/luan/lib/BasicLib.java Sun Jun 22 04:17:38 2014 +0000 @@ -16,7 +16,7 @@ import luan.LuanException; import luan.LuanSource; import luan.LuanElement; -import luan.interp.LuanCompiler; +import luan.impl.LuanCompiler; public final class BasicLib {