More Optimizations
This commit is contained in:
+13
-2
@@ -62,7 +62,8 @@ enum Expr
|
||||
ECall( e : Expr, params : Array<Expr> );
|
||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||
EWhile( cond : Expr, e : Expr );
|
||||
EFor( v : String, it : Expr, e : Expr, ?ithv: String);
|
||||
EFor( v : String, it : Expr, e : Expr);
|
||||
EForKeyValue( v : String, it : Expr, e : Expr, ithv: String);
|
||||
EBreak;
|
||||
EContinue;
|
||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||
@@ -72,7 +73,7 @@ enum Expr
|
||||
ENew( cl : String, params : Array<Expr> );
|
||||
EThrow( e : Expr );
|
||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||
EObject( fl : Array<{ name : String, e : Expr }> );
|
||||
EObject( fl : Array<ObjectField> );
|
||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||
EDoWhile( cond : Expr, e : Expr);
|
||||
@@ -83,6 +84,16 @@ enum Expr
|
||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||
}
|
||||
|
||||
class ObjectField {
|
||||
public var name:String;
|
||||
public var e:Expr;
|
||||
|
||||
public function new(name, e) {
|
||||
this.name = name;
|
||||
this.e = e;
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchCase {
|
||||
public var values : Array<Expr>;
|
||||
public var expr : Expr;
|
||||
|
||||
+65
-25
@@ -341,8 +341,10 @@ class Interp {
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
v = fop(getMapValue(arr, index), expr(e2));
|
||||
setMapValue(arr, index, v);
|
||||
var map = getMap(arr);
|
||||
|
||||
v = fop(map.get(index), expr(e2));
|
||||
map.set(index, v);
|
||||
} else {
|
||||
v = fop(arr[index], expr(e2));
|
||||
arr[index] = v;
|
||||
@@ -694,8 +696,11 @@ class Interp {
|
||||
case EDoWhile(econd, e):
|
||||
doWhileLoop(econd, e);
|
||||
return null;
|
||||
case EFor(v, it, e, ithv):
|
||||
forLoop(v, it, e, ithv);
|
||||
case EFor(v, it, e):
|
||||
forLoop(v, it, e);
|
||||
return null;
|
||||
case EForKeyValue(v, it, e, ithv):
|
||||
forLoopKeyValue(v, it, e, ithv);
|
||||
return null;
|
||||
case EBreak:
|
||||
throw SBreak;
|
||||
@@ -844,7 +849,6 @@ class Interp {
|
||||
}
|
||||
for (n in 0...keys.length) {
|
||||
map.set(keys[n], values[n]);
|
||||
//setMapValue(map, keys[n], values[n]);
|
||||
}
|
||||
return map;
|
||||
} else {
|
||||
@@ -896,7 +900,8 @@ class Interp {
|
||||
case EObject(fl):
|
||||
var o = {};
|
||||
for (f in fl)
|
||||
set(o, f.name, expr(f.e));
|
||||
UnsafeReflect.setField(o, f.name, expr(f.e));
|
||||
//set(o, f.name, expr(f.e));
|
||||
return o;
|
||||
case ETernary(econd, e1, e2):
|
||||
return if (expr(econd) == true) expr(e1) else expr(e2);
|
||||
@@ -919,9 +924,8 @@ class Interp {
|
||||
return val;
|
||||
case EMeta(a, b, e):
|
||||
var oldAccessor = isBypassAccessor;
|
||||
if(a == ":bypassAccessor") {
|
||||
if(a == ":bypassAccessor")
|
||||
isBypassAccessor = true;
|
||||
}
|
||||
var val = expr(e);
|
||||
|
||||
isBypassAccessor = oldAccessor;
|
||||
@@ -968,17 +972,11 @@ class Interp {
|
||||
restore(old);
|
||||
}
|
||||
|
||||
function makeIterator(v:Dynamic, ?allowKeyValue = false):Iterator<Dynamic> {
|
||||
function makeIterator(v:Dynamic):Iterator<Dynamic> {
|
||||
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
||||
if (v.iterator != null)
|
||||
v = v.iterator();
|
||||
#else
|
||||
if(allowKeyValue) {
|
||||
try
|
||||
v = v.keyValueIterator()
|
||||
catch (e:Dynamic) {};
|
||||
}
|
||||
|
||||
if(v.hasNext == null || v.next == null) {
|
||||
try
|
||||
v = v.iterator()
|
||||
@@ -990,20 +988,62 @@ class Interp {
|
||||
return v;
|
||||
}
|
||||
|
||||
function forLoop(n, it, e, ?ithv) {
|
||||
var isKeyValue = ithv != null;
|
||||
function makeKeyValueIterator(v:Dynamic):Iterator<Dynamic> {
|
||||
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
||||
if (v.keyValueIterator != null)
|
||||
v = v.keyValueIterator();
|
||||
|
||||
if (v.iterator != null)
|
||||
v = v.iterator();
|
||||
|
||||
if (v.hasNext == null || v.next == null)
|
||||
error(EInvalidIterator(v));
|
||||
#else
|
||||
try
|
||||
v = v.keyValueIterator()
|
||||
catch (e:Dynamic) {};
|
||||
|
||||
if (v.hasNext == null || v.next == null)
|
||||
v = makeIterator(v);
|
||||
#end
|
||||
return v;
|
||||
}
|
||||
|
||||
function forLoop(n, it, e) {
|
||||
var old = declared.length;
|
||||
if(isKeyValue)
|
||||
declared.push({n: ithv, old: locals.get(ithv), depth: depth});
|
||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||
var it = makeIterator(expr(it), isKeyValue);
|
||||
var it = makeIterator(expr(it));
|
||||
var _hasNext = it.hasNext;
|
||||
var _next = it.next;
|
||||
while (_hasNext()) {
|
||||
var next = _next();
|
||||
if(isKeyValue)
|
||||
locals.set(ithv, {r: next.key, depth: depth});
|
||||
locals.set(n, {r: isKeyValue ? next.value : next, depth: depth});
|
||||
locals.set(n, {r: next, depth: depth});
|
||||
try {
|
||||
expr(e);
|
||||
} catch (err:Stop) {
|
||||
switch (err) {
|
||||
case SContinue:
|
||||
case SBreak:
|
||||
break;
|
||||
case SReturn:
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
restore(old);
|
||||
}
|
||||
|
||||
function forLoopKeyValue(n, it, e, ithv) {
|
||||
var old = declared.length;
|
||||
declared.push({n: ithv, old: locals.get(ithv), depth: depth});
|
||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||
var it = makeKeyValueIterator(expr(it));
|
||||
var _hasNext = it.hasNext;
|
||||
var _next = it.next;
|
||||
while (_hasNext()) {
|
||||
var next = _next();
|
||||
locals.set(ithv, {r: next.key, depth: depth});
|
||||
locals.set(n, {r: next.value, depth: depth});
|
||||
try {
|
||||
expr(e);
|
||||
} catch (err:Stop) {
|
||||
@@ -1043,7 +1083,7 @@ class Interp {
|
||||
|
||||
public var useRedirects:Bool = true;
|
||||
|
||||
static function getClassType(o:Dynamic, ?cls:Class<Any>):String {
|
||||
static function getClassType(o:Dynamic, ?cls:Class<Any>):Null<String> {
|
||||
return switch (Type.typeof(o)) {
|
||||
case TNull: "Null";
|
||||
case TInt: "Int";
|
||||
@@ -1093,6 +1133,7 @@ class Interp {
|
||||
var obj = cast(o, IHScriptCustomBehaviour);
|
||||
return obj.hset(f, v);
|
||||
}
|
||||
// Can use unsafe reflect here, since we checked for null above
|
||||
if(isBypassAccessor) {
|
||||
UnsafeReflect.setField(o, f, v);
|
||||
} else {
|
||||
@@ -1116,7 +1157,6 @@ class Interp {
|
||||
}
|
||||
|
||||
function cnew(cl:String, args:Array<Dynamic>):Dynamic {
|
||||
var cl:String = cast cl;
|
||||
var c:Dynamic = resolve(cl);
|
||||
if (c == null)
|
||||
c = Type.resolveClass(cl);
|
||||
|
||||
+12
-2
@@ -198,14 +198,24 @@ class Macro {
|
||||
EWhile(convert(c), convert(e), false);
|
||||
case EFor(v, it, efor):
|
||||
#if (haxe_ver >= 4)
|
||||
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||
var p:Expr = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||
EFor({ expr : EBinop(OpIn,{ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
|
||||
#elseif (haxe_211 || haxe3)
|
||||
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||
var p:Expr = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
|
||||
#else
|
||||
EFor(v, convert(it), convert(efor));
|
||||
#end
|
||||
case EForKeyValue(v, it, efor, ithv):
|
||||
#if (haxe_ver >= 4)
|
||||
var p:Expr = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||
EFor({ expr : EBinop(OpIn,{ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor), ithv);
|
||||
#elseif (haxe_211 || haxe3)
|
||||
var p:Expr = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor), ithv);
|
||||
#else
|
||||
EFor(v, convert(it), convert(efor), ithv);
|
||||
#end
|
||||
case EBreak:
|
||||
EBreak;
|
||||
case EContinue:
|
||||
|
||||
+23
-17
@@ -288,6 +288,7 @@ class Parser {
|
||||
case EWhile(_,e): isBlock(e);
|
||||
case EDoWhile(_,e): isBlock(e);
|
||||
case EFor(_,_,e): isBlock(e);
|
||||
case EForKeyValue(_,_,e,_): isBlock(e);
|
||||
case EReturn(e): e != null && isBlock(e);
|
||||
case ETry(_, _, _, e): isBlock(e);
|
||||
case EMeta(_, _, e): isBlock(e);
|
||||
@@ -337,7 +338,7 @@ class Parser {
|
||||
break;
|
||||
}
|
||||
ensure(TDoubleDot);
|
||||
fl.push({ name : id, e : parseExpr() });
|
||||
fl.push(new ObjectField(id, parseExpr()));
|
||||
tk = token();
|
||||
switch( tk ) {
|
||||
case TBrClose:
|
||||
@@ -481,7 +482,7 @@ class Parser {
|
||||
}
|
||||
if( a.length == 1 && a[0] != null ) // What is this for???
|
||||
switch( expr(a[0]) ) {
|
||||
case EFor(_), EWhile(_), EDoWhile(_):
|
||||
case EFor(_), EForKeyValue(_), EWhile(_), EDoWhile(_):
|
||||
var tmp = "__a_" + (uid++);
|
||||
var e = mk(EBlock([
|
||||
mk(EVar(tmp, null, mk(EArrayDecl([]), p1)), p1),
|
||||
@@ -547,20 +548,22 @@ class Parser {
|
||||
function mapCompr( tmp : String, e : Expr ) {
|
||||
if( e == null ) return null;
|
||||
var edef = switch( expr(e) ) {
|
||||
case EFor(v, it, e2, ithv):
|
||||
EFor(v, it, mapCompr(tmp, e2), ithv);
|
||||
case EWhile(cond, e2):
|
||||
EWhile(cond, mapCompr(tmp, e2));
|
||||
case EDoWhile(cond, e2):
|
||||
EDoWhile(cond, mapCompr(tmp, e2));
|
||||
case EIf(cond, e1, e2) if( e2 == null ):
|
||||
EIf(cond, mapCompr(tmp, e1), null);
|
||||
case EBlock([e]):
|
||||
EBlock([mapCompr(tmp, e)]);
|
||||
case EParent(e2):
|
||||
EParent(mapCompr(tmp, e2));
|
||||
default:
|
||||
ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "push"), pmin(e), pmax(e)), [e]);
|
||||
case EFor(v, it, e2):
|
||||
EFor(v, it, mapCompr(tmp, e2));
|
||||
case EForKeyValue(v, it, e2, ithv):
|
||||
EForKeyValue(v, it, mapCompr(tmp, e2), ithv);
|
||||
case EWhile(cond, e2):
|
||||
EWhile(cond, mapCompr(tmp, e2));
|
||||
case EDoWhile(cond, e2):
|
||||
EDoWhile(cond, mapCompr(tmp, e2));
|
||||
case EIf(cond, e1, e2) if( e2 == null ):
|
||||
EIf(cond, mapCompr(tmp, e1), null);
|
||||
case EBlock([e]):
|
||||
EBlock([mapCompr(tmp, e)]);
|
||||
case EParent(e2):
|
||||
EParent(mapCompr(tmp, e2));
|
||||
default:
|
||||
ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "push"), pmin(e), pmax(e)), [e]);
|
||||
}
|
||||
return mk(edef, pmin(e), pmax(e));
|
||||
}
|
||||
@@ -759,7 +762,10 @@ class Parser {
|
||||
var eiter = parseExpr();
|
||||
ensure(TPClose);
|
||||
var e = parseExpr();
|
||||
mk(EFor(vname,eiter,e,ithv),p1,pmax(e));
|
||||
if(ithv != null)
|
||||
mk(EForKeyValue(vname,eiter,e,ithv),p1,pmax(e));
|
||||
else
|
||||
mk(EFor(vname,eiter,e),p1,pmax(e));
|
||||
case "break": mk(EBreak);
|
||||
case "continue": mk(EContinue);
|
||||
case "else": unexpected(TId(id));
|
||||
|
||||
+7
-5
@@ -217,11 +217,13 @@ class Printer {
|
||||
add(" while ( ");
|
||||
expr(cond);
|
||||
add(" )");
|
||||
case EFor(v, it, e, ithv):
|
||||
if(ithv != null)
|
||||
add("for( "+ithv+" => "+v+" in ");
|
||||
else
|
||||
add("for( "+v+" in ");
|
||||
case EFor(v, it, e):
|
||||
add("for( "+v+" in ");
|
||||
expr(it);
|
||||
add(" ) ");
|
||||
expr(e);
|
||||
case EForKeyValue(v, it, e, ithv):
|
||||
add("for( "+ithv+" => "+v+" in ");
|
||||
expr(it);
|
||||
add(" ) ");
|
||||
expr(e);
|
||||
|
||||
+3
-1
@@ -40,6 +40,7 @@ class Tools {
|
||||
case EWhile(c, e): f(c); f(e);
|
||||
case EDoWhile(c, e): f(c); f(e);
|
||||
case EFor(_, it, e): f(it); f(e);
|
||||
case EForKeyValue(_, it, e, _): f(it); f(e);
|
||||
case EBreak,EContinue:
|
||||
case EFunction(_, e, _, _): f(e);
|
||||
case EReturn(e): if( e != null ) f(e);
|
||||
@@ -77,6 +78,7 @@ class Tools {
|
||||
case EWhile(c, e): EWhile(f(c),f(e));
|
||||
case EDoWhile(c, e): EDoWhile(f(c),f(e));
|
||||
case EFor(v, it, e): EFor(v, f(it), f(e));
|
||||
case EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
||||
case EFunction(args, e, name, t): EFunction(args, f(e), name, t);
|
||||
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
||||
case EArray(e, i): EArray(f(e),f(i));
|
||||
@@ -84,7 +86,7 @@ class Tools {
|
||||
case ENew(cl,el): ENew(cl,[for( e in el ) f(e)]);
|
||||
case EThrow(e): EThrow(f(e));
|
||||
case ETry(e, v, t, c): ETry(f(e), v, t, f(c));
|
||||
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : f(fi.e) }]);
|
||||
case EObject(fl): EObject([for( fi in fl ) new ObjectField(fi.name, f(fi.e))]);
|
||||
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
|
||||
case ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) new SwitchCase([for( v in c.values ) f(v)], f(c.expr))], def == null ? null : f(def));
|
||||
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
||||
|
||||
@@ -29,6 +29,8 @@ class ListCase extends TestCase {
|
||||
assertEq("[for (k=>v in l4) k]", [for (k=>v in l4) k]);
|
||||
assertEq("[for (k=>v in l4) v]", [for (k=>v in l4) v]);
|
||||
assertEq("[for (k=>v in l4) k*v]", [for (k=>v in l4) k*v]);
|
||||
|
||||
assertEq("[for (v in l4) v]", [for (v in l4) v]);
|
||||
}
|
||||
|
||||
override function teardown() {
|
||||
|
||||
Reference in New Issue
Block a user