From 4170a4aafc640934c59a3bdc876533fcab5d343a Mon Sep 17 00:00:00 2001 From: lunarcleint <88809950+lunarcleint@users.noreply.github.com> Date: Sun, 28 Apr 2024 02:15:10 -0700 Subject: [PATCH] i cant wait to break all ur hscripts --- hscript/CustomClassHandler.hx | 3 +- hscript/Expr.hx | 10 +-- hscript/Interp.hx | 153 ++++++++++++++++++++++++++++------ hscript/Optimizer.hx | 2 + hscript/Parser.hx | 5 +- hscript/Preprocessor.hx | 105 +++++++++++++++++++++++ hscript/Tools.hx | 2 +- tests/src/tests/TestCase.hx | 2 + 8 files changed, 246 insertions(+), 36 deletions(-) diff --git a/hscript/CustomClassHandler.hx b/hscript/CustomClassHandler.hx index 3efbd40..118a43d 100644 --- a/hscript/CustomClassHandler.hx +++ b/hscript/CustomClassHandler.hx @@ -53,7 +53,8 @@ class CustomClassHandler implements IHScriptCustomConstructor { } } - _class.__custom__variables = interp.variables; + // ! lunar do NOT forget you commented this + // _class.__custom__variables = interp.variables; for(expr in fields) { @:privateAccess diff --git a/hscript/Expr.hx b/hscript/Expr.hx index f9252bf..45ca168 100644 --- a/hscript/Expr.hx +++ b/hscript/Expr.hx @@ -62,8 +62,8 @@ enum Expr #end { EConst( c : Const ); - EIdent( v : String ); - EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool ); + EIdent( v : String , ?vid : Int); + EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool , ?vid : Int); EParent( e : Expr, ?noOptimize : Bool ); EBlock( e : Array ); EField( e : Expr, f : String , ?safe : Bool ); @@ -76,12 +76,12 @@ enum Expr EForKeyValue( v : String, it : Expr, e : Expr, ithv: String); EBreak; EContinue; - EFunction( args : Array, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool ); + EFunction( args : Array, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool , ?fid : Int); EReturn( ?e : Expr ); EArray( e : Expr, index : Expr ); EMapDecl( type: MapType, keys: Array, values: Array ); EArrayDecl( e : Array ); - ENew( cl : String, params : Array ); + ENew( cl : String, params : Array , ?cid : Int); EThrow( e : Expr ); ETry( e : Expr, v : String, t : Null, ecatch : Expr ); EObject( fl : Array ); @@ -92,7 +92,7 @@ enum Expr ECheckType( e : Expr, t : CType ); EImport( c : String, mode: KImportMode ); - EClass( name:String, fields:Array, ?extend:String, interfaces:Array ); + EClass( name:String, fields:Array, ?extend:String, interfaces:Array , ?cid : Int ); } enum KImportMode { diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 22de9bf..a77acab 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -35,6 +35,7 @@ import haxe.display.Protocol.InitializeResult; import haxe.iterators.StringKeyValueIteratorUnicode; import hscript.Expr; import hscript.utils.UnsafeReflect; +import haxe.iterators.ArrayIterator; using StringTools; @@ -92,20 +93,24 @@ class Interp { } public var errorHandler:Error->Void; public var importFailedCallback:Array->Bool; - #if haxe3 // Also Applies to 4.0.0 and above - public var customClasses:Map; - public var variables:Map; - public var publicVariables:Map; - public var staticVariables:Map; + public var _variablesNames:Array = []; + public var _variables:Array = []; + public var _publicVariables:Array = []; + public var _staticVariables:Array = []; + public var _customClasses:Array = []; + public var _locals:Array = []; + + // !BACKWARDS COMPAT + public var customClasses:HScriptVariables; + public var variables:HScriptVariables; + public var publicVariables:HScriptVariables; + public var staticVariables:HScriptVariables; + + #if haxe3 public var locals:Map; var binops:MapExpr->Dynamic>; #else - public var customClasses:Hash; - public var variables:Hash; - public var publicVariables:Hash; - public var staticVariables:Hash; - public var locals:Hash; var binops:HashExpr->Dynamic>; #end @@ -132,29 +137,23 @@ class Interp { #end public function new() { - #if haxe3 - locals = new Map(); - #else - locals = new Hash(); - #end declared = new Array(); resetVariables(); initOps(); } private function resetVariables() { - #if haxe3 - customClasses = new Map(); - variables = new Map(); - publicVariables = new Map(); - staticVariables = new Map(); - #else - customClasses = new Hash(); - variables = new Hash(); - publicVariables = new Hash(); - staticVariables = new Hash(); - #end + _variablesNames = []; + _variables = []; + _publicVariables = []; + _staticVariables = []; + _customClasses = []; + _locals = []; + staticVariables = publicVariables = customClasses = variables = new HScriptVariables(this); + } + + private function setDefualtVariables() { variables.set("null", null); variables.set("true", true); variables.set("false", false); @@ -428,6 +427,15 @@ class Interp { locals = new Hash(); #end declared = new Array(); + + Preprocessor.getvars(expr, _variablesNames); + _variables = cast new haxe.ds.Vector(_variablesNames.length); + _publicVariables = cast new haxe.ds.Vector(_variablesNames.length); + _staticVariables = cast new haxe.ds.Vector(_variablesNames.length); + _customClasses = cast new haxe.ds.Vector(_variablesNames.length); + _locals = cast new haxe.ds.Vector(_variablesNames.length); + + setDefualtVariables(); return exprReturn(expr); } @@ -499,6 +507,38 @@ class Interp { #end } + public function iresolve(id:String, doException:Bool = true):Dynamic { + if (id == null) + return null; + id = StringTools.trim(id); + var l = locals.get(id); + if (l != null) + return l.r; + + for(map in [variables, publicVariables, staticVariables, customClasses]) + if (map.exists(id)) + return map.get(id); + + if (_hasScriptObject) { + // search in object + if (id == "this") { + return scriptObject; + } else if (_scriptObjectType == SObject && UnsafeReflect.hasField(scriptObject, id)) { + return UnsafeReflect.field(scriptObject, id); + } else { + if (__instanceFields.contains(id)) { + return UnsafeReflect.getProperty(scriptObject, id); + } else if (__instanceFields.contains('get_$id')) { // getter + return UnsafeReflect.getProperty(scriptObject, 'get_$id')(); + } + } + } + if (doException) + error(EUnknownVariable(id)); + //var v = variables.get(id); + return null; + } + public function resolve(id:String, doException:Bool = true):Dynamic { if (id == null) return null; @@ -509,7 +549,7 @@ class Interp { for(map in [variables, publicVariables, staticVariables, customClasses]) if (map.exists(id)) - return map[id]; + return map.get(id); if (_hasScriptObject) { // search in object @@ -1159,3 +1199,62 @@ class Interp { static inline function b2i(b:Bool) return b ? 1 : 0; } + +class HScriptVariables { + public var parent:Interp; + public function new(parent:Interp) + this.parent = parent; + + public inline function set(key:String, value:Dynamic) { + if (parent._variablesNames.contains(key)) + parent._variables[parent._variablesNames.indexOf(key)] = value; + } + + public inline function get(key:String):Dynamic { + if (parent._variablesNames.contains(key)) + return parent._variables[parent._variablesNames.indexOf(key)]; + return null; + } + + public inline function exists(key:String):Bool { + var indx:Int = parent._variablesNames.indexOf(key); + return indx != -1 && (key == "null" ? true : parent._variables[indx] != null); + } + + public inline function remove(key:String) + parent._variables[parent._variablesNames.indexOf(key)] = null; + + public inline function clear():Void { + parent._variablesNames.resize(0); + parent._variables.resize(0); + } + + public inline function copy():Map { + var map:Map = [ + for (i in 0...parent._variables.length) + parent._variablesNames[i] => parent._variables[i] + ]; + return map; + } + + public inline function iterator():ArrayIterator + return parent._variables.iterator(); + + public inline function keys():ArrayIterator + return parent._variablesNames.iterator(); + + public inline function keyValueIterator() : HScriptVariables { + _current = 0; + 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]}; + } +} \ No newline at end of file diff --git a/hscript/Optimizer.hx b/hscript/Optimizer.hx index 6d3879f..5b6df61 100644 --- a/hscript/Optimizer.hx +++ b/hscript/Optimizer.hx @@ -50,6 +50,7 @@ class Optimizer { newExprs.push(e); } } + return mk(EBlock(newExprs), s); case EIf(econd, e1, e2): @@ -430,6 +431,7 @@ class Optimizer { default: Sys.println("Unknown expr: " + e); } + return s; } diff --git a/hscript/Parser.hx b/hscript/Parser.hx index abfec49..6f2b997 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -227,9 +227,10 @@ class Parser { expr = Preprocessor.process(expr); if(Parser.optimize) { expr = Optimizer.optimize(expr); - trace("INPUT: " + s); - trace("OUTPUT: " + Printer.toString(expr)); + // trace("INPUT: " + s); + // trace("OUTPUT: " + Printer.toString(expr)); } + expr = Preprocessor.processvars(expr, []); return expr; } diff --git a/hscript/Preprocessor.hx b/hscript/Preprocessor.hx index 81385c1..bb3a142 100644 --- a/hscript/Preprocessor.hx +++ b/hscript/Preprocessor.hx @@ -144,4 +144,109 @@ class Preprocessor { } return isStringFromCharCodeFixed; } + + public static function processvars(e:Expr, vars:Array) { + 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) { + // 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: + } + } } \ No newline at end of file diff --git a/hscript/Tools.hx b/hscript/Tools.hx index a98ab6c..0a6ea4d 100644 --- a/hscript/Tools.hx +++ b/hscript/Tools.hx @@ -27,7 +27,7 @@ class Tools { public static function iter( e : Expr, f : Expr -> Void ) { switch( expr(e) ) { - case EConst(_), EIdent(_): + case EConst(_), EIdent(_): f(e); case EImport(c, _): f(e); case EClass(_, e, _, _): for( a in e ) f(a); case EVar(_, _, e): if( e != null ) f(e); diff --git a/tests/src/tests/TestCase.hx b/tests/src/tests/TestCase.hx index 8619cfe..fdd7df2 100644 --- a/tests/src/tests/TestCase.hx +++ b/tests/src/tests/TestCase.hx @@ -16,6 +16,8 @@ class TestCase extends HScriptRunner { execute(script); if(!Util.assertEq(result, expected, message, pos)) { Sys.println("> " + Printer.convertExprToString(lastExpr)); + Sys.println("> " + interp._variablesNames); + Sys.println("> " + interp._variables); return false; } return true;