Mercurial Hosting > luan
changeset 40:e3624b7cd603
implement stack trace
git-svn-id: https://luan-java.googlecode.com/svn/trunk@41 21e917c8-12df-6dd8-5cb6-c86387c605b9
line wrap: on
line diff
--- a/src/luan/Lua.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/Lua.java Fri Dec 21 10:45:54 2012 +0000 @@ -26,13 +26,6 @@ return null; } - public static String checkString(Object obj) throws LuaException { - String s = asString(obj); - if( s == null ) - throw new LuaException( "attempt to use a " + Lua.type(obj) + " as a string" ); - return s; - } - public static LuaNumber toNumber(Object obj) { return toNumber(obj,null); } @@ -52,17 +45,8 @@ return null; } - public static LuaNumber checkNumber(Object obj) throws LuaException { - LuaNumber n = toNumber(obj); - if( n == null ) - throw new LuaException( "attempt to perform arithmetic on a " + type(obj) + " value" ); - return n; - } - - public static LuaFunction checkFunction(Object obj) throws LuaException { - if( obj instanceof LuaFunction ) - return (LuaFunction)obj; - throw new LuaException( "attempt to call a " + type(obj) + " value" ); + public static Object first(Object[] a) { + return a.length==0 ? null : a[0]; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaElement.java Fri Dec 21 10:45:54 2012 +0000 @@ -0,0 +1,16 @@ +package luan; + + +public abstract class LuaElement { + abstract String toString(String fnName); + + final String function(String fnName) { + return fnName==null ? "main chunk" : "function '"+fnName+"'"; + } + + public static final LuaElement JAVA = new LuaElement(){ + @Override public String toString(String fnName) { + return "java: in " + function(fnName); + } + }; +}
--- a/src/luan/LuaException.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/LuaException.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,26 @@ public class LuaException extends Exception { - public LuaException(String msg) { - super(msg); + public LuaException(LuaState lua,LuaElement el,String msg) { + super(hideNull(msg)+stackTrace(lua,el)); + } + + public LuaException(LuaState lua,LuaElement el,Exception cause) { + super(hideNull(cause.getMessage())+stackTrace(lua,el),cause); + } + + private static String hideNull(String s) { + return s==null ? "" : s; } - public LuaException(Exception e) { - super(e); + private static String stackTrace(LuaState lua,LuaElement el) { + StringBuilder buf = new StringBuilder(); + int i = lua.stackTrace.size() - 1; + do { + StackTraceElement stackTraceElement = lua.stackTrace.get(i); + buf.append( "\n\t" ).append( el.toString(stackTraceElement.fnName) ); + el = stackTraceElement.call; + } while( --i >= 0 ); + return buf.toString(); } - }
--- a/src/luan/LuaFunction.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/LuaFunction.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,7 +3,7 @@ public abstract class LuaFunction { - public abstract Object[] call(LuaState lua,Object... args) throws LuaException; + public abstract Object[] call(LuaState lua,Object[] args) throws LuaException; public static final Object[] EMPTY_RTN = new Object[0];
--- a/src/luan/LuaJavaFunction.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/LuaJavaFunction.java Fri Dec 21 10:45:54 2012 +0000 @@ -40,7 +40,7 @@ return method.getParameterTypes(); } - @Override public Object[] call(LuaState lua,Object... args) { + @Override public Object[] call(LuaState lua,Object[] args) throws LuaException { args = fixArgs(lua,args); Object rtn; try { @@ -48,6 +48,13 @@ } catch(IllegalAccessException e) { throw new RuntimeException(e); } catch(InvocationTargetException e) { + Throwable cause = e.getCause(); + if( cause instanceof Error ) + throw (Error)cause; + if( cause instanceof RuntimeException ) + throw (RuntimeException)cause; + if( cause instanceof LuaException ) + throw (LuaException)cause; throw new RuntimeException(e); } catch(InstantiationException e) { throw new RuntimeException(e);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuaSource.java Fri Dec 21 10:45:54 2012 +0000 @@ -0,0 +1,45 @@ +package luan; + + +public final class LuaSource { + public final String name; + public final String text; + + public LuaSource(String name,String text) { + this.name = name; + this.text = text; + } + + public static final class Element extends LuaElement { + public final LuaSource source; + public final int start; + public final int end; + + public Element(LuaSource source,int start,int end) { + if( source==null ) + throw new NullPointerException("source is null"); + this.source = source; + this.start = start; + this.end = end; + } + + public String text() { + return source.text.substring(start,end); + } + + @Override public String toString(String fnName) { + return source.name + ':' + lineNumber() + ": in " + function(fnName); + } + + private int lineNumber() { + int line = 0; + int i = -1; + do { + line++; + i = source.text.indexOf('\n',i+1); + } while( i != -1 && i < start ); + return line; + } + + } +}
--- a/src/luan/LuaState.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/LuaState.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,9 +1,83 @@ package luan; +import java.util.List; +import java.util.ArrayList; + -public interface LuaState { - public LuaTable global(); - public String toString(Object obj) throws LuaException; - public LuaTable getMetatable(Object obj); - public void addMetatableGetter(MetatableGetter mg); +public abstract class LuaState { + private final LuaTable global = new LuaTable(); + private final List<MetatableGetter> mtGetters = new ArrayList<MetatableGetter>(); + final List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>(); + + public final LuaTable global() { + return global; + } + + public final LuaTable getMetatable(Object obj) { + if( obj instanceof LuaTable ) { + LuaTable table = (LuaTable)obj; + return table.getMetatable(); + } + for( MetatableGetter mg : mtGetters ) { + LuaTable table = mg.getMetatable(obj); + if( table != null ) + return table; + } + return null; + } + + public final void addMetatableGetter(MetatableGetter mg) { + mtGetters.add(mg); + } + + public Object[] call(LuaFunction fn,LuaElement calledFrom,String fnName,Object... args) throws LuaException { + stackTrace.add( new StackTraceElement(calledFrom,fnName) ); + try { + return fn.call(this,args); + } finally { + stackTrace.remove(stackTrace.size()-1); + } + } + + public final String checkString(LuaElement el,Object obj) throws LuaException { + String s = Lua.asString(obj); + if( s == null ) + throw new LuaException( this, el, "attempt to use a " + Lua.type(obj) + " as a string" ); + return s; + } + + public final LuaNumber checkNumber(LuaElement el,Object obj) throws LuaException { + LuaNumber n = Lua.toNumber(obj); + if( n == null ) + throw new LuaException( this, el, "attempt to perform arithmetic on a " + Lua.type(obj) + " value" ); + return n; + } + + public final LuaFunction checkFunction(LuaElement el,Object obj) throws LuaException { + if( obj instanceof LuaFunction ) + return (LuaFunction)obj; + throw new LuaException( this, el, "attempt to call a " + Lua.type(obj) + " value" ); + } + + public final String toString(LuaElement el,Object obj) throws LuaException { + LuaFunction fn = getHandlerFunction(el,"__tostring",obj); + if( fn != null ) + return checkString( el, Lua.first( call(fn,el,"__tostring",obj) ) ); + if( obj == null ) + return "nil"; + return obj.toString(); + } + + public final LuaFunction getHandlerFunction(LuaElement el,String op,Object obj) throws LuaException { + Object f = getHandler(op,obj); + if( f == null ) + return null; + return checkFunction(el,f); + } + + public final Object getHandler(String op,Object obj) { + LuaTable t = getMetatable(obj); + return t==null ? null : t.get(op); + } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/StackTraceElement.java Fri Dec 21 10:45:54 2012 +0000 @@ -0,0 +1,12 @@ +package luan; + + +final class StackTraceElement { + final LuaElement call; + final String fnName; + + StackTraceElement(LuaElement call,String fnName) { + this.call = call; + this.fnName = fnName; + } +}
--- a/src/luan/interp/AddExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/AddExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; final class AddExpr extends BinaryOpExpr { - AddExpr(Expr op1,Expr op2) { - super(op1,op2); + AddExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,6 +19,6 @@ LuaNumber n2 = Lua.toNumber(o2); if( n1 != null && n2 != null ) return new LuaNumber( n1.value() + n2.value() ); - return lua.arithmetic("__add",o1,o2); + return arithmetic(lua,"__add",o1,o2); } }
--- a/src/luan/interp/AndExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/AndExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -2,12 +2,13 @@ import luan.Lua; import luan.LuaException; +import luan.LuaSource; final class AndExpr extends BinaryOpExpr { - AndExpr(Expr op1,Expr op2) { - super(op1,op2); + AndExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException {
--- a/src/luan/interp/BinaryOpExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/BinaryOpExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,15 +4,21 @@ import luan.LuaTable; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; -abstract class BinaryOpExpr implements Expr { +abstract class BinaryOpExpr extends CodeImpl implements Expr { final Expr op1; final Expr op2; - BinaryOpExpr(Expr op1,Expr op2) { + BinaryOpExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se); this.op1 = op1; this.op2 = op2; } + Object arithmetic(LuaStateImpl lua,String op,Object o1,Object o2) throws LuaException { + return lua.arithmetic(se(),"__mod",o1,o2); + } + }
--- a/src/luan/interp/Chunk.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/Chunk.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,16 +1,18 @@ package luan.interp; import luan.LuaException; +import luan.LuaSource; -final class Chunk implements Expr { +final class Chunk extends CodeImpl implements Expr { final Stmt block; final int stackSize; final int numArgs; final boolean isVarArg; final UpValue.Getter[] upValueGetters; - Chunk(Stmt block,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) { + Chunk(LuaSource.Element se,Stmt block,int stackSize,int numArgs,boolean isVarArg,UpValue.Getter[] upValueGetters) { + super(se); this.block = block; this.stackSize = stackSize; this.numArgs = numArgs;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/interp/Code.java Fri Dec 21 10:45:54 2012 +0000 @@ -0,0 +1,8 @@ +package luan.interp; + +import luan.LuaSource; + + +interface Code { + public LuaSource.Element se(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/interp/CodeImpl.java Fri Dec 21 10:45:54 2012 +0000 @@ -0,0 +1,16 @@ +package luan.interp; + +import luan.LuaSource; + + +class CodeImpl implements Code { + final LuaSource.Element se; + + CodeImpl(LuaSource.Element se) { + this.se = se; + } + + @Override public final LuaSource.Element se() { + return se; + } +}
--- a/src/luan/interp/ConcatExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/ConcatExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; final class ConcatExpr extends BinaryOpExpr { - ConcatExpr(Expr op1,Expr op2) { - super(op1,op2); + ConcatExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,10 +19,10 @@ String s2 = Lua.asString(o2); if( s1 != null && s2 != null ) return s1 + s2; - LuaFunction fn = lua.getBinHandler("__concat",o1,o2); + LuaFunction fn = lua.getBinHandler(se,"__concat",o1,o2); if( fn != null ) - return Utils.first(fn.call(lua,o1,o2)); + return Lua.first(lua.call(fn,se,"__concat",o1,o2)); String type = s1==null ? Lua.type(o1) : Lua.type(o2); - throw new LuaException( "attempt to concatenate a " + type + " value" ); + throw new LuaException( lua, se, "attempt to concatenate a " + type + " value" ); } }
--- a/src/luan/interp/ConstExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/ConstExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,5 +1,7 @@ package luan.interp; +import luan.LuaSource; + final class ConstExpr implements Expr { private final Object obj; @@ -11,4 +13,8 @@ @Override public Object eval(LuaStateImpl lua) { return obj; } + + @Override public final LuaSource.Element se() { + return null; + } }
--- a/src/luan/interp/DivExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/DivExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; final class DivExpr extends BinaryOpExpr { - DivExpr(Expr op1,Expr op2) { - super(op1,op2); + DivExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,6 +19,6 @@ LuaNumber n2 = Lua.toNumber(o2); if( n1 != null && n2 != null ) return new LuaNumber( n1.value() / n2.value() ); - return lua.arithmetic("__div",o1,o2); + return arithmetic(lua,"__div",o1,o2); } }
--- a/src/luan/interp/EqExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/EqExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -5,12 +5,13 @@ import luan.LuaFunction; import luan.LuaTable; import luan.LuaException; +import luan.LuaSource; final class EqExpr extends BinaryOpExpr { - EqExpr(Expr op1,Expr op2) { - super(op1,op2); + EqExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -27,7 +28,7 @@ Object f = mt1.get("__eq"); if( f == null || !f.equals(mt2.get("__eq")) ) return null; - LuaFunction fn = Lua.checkFunction(f); - return Lua.toBoolean( Utils.first(fn.call(lua,o1,o2)) ); + LuaFunction fn = lua.checkFunction(se,f); + return Lua.toBoolean( Lua.first(lua.call(fn,se,"__eq",o1,o2)) ); } }
--- a/src/luan/interp/ExpList.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/ExpList.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,12 +4,14 @@ import java.util.ArrayList; import java.util.Collections; import luan.LuaException; +import luan.LuaSource; final class ExpList implements Expressions { private interface Adder { public void addTo(LuaStateImpl lua,List<Object> list) throws LuaException; + public Code code(); } private static class ExprAdder implements Adder { @@ -23,6 +25,10 @@ list.add( expr.eval(lua) ); } + public Code code() { + return expr; + } + } private static class ExpressionsAdder implements Adder { @@ -38,6 +44,10 @@ } } + public Code code() { + return expressions; + } + } static class Builder { @@ -70,9 +80,14 @@ private static final Object[] EMPTY = new Object[0]; static final Expressions emptyExpList = new Expressions() { + @Override public Object[] eval(LuaStateImpl lua) { return EMPTY; } + + @Override public LuaSource.Element se() { + return null; + } }; static class SingleExpList implements Expressions { @@ -85,6 +100,10 @@ @Override public Object[] eval(LuaStateImpl lua) throws LuaException { return new Object[]{expr.eval(lua)}; } + + @Override public LuaSource.Element se() { + return expr.se(); + } } private final Adder[] adders; @@ -100,4 +119,8 @@ } return list.toArray(); } + + @Override public LuaSource.Element se() { + return new LuaSource.Element(adders[0].code().se().source,adders[0].code().se().start,adders[adders.length-1].code().se().end); + } }
--- a/src/luan/interp/Expr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/Expr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,6 +3,6 @@ import luan.LuaException; -interface Expr { +interface Expr extends Code { public Object eval(LuaStateImpl lua) throws LuaException; }
--- a/src/luan/interp/Expressions.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/Expressions.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,6 +3,6 @@ import luan.LuaException; -interface Expressions { +interface Expressions extends Code { public Object[] eval(LuaStateImpl lua) throws LuaException; }
--- a/src/luan/interp/ExpressionsExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/ExpressionsExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,6 +3,7 @@ import java.util.List; import luan.Lua; import luan.LuaException; +import luan.LuaSource; final class ExpressionsExpr implements Expr { @@ -13,6 +14,11 @@ } @Override public Object eval(LuaStateImpl lua) throws LuaException { - return Utils.first( expressions.eval(lua) ); + return Lua.first( expressions.eval(lua) ); } + + public LuaSource.Element se() { + return expressions.se(); + } + }
--- a/src/luan/interp/FnCall.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/FnCall.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,15 +3,19 @@ import luan.Lua; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; -final class FnCall implements Expressions { +final class FnCall extends CodeImpl implements Expressions { final Expr fnExpr; final Expressions args; + final String fnName; - FnCall(Expr fnExpr,Expressions args) { + FnCall(LuaSource.Element se,Expr fnExpr,Expressions args) { + super(se); this.fnExpr = fnExpr; this.args = args; + this.fnName = fnExpr.se().text(); } @Override public Object[] eval(LuaStateImpl lua) throws LuaException { @@ -21,11 +25,11 @@ private Object[] call(LuaStateImpl lua,Object o) throws LuaException { if( o instanceof LuaFunction ) { LuaFunction fn = (LuaFunction)o; - return fn.call( lua, args.eval(lua) ); + return lua.call( fn, se, fnName, args.eval(lua) ); } Object h = lua.getHandler("__call",o); if( h != null ) return call(lua,h); - throw new LuaException( "attempt to call a " + Lua.type(o) + " value" ); + throw new LuaException( lua, se, "attempt to call a " + Lua.type(o) + " value" ); } }
--- a/src/luan/interp/GenericForStmt.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/GenericForStmt.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,15 +3,17 @@ import luan.Lua; import luan.LuaException; import luan.LuaFunction; +import luan.LuaSource; -final class GenericForStmt implements Stmt { +final class GenericForStmt extends CodeImpl implements Stmt { private final int iVars; private final int nVars; private final Expr iterExpr; private final Stmt block; - GenericForStmt(int iVars,int nVars,Expr iterExpr,Stmt block) { + GenericForStmt(LuaSource.Element se,int iVars,int nVars,Expr iterExpr,Stmt block) { + super(se); this.iVars = iVars; this.nVars = nVars; this.iterExpr = iterExpr; @@ -19,10 +21,10 @@ } @Override public void eval(LuaStateImpl lua) throws LuaException { - LuaFunction iter = Lua.checkFunction( iterExpr.eval(lua) ); + LuaFunction iter = lua.checkFunction( se, iterExpr.eval(lua) ); try { while(true) { - Object[] vals = iter.call(lua); + Object[] vals = lua.call(iter,iterExpr.se(),iterExpr.se().text()); if( vals.length==0 || vals[0]==null ) break; for( int i=0; i<nVars; i++ ) {
--- a/src/luan/interp/GetLocalVar.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/GetLocalVar.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,10 +1,13 @@ package luan.interp; +import luan.LuaSource; + -final class GetLocalVar implements Expr { +final class GetLocalVar extends CodeImpl implements Expr { private final int index; - GetLocalVar(int index) { + GetLocalVar(LuaSource.Element se,int index) { + super(se); this.index = index; }
--- a/src/luan/interp/GetUpVar.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/GetUpVar.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,10 +1,13 @@ package luan.interp; +import luan.LuaSource; + -final class GetUpVar implements Expr { +final class GetUpVar extends CodeImpl implements Expr { private final int index; - GetUpVar(int index) { + GetUpVar(LuaSource.Element se,int index) { + super(se); this.index = index; }
--- a/src/luan/interp/IndexExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/IndexExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,19 +4,20 @@ import luan.LuaException; import luan.LuaTable; import luan.LuaFunction; +import luan.LuaSource; final class IndexExpr extends BinaryOpExpr { - IndexExpr(Expr op1,Expr op2) { - super(op1,op2); + IndexExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { return index(lua,op1.eval(lua),op2.eval(lua)); } - private static Object index(LuaStateImpl lua,Object t,Object key) throws LuaException { + private Object index(LuaStateImpl lua,Object t,Object key) throws LuaException { Object h; if( t instanceof LuaTable ) { LuaTable tbl = (LuaTable)t; @@ -29,11 +30,11 @@ } else { h = lua.getHandler("__index",t); if( h==null ) - throw new LuaException( "attempt to index a " + Lua.type(t) + " value" ); + throw new LuaException( lua, se, "attempt to index a " + Lua.type(t) + " value" ); } if( h instanceof LuaFunction ) { LuaFunction fn = (LuaFunction)h; - return Utils.first(fn.call(lua,t,key)); + return Lua.first(lua.call(fn,se,"__index",t,key)); } return index(lua,h,key); }
--- a/src/luan/interp/LeExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LeExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,12 +4,13 @@ import luan.LuaNumber; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; final class LeExpr extends BinaryOpExpr { - LeExpr(Expr op1,Expr op2) { - super(op1,op2); + LeExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -25,12 +26,12 @@ String s2 = (String)o2; return s1.compareTo(s2) <= 0; } - LuaFunction fn = lua.getBinHandler("__le",o1,o2); + LuaFunction fn = lua.getBinHandler(se,"__le",o1,o2); if( fn != null ) - return Lua.toBoolean( Utils.first(fn.call(lua,o1,o2)) ); - fn = lua.getBinHandler("__lt",o1,o2); + return Lua.toBoolean( Lua.first(lua.call(fn,se,"__le",o1,o2)) ); + fn = lua.getBinHandler(se,"__lt",o1,o2); if( fn != null ) - return !Lua.toBoolean( Utils.first(fn.call(lua,o2,o1)) ); - throw new LuaException( "attempt to compare " + Lua.type(o1) + " with " + Lua.type(o2) ); + return !Lua.toBoolean( Lua.first(lua.call(fn,se,"__lt",o2,o1)) ); + throw new LuaException( lua, se, "attempt to compare " + Lua.type(o1) + " with " + Lua.type(o2) ); } }
--- a/src/luan/interp/LenExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LenExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -5,12 +5,13 @@ import luan.LuaTable; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; final class LenExpr extends UnaryOpExpr { - LenExpr(Expr op) { - super(op); + LenExpr(LuaSource.Element se,Expr op) { + super(se,op); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -19,13 +20,13 @@ String s = (String)o; return new LuaNumber( s.length() ); } - LuaFunction fn = lua.getHandlerFunction("__len",o); + LuaFunction fn = lua.getHandlerFunction(se,"__len",o); if( fn != null ) - return Utils.first(fn.call(lua,o)); + return Lua.first(lua.call(fn,se,"__len",o)); if( o instanceof LuaTable ) { LuaTable t = (LuaTable)o; return t.length(); } - throw new LuaException( "attempt to get length of a " + Lua.type(o) + " value" ); + throw new LuaException( lua, se, "attempt to get length of a " + Lua.type(o) + " value" ); } }
--- a/src/luan/interp/LtExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LtExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,12 +4,13 @@ import luan.LuaNumber; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; final class LtExpr extends BinaryOpExpr { - LtExpr(Expr op1,Expr op2) { - super(op1,op2); + LtExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -25,9 +26,9 @@ String s2 = (String)o2; return s1.compareTo(s2) < 0; } - LuaFunction fn = lua.getBinHandler("__lt",o1,o2); + LuaFunction fn = lua.getBinHandler(se,"__lt",o1,o2); if( fn != null ) - return Lua.toBoolean( Utils.first(fn.call(lua,o1,o2)) ); - throw new LuaException( "attempt to compare " + Lua.type(o1) + " with " + Lua.type(o2) ); + return Lua.toBoolean( Lua.first(lua.call(fn,se,"__lt",o1,o2)) ); + throw new LuaException( lua, se, "attempt to compare " + Lua.type(o1) + " with " + Lua.type(o2) ); } }
--- a/src/luan/interp/LuaClosure.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LuaClosure.java Fri Dec 21 10:45:54 2012 +0000 @@ -2,6 +2,7 @@ import luan.LuaFunction; import luan.LuaState; +import luan.LuaElement; import luan.LuaException; @@ -23,7 +24,7 @@ } } - public Object[] call(LuaState lua,Object... args) throws LuaException { + public Object[] call(LuaState lua,Object[] args) throws LuaException { return call(this,(LuaStateImpl)lua,args); }
--- a/src/luan/interp/LuaCompiler.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LuaCompiler.java Fri Dec 21 10:45:54 2012 +0000 @@ -8,22 +8,25 @@ import luan.LuaFunction; import luan.LuaState; import luan.LuaException; +import luan.LuaSource; +import luan.LuaElement; public final class LuaCompiler { private LuaCompiler() {} // never - public static LuaFunction compile(LuaState lua,String src) throws LuaException { + public static LuaFunction compile(LuaState lua,LuaSource src) throws LuaException { LuaParser parser = Parboiled.createParser(LuaParser.class); - ParsingResult<?> result = new ReportingParseRunner(parser.Target()).run(src); + parser.source = src; + ParsingResult<?> result = new ReportingParseRunner(parser.Target()).run(src.text); // ParsingResult<?> result = new TracingParseRunner(parser.Target()).run(src); if( result.hasErrors() ) - throw new LuaException( ErrorUtils.printParseErrors(result) ); + throw new LuaException( lua, null, ErrorUtils.printParseErrors(result) ); Object resultValue = result.resultValue; if( resultValue instanceof Expressions ) { final Expressions expressions = (Expressions)resultValue; return new LuaFunction() { - public Object[] call(LuaState lua,Object... args) throws LuaException { + public Object[] call(LuaState lua,Object[] args) throws LuaException { return expressions.eval((LuaStateImpl)lua); } };
--- a/src/luan/interp/LuaParser.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LuaParser.java Fri Dec 21 10:45:54 2012 +0000 @@ -19,10 +19,17 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaState; +import luan.LuaSource; class LuaParser extends BaseParser<Object> { + LuaSource source; + + LuaSource.Element se(int start) { + return new LuaSource.Element(source,start,currentIndex()); + } + static final String _ENV = "_ENV"; static final class Frame { @@ -144,20 +151,22 @@ return true; } - Chunk newChunk() { - return new Chunk( (Stmt)pop(), frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); + Chunk newChunk(int start) { + return new Chunk( se(start), (Stmt)pop(), frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); } Rule Target() { + Var<Integer> start = new Var<Integer>(); return Sequence( Spaces(), FirstOf( Sequence( ExpList(), EOI ), Sequence( + start.set(currentIndex()), action( frame.isVarArg = true ), Block(), EOI, - push( newChunk() ) + push( newChunk(start.get()) ) ) ) ); @@ -227,9 +236,11 @@ } Rule ReturnStmt() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), Keyword("return"), Expressions(), - push( new ReturnStmt( (Expressions)pop() ) ) + push( new ReturnStmt( se(start.get()), (Expressions)pop() ) ) ); } @@ -241,15 +252,17 @@ } Rule FnName() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), push(null), // marker Name(), ZeroOrMore( '.', Spaces(), - makeVarExp(), + makeVarExp(start.get()), NameExpr() ), - makeSettableVar() + makeSettableVar(start.get()) ); } @@ -272,19 +285,23 @@ } Rule GenericForStmt() { + Var<Integer> start = new Var<Integer>(); Var<Integer> stackStart = new Var<Integer>(symbolsSize()); Var<List<String>> names = new Var<List<String>>(new ArrayList<String>()); return Sequence( + start.set(currentIndex()), Keyword("for"), NameList(names), Keyword("in"), Expr(), Keyword("do"), addSymbols(names.get()), LoopBlock(), Keyword("end"), - push( new GenericForStmt( stackStart.get(), symbolsSize() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ), + push( new GenericForStmt( se(start.get()), stackStart.get(), symbolsSize() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ), popSymbols( symbolsSize() - stackStart.get() ) ); } Rule NumericForStmt() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), Keyword("for"), Name(), '=', Spaces(), Expr(), Keyword("to"), Expr(), push( new ConstExpr(new LuaNumber(1)) ), // default step Optional( @@ -294,7 +311,7 @@ ), addSymbol( (String)pop(3) ), // add "for" var to symbols Keyword("do"), LoopBlock(), Keyword("end"), - push( new NumericForStmt( symbolsSize()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ), + push( new NumericForStmt( se(start.get()), symbolsSize()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ), popSymbols(1) ); } @@ -421,10 +438,15 @@ } Rule SettableVar() { - return Sequence( Var(), makeSettableVar() ); + Var<Integer> start = new Var<Integer>(); + return Sequence( + start.set(currentIndex()), + Var(), + makeSettableVar(start.get()) + ); } - boolean makeSettableVar() { + boolean makeSettableVar(int start) { Object obj2 = pop(); if( obj2==null ) return false; @@ -432,7 +454,7 @@ if( obj1!=null ) { Expr key = expr(obj2); Expr table = expr(obj1); - return push( new SetTableEntry(table,key) ); + return push( new SetTableEntry(se(start),table,key) ); } String name = (String)obj2; int index = stackIndex(name); @@ -441,7 +463,7 @@ index = upValueIndex(name); if( index != -1 ) return push( new SetUpVar(index) ); - return push( new SetTableEntry( env(), new ConstExpr(name) ) ); + return push( new SetTableEntry( se(start), env(), new ConstExpr(name) ) ); } Rule Expr() { @@ -452,80 +474,98 @@ } Rule OrExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), AndExpr(), - ZeroOrMore( "or", Spaces(), AndExpr(), push( new OrExpr(expr(pop(1)),expr(pop())) ) ) + ZeroOrMore( "or", Spaces(), AndExpr(), push( new OrExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) ); } Rule AndExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), RelExpr(), - ZeroOrMore( "and", Spaces(), RelExpr(), push( new AndExpr(expr(pop(1)),expr(pop())) ) ) + ZeroOrMore( "and", Spaces(), RelExpr(), push( new AndExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) ); } Rule RelExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), ConcatExpr(), ZeroOrMore( FirstOf( - Sequence( "==", Spaces(), ConcatExpr(), push( new EqExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( "~=", Spaces(), ConcatExpr(), push( new NotExpr(new EqExpr(expr(pop(1)),expr(pop()))) ) ), - Sequence( "<=", Spaces(), ConcatExpr(), push( new LeExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( ">=", Spaces(), ConcatExpr(), push( new LeExpr(expr(pop()),expr(pop())) ) ), - Sequence( "<", Spaces(), ConcatExpr(), push( new LtExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( ">", Spaces(), ConcatExpr(), push( new LtExpr(expr(pop()),expr(pop())) ) ) + Sequence( "==", Spaces(), ConcatExpr(), push( new EqExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), + Sequence( "~=", Spaces(), ConcatExpr(), push( new NotExpr(se(start.get()),new EqExpr(se(start.get()),expr(pop(1)),expr(pop()))) ) ), + Sequence( "<=", Spaces(), ConcatExpr(), push( new LeExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), + Sequence( ">=", Spaces(), ConcatExpr(), push( new LeExpr(se(start.get()),expr(pop()),expr(pop())) ) ), + Sequence( "<", Spaces(), ConcatExpr(), push( new LtExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), + Sequence( ">", Spaces(), ConcatExpr(), push( new LtExpr(se(start.get()),expr(pop()),expr(pop())) ) ) ) ) ); } Rule ConcatExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), SumExpr(), - Optional( "..", Spaces(), ConcatExpr(), push( new ConcatExpr(expr(pop(1)),expr(pop())) ) ) + Optional( "..", Spaces(), ConcatExpr(), push( new ConcatExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) ); } Rule SumExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), TermExpr(), ZeroOrMore( FirstOf( - Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( '-', TestNot('-'), Spaces(), TermExpr(), push( new SubExpr(expr(pop(1)),expr(pop())) ) ) + Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), + Sequence( '-', TestNot('-'), Spaces(), TermExpr(), push( new SubExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) ) ) ); } Rule TermExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), UnaryExpr(), ZeroOrMore( FirstOf( - Sequence( '*', Spaces(), UnaryExpr(), push( new MulExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( '/', Spaces(), UnaryExpr(), push( new DivExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( '%', Spaces(), UnaryExpr(), push( new ModExpr(expr(pop(1)),expr(pop())) ) ) + Sequence( '*', Spaces(), UnaryExpr(), push( new MulExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), + Sequence( '/', Spaces(), UnaryExpr(), push( new DivExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), + Sequence( '%', Spaces(), UnaryExpr(), push( new ModExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) ) ) ); } Rule UnaryExpr() { - return FirstOf( - Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(expr(pop())) ) ), - Sequence( '-', TestNot('-'), Spaces(), PowExpr(), push( new UnmExpr(expr(pop())) ) ), - Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(expr(pop())) ) ), - PowExpr() + Var<Integer> start = new Var<Integer>(); + return Sequence( + start.set(currentIndex()), + FirstOf( + Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(se(start.get()),expr(pop())) ) ), + Sequence( '-', TestNot('-'), Spaces(), PowExpr(), push( new UnmExpr(se(start.get()),expr(pop())) ) ), + Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(se(start.get()),expr(pop())) ) ), + PowExpr() + ) ); } Rule PowExpr() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), SingleExpr(), - Optional( '^', Spaces(), PowExpr(), push( new PowExpr(expr(pop(1)),expr(pop())) ) ) + Optional( '^', Spaces(), PowExpr(), push( new PowExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) ); } @@ -543,8 +583,10 @@ } Rule Function() { + Var<Integer> start = new Var<Integer>(); Var<List<String>> names = new Var<List<String>>(new ArrayList<String>()); return Sequence( + start.set(currentIndex()), '(', incParens(), Spaces(), action( frame = new Frame(frame) ), Optional( @@ -557,7 +599,7 @@ ) ), ')', decParens(), Spaces(), Block(), Keyword("end"), - push( newChunk() ), + push( newChunk(start.get()) ), action( frame = frame.parent ) ); } @@ -570,17 +612,21 @@ } Rule VarArgs() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), "...", Spaces(), frame.isVarArg, - push( VarArgs.INSTANCE ) + push( new VarArgs(se(start.get())) ) ); } Rule TableExpr() { + Var<Integer> start = new Var<Integer>(); Var<List<TableExpr.Field>> fields = new Var<List<TableExpr.Field>>(new ArrayList<TableExpr.Field>()); Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder()); return Sequence( + start.set(currentIndex()), '{', incParens(), Spaces(), Optional( Field(fields,builder), @@ -592,7 +638,7 @@ ), '}', decParens(), Spaces(), - push( new TableExpr( fields.get().toArray(new TableExpr.Field[0]), builder.get().build() ) ) + push( new TableExpr( se(start.get()), fields.get().toArray(new TableExpr.Field[0]), builder.get().build() ) ) ); } @@ -621,14 +667,18 @@ } Rule VarExp() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), Var(), - makeVarExp() + makeVarExp(start.get()) ); } Rule Var() { + Var<Integer> start = new Var<Integer>(); return Sequence( + start.set(currentIndex()), FirstOf( Sequence( '(', incParens(), Spaces(), Expr(), ')', decParens(), Spaces(), @@ -641,12 +691,12 @@ ) ), ZeroOrMore( - makeVarExp(), + makeVarExp(start.get()), FirstOf( SubExpr(), Sequence( '.', Spaces(), NameExpr() ), Sequence( - Args(), + Args(start), push(null) // marker ) ) @@ -657,32 +707,32 @@ Expr env() { int index = stackIndex(_ENV); if( index != -1 ) - return new GetLocalVar(index); + return new GetLocalVar(null,index); index = upValueIndex(_ENV); if( index != -1 ) - return new GetUpVar(index); + return new GetUpVar(null,index); throw new RuntimeException("_ENV not found"); } - boolean makeVarExp() { + boolean makeVarExp(int start) { Object obj2 = pop(); if( obj2==null ) return true; Object obj1 = pop(); if( obj1 != null ) - return push( new IndexExpr( expr(obj1), expr(obj2) ) ); + return push( new IndexExpr( se(start), expr(obj1), expr(obj2) ) ); String name = (String)obj2; int index = stackIndex(name); if( index != -1 ) - return push( new GetLocalVar(index) ); + return push( new GetLocalVar(se(start),index) ); index = upValueIndex(name); if( index != -1 ) - return push( new GetUpVar(index) ); - return push( new IndexExpr( env(), new ConstExpr(name) ) ); + return push( new GetUpVar(se(start),index) ); + return push( new IndexExpr( se(start), env(), new ConstExpr(name) ) ); } // function should be on top of the stack - Rule Args() { + Rule Args(Var<Integer> start) { return Sequence( FirstOf( Sequence( @@ -697,7 +747,7 @@ push( new ExpList.SingleExpList(new ConstExpr(pop())) ) ) ), - push( new FnCall( expr(pop(1)), (Expressions)pop() ) ) + push( new FnCall( se(start.get()), expr(pop(1)), (Expressions)pop() ) ) ); }
--- a/src/luan/interp/LuaStateImpl.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/LuaStateImpl.java Fri Dec 21 10:45:54 2012 +0000 @@ -8,67 +8,24 @@ import luan.LuaFunction; import luan.MetatableGetter; import luan.LuaException; +import luan.LuaElement; -final class LuaStateImpl implements LuaState { - private final LuaTable global = new LuaTable(); - private final List<MetatableGetter> mtGetters = new ArrayList<MetatableGetter>(); - - @Override public LuaTable global() { - return global; - } +final class LuaStateImpl extends LuaState { - @Override public String toString(Object obj) throws LuaException { - LuaFunction fn = getHandlerFunction("__tostring",obj); - if( fn != null ) - return Lua.checkString( Utils.first( fn.call(this,obj) ) ); - if( obj == null ) - return "nil"; - return obj.toString(); + LuaFunction getBinHandler(LuaElement el,String op,Object o1,Object o2) throws LuaException { + LuaFunction f1 = getHandlerFunction(el,op,o1); + if( f1 != null ) + return f1; + return getHandlerFunction(el,op,o2); } - @Override public LuaTable getMetatable(Object obj) { - if( obj instanceof LuaTable ) { - LuaTable table = (LuaTable)obj; - return table.getMetatable(); - } - for( MetatableGetter mg : mtGetters ) { - LuaTable table = mg.getMetatable(obj); - if( table != null ) - return table; - } - return null; - } - - public void addMetatableGetter(MetatableGetter mg) { - mtGetters.add(mg); - } - - Object getHandler(String op,Object obj) throws LuaException { - LuaTable t = getMetatable(obj); - return t==null ? null : t.get(op); - } - - LuaFunction getHandlerFunction(String op,Object obj) throws LuaException { - Object f = getHandler(op,obj); - if( f == null ) - return null; - return Lua.checkFunction(f); - } - - LuaFunction getBinHandler(String op,Object o1,Object o2) throws LuaException { - LuaFunction f1 = getHandlerFunction(op,o1); - if( f1 != null ) - return f1; - return getHandlerFunction(op,o2); - } - - final Object arithmetic(String op,Object o1,Object o2) throws LuaException { - LuaFunction fn = getBinHandler(op,o1,o2); + final Object arithmetic(LuaElement el,String op,Object o1,Object o2) throws LuaException { + LuaFunction fn = getBinHandler(el,op,o1,o2); if( fn != null ) - return Utils.first(fn.call(this,o1,o2)); + return Lua.first(call(fn,el,op,o1,o2)); String type = Lua.toNumber(o1)==null ? Lua.type(o1) : Lua.type(o2); - throw new LuaException("attempt to perform arithmetic on a "+type+" value"); + throw new LuaException(this,el,"attempt to perform arithmetic on a "+type+" value"); }
--- a/src/luan/interp/ModExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/ModExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; final class ModExpr extends BinaryOpExpr { - ModExpr(Expr op1,Expr op2) { - super(op1,op2); + ModExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,6 +19,6 @@ LuaNumber n2 = Lua.toNumber(o2); if( n1 != null && n2 != null ) return new LuaNumber( n1.value() % n2.value() ); - return lua.arithmetic("__mod",o1,o2); + return arithmetic(lua,"__mod",o1,o2); } }
--- a/src/luan/interp/MulExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/MulExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; final class MulExpr extends BinaryOpExpr { - MulExpr(Expr op1,Expr op2) { - super(op1,op2); + MulExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,6 +19,6 @@ LuaNumber n2 = Lua.toNumber(o2); if( n1 != null && n2 != null ) return new LuaNumber( n1.value() * n2.value() ); - return lua.arithmetic("__mul",o1,o2); + return arithmetic(lua,"__mul",o1,o2); } }
--- a/src/luan/interp/NotExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/NotExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -2,12 +2,13 @@ import luan.Lua; import luan.LuaException; +import luan.LuaSource; final class NotExpr extends UnaryOpExpr { - NotExpr(Expr op) { - super(op); + NotExpr(LuaSource.Element se,Expr op) { + super(se,op); } @Override public Object eval(LuaStateImpl lua) throws LuaException {
--- a/src/luan/interp/NumericForStmt.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/NumericForStmt.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,16 +3,18 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; -final class NumericForStmt implements Stmt { +final class NumericForStmt extends CodeImpl implements Stmt { private final int iVar; private final Expr fromExpr; private final Expr toExpr; private final Expr stepExpr; private final Stmt block; - NumericForStmt(int iVar,Expr fromExpr,Expr toExpr,Expr stepExpr,Stmt block) { + NumericForStmt(LuaSource.Element se,int iVar,Expr fromExpr,Expr toExpr,Expr stepExpr,Stmt block) { + super(se); this.iVar = iVar; this.fromExpr = fromExpr; this.toExpr = toExpr; @@ -21,9 +23,9 @@ } @Override public void eval(LuaStateImpl lua) throws LuaException { - double v = Lua.checkNumber( fromExpr.eval(lua) ).value(); - double limit = Lua.checkNumber( toExpr.eval(lua) ).value(); - double step = Lua.checkNumber( stepExpr.eval(lua) ).value(); + double v = lua.checkNumber( se, fromExpr.eval(lua) ).value(); + double limit = lua.checkNumber( se, toExpr.eval(lua) ).value(); + double step = lua.checkNumber( se, stepExpr.eval(lua) ).value(); try { while( step > 0.0 && v <= limit || step < 0.0 && v >= limit ) { lua.stackSet( iVar, new LuaNumber(v) );
--- a/src/luan/interp/OrExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/OrExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -2,12 +2,13 @@ import luan.Lua; import luan.LuaException; +import luan.LuaSource; final class OrExpr extends BinaryOpExpr { - OrExpr(Expr op1,Expr op2) { - super(op1,op2); + OrExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException {
--- a/src/luan/interp/PowExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/PowExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; final class PowExpr extends BinaryOpExpr { - PowExpr(Expr op1,Expr op2) { - super(op1,op2); + PowExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,6 +19,6 @@ LuaNumber n2 = Lua.toNumber(o2); if( n1 != null && n2 != null ) return new LuaNumber( Math.pow( n1.value(), n2.value() ) ); - return lua.arithmetic("__pow",o1,o2); + return arithmetic(lua,"__pow",o1,o2); } }
--- a/src/luan/interp/ReturnStmt.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/ReturnStmt.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,14 +3,16 @@ import luan.Lua; import luan.LuaException; import luan.LuaFunction; +import luan.LuaSource; -final class ReturnStmt implements Stmt { +final class ReturnStmt extends CodeImpl implements Stmt { private final Expressions expressions; private final Expr tailFnExpr; boolean throwReturnException = true; - ReturnStmt(Expressions expressions) { + ReturnStmt(LuaSource.Element se,Expressions expressions) { + super(se); if( expressions instanceof FnCall ) { // tail call FnCall fnCall = (FnCall)expressions; this.expressions = fnCall.args; @@ -24,11 +26,11 @@ @Override public void eval(LuaStateImpl lua) throws LuaException { lua.returnValues = expressions.eval(lua); if( tailFnExpr != null ) { - LuaFunction tailFn = Lua.checkFunction( tailFnExpr.eval(lua) ); + LuaFunction tailFn = lua.checkFunction( se, tailFnExpr.eval(lua) ); if( tailFn instanceof LuaClosure ) { lua.tailFn = (LuaClosure)tailFn; } else { - lua.returnValues = tailFn.call(lua,lua.returnValues); + lua.returnValues = lua.call(tailFn,tailFnExpr.se(),tailFnExpr.se().text(),lua.returnValues); } } if( throwReturnException )
--- a/src/luan/interp/SetTableEntry.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/SetTableEntry.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,13 +4,15 @@ import luan.LuaTable; import luan.Lua; import luan.LuaFunction; +import luan.LuaSource; -final class SetTableEntry implements Settable { +final class SetTableEntry extends CodeImpl implements Settable { private final Expr tableExpr; private final Expr keyExpr; - SetTableEntry(Expr tableExpr,Expr keyExpr) { + SetTableEntry(LuaSource.Element se,Expr tableExpr,Expr keyExpr) { + super(se); this.tableExpr = tableExpr; this.keyExpr = keyExpr; } @@ -19,7 +21,7 @@ newindex( lua, tableExpr.eval(lua), keyExpr.eval(lua), value ); } - private static void newindex(LuaStateImpl lua,Object t,Object key,Object value) throws LuaException { + private void newindex(LuaStateImpl lua,Object t,Object key,Object value) throws LuaException { Object h; if( t instanceof LuaTable ) { LuaTable table = (LuaTable)t; @@ -33,11 +35,11 @@ } else { h = lua.getHandler("__newindex",t); if( h==null ) - throw new LuaException( "attempt to index a " + Lua.type(t) + " value" ); + throw new LuaException( lua, se, "attempt to index a " + Lua.type(t) + " value" ); } if( h instanceof LuaFunction ) { LuaFunction fn = (LuaFunction)h; - fn.call(lua,t,key,value); + lua.call(fn,se,"__newindex",t,key,value); } newindex(lua,h,key,value); }
--- a/src/luan/interp/Stmt.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/Stmt.java Fri Dec 21 10:45:54 2012 +0000 @@ -7,6 +7,6 @@ public void eval(LuaStateImpl lua) throws LuaException; static final Stmt EMPTY = new Stmt() { - public void eval(LuaStateImpl lua) {} + @Override public void eval(LuaStateImpl lua) {} }; }
--- a/src/luan/interp/SubExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/SubExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,12 +3,13 @@ import luan.Lua; import luan.LuaNumber; import luan.LuaException; +import luan.LuaSource; final class SubExpr extends BinaryOpExpr { - SubExpr(Expr op1,Expr op2) { - super(op1,op2); + SubExpr(LuaSource.Element se,Expr op1,Expr op2) { + super(se,op1,op2); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,6 +19,6 @@ LuaNumber n2 = Lua.toNumber(o2); if( n1 != null && n2 != null ) return new LuaNumber( n1.value() - n2.value() ); - return lua.arithmetic("__sub",o1,o2); + return arithmetic(lua,"__sub",o1,o2); } }
--- a/src/luan/interp/TableExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/TableExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -3,9 +3,10 @@ import luan.LuaException; import luan.LuaTable; import luan.LuaNumber; +import luan.LuaSource; -final class TableExpr implements Expr { +final class TableExpr extends CodeImpl implements Expr { static class Field { final Expr key; @@ -20,7 +21,8 @@ private final Field[] fields; private final Expressions expressions; - TableExpr(Field[] fields,Expressions expressions) { + TableExpr(LuaSource.Element se,Field[] fields,Expressions expressions) { + super(se); this.fields = fields; this.expressions = expressions; }
--- a/src/luan/interp/UnaryOpExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/UnaryOpExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,10 +1,13 @@ package luan.interp; +import luan.LuaSource; + -abstract class UnaryOpExpr implements Expr { +abstract class UnaryOpExpr extends CodeImpl implements Expr { final Expr op; - UnaryOpExpr(Expr op) { + UnaryOpExpr(LuaSource.Element se,Expr op) { + super(se); this.op = op; } }
--- a/src/luan/interp/UnmExpr.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/UnmExpr.java Fri Dec 21 10:45:54 2012 +0000 @@ -4,13 +4,14 @@ import luan.LuaNumber; import luan.LuaFunction; import luan.LuaException; +import luan.LuaSource; // unary minus final class UnmExpr extends UnaryOpExpr { - UnmExpr(Expr op) { - super(op); + UnmExpr(LuaSource.Element se,Expr op) { + super(se,op); } @Override public Object eval(LuaStateImpl lua) throws LuaException { @@ -18,9 +19,10 @@ LuaNumber n = Lua.toNumber(o); if( n != null ) return new LuaNumber( -n.value() ); - LuaFunction fn = lua.getHandlerFunction("__unm",o); - if( fn != null ) - return Utils.first(fn.call(lua,o)); - throw new LuaException("attempt to perform arithmetic on a "+Lua.type(o)+" value"); + LuaFunction fn = lua.getHandlerFunction(se,"__unm",o); + if( fn != null ) { + return Lua.first(lua.call(fn,se,"__unm",o)); + } + throw new LuaException(lua,se,"attempt to perform arithmetic on a "+Lua.type(o)+" value"); } }
--- a/src/luan/interp/Utils.java Thu Dec 20 02:54:06 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package luan.interp; - -import luan.Lua; -import luan.LuaFunction; -import luan.LuaTable; -import luan.LuaException; - - -final class Utils { - private Utils() {} // never - - static Object first(Object[] a) { - return a.length==0 ? null : a[0]; - } - -}
--- a/src/luan/interp/VarArgs.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/interp/VarArgs.java Fri Dec 21 10:45:54 2012 +0000 @@ -1,10 +1,13 @@ package luan.interp; +import luan.LuaSource; + -final class VarArgs implements Expressions { - static final VarArgs INSTANCE = new VarArgs(); +final class VarArgs extends CodeImpl implements Expressions { - private VarArgs() {} + VarArgs(LuaSource.Element se) { + super(se); + } @Override public Object[] eval(LuaStateImpl lua) { return lua.varArgs();
--- a/src/luan/lib/BasicLib.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/lib/BasicLib.java Fri Dec 21 10:45:54 2012 +0000 @@ -15,6 +15,8 @@ import luan.LuaFunction; import luan.LuaJavaFunction; import luan.LuaException; +import luan.LuaSource; +import luan.LuaElement; import luan.interp.LuaCompiler; @@ -26,13 +28,13 @@ add( global, "do_file", LuaState.class, String.class ); add( global, "get_metatable", LuaState.class, Object.class ); add( global, "ipairs", LuaTable.class ); - add( global, "load", LuaState.class, String.class ); + add( global, "load", LuaState.class, String.class, String.class ); add( global, "load_file", LuaState.class, String.class ); add( global, "pairs", LuaTable.class ); add( global, "print", LuaState.class, new Object[0].getClass() ); add( global, "raw_equal", Object.class, Object.class ); add( global, "raw_get", LuaTable.class, Object.class ); - add( global, "raw_len", Object.class ); + add( global, "raw_len", LuaState.class, Object.class ); add( global, "raw_set", LuaTable.class, Object.class, Object.class ); add( global, "set_metatable", LuaTable.class, LuaTable.class ); add( global, "to_number", Object.class, Integer.class ); @@ -69,7 +71,7 @@ for( int i=0; i<args.length; i++ ) { if( i > 0 ) System.out.print('\t'); - System.out.print( lua.toString(args[i]) ); + System.out.print( lua.toString(LuaElement.JAVA,args[i]) ); } System.out.println(); } @@ -78,8 +80,8 @@ return Lua.type(obj); } - public static LuaFunction load(LuaState lua,String ld) throws LuaException { - return LuaCompiler.compile(lua,ld); + public static LuaFunction load(LuaState lua,String text,String sourceName) throws LuaException { + return LuaCompiler.compile(lua,new LuaSource(sourceName,text)); } public static String readAll(Reader in) @@ -104,13 +106,18 @@ } - public static LuaFunction load_file(LuaState lua,String fileName) throws LuaException,IOException { - String src = fileName==null ? readAll(new InputStreamReader(System.in)) : read(new File(fileName)); - return load(lua,src); + public static LuaFunction load_file(LuaState lua,String fileName) throws LuaException { + try { + String src = fileName==null ? readAll(new InputStreamReader(System.in)) : read(new File(fileName)); + return load(lua,src,fileName); + } catch(IOException e) { + throw new LuaException(lua,LuaElement.JAVA,e); + } } - public static Object[] do_file(LuaState lua,String fileName) throws LuaException,IOException { - return load_file(lua,fileName).call(lua); + public static Object[] do_file(LuaState lua,String fileName) throws LuaException { + LuaFunction fn = load_file(lua,fileName); + return lua.call(fn,LuaElement.JAVA,null); } private static class TableIter { @@ -197,7 +204,7 @@ return table; } - public static int raw_len(Object v) throws LuaException { + public static int raw_len(LuaState lua,Object v) throws LuaException { if( v instanceof String ) { String s = (String)v; return s.length(); @@ -206,7 +213,7 @@ LuaTable t = (LuaTable)v; return t.length(); } - throw new LuaException( "bad argument #1 to 'raw_len' (table or string expected)" ); + throw new LuaException( lua, LuaElement.JAVA, "bad argument #1 to 'raw_len' (table or string expected)" ); } public static LuaNumber to_number(Object e,Integer base) { @@ -214,6 +221,6 @@ } public static String to_string(LuaState lua,Object v) throws LuaException { - return lua.toString(v); + return lua.toString(LuaElement.JAVA,v); } }
--- a/src/luan/lib/JavaLib.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/lib/JavaLib.java Fri Dec 21 10:45:54 2012 +0000 @@ -18,6 +18,7 @@ import luan.LuaException; import luan.LuaFunction; import luan.LuaJavaFunction; +import luan.LuaElement; public final class JavaLib { @@ -29,17 +30,15 @@ global.put("java",module); try { global.put( "import", new LuaJavaFunction(JavaLib.class.getMethod("importClass",LuaState.class,String.class),null) ); - module.put( "class", new LuaJavaFunction(JavaLib.class.getMethod("getClass",String.class),null) ); + module.put( "class", new LuaJavaFunction(JavaLib.class.getMethod("getClass",LuaState.class,String.class),null) ); } catch(NoSuchMethodException e) { throw new RuntimeException(e); } - add( global, "ipairs", Object.class ); - add( global, "pairs", Object.class ); } private static final LuaTable mt = new LuaTable(); static { - add( mt, "__index", Object.class, Object.class ); + add( mt, "__index", LuaState.class, Object.class, Object.class ); } private static void add(LuaTable t,String method,Class<?>... parameterTypes) { @@ -58,7 +57,7 @@ } }; - public static Object __index(Object obj,Object key) throws LuaException { + public static Object __index(LuaState lua,Object obj,Object key) throws LuaException { if( obj instanceof Static ) { if( key instanceof String ) { String name = (String)key; @@ -86,7 +85,7 @@ } } } - throw new LuaException("invalid index for java class: "+key); + throw new LuaException(lua,LuaElement.JAVA,"invalid index for java class: "+key); } Class cls = obj.getClass(); if( cls.isArray() ) { @@ -101,7 +100,7 @@ return Array.get(obj,i); } } - throw new LuaException("invalid index for java array: "+key); + throw new LuaException(lua,LuaElement.JAVA,"invalid index for java array: "+key); } if( key instanceof String ) { String name = (String)key; @@ -114,7 +113,7 @@ } } } - throw new LuaException("invalid index for java object: "+key); + throw new LuaException(lua,LuaElement.JAVA,"invalid index for java object: "+key); } private static Object member(Object obj,List<Member> members) throws LuaException { @@ -192,16 +191,16 @@ } } - public static Static getClass(String name) throws LuaException { + public static Static getClass(LuaState lua,String name) throws LuaException { try { return new Static( Class.forName(name) ); } catch(ClassNotFoundException e) { - throw new LuaException(e); + throw new LuaException(lua,LuaElement.JAVA,e); } } public static void importClass(LuaState lua,String name) throws LuaException { - lua.global().put( name.substring(name.lastIndexOf('.')+1), getClass(name) ); + lua.global().put( name.substring(name.lastIndexOf('.')+1), getClass(lua,name) ); } static class AmbiguousJavaFunction extends LuaFunction { @@ -219,63 +218,16 @@ } } - @Override public Object[] call(LuaState lua,Object... args) throws LuaException { + @Override public Object[] call(LuaState lua,Object[] args) throws LuaException { for( LuaJavaFunction fn : fnMap.get(args.length) ) { try { return fn.call(lua,args); } catch(IllegalArgumentException e) {} } - throw new LuaException("no method matched args"); + throw new LuaException(lua,LuaElement.JAVA,"no method matched args"); } } - - public static LuaFunction pairs(Object t) throws LuaException { - if( t instanceof LuaTable ) - return BasicLib.pairs((LuaTable)t); - if( t instanceof Map ) { - @SuppressWarnings("unchecked") - Map<Object,Object> m = (Map<Object,Object>)t; - return BasicLib.pairs(m.entrySet().iterator()); - } - throw new LuaException( "bad argument #1 to 'pairs' (table or Map expected)" ); - } - - private static class Iter { - private final Iterator iter; - private double i = 0.0; - - Iter(Iterable t) { - this.iter = t.iterator(); - } - - public Object[] next() { - if( !iter.hasNext() ) - return LuaFunction.EMPTY_RTN ; - return new Object[]{ new LuaNumber(i++), iter.next() }; - } - } - private static final Method nextIter; - static { - try { - nextIter = Iter.class.getMethod("next"); - nextIter.setAccessible(true); - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public static LuaFunction ipairs(Object t) throws LuaException { - if( t instanceof LuaTable ) - return BasicLib.ipairs((LuaTable)t); - if( t instanceof Iterable ) { - Iter ai = new Iter((Iterable)t); - return new LuaJavaFunction(nextIter,ai); - } - throw new LuaException( "bad argument #1 to 'ipairs' (table or Iterable expected)" ); - } - - private static class InstanceOf { private final Object obj;
--- a/src/luan/tools/CmdLine.java Thu Dec 20 02:54:06 2012 +0000 +++ b/src/luan/tools/CmdLine.java Fri Dec 21 10:45:54 2012 +0000 @@ -15,10 +15,11 @@ public class CmdLine { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { LuaState lua = LuaCompiler.newLuaState(); BasicLib.register(lua); JavaLib.register(lua); + BasicLib.make_standard(lua); boolean interactive = false; boolean showVersion = false; int i = 0; @@ -39,15 +40,15 @@ error("'-e' needs argument"); String cmd = args[i]; try { - LuaFunction fn = BasicLib.load(lua,cmd); - fn.call(lua); + LuaFunction fn = BasicLib.load(lua,cmd,"(command line)"); + lua.call(fn,null,null); } catch(LuaException e) { System.err.println("command line error: "+e.getMessage()); System.exit(-1); } } else if( arg.equals("-") ) { try { - BasicLib.do_file(lua,null); + BasicLib.do_file(lua,"stdin"); } catch(LuaException e) { System.err.println(e.getMessage()); System.exit(-1); @@ -72,10 +73,10 @@ lua.global().put("arg",argsTable); try { LuaFunction fn = BasicLib.load_file(lua,file); - fn.call(lua,varArgs); + lua.call(fn,null,null,varArgs); } catch(LuaException e) { -// System.err.println(e.getMessage()); - e.printStackTrace(); + System.err.println(e); +// e.printStackTrace(); System.exit(-1); } } @@ -102,8 +103,8 @@ System.out.print("> "); String input = new Scanner(System.in).nextLine(); try { - LuaFunction fn = BasicLib.load(lua,input); - Object[] rtn = fn.call(lua); + LuaFunction fn = BasicLib.load(lua,input,"stdin"); + Object[] rtn = lua.call(fn,null,null); if( rtn.length > 0 ) BasicLib.print(lua,rtn); } catch(LuaException e) {