From 4eb64866003cefce0a6e8089bc69b14c7cabcb8c Mon Sep 17 00:00:00 2001 From: Nicolas Cannasse Date: Mon, 7 Jul 2008 17:15:10 +0000 Subject: [PATCH] added += and other assign-ops added EInvalidAccess when null object added ?: expression --- Test.hx | 6 +++--- haxelib.xml | 2 +- hscript/Expr.hx | 1 + hscript/Interp.hx | 44 ++++++++++++++++++++++++++++++++++++++++++++ hscript/Parser.hx | 12 ++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/Test.hx b/Test.hx index a9b2ce2..030faea 100644 --- a/Test.hx +++ b/Test.hx @@ -4,7 +4,7 @@ class Test { var script = " var sum = 0; for( a in angles ) - sum = sum + Math.cos(a); + sum += Math.cos(a); sum; "; var p = new hscript.Parser(); @@ -20,7 +20,7 @@ class Test { return Math.cos(a); } function bar(x) { - sum = sum + foo(x); + sum += foo(x); } for( x in angles ) bar(x); @@ -34,7 +34,7 @@ class Test { var i = 0; var sum = 0; while( i < angles.length ) - sum = sum + Math.cos(angles[i++]); + sum += Math.cos(angles[i++]); sum; "; var program = p.parseString(script); diff --git a/haxelib.xml b/haxelib.xml index 0c4d5ae..10d7528 100644 --- a/haxelib.xml +++ b/haxelib.xml @@ -1,5 +1,5 @@ haXe Script is a scripting engine for a subset of the haXe language - Added functions, return, arrays + Added += and ?: \ No newline at end of file diff --git a/hscript/Expr.hx b/hscript/Expr.hx index b2e7b3c..79cf8c2 100644 --- a/hscript/Expr.hx +++ b/hscript/Expr.hx @@ -58,4 +58,5 @@ enum Error { EUnknownVariable( v : String ); EInvalidIterator( v : String ); EInvalidOp( op : String ); + EInvalidAccess( f : String ); } diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 9ae9482..8ba4479 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -70,6 +70,17 @@ class Interp { binops.set("||",function(e1,e2) return me.expr(e1) == true || me.expr(e2) == true); binops.set("&&",function(e1,e2) return me.expr(e1) == true && me.expr(e2) == true); binops.set("=",assign); + assignOp("+=",function(v1:Dynamic,v2:Dynamic) return v1 + v2); + assignOp("-=",function(v1:Float,v2:Float) return v1 - v2); + assignOp("*=",function(v1:Float,v2:Float) return v1 * v2); + assignOp("/=",function(v1:Float,v2:Float) return v1 / v2); + assignOp("%=",function(v1:Float,v2:Float) return v1 % v2); + assignOp("&=",function(v1,v2) return v1 & v2); + assignOp("|=",function(v1,v2) return v1 | v2); + assignOp("^=",function(v1,v2) return v1 ^ v2); + assignOp("<<=",function(v1,v2) return v1 << v2); + assignOp(">>=",function(v1,v2) return v1 >> v2); + assignOp(">>>=",function(v1,v2) return v1 >>> v2); } function assign( e1 : Expr, e2 : Expr ) { @@ -90,6 +101,36 @@ class Interp { return v; } + function assignOp( op, fop ) { + var me = this; + binops.set(op,function(e1,e2) return me.evalAssignOp(op,fop,e1,e2)); + } + + function evalAssignOp(op,fop,e1,e2) : Dynamic { + var v; + switch( e1 ) { + case EIdent(id): + var l = locals.get(id); + v = fop(expr(e1),expr(e2)); + if( l == null ) + variables.set(id,v) + else + l.r = v; + case EField(e,f): + var obj = expr(e); + v = fop(get(obj,f),expr(e2)); + v = set(obj,f,v); + case EArray(e,index): + var arr = expr(e); + var index = expr(index); + v = fop(arr[index],expr(e2)); + arr[index] = v; + default: + throw Error.EInvalidOp(op); + } + return v; + } + function increment( e : Expr, prefix : Bool, delta : Int ) : Dynamic { switch(e) { case EIdent(id): @@ -212,6 +253,7 @@ class Interp { switch(e) { case EField(e,f): var obj = expr(e); + if( obj == null ) throw Error.EInvalidAccess(f); return call(obj,Reflect.field(obj,f),args); default: return call(null,expr(e),args); @@ -293,10 +335,12 @@ class Interp { } function get( o : Dynamic, f : String ) { + if( o == null ) throw Error.EInvalidAccess(f); return Reflect.field(o,f); } function set( o : Dynamic, f : String, v : Dynamic ) { + if( o == null ) throw Error.EInvalidAccess(f); Reflect.setField(o,f,v); return v; } diff --git a/hscript/Parser.hx b/hscript/Parser.hx index 97a42da..8210092 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -39,6 +39,8 @@ enum Token { TSemicolon; TBkOpen; TBkClose; + TQuestion; + TDoubleDot; } class Parser { @@ -283,6 +285,12 @@ class Parser { tk = token(s); if( tk != TBkClose ) unexpected(tk); return parseExprNext(s,EArray(e1,e2)); + case TQuestion: + var e2 = parseExpr(s); + tk = token(s); + if( tk != TDoubleDot ) unexpected(tk); + var e3 = parseExpr(s); + return EIf(e1,e2,e3); default: tokens.add(tk); return e1; @@ -387,6 +395,8 @@ class Parser { case 93: return TBkClose; case 39: return TConst( CString(readString(s,39)) ); case 34: return TConst( CString(readString(s,34)) ); + case 63: return TQuestion; + case 58: return TDoubleDot; default: if( ops[char] ) { var op = Std.chr(char); @@ -440,6 +450,8 @@ class Parser { case TSemicolon: ";"; case TBkOpen: "["; case TBkClose: "]"; + case TQuestion: "?"; + case TDoubleDot: ":"; } }