Mercurial Hosting > luan
changeset 650:d658eab7bf4c
finish compiling operators
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 31 Mar 2016 22:43:51 -0600 |
parents | 37f0cf43f191 |
children | 140cc5191b7a |
files | core/src/luan/impl/$Luan.java core/src/luan/impl/LuanJavaCompiler.java core/src/luan/impl/LuanParser.java |
diffstat | 3 files changed, 215 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
diff -r 37f0cf43f191 -r d658eab7bf4c core/src/luan/impl/$Luan.java --- a/core/src/luan/impl/$Luan.java Wed Mar 30 22:42:27 2016 -0600 +++ b/core/src/luan/impl/$Luan.java Thu Mar 31 22:43:51 2016 -0600 @@ -1,5 +1,6 @@ package luan.impl; +import java.util.Arrays; import java.util.List; import java.util.ArrayList; import luan.Luan; @@ -58,8 +59,120 @@ throw new LuanException("attempt to perform arithmetic on a "+Luan.type(o)+" value"); } - public static Boolean not(Object o) throws LuanException { + public static boolean not(Object o) throws LuanException { return !Luan.checkBoolean(o); } + private static Object arithmetic(LuanState luan,String op,Object o1,Object o2) throws LuanException { + LuanFunction fn = Luan.getBinHandler(op,o1,o2); + if( fn != null ) + return Luan.first(fn.call(luan,new Object[]{o1,o2})); + String type = !(o1 instanceof Number) ? Luan.type(o1) : Luan.type(o2); + throw new LuanException("attempt to perform arithmetic on a "+type+" value"); + } + + public static Object pow(LuanState luan,Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) + return Math.pow( ((Number)o1).doubleValue(), ((Number)o2).doubleValue() ); + return arithmetic(luan,"__pow",o1,o2); + } + + public static Object mul(LuanState luan,Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) + return ((Number)o1).doubleValue() * ((Number)o2).doubleValue(); + return arithmetic(luan,"__mul",o1,o2); + } + + public static Object div(LuanState luan,Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) + return ((Number)o1).doubleValue() / ((Number)o2).doubleValue(); + return arithmetic(luan,"__div",o1,o2); + } + + public static Object mod(LuanState luan,Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) { + double d1 = ((Number)o1).doubleValue(); + double d2 = ((Number)o2).doubleValue(); + return d1 - Math.floor(d1/d2)*d2; + } + return arithmetic(luan,"__mod",o1,o2); + } + + public static Object add(LuanState luan,Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) + return ((Number)o1).doubleValue() + ((Number)o2).doubleValue(); + return arithmetic(luan,"__add",o1,o2); + } + + public static Object sub(LuanState luan,Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) + return ((Number)o1).doubleValue() - ((Number)o2).doubleValue(); + return arithmetic(luan,"__sub",o1,o2); + } + + public static Object concat(LuanState luan,Object o1,Object o2) throws LuanException { + LuanFunction fn = Luan.getBinHandler("__concat",o1,o2); + if( fn != null ) + return Luan.first(fn.call(luan,new Object[]{o1,o2})); + String s1 = luan.toString(o1); + String s2 = luan.toString(o2); + return s1 + s2; + } + + public static boolean eq(LuanState luan,Object o1,Object o2) throws LuanException { + 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 instanceof byte[] && o2 instanceof byte[] ) { + byte[] b1 = (byte[])o1; + byte[] b2 = (byte[])o2; + return Arrays.equals(b1,b2); + } + if( !(o1 instanceof LuanTable && o2 instanceof LuanTable) ) + return false; + LuanTable t1 = (LuanTable)o1; + LuanTable t2 = (LuanTable)o2; + LuanTable mt1 = t1.getMetatable(); + LuanTable mt2 = t2.getMetatable(); + if( mt1==null || mt2==null ) + return false; + Object f = mt1.rawGet("__eq"); + if( f == null || !f.equals(mt2.rawGet("__eq")) ) + return false; + LuanFunction fn = Luan.checkFunction(f); + return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) ); + } + + public static boolean le(LuanState luan,Object o1,Object o2) throws LuanException { + 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; + } + LuanFunction fn = Luan.getBinHandler("__le",o1,o2); + if( fn != null ) + return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) ); + fn = Luan.getBinHandler("__lt",o1,o2); + if( fn != null ) + return !Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o2,o1})) ); + throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); + } + + public static boolean lt(LuanState luan,Object o1,Object o2) throws LuanException { + return Luan.isLessThan(luan,o1,o2); + } + + public static boolean cnd(Object o) throws LuanException { + return !(o == null || Boolean.FALSE.equals(o)); + } + }
diff -r 37f0cf43f191 -r d658eab7bf4c core/src/luan/impl/LuanJavaCompiler.java --- a/core/src/luan/impl/LuanJavaCompiler.java Wed Mar 30 22:42:27 2016 -0600 +++ b/core/src/luan/impl/LuanJavaCompiler.java Thu Mar 31 22:43:51 2016 -0600 @@ -57,8 +57,8 @@ outer: for( int i=0; true; i++ ) { if( i > max ) - throw new RuntimeException(); - if( byteCode[i]==1 && byteCode[i+1]*256 + byteCode[i+2] == len ) { + throw new RuntimeException("len="+len); + if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) { for( int j=i+3; j<i+3+len; j++ ) { if( byteCode[j] != '$' ) continue outer;
diff -r 37f0cf43f191 -r d658eab7bf4c core/src/luan/impl/LuanParser.java --- a/core/src/luan/impl/LuanParser.java Wed Mar 30 22:42:27 2016 -0600 +++ b/core/src/luan/impl/LuanParser.java Thu Mar 31 22:43:51 2016 -0600 @@ -181,7 +181,7 @@ FnDef Expression() throws ParseException { Spaces(In.NOTHING); int start = parser.begin(); - Expressions expr = ExprZ(In.NOTHING); + Expressions expr = exp(ExprZ(In.NOTHING)); if( expr != null && parser.endOfInput() ) { Stmt stmt = new ReturnStmt( expr ); return parser.success(newFnDef(start,stmt)); @@ -279,7 +279,7 @@ while(true) { if( parser.match( "<%=" ) ) { Spaces(inTemplate); - builder.add( RequiredExpr(inTemplate) ); + builder.add( exp(RequiredExpr(inTemplate)) ); RequiredMatch( "%>" ); } else if( parser.match( "<%" ) ) { Spaces(inTemplate); @@ -355,7 +355,7 @@ List<String> names = RequiredNameList(In.NOTHING); if( !Keyword("in",In.NOTHING) ) return parser.failure(null); - Expr expr = expr(RequiredExpr(In.NOTHING)); + Expr expr = expr(exp(RequiredExpr(In.NOTHING))); RequiredKeyword("do",In.NOTHING); addSymbols(names); Stmt loop = RequiredLoopBlock(); @@ -435,7 +435,7 @@ parser.begin(); if( !Keyword("while",In.NOTHING) ) return parser.failure(null); - Expr cnd = expr(RequiredExpr(In.NOTHING)); + Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); RequiredKeyword("do",In.NOTHING); Stmt loop = RequiredLoopBlock(); RequiredKeyword("end",In.NOTHING); @@ -448,7 +448,7 @@ return parser.failure(null); Stmt loop = RequiredLoopBlock(); RequiredKeyword("until",In.NOTHING); - Expr cnd = expr(RequiredExpr(In.NOTHING)); + Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); return parser.success( new RepeatStmt(loop,cnd) ); } @@ -468,7 +468,7 @@ private Stmt IfStmt2() throws ParseException { parser.currentIndex(); - Expr cnd = expr(RequiredExpr(In.NOTHING)); + Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); RequiredKeyword("then",In.NOTHING); Stmt thenBlock = RequiredBlock(); Stmt elseBlock; @@ -507,7 +507,7 @@ private Stmt ExpressionsStmt() throws ParseException { parser.begin(); - Expressions exp = ExprZ(In.NOTHING); + Expressions exp = exp(ExprZ(In.NOTHING)); if( exp instanceof StmtExp ) return parser.success( new ExpressionsStmt(exp) ); return parser.failure(null); @@ -521,102 +521,124 @@ return parser.success( var.settable() ); } - private Expressions RequiredExpr(In in) throws ParseException { + private ExpString RequiredExpr(In in) throws ParseException { parser.begin(); return parser.success(required(ExprZ(in),"Bad expression")); } - private Expressions ExprZ(In in) throws ParseException { + private ExpString ExprZ(In in) throws ParseException { return OrExpr(in); } - private Expressions OrExpr(In in) throws ParseException { + private ExpString OrExpr(In in) throws ParseException { parser.begin(); - Expressions exp = AndExpr(in); + ExpString exp = AndExpr(in); if( exp==null ) return parser.failure(null); while( Keyword("or",in) ) { - Expressions exp2 = AndExpr(in); - exp = new OrExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(RelExpr(in)).expr(); + String code = "($Luan.cnd($cnd = " + exp.code + ") ? $cnd : (" + exp2.code + "))"; + exp = new ExpString(code,true,true); } return parser.success(exp); } - private Expressions AndExpr(In in) throws ParseException { + private ExpString AndExpr(In in) throws ParseException { parser.begin(); - Expressions exp = RelExpr(in); + ExpString exp = RelExpr(in); if( exp==null ) return parser.failure(null); while( Keyword("and",in) ) { - Expressions exp2 = RelExpr(in); - exp = new AndExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(RelExpr(in)).expr(); + String code = "($Luan.cnd($cnd = " + exp.code + ") ? (" + exp2.code + ") : $cnd)"; + exp = new ExpString(code,true,true); } return parser.success(exp); } - private Expressions RelExpr(In in) throws ParseException { + private ExpString RelExpr(In in) throws ParseException { parser.begin(); - Expressions exp = ConcatExpr(in); + ExpString exp = ConcatExpr(in); if( exp==null ) return parser.failure(null); while(true) { if( parser.match("==") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new EqExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "$Luan.eq($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else if( parser.match("~=") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new NotExpr( new EqExpr( expr(exp), required(expr(exp2)) ) ); + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "!$Luan.eq($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else if( parser.match("<=") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new LeExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "$Luan.le($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else if( parser.match(">=") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new LeExpr( required(expr(exp2)), expr(exp) ); + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "$Luan.le($luan," + exp2.code + "," + exp.code + ")"; + exp = new ExpString(code,true,false); } else if( parser.match("<") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new LtExpr( expr(exp), required(expr(exp2)) ); - } else if( parser.match(">") ) { + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "$Luan.lt($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); + } else if( parser.match(">") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new LtExpr( required(expr(exp2)), expr(exp) ); + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "$Luan.lt($luan," + exp2.code + "," + exp.code + ")"; + exp = new ExpString(code,true,false); } else break; } return parser.success(exp); } - private Expressions ConcatExpr(In in) throws ParseException { + private ExpString ConcatExpr(In in) throws ParseException { parser.begin(); - Expressions exp = SumExpr(in); + ExpString exp = SumExpr(in); if( exp==null ) return parser.failure(null); if( parser.match("..") ) { Spaces(in); - Expressions exp2 = ConcatExpr(in); - exp = new ConcatExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(ConcatExpr(in)).expr(); + String code = "$Luan.concat($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } return parser.success(exp); } - private Expressions SumExpr(In in) throws ParseException { + private ExpString SumExpr(In in) throws ParseException { parser.begin(); - Expressions exp = TermExpr(in); + ExpString exp = TermExpr(in); if( exp==null ) return parser.failure(null); while(true) { if( parser.match('+') ) { Spaces(in); - Expressions exp2 = TermExpr(in); - exp = new AddExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(TermExpr(in)).expr(); + String code = "$Luan.add($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else if( Minus() ) { Spaces(in); - Expressions exp2 = TermExpr(in); - exp = new SubExpr( expr(exp), required(expr(exp2)) ); + exp = exp.expr(); + ExpString exp2 = required(TermExpr(in)).expr(); + String code = "$Luan.sub($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else break; } @@ -628,25 +650,30 @@ return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); } - private Expressions TermExpr(In in) throws ParseException { + private ExpString TermExpr(In in) throws ParseException { parser.begin(); - ExpString expStr = UnaryExpr(in); - if( expStr==null ) + ExpString exp = UnaryExpr(in); + if( exp==null ) return parser.failure(null); - Expressions exp = expStr.toExpressions(); while(true) { if( parser.match('*') ) { Spaces(in); - Expressions exp2 = required(UnaryExpr(in)).toExpressions(); - exp = new MulExpr( expr(exp), expr(exp2) ); + exp = exp.expr(); + ExpString exp2 = required(UnaryExpr(in)).expr(); + String code = "$Luan.mul($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else if( parser.match('/') ) { Spaces(in); - Expressions exp2 = required(UnaryExpr(in)).toExpressions(); - exp = new DivExpr( expr(exp), expr(exp2) ); + exp = exp.expr(); + ExpString exp2 = required(UnaryExpr(in)).expr(); + String code = "$Luan.div($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else if( Mod() ) { Spaces(in); - Expressions exp2 = required(UnaryExpr(in)).toExpressions(); - exp = new ModExpr( expr(exp), expr(exp2) ); + exp = exp.expr(); + ExpString exp2 = required(UnaryExpr(in)).expr(); + String code = "$Luan.mod($luan," + exp.code + "," + exp2.code + ")"; + exp = new ExpString(code,true,false); } else break; } @@ -681,23 +708,25 @@ exp = new ExpString(code,true,false); return parser.success(exp); } - Expressions exp = PowExpr(in); + ExpString exp = PowExpr(in); if( exp==null ) return parser.failure(null); - return parser.success(new ExpString(exp)); + return parser.success(exp); } - private Expressions PowExpr(In in) throws ParseException { + private ExpString PowExpr(In in) throws ParseException { parser.begin(); Expressions exp = SingleExpr(in); if( exp==null ) return parser.failure(null); + ExpString exp1 = new ExpString(exp); if( parser.match('^') ) { Spaces(in); - Expressions exp2 = PowExpr(in); - exp = new PowExpr( expr(exp), required(expr(exp2)) ); + ExpString exp2 = required(PowExpr(in)); + String code = "$Luan.pow($luan," + exp1.code + "," + exp2.code + ")"; + exp1 = new ExpString(code,true,false); } - return parser.success(exp); + return parser.success(exp1); } private Expressions SingleExpr(In in) throws ParseException { @@ -790,11 +819,11 @@ exp = NameExpr(In.NOTHING); if( exp!=null && parser.match('=') ) { Spaces(In.NOTHING); - fields.add( new TableExpr.Field( exp, required(expr(ExprZ(In.NOTHING))) ) ); + fields.add( new TableExpr.Field( exp, required(expr(exp(ExprZ(In.NOTHING)))) ) ); return parser.success(); } parser.rollback(); - Expressions exprs = ExprZ(In.NOTHING); + Expressions exprs = exp(ExprZ(In.NOTHING)); if( exprs != null ) { builder.add(exprs); return parser.success(); @@ -823,7 +852,7 @@ if( parser.match('(') ) { In inParens = in.parens(); Spaces(inParens); - Expr exp = expr(RequiredExpr(inParens)); + Expr exp = expr(exp(RequiredExpr(inParens))); RequiredMatch(')'); Spaces(in); return exprVar(exp); @@ -983,7 +1012,7 @@ builder.add(exp); return parser.success(); } - exp = ExprZ(in); + exp = exp(ExprZ(in)); if( exp==null ) return parser.failure(); builder.add(exp); @@ -994,7 +1023,7 @@ builder.add(exp); return parser.success(); } - builder.add( RequiredExpr(in) ); + builder.add( exp(RequiredExpr(in)) ); } return parser.success(); } @@ -1004,7 +1033,7 @@ if( !parser.match('[') || parser.test("[") || parser.test("=") ) return parser.failure(null); Spaces(In.NOTHING); - Expr exp = expr(RequiredExpr(In.NOTHING)); + Expr exp = expr(exp(RequiredExpr(In.NOTHING))); RequiredMatch(']'); Spaces(in); return parser.success(exp); @@ -1379,7 +1408,7 @@ } ExpString expr() { - return isExpr ? this : new ExpString( "$Luan.first(" + code + ")", true, false ); + return isExpr ? this : new ExpString( "$Luan.first(" + code + ")", true, isStmt ); } Expressions toExpressions() { @@ -1391,6 +1420,7 @@ +"\n" +"public class " + className +" implements " + superClass + " {\n" +" @Override public Object eval(LuanStateImpl $luan) throws LuanException {\n" + +" Object $cnd;\n" +" return " + code + ";\n" +" }\n" +"}\n" @@ -1409,4 +1439,8 @@ } } + private static Expressions exp(ExpString expStr) { + return expStr==null ? null : expStr.toExpressions(); + } + }