More Optimizations

This commit is contained in:
NeeEoo
2024-04-23 16:52:26 +02:00
parent a16e74dee6
commit a727148447
7 changed files with 125 additions and 52 deletions
+13 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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));
+2
View File
@@ -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() {