we spent like 5 hours
Co-authored-by: Ne_Eo <NeeEoo@users.noreply.github.com>
This commit is contained in:
@@ -29,6 +29,7 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function hnew(args:Array<Dynamic>):Dynamic {
|
public function hnew(args:Array<Dynamic>):Dynamic {
|
||||||
|
/*
|
||||||
var interp = new Interp();
|
var interp = new Interp();
|
||||||
interp.errorHandler = ogInterp.errorHandler;
|
interp.errorHandler = ogInterp.errorHandler;
|
||||||
|
|
||||||
@@ -78,8 +79,9 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
if(newFunc != null) {
|
if(newFunc != null) {
|
||||||
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return _class;
|
throw "todo: do all this lmao -lunar";
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toString():String {
|
public function toString():String {
|
||||||
|
|||||||
+192
-12
@@ -62,28 +62,28 @@ enum Expr
|
|||||||
#end
|
#end
|
||||||
{
|
{
|
||||||
EConst( c : Const );
|
EConst( c : Const );
|
||||||
EIdent( v : String , ?vid : Int);
|
EIdent( v : VarN );
|
||||||
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool , ?vid : Int);
|
EVar( n : VarN, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
||||||
EParent( e : Expr, ?noOptimize : Bool );
|
EParent( e : Expr, ?noOptimize : Bool );
|
||||||
EBlock( e : Array<Expr> );
|
EBlock( e : Array<Expr> );
|
||||||
EField( e : Expr, f : String , ?safe : Bool );
|
EField( e : Expr, f : String , ?safe : Bool );
|
||||||
EBinop( op : String, e1 : Expr, e2 : Expr );
|
EBinop( op : Binop, e1 : Expr, e2 : Expr );
|
||||||
EUnop( op : String, prefix : Bool, e : Expr );
|
EUnop( op : Unop, prefix : Bool, e : Expr );
|
||||||
ECall( e : Expr, params : Array<Expr> );
|
ECall( e : Expr, params : Array<Expr> );
|
||||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||||
EWhile( cond : Expr, e : Expr );
|
EWhile( cond : Expr, e : Expr );
|
||||||
EFor( v : String, it : Expr, e : Expr);
|
EFor( v : VarN, it : Expr, e : Expr);
|
||||||
EForKeyValue( v : String, it : Expr, e : Expr, ithv: String);
|
EForKeyValue( v : VarN, it : Expr, e : Expr, ithv: VarN);
|
||||||
EBreak;
|
EBreak;
|
||||||
EContinue;
|
EContinue;
|
||||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool , ?fid : Int);
|
EFunction( args : Array<Argument>, e : Expr, ?name : VarN, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||||
EReturn( ?e : Expr );
|
EReturn( ?e : Expr );
|
||||||
EArray( e : Expr, index : Expr );
|
EArray( e : Expr, index : Expr );
|
||||||
EMapDecl( type: MapType, keys: Array<Expr>, values: Array<Expr> );
|
EMapDecl( type: MapType, keys: Array<Expr>, values: Array<Expr> );
|
||||||
EArrayDecl( e : Array<Expr> );
|
EArrayDecl( e : Array<Expr> );
|
||||||
ENew( cl : String, params : Array<Expr> , ?cid : Int);
|
ENew( cl : VarN, params : Array<Expr> );
|
||||||
EThrow( e : Expr );
|
EThrow( e : Expr );
|
||||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
ETry( e : Expr, v : VarN, t : Null<CType>, ecatch : Expr );
|
||||||
EObject( fl : Array<ObjectField> );
|
EObject( fl : Array<ObjectField> );
|
||||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||||
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||||
@@ -92,12 +92,182 @@ enum Expr
|
|||||||
ECheckType( e : Expr, t : CType );
|
ECheckType( e : Expr, t : CType );
|
||||||
|
|
||||||
EImport( c : String, mode: KImportMode );
|
EImport( c : String, mode: KImportMode );
|
||||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> , ?cid : Int );
|
EClass( name:VarN, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||||
|
|
||||||
|
EInfo( info: InfoClass, e: Expr );
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Binop {
|
||||||
|
/**
|
||||||
|
`+`
|
||||||
|
**/
|
||||||
|
OpAdd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`*`
|
||||||
|
**/
|
||||||
|
OpMult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`/`
|
||||||
|
**/
|
||||||
|
OpDiv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`-`
|
||||||
|
**/
|
||||||
|
OpSub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`=`
|
||||||
|
**/
|
||||||
|
OpAssign;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`==`
|
||||||
|
**/
|
||||||
|
OpEq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`!=`
|
||||||
|
**/
|
||||||
|
OpNotEq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`>`
|
||||||
|
**/
|
||||||
|
OpGt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`>=`
|
||||||
|
**/
|
||||||
|
OpGte;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`<`
|
||||||
|
**/
|
||||||
|
OpLt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`<=`
|
||||||
|
**/
|
||||||
|
OpLte;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`&`
|
||||||
|
**/
|
||||||
|
OpAnd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`|`
|
||||||
|
**/
|
||||||
|
OpOr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`^`
|
||||||
|
**/
|
||||||
|
OpXor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`&&`
|
||||||
|
**/
|
||||||
|
OpBoolAnd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`||`
|
||||||
|
**/
|
||||||
|
OpBoolOr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`<<`
|
||||||
|
**/
|
||||||
|
OpShl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`>>`
|
||||||
|
**/
|
||||||
|
OpShr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`>>>`
|
||||||
|
**/
|
||||||
|
OpUShr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`%`
|
||||||
|
**/
|
||||||
|
OpMod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`+=` `-=` `/=` `*=` `<<=` `>>=` `>>>=` `|=` `&=` `^=` `%=`
|
||||||
|
**/
|
||||||
|
OpAssignOp(op:Binop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
`...`
|
||||||
|
**/
|
||||||
|
OpInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`=>`
|
||||||
|
**/
|
||||||
|
OpArrow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`is`
|
||||||
|
**/
|
||||||
|
OpIs; // used to be OpIn, but our system treats that differently
|
||||||
|
|
||||||
|
/**
|
||||||
|
`??`
|
||||||
|
**/
|
||||||
|
OpNullCoal;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum abstract Unop(Int) {
|
||||||
|
/**
|
||||||
|
`++`
|
||||||
|
**/
|
||||||
|
var OpIncrement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`--`
|
||||||
|
**/
|
||||||
|
var OpDecrement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`!`
|
||||||
|
**/
|
||||||
|
var OpNot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`-`
|
||||||
|
**/
|
||||||
|
var OpNeg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`~`
|
||||||
|
**/
|
||||||
|
var OpNegBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`...`
|
||||||
|
**/
|
||||||
|
var OpSpread;
|
||||||
|
}
|
||||||
|
|
||||||
|
class InfoClass {
|
||||||
|
public var variables:Array<String>;
|
||||||
|
|
||||||
|
public function new(variables:Array<String>) {
|
||||||
|
this.variables = variables;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum KImportMode {
|
enum KImportMode {
|
||||||
INormal;
|
INormal;
|
||||||
IAs( name : String );
|
IAs( name : String );
|
||||||
|
IAsReturn;
|
||||||
IAll;
|
IAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,10 +291,9 @@ class SwitchCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
//typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||||
class Argument {
|
class Argument {
|
||||||
public var name : String;
|
public var name : VarN;
|
||||||
public var t : Null<CType>;
|
public var t : Null<CType>;
|
||||||
public var opt : Bool;
|
public var opt : Bool;
|
||||||
public var value : Null<Expr>;
|
public var value : Null<Expr>;
|
||||||
@@ -134,6 +303,10 @@ class Argument {
|
|||||||
this.opt = opt;
|
this.opt = opt;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toString() {
|
||||||
|
return (opt ? "?" : "") + name + (t != null ? ":" + Printer.convertTypeToString(t) : "") + (value != null ? "=" + Printer.convertExprToString(value) : "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
||||||
@@ -205,3 +378,10 @@ typedef VarDecl = {
|
|||||||
var expr : Null<Expr>;
|
var expr : Null<Expr>;
|
||||||
var type : Null<CType>;
|
var type : Null<CType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract VarN(Dynamic) from Int from String to Int to String {}
|
||||||
|
// abstract VarN(Int) from Int to Int {}
|
||||||
|
//enum VarN {
|
||||||
|
// VInt(v:Int);
|
||||||
|
// VStr(v:String);
|
||||||
|
//}
|
||||||
+275
-175
@@ -60,7 +60,7 @@ class DeclaredVar {
|
|||||||
|
|
||||||
@:structInit
|
@:structInit
|
||||||
class RedeclaredVar {
|
class RedeclaredVar {
|
||||||
public var n:String;
|
public var n:VarN;
|
||||||
public var old:DeclaredVar;
|
public var old:DeclaredVar;
|
||||||
public var depth:Int;
|
public var depth:Int;
|
||||||
}
|
}
|
||||||
@@ -96,9 +96,6 @@ class Interp {
|
|||||||
|
|
||||||
public var _variablesNames:Array<String> = [];
|
public var _variablesNames:Array<String> = [];
|
||||||
public var _variables:Array<Dynamic> = [];
|
public var _variables:Array<Dynamic> = [];
|
||||||
public var _publicVariables:Array<Dynamic> = [];
|
|
||||||
public var _staticVariables:Array<Dynamic> = [];
|
|
||||||
public var _customClasses:Array<Dynamic> = [];
|
|
||||||
public var _locals:Array<DeclaredVar> = [];
|
public var _locals:Array<DeclaredVar> = [];
|
||||||
|
|
||||||
// !BACKWARDS COMPAT
|
// !BACKWARDS COMPAT
|
||||||
@@ -107,17 +104,15 @@ class Interp {
|
|||||||
public var publicVariables:HScriptVariables;
|
public var publicVariables:HScriptVariables;
|
||||||
public var staticVariables:HScriptVariables;
|
public var staticVariables:HScriptVariables;
|
||||||
|
|
||||||
#if haxe3
|
//#if haxe3
|
||||||
public var locals:Map<String, DeclaredVar>;
|
//var binops:Map<String, Expr->Expr->Dynamic>;
|
||||||
var binops:Map<String, Expr->Expr->Dynamic>;
|
//#else
|
||||||
#else
|
//var binops:Hash<Expr->Expr->Dynamic>;
|
||||||
public var locals:Hash<DeclaredVar>;
|
//#end
|
||||||
var binops:Hash<Expr->Expr->Dynamic>;
|
|
||||||
#end
|
|
||||||
|
|
||||||
var depth:Int = 0;
|
var depth:Int = 0;
|
||||||
var inTry:Bool;
|
var inTry:Bool;
|
||||||
var declared:Array<RedeclaredVar>;
|
var declared:Array<RedeclaredVar> = [];
|
||||||
var returnValue:Dynamic;
|
var returnValue:Dynamic;
|
||||||
|
|
||||||
var isBypassAccessor:Bool = false;
|
var isBypassAccessor:Bool = false;
|
||||||
@@ -137,21 +132,18 @@ class Interp {
|
|||||||
#end
|
#end
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
declared = new Array();
|
|
||||||
resetVariables();
|
resetVariables();
|
||||||
initOps();
|
//initOps();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resetVariables() {
|
private function resetVariables() {
|
||||||
_variablesNames = [];
|
_variablesNames = [];
|
||||||
_variables = [];
|
loadTables(0);
|
||||||
_customClasses = [];
|
|
||||||
_locals = [];
|
|
||||||
|
|
||||||
staticVariables = publicVariables = customClasses = variables = new HScriptVariables(this);
|
staticVariables = publicVariables = customClasses = variables = new HScriptVariables(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setDefualtVariables() {
|
private function setDefaultVariables() {
|
||||||
variables.set("null", null);
|
variables.set("null", null);
|
||||||
variables.set("true", true);
|
variables.set("true", true);
|
||||||
variables.set("false", false);
|
variables.set("false", false);
|
||||||
@@ -180,7 +172,7 @@ class Interp {
|
|||||||
return cast {fileName: "hscript", lineNumber: 0};
|
return cast {fileName: "hscript", lineNumber: 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
function initOps() {
|
/*function initOps() {
|
||||||
var me = this;
|
var me = this;
|
||||||
#if haxe3
|
#if haxe3
|
||||||
binops = new Map();
|
binops = new Map();
|
||||||
@@ -230,66 +222,141 @@ class Interp {
|
|||||||
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 == null ? v2 : v1);
|
assignOp("??"+"=", function(v1, v2) return v1 == null ? v2 : v1);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
function runBinop(op:Binop, e1:Expr, e2:Expr):Dynamic {
|
||||||
|
return switch (op) {
|
||||||
|
case OpAdd: expr(e1) + expr(e2);
|
||||||
|
case OpSub: expr(e1) - expr(e2);
|
||||||
|
case OpMult: expr(e1) * expr(e2);
|
||||||
|
case OpDiv: expr(e1) / expr(e2);
|
||||||
|
case OpMod: expr(e1) % expr(e2);
|
||||||
|
case OpAnd: expr(e1) & expr(e2);
|
||||||
|
case OpOr: expr(e1) | expr(e2);
|
||||||
|
case OpXor: expr(e1) ^ expr(e2);
|
||||||
|
case OpShl: expr(e1) << expr(e2);
|
||||||
|
case OpShr: expr(e1) >> expr(e2);
|
||||||
|
case OpUShr: expr(e1) >>> expr(e2);
|
||||||
|
case OpEq: expr(e1) == expr(e2);
|
||||||
|
case OpNotEq: expr(e1) != expr(e2);
|
||||||
|
case OpGt: expr(e1) > expr(e2);
|
||||||
|
case OpGte: expr(e1) >= expr(e2);
|
||||||
|
case OpLt: expr(e1) < expr(e2);
|
||||||
|
case OpLte: expr(e1) <= expr(e2);
|
||||||
|
case OpBoolAnd: expr(e1) == true && expr(e2) == true;
|
||||||
|
case OpBoolOr: expr(e1) == true || expr(e2) == true;
|
||||||
|
//case OpIs: false;
|
||||||
|
case OpIs: checkIsType(e1, e2);
|
||||||
|
case OpInterval: {
|
||||||
|
new #if (haxe_211 || haxe3) IntIterator #else IntIter #end(expr(e1), expr(e2));
|
||||||
|
}
|
||||||
|
//case OpIn: false;
|
||||||
|
case OpNullCoal: {
|
||||||
|
var e1 = expr(e1);
|
||||||
|
if (e1 == null) expr(e2) else e1;
|
||||||
|
};
|
||||||
|
case OpAssign: assign(e1, e2);
|
||||||
|
case OpAssignOp(OpAdd): evalAssignOp((a:()->Dynamic, b:()->Dynamic) -> a() + b(), e1, e2);
|
||||||
|
case OpAssignOp(OpSub): evalAssignOp((a:()->Float, b:()->Float) -> a() - b(), e1, e2);
|
||||||
|
case OpAssignOp(OpMult): evalAssignOp((a:()->Float, b:()->Float) -> a() * b(), e1, e2);
|
||||||
|
case OpAssignOp(OpDiv): evalAssignOp((a:()->Float, b:()->Float) -> a() / b(), e1, e2);
|
||||||
|
case OpAssignOp(OpMod): evalAssignOp((a:()->Float, b:()->Float) -> a() % b(), e1, e2);
|
||||||
|
case OpAssignOp(OpAnd): evalAssignOp((a:()->Int, b:()->Int) -> a() & b(), e1, e2);
|
||||||
|
case OpAssignOp(OpOr): evalAssignOp((a:()->Int, b:()->Int) -> a() | b(), e1, e2);
|
||||||
|
case OpAssignOp(OpXor): evalAssignOp((a:()->Int, b:()->Int) -> a() ^ b(), e1, e2);
|
||||||
|
case OpAssignOp(OpShl): evalAssignOp((a:()->Int, b:()->Int) -> a() << b(), e1, e2);
|
||||||
|
case OpAssignOp(OpShr): evalAssignOp((a:()->Int, b:()->Int) -> a() >> b(), e1, e2);
|
||||||
|
case OpAssignOp(OpUShr): evalAssignOp((a:()->Int, b:()->Int) -> a() >>> b(), e1, e2);
|
||||||
|
case OpAssignOp(OpNullCoal): evalAssignOp((a:()->Dynamic, b:()->Dynamic) -> {
|
||||||
|
var a = a();
|
||||||
|
return a == null ? b() : a;
|
||||||
|
}, e1, e2);
|
||||||
|
default: error(EInvalidOp(Printer.getBinaryOp(op) + " " + op));
|
||||||
|
|
||||||
|
//case OpAssignOp(op): getBinaryOp(op)(e1, e2);
|
||||||
|
|
||||||
|
//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);
|
||||||
|
//assignOp("??"+"=", function(v1, v2) return v1 == null ? v2 : v1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIsType(e1,e2): Bool {
|
function checkIsType(e1,e2): Bool {
|
||||||
var expr1:Dynamic = expr(e1);
|
var expr1:Dynamic = expr(e1);
|
||||||
|
|
||||||
return switch(Tools.expr(e2)) {
|
switch(Tools.expr(e2)) {
|
||||||
case EIdent("Class"):
|
case EIdent(id):
|
||||||
Std.isOfType(expr1, Class);
|
var sid = _variablesNames[id];
|
||||||
case EIdent("Map") | EIdent("IMap"):
|
if (sid == "Class")
|
||||||
Std.isOfType(expr1, IMap);
|
return Std.isOfType(expr1, Class);
|
||||||
|
if (sid == "Map" || sid == "IMap")
|
||||||
|
return Std.isOfType(expr1, IMap);
|
||||||
default:
|
default:
|
||||||
var expr2:Dynamic = expr(e2);
|
|
||||||
expr2 != null ? Std.isOfType(expr1, expr2) : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expr2:Dynamic = expr(e2);
|
||||||
|
return expr2 != null ? Std.isOfType(expr1, expr2) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setVar(name:String, v:Dynamic) {
|
public inline function setVar(name:String, v:Dynamic) {
|
||||||
if (allowStaticVariables && staticVariables.exists(name))
|
isetVar(_variablesNames.indexOf(name), v);
|
||||||
staticVariables.set(name, v);
|
}
|
||||||
else if (allowPublicVariables && publicVariables.exists(name))
|
|
||||||
publicVariables.set(name, v);
|
public function isetVar(id:Int, v:Dynamic) {
|
||||||
|
var sid:String = _variablesNames[id];
|
||||||
|
if (allowStaticVariables && staticVariables.exists(sid))
|
||||||
|
staticVariables.set(sid, v);
|
||||||
|
else if (allowPublicVariables && publicVariables.exists(sid))
|
||||||
|
publicVariables.set(sid, v);
|
||||||
else
|
else
|
||||||
variables.set(name, v);
|
_variables[id] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function assign(e1:Expr, e2:Expr):Dynamic {
|
function assign(e1:Expr, e2:Expr):Dynamic {
|
||||||
var v = expr(e2);
|
var v = expr(e2);
|
||||||
switch (Tools.expr(e1)) {
|
switch (Tools.expr(e1)) {
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
var l = locals.get(id);
|
var iname:String = _variablesNames[id];
|
||||||
|
var l = _locals[id];
|
||||||
if (l == null) {
|
if (l == null) {
|
||||||
if (!variables.exists(id) && !staticVariables.exists(id) && !publicVariables.exists(id) && _hasScriptObject) {
|
// TODO: WHEN ADDING ENUM DEFINED THING CHANGE THIS
|
||||||
|
if (_variables[id] != null && !staticVariables.exists(iname) && !publicVariables.exists(iname) && _hasScriptObject) {
|
||||||
if (_scriptObjectType == SObject) {
|
if (_scriptObjectType == SObject) {
|
||||||
UnsafeReflect.setField(scriptObject, id, v);
|
UnsafeReflect.setField(scriptObject, iname, v);
|
||||||
} else {
|
} else {
|
||||||
if (isBypassAccessor) {
|
if (isBypassAccessor) {
|
||||||
if (__instanceFields.contains(id)) {
|
if (__instanceFields.contains(iname)) {
|
||||||
UnsafeReflect.setField(scriptObject, id, v);
|
UnsafeReflect.setField(scriptObject, iname, v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__instanceFields.contains(id)) {
|
if (__instanceFields.contains(iname)) {
|
||||||
UnsafeReflect.setProperty(scriptObject, id, v);
|
UnsafeReflect.setProperty(scriptObject, iname, v);
|
||||||
} else if (__instanceFields.contains('set_$id')) { // setter
|
} else if (__instanceFields.contains('set_$iname')) { // setter
|
||||||
UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
|
UnsafeReflect.getProperty(scriptObject, 'set_$iname')(v);
|
||||||
} else {
|
} else {
|
||||||
setVar(id, v);
|
isetVar(id, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setVar(id, v);
|
isetVar(id, v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
l.r = v;
|
l.r = v;
|
||||||
if (l.depth == 0) {
|
if (l.depth == 0) {
|
||||||
setVar(id, v);
|
isetVar(id, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO
|
|
||||||
case EField(e, f, s):
|
case EField(e, f, s):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
if(s && obj == null) return null;
|
if(s && obj == null) return null;
|
||||||
@@ -309,30 +376,34 @@ class Interp {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function assignOp(op, fop:Dynamic->Dynamic->Dynamic) {
|
//function assignOp(op, fop:Dynamic->Dynamic->Dynamic) {
|
||||||
var me = this;
|
// var me = this;
|
||||||
binops.set(op, function(e1, e2) return me.evalAssignOp(op, fop, e1, e2));
|
// binops.set(op, function(e1, e2) return me.evalAssignOp(op, fop, e1, e2));
|
||||||
}
|
//}
|
||||||
|
|
||||||
function evalAssignOp(op, fop, e1, e2):Dynamic {
|
// kk
|
||||||
var v;
|
function evalAssignOp(fop:(a:()->Dynamic, b:()->Dynamic)->Dynamic, e1, e2):Dynamic {
|
||||||
|
var aFunc:()->Dynamic = () -> expr(e1);
|
||||||
|
var bFunc:()->Dynamic = () -> expr(e2); // push first, wait we gotta remove the comments xd
|
||||||
|
var v:Dynamic = null;
|
||||||
switch (Tools.expr(e1)) {
|
switch (Tools.expr(e1)) {
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
var l = locals.get(id);
|
var l = _locals[id];
|
||||||
v = fop(expr(e1), expr(e2));
|
v = fop(aFunc, bFunc);
|
||||||
if (l == null) {
|
if (l == null) {
|
||||||
if(_hasScriptObject) {
|
if(_hasScriptObject) {
|
||||||
|
var iname:String = _variablesNames[id];
|
||||||
if(_scriptObjectType == SObject) {
|
if(_scriptObjectType == SObject) {
|
||||||
UnsafeReflect.setField(scriptObject, id, v);
|
UnsafeReflect.setField(scriptObject, iname, v);
|
||||||
} else if (__instanceFields.contains(id)) {
|
} else if (__instanceFields.contains(iname)) {
|
||||||
UnsafeReflect.setProperty(scriptObject, id, v);
|
UnsafeReflect.setProperty(scriptObject, iname, v);
|
||||||
} else if (__instanceFields.contains('set_$id')) { // setter
|
} else if (__instanceFields.contains('set_$iname')) { // setter
|
||||||
UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
|
UnsafeReflect.getProperty(scriptObject, 'set_$iname')(v);
|
||||||
} else {
|
} else {
|
||||||
setVar(id, v);
|
isetVar(id, v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setVar(id, v);
|
isetVar(id, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -340,7 +411,7 @@ class Interp {
|
|||||||
case EField(e, f, s):
|
case EField(e, f, s):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
if(s && obj == null) return null;
|
if(s && obj == null) return null;
|
||||||
v = fop(get(obj, f), expr(e2));
|
v = fop(() ->get(obj, f), bFunc);
|
||||||
v = set(obj, f, v);
|
v = set(obj, f, v);
|
||||||
case EArray(e, index):
|
case EArray(e, index):
|
||||||
var arr:Dynamic = expr(e);
|
var arr:Dynamic = expr(e);
|
||||||
@@ -348,14 +419,14 @@ class Interp {
|
|||||||
if (isMap(arr)) {
|
if (isMap(arr)) {
|
||||||
var map = getMap(arr);
|
var map = getMap(arr);
|
||||||
|
|
||||||
v = fop(map.get(index), expr(e2));
|
v = fop(()->map.get(index), bFunc);
|
||||||
map.set(index, v);
|
map.set(index, v);
|
||||||
} else {
|
} else {
|
||||||
v = fop(arr[index], expr(e2));
|
v = fop(()->arr[index], bFunc);
|
||||||
arr[index] = v;
|
arr[index] = v;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return error(EInvalidOp(op));
|
return error(ECustom("Unknown field when handing assign operation"));
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -367,16 +438,16 @@ class Interp {
|
|||||||
#end
|
#end
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
var l = locals.get(id);
|
var l = _locals[id];
|
||||||
var v:Dynamic = (l == null) ? resolve(id) : l.r;
|
var v:Dynamic = (l == null) ? iresolve(id) : l.r;
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
if (l == null)
|
if (l == null)
|
||||||
setVar(id, v)
|
isetVar(id, v)
|
||||||
else
|
else
|
||||||
l.r = v;
|
l.r = v;
|
||||||
} else if (l == null)
|
} else if (l == null)
|
||||||
setVar(id, v + delta)
|
isetVar(id, v + delta)
|
||||||
else
|
else
|
||||||
l.r = v + delta;
|
l.r = v + delta;
|
||||||
return v;
|
return v;
|
||||||
@@ -418,21 +489,9 @@ class Interp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function execute(expr:Expr):Dynamic {
|
public function execute(expr:Expr):Dynamic {
|
||||||
depth = 0;
|
depth = 0; declared = [];
|
||||||
#if haxe3
|
_locals = [];
|
||||||
locals = new Map();
|
|
||||||
#else
|
|
||||||
locals = new Hash();
|
|
||||||
#end
|
|
||||||
declared = new Array();
|
|
||||||
|
|
||||||
Preprocessor.getvars(expr, _variablesNames);
|
|
||||||
_variables = cast new haxe.ds.Vector<Dynamic>(_variablesNames.length);
|
|
||||||
_customClasses = cast new haxe.ds.Vector<Dynamic>(_variablesNames.length);
|
|
||||||
_locals = cast new haxe.ds.Vector<Dynamic>(_variablesNames.length);
|
|
||||||
|
|
||||||
setDefualtVariables();
|
|
||||||
variables.loadDefaults();
|
|
||||||
return exprReturn(expr);
|
return exprReturn(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,6 +515,7 @@ class Interp {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch(e:Error) {
|
} catch(e:Error) {
|
||||||
|
Sys.println(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
|
||||||
if (errorHandler != null)
|
if (errorHandler != null)
|
||||||
errorHandler(e);
|
errorHandler(e);
|
||||||
else
|
else
|
||||||
@@ -467,21 +527,15 @@ class Interp {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function duplicate<T>(h:#if haxe3 Map<String, T> #else Hash<T> #end) {
|
// TODO: use array.copy();
|
||||||
#if haxe3
|
public function duplicate<T>(array:Array<T>):Array<T> {
|
||||||
var h2 = new Map();
|
return [for (a in array) a];
|
||||||
#else
|
|
||||||
var h2 = new Hash();
|
|
||||||
#end
|
|
||||||
for (k in h.keys())
|
|
||||||
h2.set(k, h.get(k));
|
|
||||||
return h2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function restore(old:Int) {
|
function restore(old:Int) {
|
||||||
while (declared.length > old) {
|
while (declared.length > old) {
|
||||||
var d = declared.pop();
|
var d = declared.pop();
|
||||||
locals.set(d.n, d.old);
|
_locals[d.n] = d.old;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,38 +558,43 @@ class Interp {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resolve(id:String, doException:Bool = true):Dynamic {
|
public function iresolve(id:Int, doException:Bool = true):Dynamic {
|
||||||
if (id == null)
|
var l = _locals[id];
|
||||||
return null;
|
|
||||||
id = StringTools.trim(id);
|
|
||||||
var l = locals.get(id);
|
|
||||||
if (l != null)
|
if (l != null)
|
||||||
return l.r;
|
return l.r;
|
||||||
|
|
||||||
for(map in [variables, publicVariables, staticVariables, customClasses])
|
if (_variables[id] != null) return _variables[id];
|
||||||
if (map.exists(id))
|
|
||||||
return map.get(id);
|
var sid:String = _variablesNames[id];
|
||||||
|
for(map in [publicVariables, staticVariables, customClasses])
|
||||||
|
if (map.exists(sid))
|
||||||
|
return map.get(sid);
|
||||||
|
|
||||||
if (_hasScriptObject) {
|
if (_hasScriptObject) {
|
||||||
// search in object
|
// search in object
|
||||||
if (id == "this") {
|
if (sid == "this") {
|
||||||
return scriptObject;
|
return scriptObject;
|
||||||
} else if (_scriptObjectType == SObject && UnsafeReflect.hasField(scriptObject, id)) {
|
} else if (_scriptObjectType == SObject && UnsafeReflect.hasField(scriptObject, sid)) {
|
||||||
return UnsafeReflect.field(scriptObject, id);
|
return UnsafeReflect.field(scriptObject, sid);
|
||||||
} else {
|
} else {
|
||||||
if (__instanceFields.contains(id)) {
|
if (__instanceFields.contains(sid)) {
|
||||||
return UnsafeReflect.getProperty(scriptObject, id);
|
return UnsafeReflect.getProperty(scriptObject, sid);
|
||||||
} else if (__instanceFields.contains('get_$id')) { // getter
|
} else if (__instanceFields.contains('get_$sid')) { // getter
|
||||||
return UnsafeReflect.getProperty(scriptObject, 'get_$id')();
|
return UnsafeReflect.getProperty(scriptObject, 'get_$sid')();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doException)
|
if (doException)
|
||||||
error(EUnknownVariable(id));
|
error(EUnknownVariable(sid));
|
||||||
//var v = variables.get(id);
|
//var v = variables.get(id);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public inline function resolve(id:String, doException:Bool = true):Dynamic {
|
||||||
|
if (id != null) id = StringTools.trim(id);
|
||||||
|
return iresolve(_variablesNames.indexOf(id), doException);
|
||||||
|
}
|
||||||
|
|
||||||
function getClass(c:String):haxe.ds.Either<Class<Any>, Enum<Any>> {
|
function getClass(c:String):haxe.ds.Either<Class<Any>, Enum<Any>> {
|
||||||
if (importBlocklist.contains(c))
|
if (importBlocklist.contains(c))
|
||||||
return null;
|
return null;
|
||||||
@@ -558,9 +617,19 @@ class Interp {
|
|||||||
var e = e.e;
|
var e = e.e;
|
||||||
#end
|
#end
|
||||||
switch (e) {
|
switch (e) {
|
||||||
|
case EInfo(info, e):
|
||||||
|
_variablesNames = info.variables.copy();
|
||||||
|
loadTables(_variablesNames.length);
|
||||||
|
|
||||||
|
setDefaultVariables();
|
||||||
|
variables.loadDefaults();
|
||||||
|
|
||||||
|
return expr(e);
|
||||||
case EClass(name, fields, extend, interfaces):
|
case EClass(name, fields, extend, interfaces):
|
||||||
if (customClasses.exists(name))
|
var className:String = _variablesNames[name];
|
||||||
error(EAlreadyExistingClass(name));
|
// TODO: Change this when we add undefined thing
|
||||||
|
if (_variables[name] != null)
|
||||||
|
error(EAlreadyExistingClass(className));
|
||||||
|
|
||||||
inline function importVar(thing:String):String {
|
inline function importVar(thing:String):String {
|
||||||
if (thing == null)
|
if (thing == null)
|
||||||
@@ -568,7 +637,7 @@ class Interp {
|
|||||||
final variable:Class<Any> = variables.exists(thing) ? cast variables.get(thing) : null;
|
final variable:Class<Any> = variables.exists(thing) ? cast variables.get(thing) : null;
|
||||||
return variable == null ? thing : Type.getClassName(variable);
|
return variable == null ? thing : Type.getClassName(variable);
|
||||||
}
|
}
|
||||||
customClasses.set(name, new CustomClassHandler(this, name, fields, importVar(extend), [for (i in interfaces) importVar(i)]));
|
_variables[name] = new CustomClassHandler(this, className, fields, importVar(extend), [for (i in interfaces) importVar(i)]);
|
||||||
case EImport(c, mode):
|
case EImport(c, mode):
|
||||||
if (!importEnabled) return null;
|
if (!importEnabled) return null;
|
||||||
|
|
||||||
@@ -583,11 +652,12 @@ class Interp {
|
|||||||
var lastName:String = splitClassName[splitClassName.length-1];
|
var lastName:String = splitClassName[splitClassName.length-1];
|
||||||
var varName:String = switch(mode) {
|
var varName:String = switch(mode) {
|
||||||
case IAs(name): name;
|
case IAs(name): name;
|
||||||
|
case IAsReturn: null;
|
||||||
default: lastName;
|
default: lastName;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class is already imported
|
// Class is already imported
|
||||||
if (variables.exists(varName))
|
if (varName != null && variables.exists(varName))
|
||||||
return variables.get(varName);
|
return variables.get(varName);
|
||||||
|
|
||||||
// Orginal class
|
// Orginal class
|
||||||
@@ -619,11 +689,13 @@ class Interp {
|
|||||||
if(v == null) v = UnsafeReflect.field(classOrEnum, lastName);
|
if(v == null) v = UnsafeReflect.field(classOrEnum, lastName);
|
||||||
if(v == null) error(EInvalidAccess(lastName, c));
|
if(v == null) error(EInvalidAccess(lastName, c));
|
||||||
|
|
||||||
variables.set(varName, v);
|
if (varName != null)
|
||||||
|
variables.set(varName, v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
variables.set(varName, classOrEnum);
|
if (varName != null)
|
||||||
|
variables.set(varName, classOrEnum);
|
||||||
return classOrEnum;
|
return classOrEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,18 +712,25 @@ class Interp {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
return resolve(id);
|
return iresolve(id);
|
||||||
case EVar(n, _, e, isPublic, isStatic):
|
case EVar(n, _, e, isPublic, isStatic):
|
||||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
declared.push({n: n, old: _locals[n], depth: depth});
|
||||||
locals.set(n, {r: (e == null) ? null : expr(e), depth: depth});
|
_locals[n] = {r: (e == null) ? null : expr(e), depth: depth};
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
if(isStatic == true) {
|
if(isPublic == true || isStatic == true) {
|
||||||
if(!staticVariables.exists(n)) { // dont overwrite existing static variables
|
var varName:String = _variablesNames[n];
|
||||||
staticVariables.set(n, locals[n].r);
|
if(isStatic == true) {
|
||||||
|
if(!staticVariables.exists(varName)) { // dont overwrite existing static variables
|
||||||
|
staticVariables.set(varName, _locals[n].r);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isPublic) {
|
||||||
|
publicVariables.set(varName, _locals[n].r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
(isPublic ? publicVariables : variables).set(n, locals[n].r);
|
else
|
||||||
|
_variables[n] = _locals[n].r;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
case EParent(e):
|
case EParent(e):
|
||||||
@@ -669,35 +748,33 @@ class Interp {
|
|||||||
return null;
|
return null;
|
||||||
return get(field, f);
|
return get(field, f);
|
||||||
case EBinop(op, e1, e2):
|
case EBinop(op, e1, e2):
|
||||||
var fop = binops.get(op);
|
//var fop = binops.get(op);
|
||||||
#if debug
|
//#if debug
|
||||||
if (fop == null)
|
//if (fop == null)
|
||||||
error(EInvalidOp(op));
|
// error(EInvalidOp(op));
|
||||||
#end
|
//#end
|
||||||
return fop(e1, e2);
|
return runBinop(op, e1, e2);
|
||||||
case EUnop(op, prefix, e):
|
case EUnop(op, prefix, e):
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case "!":
|
case OpIncrement:
|
||||||
return expr(e) != true;
|
|
||||||
case "-":
|
|
||||||
return -expr(e);
|
|
||||||
case "++":
|
|
||||||
return increment(e, prefix, 1);
|
return increment(e, prefix, 1);
|
||||||
case "--":
|
case OpDecrement:
|
||||||
return increment(e, prefix, -1);
|
return increment(e, prefix, -1);
|
||||||
case "~":
|
case OpNot:
|
||||||
|
return expr(e) != true;
|
||||||
|
case OpNeg:
|
||||||
|
return -expr(e);
|
||||||
|
case OpNegBits:
|
||||||
#if (neko && !haxe3)
|
#if (neko && !haxe3)
|
||||||
return haxe.Int32.complement(expr(e));
|
return haxe.Int32.complement(expr(e));
|
||||||
#else
|
#else
|
||||||
return ~expr(e);
|
return ~expr(e);
|
||||||
#end
|
#end
|
||||||
default:
|
case OpSpread:
|
||||||
error(EInvalidOp(op));
|
error(EInvalidOp("..."));
|
||||||
}
|
}
|
||||||
case ECall(e, params):
|
case ECall(e, params):
|
||||||
var args = new Array();
|
var args:Array<Dynamic> = [for(p in params) expr(p)];
|
||||||
for(i in 0...params.length)
|
|
||||||
args.push(expr(params[i]));
|
|
||||||
|
|
||||||
switch (Tools.expr(e)) {
|
switch (Tools.expr(e)) {
|
||||||
case EField(e, f, s):
|
case EField(e, f, s):
|
||||||
@@ -732,21 +809,25 @@ class Interp {
|
|||||||
returnValue = e == null ? null : expr(e);
|
returnValue = e == null ? null : expr(e);
|
||||||
throw SReturn;
|
throw SReturn;
|
||||||
case EFunction(params, fexpr, name, _, isPublic, isStatic, isOverride):
|
case EFunction(params, fexpr, name, _, isPublic, isStatic, isOverride):
|
||||||
var __capturedLocals = duplicate(locals);
|
var __capturedLocals = duplicate(_locals);
|
||||||
var capturedLocals:Map<String, DeclaredVar> = [];
|
var capturedLocals:Array<DeclaredVar> = [];
|
||||||
for(k=>e in __capturedLocals)
|
for(k=>e in __capturedLocals)
|
||||||
if (e != null && e.depth > 0)
|
if (e != null && e.depth > 0)
|
||||||
capturedLocals.set(k, e);
|
capturedLocals[k] = e;
|
||||||
|
else
|
||||||
|
capturedLocals[k] = null;
|
||||||
|
// TODO: REPLACE THIS WITH UNDEFINED WHEN WE ADD -lunar
|
||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
var hasOpt = false, minParams = 0;
|
var hasOpt = false, minParams = 0;
|
||||||
|
//for (a in params) trace(a.name);
|
||||||
for (p in params)
|
for (p in params)
|
||||||
if (p.opt)
|
if (p.opt)
|
||||||
hasOpt = true;
|
hasOpt = true;
|
||||||
else
|
else
|
||||||
minParams++;
|
minParams++;
|
||||||
var f = function(args:Array<Dynamic>) {
|
var f = function(args:Array<Dynamic>) {
|
||||||
if (me.locals == null || me.variables == null) return null;
|
if (me._locals == null || me._variables == null) return null;
|
||||||
|
|
||||||
if (((args == null) ? 0 : args.length) != params.length) {
|
if (((args == null) ? 0 : args.length) != params.length) {
|
||||||
if (args.length < minParams) {
|
if (args.length < minParams) {
|
||||||
@@ -770,18 +851,18 @@ class Interp {
|
|||||||
args2.push(args[pos++]);
|
args2.push(args[pos++]);
|
||||||
args = args2;
|
args = args2;
|
||||||
}
|
}
|
||||||
var old = me.locals, depth = me.depth;
|
var old = me._locals, depth = me.depth;
|
||||||
me.depth++;
|
me.depth++;
|
||||||
me.locals = me.duplicate(capturedLocals);
|
me._locals = me.duplicate(capturedLocals);
|
||||||
for (i in 0...params.length)
|
for (i in 0...params.length)
|
||||||
me.locals.set(params[i].name, {r: args[i], depth: depth});
|
me._locals[params[i].name] = {r: args[i], depth: depth};
|
||||||
var r = null;
|
var r = null;
|
||||||
var oldDecl = declared.length;
|
var oldDecl = declared.length;
|
||||||
if (inTry)
|
if (inTry)
|
||||||
try {
|
try {
|
||||||
r = me.exprReturn(fexpr);
|
r = me.exprReturn(fexpr);
|
||||||
} catch (e:Dynamic) {
|
} catch (e:Dynamic) {
|
||||||
me.locals = old;
|
me._locals = old;
|
||||||
me.depth = depth;
|
me.depth = depth;
|
||||||
#if neko
|
#if neko
|
||||||
neko.Lib.rethrow(e);
|
neko.Lib.rethrow(e);
|
||||||
@@ -792,7 +873,7 @@ class Interp {
|
|||||||
else
|
else
|
||||||
r = me.exprReturn(fexpr);
|
r = me.exprReturn(fexpr);
|
||||||
restore(oldDecl);
|
restore(oldDecl);
|
||||||
me.locals = old;
|
me._locals = old;
|
||||||
me.depth = depth;
|
me.depth = depth;
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
@@ -800,13 +881,18 @@ class Interp {
|
|||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
// global function
|
// global function
|
||||||
((isStatic && allowStaticVariables) ? staticVariables : ((isPublic && allowPublicVariables) ? publicVariables : variables)).set(name, f);
|
if ((isStatic && allowStaticVariables))
|
||||||
|
staticVariables.set(_variablesNames[name], f);
|
||||||
|
else if (isPublic && allowPublicVariables)
|
||||||
|
publicVariables.set(_variablesNames[name], f);
|
||||||
|
else
|
||||||
|
_variables[name] = f;
|
||||||
} else {
|
} else {
|
||||||
// function-in-function is a local function
|
// function-in-function is a local function
|
||||||
declared.push({n: name, old: locals.get(name), depth: depth});
|
declared.push({n: name, old: _locals[name], depth: depth});
|
||||||
var ref:DeclaredVar = {r: f, depth: depth};
|
var ref:DeclaredVar = {r: f, depth: depth};
|
||||||
locals.set(name, ref);
|
_locals[name] = ref;
|
||||||
capturedLocals.set(name, ref); // allow self-recursion
|
capturedLocals[name] = ref; // allow self-recursion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@@ -870,7 +956,7 @@ class Interp {
|
|||||||
var a = new Array();
|
var a = new Array();
|
||||||
for (i in 0...params.length)
|
for (i in 0...params.length)
|
||||||
a.push(expr(params[i]));
|
a.push(expr(params[i]));
|
||||||
return cnew(cl, a);
|
return cnew(_variablesNames[cl], a);
|
||||||
case EThrow(e):
|
case EThrow(e):
|
||||||
throw expr(e);
|
throw expr(e);
|
||||||
case ETry(e, n, _, ecatch):
|
case ETry(e, n, _, ecatch):
|
||||||
@@ -890,8 +976,8 @@ class Interp {
|
|||||||
restore(old);
|
restore(old);
|
||||||
inTry = oldTry;
|
inTry = oldTry;
|
||||||
// declare 'v'
|
// declare 'v'
|
||||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
declared.push({n: n, old: _locals[n], depth: depth});
|
||||||
locals.set(n, {r: err, depth: depth});
|
_locals[n] = {r: err, depth: depth};
|
||||||
var v:Dynamic = expr(ecatch);
|
var v:Dynamic = expr(ecatch);
|
||||||
restore(old);
|
restore(old);
|
||||||
return v;
|
return v;
|
||||||
@@ -1010,13 +1096,13 @@ class Interp {
|
|||||||
|
|
||||||
function forLoop(n, it, e) {
|
function forLoop(n, it, e) {
|
||||||
var old = declared.length;
|
var old = declared.length;
|
||||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
declared.push({n: n, old: _locals[n], depth: depth});
|
||||||
var it = makeIterator(expr(it));
|
var it = makeIterator(expr(it));
|
||||||
var _hasNext = it.hasNext;
|
var _hasNext = it.hasNext;
|
||||||
var _next = it.next;
|
var _next = it.next;
|
||||||
while (_hasNext()) {
|
while (_hasNext()) {
|
||||||
var next = _next();
|
var next = _next();
|
||||||
locals.set(n, {r: next, depth: depth});
|
_locals[n] = {r: next, depth: depth};
|
||||||
try {
|
try {
|
||||||
expr(e);
|
expr(e);
|
||||||
} catch (err:Stop) {
|
} catch (err:Stop) {
|
||||||
@@ -1034,15 +1120,15 @@ class Interp {
|
|||||||
|
|
||||||
function forLoopKeyValue(n, it, e, ithv) {
|
function forLoopKeyValue(n, it, e, ithv) {
|
||||||
var old = declared.length;
|
var old = declared.length;
|
||||||
declared.push({n: ithv, old: locals.get(ithv), depth: depth});
|
declared.push({n: ithv, old: _locals[ithv], depth: depth});
|
||||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
declared.push({n: n, old: _locals[n], depth: depth});
|
||||||
var it = makeKeyValueIterator(expr(it));
|
var it = makeKeyValueIterator(expr(it));
|
||||||
var _hasNext = it.hasNext;
|
var _hasNext = it.hasNext;
|
||||||
var _next = it.next;
|
var _next = it.next;
|
||||||
while (_hasNext()) {
|
while (_hasNext()) {
|
||||||
var next = _next();
|
var next = _next();
|
||||||
locals.set(ithv, {r: next.key, depth: depth});
|
_locals[ithv] = {r: next.key, depth: depth};
|
||||||
locals.set(n, {r: next.value, depth: depth});
|
_locals[n] = {r: next.value, depth: depth};
|
||||||
try {
|
try {
|
||||||
expr(e);
|
expr(e);
|
||||||
} catch (err:Stop) {
|
} catch (err:Stop) {
|
||||||
@@ -1162,9 +1248,34 @@ class Interp {
|
|||||||
return (c is IHScriptCustomConstructor) ? cast(c, IHScriptCustomConstructor).hnew(args) : Type.createInstance(c, args);
|
return (c is IHScriptCustomConstructor) ? cast(c, IHScriptCustomConstructor).hnew(args) : Type.createInstance(c, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline function loadTables(len:Int) {
|
||||||
|
_variables = cast new haxe.ds.Vector<Dynamic>(len);
|
||||||
|
_locals = cast new haxe.ds.Vector<Dynamic>(len);
|
||||||
|
}
|
||||||
|
|
||||||
static inline function b2i(b:Bool) return b ? 1 : 0;
|
static inline function b2i(b:Bool) return b ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HScriptVariablesKeyValueIterator {
|
||||||
|
public var names:Array<String> = [];
|
||||||
|
public var values:Array<Dynamic> = [];
|
||||||
|
|
||||||
|
public function new(names:Array<String>, values:Array<Dynamic>) {
|
||||||
|
this.names = names;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:noCompletion public var _current:Int = 0;
|
||||||
|
public inline function hasNext():Bool {
|
||||||
|
return _current < names.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline function next():{key:String, value:Dynamic} {
|
||||||
|
_current++;
|
||||||
|
return {value: values[_current], key: names[_current]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class HScriptVariables {
|
class HScriptVariables {
|
||||||
public var defaults:Map<String, Dynamic> = [];
|
public var defaults:Map<String, Dynamic> = [];
|
||||||
public var usedefaults:Bool = true;
|
public var usedefaults:Bool = true;
|
||||||
@@ -1219,18 +1330,7 @@ class HScriptVariables {
|
|||||||
public inline function keys():ArrayIterator<String>
|
public inline function keys():ArrayIterator<String>
|
||||||
return parent._variablesNames.iterator();
|
return parent._variablesNames.iterator();
|
||||||
|
|
||||||
public inline function keyValueIterator() : HScriptVariables {
|
public function keyValueIterator() : HScriptVariablesKeyValueIterator {
|
||||||
_current = 0;
|
return new HScriptVariablesKeyValueIterator(parent._variablesNames, parent._variables);
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@:noCompletion public var _current:Int = 0;
|
|
||||||
public inline function hasNext():Bool {
|
|
||||||
return _current < parent._variablesNames.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function next():{key:String, value:Dynamic} {
|
|
||||||
_current++;
|
|
||||||
return {value: parent._variables[_current], key: parent._variablesNames[_current]};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+32
-31
@@ -74,7 +74,7 @@ class Optimizer {
|
|||||||
var c2 = getBool(e2);
|
var c2 = getBool(e2);
|
||||||
|
|
||||||
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
||||||
return optimize(mk(EUnop("!", true, econd), s));
|
return optimize(mk(EUnop(OpNot, true, econd), s));
|
||||||
}
|
}
|
||||||
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
||||||
return optimize(mk(Tools.expr(econd), s));
|
return optimize(mk(Tools.expr(econd), s));
|
||||||
@@ -113,7 +113,7 @@ class Optimizer {
|
|||||||
var c2 = getBool(e2);
|
var c2 = getBool(e2);
|
||||||
|
|
||||||
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
if(c1 == false && c2 == true) { // (VAR ? false : true)
|
||||||
return optimize(mk(EUnop("!", true, econd), s));
|
return optimize(mk(EUnop(OpNot, true, econd), s));
|
||||||
}
|
}
|
||||||
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
if(c1 == true && c2 == false) { // (VAR ? true : false)
|
||||||
return optimize(mk(Tools.expr(econd), s));
|
return optimize(mk(Tools.expr(econd), s));
|
||||||
@@ -391,9 +391,9 @@ class Optimizer {
|
|||||||
// Possible bugs here
|
// Possible bugs here
|
||||||
if(isNumber(e1) && !isConstant(e2)) {
|
if(isNumber(e1) && !isConstant(e2)) {
|
||||||
var c1 = getNumber(e1);
|
var c1 = getNumber(e1);
|
||||||
if(compareNumber(c1, 0) && op == "+")
|
if(compareNumber(c1, 0) && op == OpAdd)
|
||||||
return mk(Tools.expr(e2), s);
|
return mk(Tools.expr(e2), s);
|
||||||
if(compareNumber(c1, 1) && op == "*")
|
if(compareNumber(c1, 1) && op == OpMult)
|
||||||
return mk(Tools.expr(e2), s);
|
return mk(Tools.expr(e2), s);
|
||||||
//if(compareNumber(c1, 0) && op == "*")
|
//if(compareNumber(c1, 0) && op == "*")
|
||||||
// return mk(convertConstant(0), s);
|
// return mk(convertConstant(0), s);
|
||||||
@@ -401,11 +401,11 @@ class Optimizer {
|
|||||||
|
|
||||||
if(!isConstant(e1) && isNumber(e2)) {
|
if(!isConstant(e1) && isNumber(e2)) {
|
||||||
var c2 = getNumber(e2);
|
var c2 = getNumber(e2);
|
||||||
if(op == "+" && compareNumber(c2, 0))
|
if(op == OpAdd && compareNumber(c2, 0))
|
||||||
return mk(Tools.expr(e1), s);
|
return mk(Tools.expr(e1), s);
|
||||||
if(op == "/" && compareNumber(c2, 1))
|
if(op == OpDiv && compareNumber(c2, 1))
|
||||||
return mk(Tools.expr(e1), s);
|
return mk(Tools.expr(e1), s);
|
||||||
if(op == "*" && compareNumber(c2, 1))
|
if(op == OpMult && compareNumber(c2, 1))
|
||||||
return mk(Tools.expr(e1), s);
|
return mk(Tools.expr(e1), s);
|
||||||
//if(op == "*" && compareNumber(c2, 0))
|
//if(op == "*" && compareNumber(c2, 0))
|
||||||
// return mk(convertConstant(0), s);
|
// return mk(convertConstant(0), s);
|
||||||
@@ -419,11 +419,12 @@ class Optimizer {
|
|||||||
if(isConstant(e) && prefix) {
|
if(isConstant(e) && prefix) {
|
||||||
var constant:Dynamic = getConstant(e);
|
var constant:Dynamic = getConstant(e);
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case "-": return mk(convertConstant(-constant), s);
|
case OpNeg: return mk(convertConstant(-constant), s);
|
||||||
case "!": return mk(convertConstant(!constant), s);
|
case OpNot: return mk(convertConstant(!constant), s);
|
||||||
case "~":
|
case OpNegBits:
|
||||||
var complement = #if (neko && !haxe3) haxe.Int32.complement(constant) #else ~constant #end;
|
var complement = #if (neko && !haxe3) haxe.Int32.complement(constant) #else ~constant #end;
|
||||||
return mk(convertConstant(complement), s);
|
return mk(convertConstant(complement), s);
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,29 +606,29 @@ class Optimizer {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
static function optimizeOp(op, f1:Dynamic, f2:Dynamic):Dynamic {
|
static function optimizeOp(op:Binop, f1:Dynamic, f2:Dynamic):Dynamic {
|
||||||
//trace("Optimizing " + f1 + " " + op + " " + f2);
|
//trace("Optimizing " + f1 + " " + op + " " + f2);
|
||||||
return switch(op) {
|
return switch(op) {
|
||||||
case "+": f1 + f2;
|
case OpAdd: f1 + f2;
|
||||||
case "-": f1 - f2;
|
case OpSub: f1 - f2;
|
||||||
case "*": f1 * f2;
|
case OpMult: f1 * f2;
|
||||||
case "/": f1 / f2;
|
case OpDiv: f1 / f2;
|
||||||
case "%": f1 % f2;
|
case OpMod: f1 % f2;
|
||||||
case "&": f1 & f2;
|
case OpAnd: f1 & f2;
|
||||||
case "|": f1 | f2;
|
case OpOr: f1 | f2;
|
||||||
case "^": f1 ^ f2;
|
case OpXor: f1 ^ f2;
|
||||||
case "<<": f1 << f2;
|
case OpShl: f1 << f2;
|
||||||
case ">>": f1 >> f2;
|
case OpShr: f1 >> f2;
|
||||||
case ">>>": f1 >>> f2;
|
case OpUShr: f1 >>> f2;
|
||||||
case "==": f1 == f2;
|
case OpEq: f1 == f2;
|
||||||
case "!=": f1 != f2;
|
case OpNotEq: f1 != f2;
|
||||||
case ">=": f1 >= f2;
|
case OpGte: f1 >= f2;
|
||||||
case "<=": f1 <= f2;
|
case OpLte: f1 <= f2;
|
||||||
case ">": f1 > f2;
|
case OpGt: f1 > f2;
|
||||||
case "<": f1 < f2;
|
case OpLt: f1 < f2;
|
||||||
case "||": f1 == true || f2 == true;
|
case OpBoolOr: f1 == true || f2 == true;
|
||||||
case "&&": f1 == true && f2 == true;
|
case OpBoolAnd: f1 == true && f2 == true;
|
||||||
case "??": f1 == null ? f2 : f1;
|
case OpNullCoal: f1 == null ? f2 : f1;
|
||||||
default: null;
|
default: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-24
@@ -225,12 +225,11 @@ class Parser {
|
|||||||
}
|
}
|
||||||
var expr = if( a.length == 1 ) a[0] else mk(EBlock(a),0);
|
var expr = if( a.length == 1 ) a[0] else mk(EBlock(a),0);
|
||||||
expr = Preprocessor.process(expr);
|
expr = Preprocessor.process(expr);
|
||||||
if(Parser.optimize) {
|
if(Parser.optimize)
|
||||||
expr = Optimizer.optimize(expr);
|
expr = Optimizer.optimize(expr);
|
||||||
// trace("INPUT: " + s);
|
expr = Postprocessor.processvars(expr);
|
||||||
// trace("OUTPUT: " + Printer.toString(expr));
|
// trace("INPUT: " + s); // useful for debugging
|
||||||
}
|
//trace("OUTPUT: " + Printer.toString(expr));
|
||||||
expr = Preprocessor.processvars(expr, []);
|
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +465,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
e = mk(EBinop("+", e, er));
|
e = mk(EBinop(OpAdd, e, er));
|
||||||
//e = mk(EParent(e));
|
//e = mk(EParent(e));
|
||||||
}
|
}
|
||||||
while(tg.length > 0) {
|
while(tg.length > 0) {
|
||||||
@@ -629,7 +628,7 @@ class Parser {
|
|||||||
var isTypeMap = (nextType != null) && nextType.match(CTPath(["Map"], [_, _]));
|
var isTypeMap = (nextType != null) && nextType.match(CTPath(["Map"], [_, _]));
|
||||||
var isMap = isTypeMap;
|
var isMap = isTypeMap;
|
||||||
if(!isMap) {
|
if(!isMap) {
|
||||||
isMap = Lambda.exists(a, (e) -> Tools.expr(e).match(EBinop("=>", _))); // Check if any element is a => b
|
isMap = Lambda.exists(a, (e) -> Tools.expr(e).match(EBinop(OpArrow, _))); // Check if any element is a => b
|
||||||
}
|
}
|
||||||
if(isMap) {
|
if(isMap) {
|
||||||
// TODO: clean up this code more
|
// TODO: clean up this code more
|
||||||
@@ -641,7 +640,7 @@ class Parser {
|
|||||||
var values:Array<Expr> = [];
|
var values:Array<Expr> = [];
|
||||||
for (e in a) {
|
for (e in a) {
|
||||||
switch (Tools.expr(e)) {
|
switch (Tools.expr(e)) {
|
||||||
case EBinop("=>", eKey, eValue): {
|
case EBinop(OpArrow, eKey, eValue): {
|
||||||
switch(Tools.expr(eKey)) {
|
switch(Tools.expr(eKey)) {
|
||||||
case EConst(CInt(_)):// | EConst(CFloat(_)):
|
case EConst(CInt(_)):// | EConst(CFloat(_)):
|
||||||
isKeyInt = true;
|
isKeyInt = true;
|
||||||
@@ -791,7 +790,7 @@ class Parser {
|
|||||||
default:
|
default:
|
||||||
// tmp.set(k, v);
|
// tmp.set(k, v);
|
||||||
switch( Tools.expr(e) ) {
|
switch( Tools.expr(e) ) {
|
||||||
case EBinop("=>", e1, e2):
|
case EBinop(OpArrow, e1, e2):
|
||||||
//ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "set"), pmin(e), pmax(e)), [e1, e2]);
|
//ECall( mk(EField(mk(EIdent(tmp), pmin(e), pmax(e)), "set"), pmin(e), pmax(e)), [e1, e2]);
|
||||||
ECall( mk(EIdent(tmp), pmin(e), pmax(e)), [e1, e2]);
|
ECall( mk(EIdent(tmp), pmin(e), pmax(e)), [e1, e2]);
|
||||||
default: // default incase of error
|
default: // default incase of error
|
||||||
@@ -824,37 +823,48 @@ class Parser {
|
|||||||
isMapCompr(e2);
|
isMapCompr(e2);
|
||||||
default:
|
default:
|
||||||
// tmp.set(k, v);
|
// tmp.set(k, v);
|
||||||
return Tools.expr(e).match(EBinop("=>", _));
|
return Tools.expr(e).match(EBinop(OpArrow, _));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeUnop( op, e ) {
|
function makeUnop( op:String, e:Expr ):Expr {
|
||||||
|
var op = Tools.getUnopEnum(op);
|
||||||
|
return _makeUnop(op, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _makeUnop( op:Unop, e:Expr ):Expr {
|
||||||
if( e == null && resumeErrors )
|
if( e == null && resumeErrors )
|
||||||
return null;
|
return null;
|
||||||
return switch( Tools.expr(e) ) {
|
return switch( Tools.expr(e) ) {
|
||||||
case EBinop(bop, e1, e2): mk(EBinop(bop, makeUnop(op, e1), e2), pmin(e1), pmax(e2));
|
case EBinop(bop, e1, e2): mk(EBinop(bop, _makeUnop(op, e1), e2), pmin(e1), pmax(e2));
|
||||||
case ETernary(e1, e2, e3): mk(ETernary(makeUnop(op, e1), e2, e3), pmin(e1), pmax(e3));
|
case ETernary(e1, e2, e3): mk(ETernary(_makeUnop(op, e1), e2, e3), pmin(e1), pmax(e3));
|
||||||
default: mk(EUnop(op,true,e),pmin(e),pmax(e));
|
default: mk(EUnop(op,true,e),pmin(e),pmax(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeBinop( op, e1, e ) {
|
function makeBinop( op:String, e1:Expr, e:Expr ) {
|
||||||
// TODO: clean this up
|
// TODO: clean this up
|
||||||
if(!Tools.isValidBinOp(op))
|
if(!Tools.isValidBinOp(op))
|
||||||
error(EInvalidOp(op),pmin(e1),pmax(e1));
|
error(EInvalidOp(op),pmin(e1),pmax(e1));
|
||||||
|
var op = Tools.getOpEnum(op);
|
||||||
|
return _makeBinop(op, e1, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _makeBinop( op:Binop, e1:Expr, e:Expr ) {
|
||||||
|
// TODO: clean this up
|
||||||
if( e == null && resumeErrors )
|
if( e == null && resumeErrors )
|
||||||
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
||||||
return switch( Tools.expr(e) ) {
|
return switch( Tools.expr(e) ) {
|
||||||
case EBinop(op2,e2,e3):
|
case EBinop(op2,e2,e3):
|
||||||
if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) )
|
if( opPriority.get(Printer.getBinaryOp(op)) <= opPriority.get(Printer.getBinaryOp(op2)) && !opRightAssoc.exists(Printer.getBinaryOp(op)) )
|
||||||
mk(EBinop(op2,makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3));
|
mk(EBinop(op2,_makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3));
|
||||||
else
|
else
|
||||||
mk(EBinop(op, e1, e), pmin(e1), pmax(e));
|
mk(EBinop(op, e1, e), pmin(e1), pmax(e));
|
||||||
case ETernary(e2,e3,e4):
|
case ETernary(e2,e3,e4):
|
||||||
if( opRightAssoc.exists(op) )
|
if( opRightAssoc.exists(Printer.getBinaryOp(op)) )
|
||||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
||||||
else
|
else
|
||||||
mk(ETernary(makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e));
|
mk(ETernary(_makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e));
|
||||||
default:
|
default:
|
||||||
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
mk(EBinop(op,e1,e),pmin(e1),pmax(e));
|
||||||
}
|
}
|
||||||
@@ -1328,7 +1338,7 @@ class Parser {
|
|||||||
push(tk);
|
push(tk);
|
||||||
return e1;
|
return e1;
|
||||||
}
|
}
|
||||||
return parseExprNext(mk(EUnop(op,false,e1),pmin(e1)));
|
return parseExprNext(mk(EUnop(Tools.getUnopEnum(op),false,e1),pmin(e1)));
|
||||||
}
|
}
|
||||||
return makeBinop(op,e1,parseExpr());
|
return makeBinop(op,e1,parseExpr());
|
||||||
case TDot | TQuestionDot:
|
case TDot | TQuestionDot:
|
||||||
@@ -2270,7 +2280,7 @@ class Parser {
|
|||||||
case '?'.code:
|
case '?'.code:
|
||||||
var orp = readPos;
|
var orp = readPos;
|
||||||
if (readChar() == '='.code)
|
if (readChar() == '='.code)
|
||||||
return TOp("??"+"=");
|
return TOp("??" + "=");
|
||||||
|
|
||||||
this.readPos = orp;
|
this.readPos = orp;
|
||||||
return TOp("??");
|
return TOp("??");
|
||||||
@@ -2459,7 +2469,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
mk(EIdent(id), tokenMin, tokenMax);
|
mk(EIdent(id), tokenMin, tokenMax);
|
||||||
case TOp("!"):
|
case TOp("!"):
|
||||||
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
|
mk(EUnop(OpNot, true, parsePreproCond()), tokenMin, tokenMax);
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
}
|
}
|
||||||
@@ -2477,13 +2487,13 @@ class Parser {
|
|||||||
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName() + " with " + Tools.expr(e2).getName()), readPos, readPos);
|
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName() + " with " + Tools.expr(e2).getName()), readPos, readPos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case EUnop("!", _, e):
|
case EUnop(OpNot, _, e):
|
||||||
return !evalPreproCond(e);
|
return !evalPreproCond(e);
|
||||||
case EParent(e):
|
case EParent(e):
|
||||||
return evalPreproCond(e);
|
return evalPreproCond(e);
|
||||||
case EBinop("&&", e1, e2):
|
case EBinop(OpBoolAnd, e1, e2):
|
||||||
return evalPreproCond(e1) && evalPreproCond(e2);
|
return evalPreproCond(e1) && evalPreproCond(e2);
|
||||||
case EBinop("||", e1, e2):
|
case EBinop(OpBoolOr, e1, e2):
|
||||||
return evalPreproCond(e1) || evalPreproCond(e2);
|
return evalPreproCond(e1) || evalPreproCond(e2);
|
||||||
default:
|
default:
|
||||||
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName()), readPos, readPos);
|
error(EInvalidPreprocessor("Can't eval " + Tools.expr(e).getName()), readPos, readPos);
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
import hscript.Expr;
|
||||||
|
import hscript.Error;
|
||||||
|
import hscript.Tools;
|
||||||
|
import hscript.Parser;
|
||||||
|
|
||||||
|
@:access(hscript.Parser)
|
||||||
|
class Postprocessor {
|
||||||
|
static inline function expr(e:Expr) return Tools.expr(e);
|
||||||
|
|
||||||
|
static function mk(e:ExprDef, s:Expr):Expr {
|
||||||
|
#if hscriptPos
|
||||||
|
return new Expr(e, s.pmin, s.pmax, s.origin, s.line);
|
||||||
|
#else
|
||||||
|
return e;
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function processvars(e:Expr, ?vars:Array<String>) {
|
||||||
|
if(vars == null) vars = [];
|
||||||
|
for(v in getvars(e)) vars.push(v);
|
||||||
|
e = _processvars(e, vars);
|
||||||
|
|
||||||
|
//trace(vars);
|
||||||
|
|
||||||
|
return mk(EInfo(new InfoClass(vars), e), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function _processvars(e:Expr, vars:Array<String>):Expr {
|
||||||
|
if(e == null) return null;
|
||||||
|
var ge = e;
|
||||||
|
var doExtra = true;
|
||||||
|
var e = switch (expr(e)) {
|
||||||
|
case EIdent(v) if (v is String):
|
||||||
|
//trace(v +" -> " + vars.indexOf(v));
|
||||||
|
mk(EIdent(vars.indexOf(v)), e);
|
||||||
|
case EVar(n, t, _e, p, s) if (n is String):
|
||||||
|
//trace(n + " -> " + vars.indexOf(n));
|
||||||
|
mk(EVar(vars.indexOf(n), t, _e, p, s), e);
|
||||||
|
case EImport(c, IAs(n)) if (n is String):
|
||||||
|
//trace(n + " -> " + vars.indexOf(n));
|
||||||
|
// IAsReturn, doesnt store it in variables array, only returns the import as a expression like value
|
||||||
|
mk(EVar(vars.indexOf(n), null, mk(EImport(c, IAsReturn), e), false, false), e);
|
||||||
|
case EFunction(args, _e, n, r, p, s, o) if (n is String):
|
||||||
|
var _args:Array<Argument> = [
|
||||||
|
for (arg in args)
|
||||||
|
new Argument(vars.indexOf(arg.name), arg.t, arg.opt, arg.value)
|
||||||
|
];
|
||||||
|
mk(EFunction(_args, _e, vars.indexOf(n), r, p, s, o), e);
|
||||||
|
case EFunction(args, _e, null, r, p, s, o):
|
||||||
|
var _args:Array<Argument> = [
|
||||||
|
for (arg in args)
|
||||||
|
new Argument(vars.indexOf(arg.name), arg.t, arg.opt, arg.value)
|
||||||
|
];
|
||||||
|
mk(EFunction(_args, _e, null, r, p, s, o), e);
|
||||||
|
case ENew(cl, p) if (cl is String):
|
||||||
|
var p = [for(arg in p) arg];
|
||||||
|
mk(ENew(vars.indexOf(cl), p), e);
|
||||||
|
case EClass(n, fls, extnd, i) if (n is String):
|
||||||
|
var fls:Array<Expr> = [for(f in fls) f];
|
||||||
|
mk(EClass(vars.indexOf(n), fls, extnd, i), e);
|
||||||
|
case ETry(_e, v, t, ec) if (v is String):
|
||||||
|
mk(ETry(_e, vars.indexOf(v), t, ec), e);
|
||||||
|
case EFor(v, it, _e) if (v is String):
|
||||||
|
//trace(v + " -> " + vars.indexOf(v));
|
||||||
|
mk(EFor(vars.indexOf(v), it, _e), e);
|
||||||
|
case EForKeyValue(v, it, _e, ithv) if (v is String && ithv is String):
|
||||||
|
//trace(v + " -> " + vars.indexOf(v));
|
||||||
|
//trace(ithv + " -> " + vars.indexOf(ithv));
|
||||||
|
mk(EForKeyValue(vars.indexOf(v), it, _e, vars.indexOf(ithv)), e);
|
||||||
|
default: {
|
||||||
|
doExtra = false;
|
||||||
|
e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
e = Tools.map(e, function(e) {
|
||||||
|
return _processvars(e, vars);
|
||||||
|
});
|
||||||
|
|
||||||
|
//if(doExtra) e = _processvars(e, vars);
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getvars(se:Expr, ?vars:Array<String>):Array<String> {
|
||||||
|
inline function pushVar(v:VarN) {
|
||||||
|
if(v is String) {
|
||||||
|
var v:String = cast v;
|
||||||
|
if (!vars.contains(v))
|
||||||
|
vars.push(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(vars == null) vars = [];
|
||||||
|
Tools.iterExprRecursive(se, (e) -> {
|
||||||
|
switch (expr(e)) {
|
||||||
|
case EVar(n, t, e, _,_): pushVar(n);
|
||||||
|
case EIdent(v): pushVar(v);
|
||||||
|
case EFunction(args,e,name,_,_,_,_):
|
||||||
|
pushVar(name);
|
||||||
|
for (a in args) {
|
||||||
|
pushVar(a.name);
|
||||||
|
}
|
||||||
|
case EFor(v,it,e): pushVar(v);
|
||||||
|
case EForKeyValue(v,it,e,ithv): pushVar(ithv); pushVar(v);
|
||||||
|
case ETry(e, v, _, ec): pushVar(v);
|
||||||
|
case ENew(cl, params): pushVar(cl);
|
||||||
|
case EClass(name, fls,_,_): pushVar(name);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return vars;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -144,109 +144,4 @@ class Preprocessor {
|
|||||||
}
|
}
|
||||||
return isStringFromCharCodeFixed;
|
return isStringFromCharCodeFixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function processvars(e:Expr, vars:Array<String>) {
|
|
||||||
getvars(e, vars);
|
|
||||||
e = Tools.map(e, function(e) {
|
|
||||||
return switch (expr(e)) {
|
|
||||||
case EIdent(v, _):
|
|
||||||
return mk(EIdent(v, vars.indexOf(v)), e);
|
|
||||||
case EVar(n, t, e, p, s, _):
|
|
||||||
return mk(EVar(n, t, e, p, s, vars.indexOf(n)), e);
|
|
||||||
case EFunction(args, e, n, r, p, s, o, _):
|
|
||||||
return mk(EFunction(args, e, n, r, p, s, o, vars.indexOf(n)), e);
|
|
||||||
case ENew(cl, p, _):
|
|
||||||
return mk(ENew(cl, p, vars.indexOf(cl)), e);
|
|
||||||
case EClass(n, fls, extnd, i, _):
|
|
||||||
return mk(EClass(n, fls, extnd, i, vars.indexOf(n)), e);
|
|
||||||
default: e;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getvars(e:Expr, vars:Array<String>) {
|
|
||||||
// TODO: Use a Tools function to make this cleaner (im too lazy rn) -lunar
|
|
||||||
switch (expr(e)) {
|
|
||||||
case EIdent(v):
|
|
||||||
if (!vars.contains(v))
|
|
||||||
vars.push(v);
|
|
||||||
case EBlock(e):
|
|
||||||
for (expr in e)
|
|
||||||
getvars(expr, vars);
|
|
||||||
case EFunction(_,e,name,_,_,_,_):
|
|
||||||
getvars(e, vars);
|
|
||||||
if (!vars.contains(name))
|
|
||||||
vars.push(name);
|
|
||||||
case ESwitch(e,cases,de):
|
|
||||||
for (c in cases)
|
|
||||||
getvars(c.expr, vars);
|
|
||||||
getvars(de, vars);
|
|
||||||
case EObject(fls):
|
|
||||||
for (fl in fls) getvars(fl.e, vars);
|
|
||||||
case EVar(n, t, e, _,_):
|
|
||||||
if (!vars.contains(n))
|
|
||||||
vars.push(n);
|
|
||||||
getvars(e, vars);
|
|
||||||
case EIf(c,e1,e2):
|
|
||||||
getvars(c, vars);
|
|
||||||
getvars(e1, vars);
|
|
||||||
getvars(e2, vars);
|
|
||||||
case EBinop(_,e1,e2):
|
|
||||||
getvars(e1, vars);
|
|
||||||
getvars(e2, vars);
|
|
||||||
case EUnop(_,_,e): getvars(e, vars);
|
|
||||||
case EWhile(c,e):
|
|
||||||
getvars(c, vars);
|
|
||||||
getvars(e, vars);
|
|
||||||
case EDoWhile(e1,e2):
|
|
||||||
getvars(e1, vars);
|
|
||||||
getvars(e2, vars);
|
|
||||||
case EFor(_,it,e):
|
|
||||||
getvars(it, vars);
|
|
||||||
getvars(e, vars);
|
|
||||||
case EForKeyValue(_,it,e,_):
|
|
||||||
getvars(it, vars);
|
|
||||||
getvars(e, vars);
|
|
||||||
case EReturn(e): getvars(e, vars);
|
|
||||||
case ETry(e, _, _, ec):
|
|
||||||
getvars(e, vars);
|
|
||||||
getvars(ec, vars);
|
|
||||||
case ECall(e, params):
|
|
||||||
getvars(e, vars);
|
|
||||||
for (e in params) getvars(e, vars);
|
|
||||||
case EParent(e, _): getvars(e, vars);
|
|
||||||
case EArray(e, indx):
|
|
||||||
getvars(e, vars);
|
|
||||||
getvars(indx, vars);
|
|
||||||
case EMapDecl(_, keys, values):
|
|
||||||
for (k in keys) getvars(k, vars);
|
|
||||||
for (v in values) getvars(v, vars);
|
|
||||||
case EArrayDecl(list):
|
|
||||||
for (e in list) getvars(e, vars);
|
|
||||||
case ENew(cl, params):
|
|
||||||
if (!vars.contains(cl))
|
|
||||||
vars.push(cl);
|
|
||||||
for (e in params) getvars(e, vars);
|
|
||||||
case EThrow(e):
|
|
||||||
getvars(e, vars);
|
|
||||||
case ETernary(e, e1, e2):
|
|
||||||
getvars(e1, vars);
|
|
||||||
getvars(e2, vars);
|
|
||||||
getvars(e, vars);
|
|
||||||
case EMeta(_, args, e):
|
|
||||||
for (a in args) getvars(a, vars);
|
|
||||||
getvars(e, vars);
|
|
||||||
case ECheckType(e, _):
|
|
||||||
getvars(e, vars);
|
|
||||||
case EField(e, _, _):
|
|
||||||
getvars(e, vars);
|
|
||||||
case EClass(name, fls,_,_):
|
|
||||||
if (!vars.contains(name))
|
|
||||||
vars.push(name);
|
|
||||||
for (fl in fls) getvars(fl, vars);
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+79
-12
@@ -49,6 +49,11 @@ class Printer {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function convertTypeToString( t : CType ) {
|
||||||
|
var printer = new Printer();
|
||||||
|
return printer.typeToString(t);
|
||||||
|
}
|
||||||
|
|
||||||
inline function add<T>(s:T) buf.add(s);
|
inline function add<T>(s:T) buf.add(s);
|
||||||
|
|
||||||
function type( t : CType ) {
|
function type( t : CType ) {
|
||||||
@@ -73,11 +78,14 @@ class Printer {
|
|||||||
type(t);
|
type(t);
|
||||||
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
|
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
|
||||||
add('(');
|
add('(');
|
||||||
for (a in args)
|
var first = true;
|
||||||
|
for (i=>a in args) {
|
||||||
switch a {
|
switch a {
|
||||||
case CTNamed(_, _): type(a);
|
case CTNamed(_, _): type(a);
|
||||||
default: type(CTNamed('_', a));
|
default: type(CTNamed('_', a));
|
||||||
}
|
}
|
||||||
|
if( i != args.length - 1 ) add(", ");
|
||||||
|
}
|
||||||
add(')->');
|
add(')->');
|
||||||
type(ret);
|
type(ret);
|
||||||
case CTFun(args, ret):
|
case CTFun(args, ret):
|
||||||
@@ -196,6 +204,59 @@ class Printer {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVar(v:VarN) {
|
||||||
|
if( v == null ) {
|
||||||
|
return ("??NULL??");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(v is Int) {
|
||||||
|
return ("$" + v);
|
||||||
|
} else {
|
||||||
|
return (v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getBinaryOp(op:Binop) {
|
||||||
|
return switch(op) {
|
||||||
|
case OpAdd: "+";
|
||||||
|
case OpSub: "-";
|
||||||
|
case OpMult: "*";
|
||||||
|
case OpDiv: "/";
|
||||||
|
case OpMod: "%";
|
||||||
|
case OpAnd: "&";
|
||||||
|
case OpOr: "|";
|
||||||
|
case OpXor: "^";
|
||||||
|
case OpShl: "<<";
|
||||||
|
case OpShr: ">>";
|
||||||
|
case OpUShr: ">>>";
|
||||||
|
case OpEq: "==";
|
||||||
|
case OpNotEq: "!=";
|
||||||
|
case OpGt: ">";
|
||||||
|
case OpGte: ">=";
|
||||||
|
case OpLt: "<";
|
||||||
|
case OpLte: "<=";
|
||||||
|
case OpBoolAnd: "&&";
|
||||||
|
case OpBoolOr: "||";
|
||||||
|
case OpIs: "is";
|
||||||
|
case OpNullCoal: "??";
|
||||||
|
case OpAssign: "=";
|
||||||
|
case OpArrow: "=>";
|
||||||
|
case OpInterval: "...";
|
||||||
|
case OpAssignOp(op): getBinaryOp(op) + "=";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getUnaryOp(op:Unop) {
|
||||||
|
return switch(op) {
|
||||||
|
case OpIncrement: "++";
|
||||||
|
case OpDecrement: "--";
|
||||||
|
case OpNot: "!";
|
||||||
|
case OpNeg: "-";
|
||||||
|
case OpNegBits: "~";
|
||||||
|
case OpSpread: "...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function expr( e : Expr ) {
|
function expr( e : Expr ) {
|
||||||
if( e == null ) {
|
if( e == null ) {
|
||||||
add("??NULL??");
|
add("??NULL??");
|
||||||
@@ -213,7 +274,7 @@ class Printer {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
case EClass(name, fields, extend, interfaces):
|
case EClass(name, fields, extend, interfaces):
|
||||||
add('class $name');
|
add('class ${getVar(name)}');
|
||||||
if (extend != null)
|
if (extend != null)
|
||||||
add(' extends $extend');
|
add(' extends $extend');
|
||||||
for(_interface in interfaces) {
|
for(_interface in interfaces) {
|
||||||
@@ -238,9 +299,9 @@ class Printer {
|
|||||||
add('"');
|
add('"');
|
||||||
}
|
}
|
||||||
case EIdent(v):
|
case EIdent(v):
|
||||||
add(v);
|
add(getVar(v));
|
||||||
case EVar(n, t, e): // TODO: static, public, override
|
case EVar(n, t, e): // TODO: static, public, override
|
||||||
add("var " + n);
|
add("var " + getVar(n));
|
||||||
if( t != null )
|
if( t != null )
|
||||||
addType(t);
|
addType(t);
|
||||||
else
|
else
|
||||||
@@ -282,8 +343,7 @@ class Printer {
|
|||||||
expr(e);
|
expr(e);
|
||||||
add((s == true ? "?." : ".") + f);
|
add((s == true ? "?." : ".") + f);
|
||||||
case EBinop(op, e1, e2):
|
case EBinop(op, e1, e2):
|
||||||
var shouldParen = false;
|
/*var op1 = switch(Tools.expr(e1)) {
|
||||||
var op1 = switch(Tools.expr(e1)) {
|
|
||||||
case EBinop(op, _, _): op;
|
case EBinop(op, _, _): op;
|
||||||
case EConst(_): "_";
|
case EConst(_): "_";
|
||||||
case EIdent(_): "_";
|
case EIdent(_): "_";
|
||||||
@@ -295,7 +355,10 @@ class Printer {
|
|||||||
case EIdent(_): "_";
|
case EIdent(_): "_";
|
||||||
default: null;
|
default: null;
|
||||||
}
|
}
|
||||||
var paran = Tools.checkOpPrecedence(op, op1, op2);
|
var paran = Tools.checkOpPrecedence(op, op1, op2);*/
|
||||||
|
var paran = 2;
|
||||||
|
|
||||||
|
var op = getBinaryOp(op);
|
||||||
|
|
||||||
if(paran == 0 || paran == 2) {
|
if(paran == 0 || paran == 2) {
|
||||||
add("(");
|
add("(");
|
||||||
@@ -316,6 +379,8 @@ class Printer {
|
|||||||
expr(e2);
|
expr(e2);
|
||||||
}
|
}
|
||||||
case EUnop(op, pre, e):
|
case EUnop(op, pre, e):
|
||||||
|
var op = getUnaryOp(op);
|
||||||
|
|
||||||
if( pre ) {
|
if( pre ) {
|
||||||
add(op);
|
add(op);
|
||||||
expr(e);
|
expr(e);
|
||||||
@@ -364,12 +429,12 @@ class Printer {
|
|||||||
expr(cond);
|
expr(cond);
|
||||||
add(" )");
|
add(" )");
|
||||||
case EFor(v, it, e):
|
case EFor(v, it, e):
|
||||||
add("for( "+v+" in ");
|
add("for( "+getVar(v)+" in ");
|
||||||
expr(it);
|
expr(it);
|
||||||
add(" )");
|
add(" )");
|
||||||
block(e, true);
|
block(e, true);
|
||||||
case EForKeyValue(v, it, e, ithv):
|
case EForKeyValue(v, it, e, ithv):
|
||||||
add("for( "+ithv+" => "+v+" in ");
|
add("for( "+getVar(ithv)+" => "+getVar(v)+" in ");
|
||||||
expr(it);
|
expr(it);
|
||||||
add(" )");
|
add(" )");
|
||||||
block(e, true);
|
block(e, true);
|
||||||
@@ -380,13 +445,13 @@ class Printer {
|
|||||||
case EFunction(params, e, name, ret): // TODO: static, public, override
|
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||||
add("function");
|
add("function");
|
||||||
if( name != null )
|
if( name != null )
|
||||||
add(" " + name);
|
add(" " + getVar(name));
|
||||||
add("(");
|
add("(");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( a in params ) {
|
for( a in params ) {
|
||||||
if( first ) first = false else add(", ");
|
if( first ) first = false else add(", ");
|
||||||
if( a.opt ) add("?");
|
if( a.opt ) add("?");
|
||||||
add(a.name);
|
add(getVar(a.name));
|
||||||
addType(a.t);
|
addType(a.t);
|
||||||
}
|
}
|
||||||
add(")");
|
add(")");
|
||||||
@@ -423,7 +488,7 @@ class Printer {
|
|||||||
}
|
}
|
||||||
add("]");
|
add("]");
|
||||||
case ENew(cl, args):
|
case ENew(cl, args):
|
||||||
add("new " + cl + "(");
|
add("new " + getVar(cl) + "(");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( e in args ) {
|
for( e in args ) {
|
||||||
if( first ) first = false else add(", ");
|
if( first ) first = false else add(", ");
|
||||||
@@ -513,6 +578,8 @@ class Printer {
|
|||||||
add(" : ");
|
add(" : ");
|
||||||
addType(t);
|
addType(t);
|
||||||
add(")");
|
add(")");
|
||||||
|
case EInfo(_, e):
|
||||||
|
expr(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+156
-63
@@ -27,75 +27,119 @@ class Tools {
|
|||||||
|
|
||||||
public static function iter( e : Expr, f : Expr -> Void ) {
|
public static function iter( e : Expr, f : Expr -> Void ) {
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_): f(e);
|
case EConst(_), EIdent(_): f(e);
|
||||||
case EImport(c, _): f(e);
|
case EImport(c, _): f(e);
|
||||||
case EClass(_, e, _, _): for( a in e ) f(a);
|
case EClass(_, e, _, _): for( a in e ) f(a);
|
||||||
case EVar(_, _, e): if( e != null ) f(e);
|
case EVar(_, _, e): if( e != null ) f(e);
|
||||||
case EParent(e): f(e);
|
case EParent(e, _): f(e);
|
||||||
case EBlock(el): for( e in el ) f(e);
|
case EBlock(el): for( e in el ) f(e);
|
||||||
case EField(e, _): f(e);
|
case EField(e, _): f(e);
|
||||||
case EBinop(_, e1, e2): f(e1); f(e2);
|
case EBinop(_, e1, e2): f(e1); f(e2);
|
||||||
case EUnop(_, _, e): f(e);
|
case EUnop(_, _, e): f(e);
|
||||||
case ECall(e, args): f(e); for( a in args ) f(a);
|
case ECall(e, args): f(e); for( a in args ) f(a);
|
||||||
case EIf(c, e1, e2): f(c); f(e1); if( e2 != null ) f(e2);
|
case EIf(c, e1, e2): f(c); f(e1); if( e2 != null ) f(e2);
|
||||||
case EWhile(c, e): f(c); f(e);
|
case EWhile(c, e): f(c); f(e);
|
||||||
case EDoWhile(c, e): f(c); f(e);
|
case EDoWhile(c, e): f(c); f(e);
|
||||||
case EFor(_, it, e): f(it); f(e);
|
case EFor(_, it, e): f(it); f(e);
|
||||||
case EForKeyValue(_, it, e, _): f(it); f(e);
|
case EForKeyValue(_, it, e, _): f(it); f(e);
|
||||||
case EBreak,EContinue:
|
case EBreak,EContinue:
|
||||||
case EFunction(_, e, _, _): f(e);
|
case EFunction(_, e, _, _): f(e);
|
||||||
case EReturn(e): if( e != null ) f(e);
|
case EReturn(e): if( e != null ) f(e);
|
||||||
case EArray(e, i): f(e); f(i);
|
case EArray(e, i): f(e); f(i);
|
||||||
case EMapDecl(type, keys, values): for( e in keys ) f(e); for( e in values ) f(e);
|
case EMapDecl(type, keys, values): for( e in keys ) f(e); for( e in values ) f(e);
|
||||||
case EArrayDecl(el): for( e in el ) f(e);
|
case EArrayDecl(el): for( e in el ) f(e);
|
||||||
case ENew(_,el): for( e in el ) f(e);
|
case ENew(_,el): for( e in el ) f(e);
|
||||||
case EThrow(e): f(e);
|
case EThrow(e): f(e);
|
||||||
case ETry(e, _, _, c): f(e); f(c);
|
case ETry(e, _, _, c): f(e); f(c);
|
||||||
case EObject(fl): for( fi in fl ) f(fi.e);
|
case EObject(fl): for( fi in fl ) f(fi.e);
|
||||||
case ETernary(c, e1, e2): f(c); f(e1); f(e2);
|
case ETernary(c, e1, e2): f(c); f(e1); f(e2);
|
||||||
case ESwitch(e, cases, def):
|
case ESwitch(e, cases, def):
|
||||||
f(e);
|
f(e);
|
||||||
for( c in cases ) {
|
for( c in cases ) {
|
||||||
for( v in c.values ) f(v);
|
for( v in c.values ) f(v);
|
||||||
f(c.expr);
|
f(c.expr);
|
||||||
}
|
}
|
||||||
if( def != null ) f(def);
|
if( def != null ) f(def);
|
||||||
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
||||||
case ECheckType(e,_): f(e);
|
case ECheckType(e,_): f(e);
|
||||||
|
case EInfo(info, e): f(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function iterExprRecursive( ve : Expr, f : Expr -> Void ) {
|
||||||
|
var rec = (e:Expr) -> iterExprRecursive(e, f);
|
||||||
|
f(ve);
|
||||||
|
switch( expr(ve) ) {
|
||||||
|
case EConst(_), EIdent(_): {}
|
||||||
|
case EImport(c, _): {}
|
||||||
|
case EClass(_, e, _, _): for( a in e ) rec(a);
|
||||||
|
case EVar(_, _, e): if( e != null ) rec(e);
|
||||||
|
case EParent(e, _): rec(e);
|
||||||
|
case EBlock(el): for( e in el ) rec(e);
|
||||||
|
case EField(e, _): rec(e);
|
||||||
|
case EBinop(_, e1, e2): rec(e1); rec(e2);
|
||||||
|
case EUnop(_, _, e): rec(e);
|
||||||
|
case ECall(e, args): rec(e); for( a in args ) rec(a);
|
||||||
|
case EIf(c, e1, e2): rec(c); rec(e1); if( e2 != null ) rec(e2);
|
||||||
|
case EWhile(c, e): rec(c); rec(e);
|
||||||
|
case EDoWhile(c, e): rec(c); rec(e);
|
||||||
|
case EFor(_, it, e): rec(it); rec(e);
|
||||||
|
case EForKeyValue(_, it, e, _): rec(it); rec(e);
|
||||||
|
case EBreak,EContinue: {}
|
||||||
|
case EFunction(_, e, _, _): rec(e);
|
||||||
|
case EReturn(e): if( e != null ) rec(e);
|
||||||
|
case EArray(e, i): rec(e); rec(i);
|
||||||
|
case EMapDecl(type, keys, values): for( e in keys ) rec(e); for( e in values ) rec(e);
|
||||||
|
case EArrayDecl(el): for( e in el ) rec(e);
|
||||||
|
case ENew(_,el): for( e in el ) rec(e);
|
||||||
|
case EThrow(e): rec(e);
|
||||||
|
case ETry(e, _, _, c): rec(e); rec(c);
|
||||||
|
case EObject(fl): for( fi in fl ) rec(fi.e);
|
||||||
|
case ETernary(c, e1, e2): rec(c); rec(e1); rec(e2);
|
||||||
|
case ESwitch(e, cases, def):
|
||||||
|
rec(e);
|
||||||
|
for( c in cases ) {
|
||||||
|
for( v in c.values ) rec(v);
|
||||||
|
rec(c.expr);
|
||||||
|
}
|
||||||
|
if( def != null ) rec(def);
|
||||||
|
case EMeta(name, args, e): if( args != null ) for( a in args ) rec(a); rec(e);
|
||||||
|
case ECheckType(e,_): rec(e);
|
||||||
|
case EInfo(info, e): rec(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function map( e : Expr, f : Expr -> Expr ) {
|
public static function map( e : Expr, f : Expr -> Expr ) {
|
||||||
var edef = switch( expr(e) ) {
|
var edef = switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
||||||
case EVar(n, t, e, p, s): EVar(n, t, if( e != null ) f(e) else null, p, s);
|
case EVar(n, t, e, p, s): EVar(n, t, if( e != null ) f(e) else null, p, s);
|
||||||
case EParent(e, no): EParent(f(e), no);
|
case EParent(e, no): EParent(f(e), no);
|
||||||
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
||||||
case EField(e, fi, s): EField(f(e),fi,s);
|
case EField(e, fi, s): EField(f(e),fi,s);
|
||||||
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
|
case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2));
|
||||||
case EUnop(op, pre, e): EUnop(op, pre, f(e));
|
case EUnop(op, pre, e): EUnop(op, pre, f(e));
|
||||||
case ECall(e, args): ECall(f(e),[for( a in args ) f(a)]);
|
case ECall(e, args): ECall(f(e),[for( a in args ) f(a)]);
|
||||||
case EIf(c, e1, e2): EIf(f(c),f(e1),if( e2 != null ) f(e2) else null);
|
case EIf(c, e1, e2): EIf(f(c),f(e1),if( e2 != null ) f(e2) else null);
|
||||||
case EWhile(c, e): EWhile(f(c),f(e));
|
case EWhile(c, e): EWhile(f(c),f(e));
|
||||||
case EDoWhile(c, e): EDoWhile(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 EFor(v, it, e): EFor(v, f(it), f(e));
|
||||||
case EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
case EForKeyValue(v, it, e, ithv): EForKeyValue(v, f(it), f(e), ithv);
|
||||||
case EFunction(args, e, name, t, p, s, o): EFunction(args, f(e), name, t, p, s, o);
|
case EFunction(args, e, name, t, p, s, o): EFunction(args, f(e), name, t, p, s, o);
|
||||||
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
||||||
case EArray(e, i): EArray(f(e),f(i));
|
case EArray(e, i): EArray(f(e),f(i));
|
||||||
case EMapDecl(type, keys, values): EMapDecl(type, [for( e in keys ) f(e)], [for( e in values ) f(e)]);
|
case EMapDecl(type, keys, values): EMapDecl(type, [for( e in keys ) f(e)], [for( e in values ) f(e)]);
|
||||||
case EArrayDecl(el): EArrayDecl([for( e in el ) f(e)]);
|
case EArrayDecl(el): EArrayDecl([for( e in el ) f(e)]);
|
||||||
case ENew(cl,el): ENew(cl,[for( e in el ) f(e)]);
|
case ENew(cl,el): ENew(cl,[for( e in el ) f(e)]);
|
||||||
case EThrow(e): EThrow(f(e));
|
case EThrow(e): EThrow(f(e));
|
||||||
case ETry(e, v, t, c): ETry(f(e), v, t, f(c));
|
case ETry(e, v, t, c): ETry(f(e), v, t, f(c));
|
||||||
case EObject(fl): EObject([for( fi in fl ) new ObjectField(fi.name, 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 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 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));
|
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
||||||
case ECheckType(e,t): ECheckType(f(e), t);
|
case ECheckType(e,t): ECheckType(f(e), t);
|
||||||
case EImport(c, m): EImport(c, m);
|
case EImport(c, m): EImport(c, m);
|
||||||
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
||||||
|
case EInfo(info, e): EInfo(info, f(e));
|
||||||
}
|
}
|
||||||
return mk(edef, e);
|
return mk(edef, e);
|
||||||
}
|
}
|
||||||
@@ -133,6 +177,55 @@ class Tools {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getOpEnum(op:String):Binop {
|
||||||
|
return switch(op) {
|
||||||
|
case "+": OpAdd;
|
||||||
|
case "-": OpSub;
|
||||||
|
case "*": OpMult;
|
||||||
|
case "/": OpDiv;
|
||||||
|
case "%": OpMod;
|
||||||
|
case "&": OpAnd;
|
||||||
|
case "|": OpOr;
|
||||||
|
case "^": OpXor;
|
||||||
|
case "<<": OpShl;
|
||||||
|
case ">>": OpShr;
|
||||||
|
case ">>>": OpUShr;
|
||||||
|
case "==": OpEq;
|
||||||
|
case "!=": OpNotEq;
|
||||||
|
case ">=": OpGte;
|
||||||
|
case "<=": OpLte;
|
||||||
|
case ">": OpGt;
|
||||||
|
case "<": OpLt;
|
||||||
|
case "||": OpBoolOr;
|
||||||
|
case "&&": OpBoolAnd;
|
||||||
|
case "is": OpIs;
|
||||||
|
case "=": OpAssign;
|
||||||
|
case "=>": OpArrow;
|
||||||
|
case "??": OpNullCoal;
|
||||||
|
case "...": OpInterval;
|
||||||
|
default: {
|
||||||
|
var op2 = op.substr(0, op.length - 1);
|
||||||
|
trace(op + " -> " + op2);
|
||||||
|
if(isValidBinOp(op2)) {
|
||||||
|
return OpAssignOp(getOpEnum(op2));
|
||||||
|
}
|
||||||
|
throw "Unknown binary operator: " + op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getUnopEnum(op:String):Unop {
|
||||||
|
return switch(op) {
|
||||||
|
case "++": OpIncrement;
|
||||||
|
case "--": OpDecrement;
|
||||||
|
case "!": OpNot;
|
||||||
|
case "-": OpNeg;
|
||||||
|
case "~": OpNegBits;
|
||||||
|
case "...": OpSpread;
|
||||||
|
default: throw "Unknown unary operator: " + op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static var priorities = [
|
static var priorities = [
|
||||||
["%"],
|
["%"],
|
||||||
["*", "/"],
|
["*", "/"],
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ class Util {
|
|||||||
// Print stack trace
|
// Print stack trace
|
||||||
var stack = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
var stack = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
||||||
Sys.println("## Stack trace: " + stack);
|
Sys.println("## Stack trace: " + stack);
|
||||||
|
Sys.exit(1);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class FinalCase extends TestCase {
|
|||||||
assertDisplay("(i - x) * 30 + 90", ((i-x) * 30) + 90);
|
assertDisplay("(i - x) * 30 + 90", ((i-x) * 30) + 90);
|
||||||
assertDisplay("i - x * 30 + 90", i-x * 30 + 90);
|
assertDisplay("i - x * 30 + 90", i-x * 30 + 90);
|
||||||
|
|
||||||
|
/*
|
||||||
// Test operator precedence
|
// Test operator precedence
|
||||||
assertDisplay("i / x * 30 + 90", i / x * 30 + 90);
|
assertDisplay("i / x * 30 + 90", i / x * 30 + 90);
|
||||||
assertDisplay("i / (x * 30) + 90", i / (x * 30) + 90);
|
assertDisplay("i / (x * 30) + 90", i / (x * 30) + 90);
|
||||||
@@ -44,6 +45,7 @@ class FinalCase extends TestCase {
|
|||||||
bloomShader.dim = dim = .8 + (.3 * FlxMath.fastSin(__totalTime));
|
bloomShader.dim = dim = .8 + (.3 * FlxMath.fastSin(__totalTime));
|
||||||
bloomShader.size = size = 18 + (8 * FlxMath.fastSin(__totalTime));
|
bloomShader.size = size = 18 + (8 * FlxMath.fastSin(__totalTime));
|
||||||
');
|
');
|
||||||
|
*/
|
||||||
|
|
||||||
Util.parse('sprite.setPosition(codesList.x + (sprite.ID % 2 == 1 ? 240 : 67),codesList.y + (15 * sprite.ID) + (sprite.ID%2 == 1 ? 35 : 54));');
|
Util.parse('sprite.setPosition(codesList.x + (sprite.ID % 2 == 1 ? 240 : 67),codesList.y + (15 * sprite.ID) + (sprite.ID%2 == 1 ? 35 : 54));');
|
||||||
|
|
||||||
@@ -74,7 +76,6 @@ class FinalCase extends TestCase {
|
|||||||
|
|
||||||
assertEq("[for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]", [for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]);
|
assertEq("[for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]", [for(i in 0...10) if(i % 2 == 0) i => isEven(i) else i => isEven(i)]);
|
||||||
assertEq("[for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]", [for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]);
|
assertEq("[for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]", [for(i in 0...10) if(i % 2 == 0) isEven(i) else isEven(i)]);
|
||||||
|
|
||||||
headerCode = "function area(a:Int, b:Int):Int { return a * b; };";
|
headerCode = "function area(a:Int, b:Int):Int { return a * b; };";
|
||||||
function area(a:Int, b:Int):Int { return a * b; }
|
function area(a:Int, b:Int):Int { return a * b; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user