Classes work more reliably + Optimizations
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package hscript;
|
||||
|
||||
import hscript.Interp.DeclaredVar;
|
||||
import hscript.utils.UnsafeReflect;
|
||||
using StringTools;
|
||||
|
||||
class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
@@ -11,12 +13,18 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
public var extend:String;
|
||||
public var interfaces:Array<String>;
|
||||
|
||||
public var cl:Class<Dynamic>;
|
||||
|
||||
public function new(ogInterp:Interp, name:String, fields:Array<Expr>, ?extend:String, ?interfaces:Array<String>) {
|
||||
this.ogInterp = ogInterp;
|
||||
this.name = name;
|
||||
this.fields = fields;
|
||||
this.extend = extend;
|
||||
this.interfaces = interfaces;
|
||||
|
||||
this.cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
||||
if(cl == null)
|
||||
ogInterp.error(EInvalidClass(extend));
|
||||
}
|
||||
|
||||
public function hnew(args:Array<Dynamic>):Dynamic {
|
||||
@@ -24,14 +32,10 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
|
||||
interp.errorHandler = ogInterp.errorHandler;
|
||||
|
||||
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
||||
if(cl == null)
|
||||
ogInterp.error(EInvalidClass(extend));
|
||||
|
||||
var _class = Type.createInstance(cl, args);
|
||||
var _class:IHScriptCustomClassBehaviour = Type.createInstance(cl, args);
|
||||
|
||||
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
|
||||
var capturedLocals:Map<String, {r:Dynamic, depth:Int}> = [];
|
||||
var capturedLocals:Map<String, DeclaredVar> = [];
|
||||
for(k=>e in __capturedLocals)
|
||||
if (e != null && e.depth <= 0)
|
||||
capturedLocals.set(k, e);
|
||||
@@ -49,6 +53,15 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
var comparisonMap = new Map();
|
||||
for(key => value in interp.variables) {
|
||||
comparisonMap.set(key, value);
|
||||
}
|
||||
|
||||
_class.__custom__variables = interp.variables;
|
||||
|
||||
//trace(fields);
|
||||
|
||||
for(expr in fields) {
|
||||
@:privateAccess
|
||||
interp.exprReturn(expr);
|
||||
@@ -58,14 +71,33 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
|
||||
_class.__interp = interp;
|
||||
interp.scriptObject = _class;
|
||||
|
||||
var newFunc = interp.variables.get("new");
|
||||
if(newFunc != null) {
|
||||
Reflect.callMethod(null, newFunc, args);
|
||||
// get only variables that were not set before
|
||||
var classVariables = [for(key => value in interp.variables) if(!comparisonMap.exists(key) || comparisonMap[key] != value) key => value];
|
||||
for(variable => value in classVariables) {
|
||||
if(variable == "this" || variable == "super") continue;
|
||||
@:privateAccess
|
||||
if(!interp.__instanceFields.contains(variable)) {
|
||||
interp.__instanceFields.push(variable);
|
||||
}
|
||||
}
|
||||
|
||||
//trace([for(key => value in classVariables) key]);
|
||||
//@:privateAccess
|
||||
//trace(interp.__instanceFields);
|
||||
|
||||
_class.__allowSetGet = false;
|
||||
|
||||
for(variable => value in interp.variables) {
|
||||
if(variable == "this") continue;
|
||||
|
||||
if(variable.startsWith("set_") || variable.startsWith("get_")) {
|
||||
_class.__allowSetGet = true;
|
||||
}
|
||||
}
|
||||
|
||||
var newFunc = interp.variables.get("new");
|
||||
if(newFunc != null) {
|
||||
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
|
||||
}
|
||||
|
||||
return _class;
|
||||
@@ -76,29 +108,44 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
class TemplateClass implements IHScriptCustomBehaviour {
|
||||
class TemplateClass implements IHScriptCustomClassBehaviour implements IHScriptCustomBehaviour {
|
||||
public var __interp:Interp;
|
||||
public var __allowSetGet:Bool = true;
|
||||
public var __custom__variables:Map<String, Dynamic>;
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
if(this.__interp.variables.exists("set_" + name)) {
|
||||
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||
}
|
||||
if (this.__interp.variables.exists(name)) {
|
||||
this.__interp.variables.set(name, val);
|
||||
if(__allowSetGet && __custom__variables.exists("set_" + name))
|
||||
return __callSetter(name, val);
|
||||
if (__custom__variables.exists(name)) {
|
||||
__custom__variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
Reflect.setProperty(this, name, val);
|
||||
return Reflect.field(this, name);
|
||||
UnsafeReflect.setProperty(this, name, val);
|
||||
return UnsafeReflect.field(this, name);
|
||||
}
|
||||
public function hget(name:String):Dynamic {
|
||||
if(this.__interp.variables.exists("get_" + name))
|
||||
return this.__interp.variables.get("get_" + name)();
|
||||
if (this.__interp.variables.exists(name))
|
||||
return this.__interp.variables.get(name);
|
||||
return Reflect.getProperty(this, name);
|
||||
if(__allowSetGet && __custom__variables.exists("get_" + name))
|
||||
return __callGetter(name);
|
||||
if (__custom__variables.exists(name))
|
||||
return __custom__variables.get(name);
|
||||
return UnsafeReflect.getProperty(this, name);
|
||||
}
|
||||
|
||||
public function __callGetter(name:String):Dynamic {
|
||||
__allowSetGet = false;
|
||||
var v = __custom__variables.get("get_" + name)();
|
||||
__allowSetGet = true;
|
||||
return v;
|
||||
}
|
||||
|
||||
public function __callSetter(name:String, val:Dynamic):Dynamic {
|
||||
__allowSetGet = false;
|
||||
var v = __custom__variables.get("set_" + name)(val);
|
||||
__allowSetGet = true;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
class StaticHandler {
|
||||
final class StaticHandler {
|
||||
public function new() {}
|
||||
}
|
||||
+31
-14
@@ -21,6 +21,16 @@
|
||||
*/
|
||||
package hscript;
|
||||
|
||||
typedef Int8 = #if cpp cpp.Int8 #else Int #end;
|
||||
typedef Int16 = #if cpp cpp.Int16 #else Int #end;
|
||||
typedef Int32 = #if cpp cpp.Int32 #else Int #end;
|
||||
typedef Int64 = #if cpp cpp.Int64 #else Int #end;
|
||||
|
||||
typedef UInt8 = #if cpp cpp.UInt8 #else Int #end;
|
||||
typedef UInt16 = #if cpp cpp.UInt16 #else Int #end;
|
||||
typedef UInt32 = #if cpp cpp.UInt32 #else Int #end;
|
||||
typedef UInt64 = #if cpp cpp.UInt64 #else Int #end;
|
||||
|
||||
enum Const {
|
||||
CInt( v : Int );
|
||||
CFloat( f : Float );
|
||||
@@ -31,12 +41,13 @@ enum Const {
|
||||
}
|
||||
|
||||
#if hscriptPos
|
||||
typedef Expr = {
|
||||
var e : ExprDef;
|
||||
var pmin : Int;
|
||||
var pmax : Int;
|
||||
var origin : String;
|
||||
var line : Int;
|
||||
@:structInit
|
||||
final class Expr {
|
||||
public var e : ExprDef;
|
||||
public var pmin : Int;
|
||||
public var pmax : Int;
|
||||
public var origin : String;
|
||||
public var line : Int;
|
||||
}
|
||||
enum ExprDef {
|
||||
#else
|
||||
@@ -66,7 +77,7 @@ enum Expr {
|
||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||
EObject( fl : Array<{ name : String, e : Expr }> );
|
||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr );
|
||||
ESwitch( e : Expr, cases : Array<SwitchCase>, ?defaultExpr : Expr );
|
||||
EDoWhile( cond : Expr, e : Expr);
|
||||
EMeta( name : String, args : Array<Expr>, e : Expr );
|
||||
ECheckType( e : Expr, t : CType );
|
||||
@@ -75,6 +86,12 @@ enum Expr {
|
||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||
}
|
||||
|
||||
@:structInit
|
||||
final class SwitchCase {
|
||||
public var values : Array<Expr>;
|
||||
public var expr : Expr;
|
||||
}
|
||||
|
||||
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||
|
||||
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
||||
@@ -157,13 +174,13 @@ typedef FieldDecl = {
|
||||
var access : Array<FieldAccess>;
|
||||
}
|
||||
|
||||
enum FieldAccess {
|
||||
APublic;
|
||||
APrivate;
|
||||
AInline;
|
||||
AOverride;
|
||||
AStatic;
|
||||
AMacro;
|
||||
enum abstract FieldAccess(UInt8) {
|
||||
var APublic;
|
||||
var APrivate;
|
||||
var AInline;
|
||||
var AOverride;
|
||||
var AStatic;
|
||||
var AMacro;
|
||||
}
|
||||
|
||||
enum FieldKind {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package hscript;
|
||||
|
||||
interface IHScriptCustomClassBehaviour {
|
||||
public var __interp:Interp;
|
||||
public var __custom__variables:Map<String, Dynamic>;
|
||||
public var __allowSetGet:Bool;
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic;
|
||||
public function hget(name:String):Dynamic;
|
||||
|
||||
public function __callGetter(name:String):Dynamic;
|
||||
|
||||
public function __callSetter(name:String, val:Dynamic):Dynamic;
|
||||
}
|
||||
+227
-108
@@ -28,9 +28,7 @@
|
||||
*/
|
||||
package hscript;
|
||||
|
||||
import haxe.iterators.StringKeyValueIteratorUnicode;
|
||||
import haxe.EnumTools;
|
||||
import haxe.display.Protocol.InitializeResult;
|
||||
import hscript.utils.UnsafeReflect;
|
||||
import haxe.PosInfos;
|
||||
import hscript.Expr;
|
||||
import haxe.Constraints.IMap;
|
||||
@@ -43,10 +41,58 @@ private enum Stop {
|
||||
SReturn;
|
||||
}
|
||||
|
||||
enum abstract ScriptObjectType(UInt8) {
|
||||
var SClass;
|
||||
var SObject;
|
||||
var SStaticClass;
|
||||
var SCustomClass;
|
||||
var SBehaviourClass;
|
||||
var SNull;
|
||||
}
|
||||
|
||||
@:structInit
|
||||
class DeclaredVar {
|
||||
public var r:Dynamic;
|
||||
public var depth:Int;
|
||||
}
|
||||
|
||||
@:structInit
|
||||
class RedeclaredVar {
|
||||
public var n:String;
|
||||
public var old:DeclaredVar;
|
||||
public var depth:Int;
|
||||
}
|
||||
|
||||
class Interp {
|
||||
public var scriptObject(default, set):Dynamic;
|
||||
private var _hasScriptObject(default, null):Bool = false;
|
||||
private var _scriptObjectType(default, null):ScriptObjectType = SNull;
|
||||
public function set_scriptObject(v:Dynamic) {
|
||||
__instanceFields = (v == null) ? [] : Type.getInstanceFields(Type.getClass(v));
|
||||
switch(Type.typeof(v)) {
|
||||
case TClass(c): // Class Access
|
||||
__instanceFields = Type.getInstanceFields(c);
|
||||
if(c is IHScriptCustomClassBehaviour) {
|
||||
_scriptObjectType = SCustomClass;
|
||||
} else if(c is IHScriptCustomBehaviour) {
|
||||
_scriptObjectType = SBehaviourClass;
|
||||
} else {
|
||||
_scriptObjectType = SClass;
|
||||
}
|
||||
case TObject: // Object Access or Static Class Access
|
||||
var cls = Type.getClass(v);
|
||||
switch(Type.typeof(cls)) {
|
||||
case TClass(c): // Static Class Access
|
||||
__instanceFields = Type.getInstanceFields(c);
|
||||
_scriptObjectType = SStaticClass;
|
||||
default: // Object Access
|
||||
__instanceFields = Reflect.fields(v);
|
||||
_scriptObjectType = SObject;
|
||||
}
|
||||
default: // Null or other
|
||||
__instanceFields = [];
|
||||
_scriptObjectType = SNull;
|
||||
}
|
||||
_hasScriptObject = v != null;
|
||||
return scriptObject = v;
|
||||
}
|
||||
public var errorHandler:Error->Void;
|
||||
@@ -57,7 +103,7 @@ class Interp {
|
||||
public var publicVariables:Map<String, Dynamic>;
|
||||
public var staticVariables:Map<String, Dynamic>;
|
||||
|
||||
public var locals:Map<String, {r:Dynamic, depth:Int}>;
|
||||
public var locals:Map<String, DeclaredVar>;
|
||||
var binops:Map<String, Expr->Expr->Dynamic>;
|
||||
#else
|
||||
public var customClasses:Hash<Dynamic>;
|
||||
@@ -65,13 +111,13 @@ class Interp {
|
||||
public var publicVariables:Hash<Dynamic>;
|
||||
public var staticVariables:Hash<Dynamic>;
|
||||
|
||||
public var locals:Hash<{r:Dynamic, depth:Int}>;
|
||||
public var locals:Hash<DeclaredVar>;
|
||||
var binops:Hash<Expr->Expr->Dynamic>;
|
||||
#end
|
||||
|
||||
var depth:Int = 0;
|
||||
var inTry:Bool;
|
||||
var declared:Array<{n:String, old:{r:Dynamic, depth:Int}, depth:Int}>;
|
||||
var declared:Array<RedeclaredVar>;
|
||||
var returnValue:Dynamic;
|
||||
|
||||
var isBypassAccessor:Bool = false;
|
||||
@@ -214,22 +260,34 @@ class Interp {
|
||||
var v = expr(e2);
|
||||
switch (Tools.expr(e1)) {
|
||||
case EIdent(id):
|
||||
var l = locals.get(id);
|
||||
if (l == null) {
|
||||
if (!variables.exists(id) && !staticVariables.exists(id) && !publicVariables.exists(id) && scriptObject != null) {
|
||||
if (Type.typeof(scriptObject) == TObject) {
|
||||
Reflect.setField(scriptObject, id, v);
|
||||
if (!locals.exists(id)) {
|
||||
if (_hasScriptObject && !variables.exists(id) && !staticVariables.exists(id) && !publicVariables.exists(id)) {
|
||||
if (_scriptObjectType == SObject) {
|
||||
UnsafeReflect.setField(scriptObject, id, v);
|
||||
} else {
|
||||
if (_scriptObjectType == SCustomClass) {
|
||||
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
|
||||
if(isBypassAccessor) {
|
||||
obj.__allowSetGet = false;
|
||||
var res = obj.hset(id, v);
|
||||
obj.__allowSetGet = true;
|
||||
return res;
|
||||
}
|
||||
return obj.hset(id, v);
|
||||
} else if (_scriptObjectType == SBehaviourClass) {
|
||||
var obj = cast(scriptObject, IHScriptCustomBehaviour);
|
||||
return obj.hset(id, v);
|
||||
}
|
||||
if (isBypassAccessor) {
|
||||
if (__instanceFields.contains(id)) {
|
||||
Reflect.setField(scriptObject, id, v);
|
||||
UnsafeReflect.setField(scriptObject, id, v);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
if (__instanceFields.contains(id)) {
|
||||
Reflect.setProperty(scriptObject, id, v);
|
||||
UnsafeReflect.setProperty(scriptObject, id, v);
|
||||
} else if (__instanceFields.contains('set_$id')) { // setter
|
||||
Reflect.getProperty(scriptObject, 'set_$id')(v);
|
||||
UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
|
||||
} else {
|
||||
setVar(id, v);
|
||||
}
|
||||
@@ -238,6 +296,7 @@ class Interp {
|
||||
setVar(id, v);
|
||||
}
|
||||
} else {
|
||||
var l = locals.get(id);
|
||||
l.r = v;
|
||||
if (l.depth == 0) {
|
||||
setVar(id, v);
|
||||
@@ -275,12 +334,38 @@ class Interp {
|
||||
var l = locals.get(id);
|
||||
v = fop(expr(e1), expr(e2));
|
||||
if (l == null) {
|
||||
if (__instanceFields.contains(id)) {
|
||||
Reflect.setProperty(scriptObject, id, v);
|
||||
} else if (__instanceFields.contains('set_$id')) { // setter
|
||||
Reflect.getProperty(scriptObject, 'set_$id')(v);
|
||||
} else {
|
||||
setVar(id, v);
|
||||
if(_hasScriptObject) {
|
||||
if(_scriptObjectType == SObject) {
|
||||
UnsafeReflect.setField(scriptObject, id, v);
|
||||
return v;
|
||||
} else if (_scriptObjectType == SCustomClass) {
|
||||
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
|
||||
if(isBypassAccessor) {
|
||||
obj.__allowSetGet = false;
|
||||
var res = obj.hset(id, v);
|
||||
obj.__allowSetGet = true;
|
||||
return res;
|
||||
}
|
||||
return obj.hset(id, v);
|
||||
} else if(_scriptObjectType == SBehaviourClass) {
|
||||
var obj = cast(scriptObject, IHScriptCustomBehaviour);
|
||||
return obj.hset(id, v);
|
||||
}
|
||||
|
||||
if (isBypassAccessor) {
|
||||
if (__instanceFields.contains(id)) {
|
||||
UnsafeReflect.setField(scriptObject, id, v);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
if (__instanceFields.contains(id)) {
|
||||
UnsafeReflect.setProperty(scriptObject, id, v);
|
||||
} else if (__instanceFields.contains('set_$id')) { // setter
|
||||
UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
|
||||
} else {
|
||||
setVar(id, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -294,8 +379,10 @@ class Interp {
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
v = fop(getMapValue(arr, index), expr(e2));
|
||||
setMapValue(arr, index, v);
|
||||
var map = getMap(arr);
|
||||
|
||||
v = fop(map.get(index), expr(e2));
|
||||
map.set(index, v);
|
||||
} else {
|
||||
v = fop(arr[index], expr(e2));
|
||||
arr[index] = v;
|
||||
@@ -313,19 +400,24 @@ class Interp {
|
||||
#end
|
||||
switch (e) {
|
||||
case EIdent(id):
|
||||
var l = locals.get(id);
|
||||
var v:Dynamic = (l == null) ? resolve(id) : l.r;
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
if (l == null)
|
||||
setVar(id, v)
|
||||
else
|
||||
if(locals.exists(id)) {
|
||||
var l = locals.get(id);
|
||||
var v:Dynamic = l.r;
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
l.r = v;
|
||||
} else if (l == null)
|
||||
setVar(id, v + delta)
|
||||
else
|
||||
l.r = v + delta;
|
||||
return v;
|
||||
} else
|
||||
l.r = v + delta;
|
||||
return v;
|
||||
} else {
|
||||
var v:Dynamic = resolve(id);
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
setVar(id, v);
|
||||
} else
|
||||
setVar(id, v + delta);
|
||||
return v;
|
||||
}
|
||||
case EField(e, f, s):
|
||||
var obj = expr(e);
|
||||
if(s && obj == null) return null;
|
||||
@@ -340,12 +432,14 @@ class Interp {
|
||||
var arr:Dynamic = expr(e);
|
||||
var index:Dynamic = expr(index);
|
||||
if (isMap(arr)) {
|
||||
var v = getMapValue(arr, index);
|
||||
var map = getMap(arr);
|
||||
|
||||
var v = map.get(index);
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
setMapValue(arr, index, v);
|
||||
map.set(index, v);
|
||||
} else {
|
||||
setMapValue(arr, index, v + delta);
|
||||
map.set(index, v + delta);
|
||||
}
|
||||
return v;
|
||||
} else {
|
||||
@@ -445,32 +539,48 @@ class Interp {
|
||||
if (id == null)
|
||||
return null;
|
||||
id = StringTools.trim(id);
|
||||
var l = locals.get(id);
|
||||
if (l != null)
|
||||
return l.r;
|
||||
if (locals.exists(id))
|
||||
return locals.get(id).r;
|
||||
|
||||
var v = variables.get(id);
|
||||
for(map in [variables, publicVariables, staticVariables, customClasses])
|
||||
if (map.exists(id))
|
||||
return map[id];
|
||||
if(variables.exists(id))
|
||||
return variables.get(id);
|
||||
if(publicVariables.exists(id))
|
||||
return publicVariables.get(id);
|
||||
if(staticVariables.exists(id))
|
||||
return staticVariables.get(id);
|
||||
if(customClasses.exists(id))
|
||||
return customClasses.get(id);
|
||||
|
||||
if (scriptObject != null) {
|
||||
if (_hasScriptObject) {
|
||||
// search in object
|
||||
if (id == "this") {
|
||||
return scriptObject;
|
||||
} else if ((Type.typeof(scriptObject) == TObject) && Reflect.hasField(scriptObject, id)) {
|
||||
return Reflect.field(scriptObject, id);
|
||||
} else {
|
||||
} else if (_scriptObjectType == SObject && UnsafeReflect.hasField(scriptObject, id)) {
|
||||
return UnsafeReflect.field(scriptObject, id);
|
||||
} else if(_scriptObjectType == SCustomClass) {
|
||||
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
|
||||
if(isBypassAccessor) {
|
||||
obj.__allowSetGet = false;
|
||||
var res = obj.hget(id);
|
||||
obj.__allowSetGet = true;
|
||||
return res;
|
||||
}
|
||||
return obj.hget(id);
|
||||
} else if(_scriptObjectType == SBehaviourClass) {
|
||||
var obj = cast(scriptObject, IHScriptCustomBehaviour);
|
||||
return obj.hget(id);
|
||||
}
|
||||
else {
|
||||
if (__instanceFields.contains(id)) {
|
||||
return Reflect.getProperty(scriptObject, id);
|
||||
return UnsafeReflect.getProperty(scriptObject, id);
|
||||
} else if (__instanceFields.contains('get_$id')) { // getter
|
||||
return Reflect.getProperty(scriptObject, 'get_$id')();
|
||||
return UnsafeReflect.getProperty(scriptObject, 'get_$id')();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doException)
|
||||
error(EUnknownVariable(id));
|
||||
return v;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function expr(e:Expr):Dynamic {
|
||||
@@ -541,10 +651,10 @@ class Interp {
|
||||
var enumThingy = {};
|
||||
for (c in en.getConstructors()) {
|
||||
try {
|
||||
Reflect.setField(enumThingy, c, en.createByName(c));
|
||||
UnsafeReflect.setField(enumThingy, c, en.createByName(c));
|
||||
} catch(e) {
|
||||
try {
|
||||
Reflect.setField(enumThingy, c, Reflect.field(en, c));
|
||||
UnsafeReflect.setField(enumThingy, c, UnsafeReflect.field(en, c));
|
||||
} catch(ex) {
|
||||
throw e;
|
||||
}
|
||||
@@ -621,9 +731,7 @@ class Interp {
|
||||
error(EInvalidOp(op));
|
||||
}
|
||||
case ECall(e, params):
|
||||
var args = new Array();
|
||||
for (p in params)
|
||||
args.push(expr(p));
|
||||
var args:Array<Dynamic> = [for(p in params) expr(p)];
|
||||
|
||||
switch (Tools.expr(e)) {
|
||||
case EField(e, f, s):
|
||||
@@ -656,7 +764,7 @@ class Interp {
|
||||
throw SReturn;
|
||||
case EFunction(params, fexpr, name, _, isPublic, isStatic, isOverride):
|
||||
var __capturedLocals = duplicate(locals);
|
||||
var capturedLocals:Map<String, {r:Dynamic, depth:Int}> = [];
|
||||
var capturedLocals:Map<String, DeclaredVar> = [];
|
||||
for(k=>e in __capturedLocals)
|
||||
if (e != null && e.depth > 0)
|
||||
capturedLocals.set(k, e);
|
||||
@@ -727,7 +835,7 @@ class Interp {
|
||||
} else {
|
||||
// function-in-function is a local function
|
||||
declared.push({n: name, old: locals.get(name), depth: depth});
|
||||
var ref = {r: f, depth: depth};
|
||||
var ref:DeclaredVar = {r: f, depth: depth};
|
||||
locals.set(name, ref);
|
||||
capturedLocals.set(name, ref); // allow self-recursion
|
||||
}
|
||||
@@ -844,7 +952,7 @@ class Interp {
|
||||
case EObject(fl):
|
||||
var o = {};
|
||||
for (f in fl)
|
||||
set(o, f.name, expr(f.e));
|
||||
UnsafeReflect.setField(o, f.name, expr(f.e));
|
||||
return o;
|
||||
case ETernary(econd, e1, e2):
|
||||
return if (expr(econd) == true) expr(e1) else expr(e2);
|
||||
@@ -945,8 +1053,10 @@ class Interp {
|
||||
declared.push({n: ithv, old: locals.get(ithv), depth: depth});
|
||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||
var it = makeIterator(expr(it), isKeyValue);
|
||||
while (it.hasNext()) {
|
||||
var next = it.next();
|
||||
var _hasNext = it.hasNext;
|
||||
var _next = it.next;
|
||||
while (_hasNext()) {
|
||||
var next = _next();
|
||||
if(isKeyValue)
|
||||
locals.set(ithv, {r: next.key, depth: depth});
|
||||
locals.set(n, {r: isKeyValue ? next.value : next, depth: depth});
|
||||
@@ -969,81 +1079,91 @@ class Interp {
|
||||
return (o is IMap);
|
||||
}
|
||||
|
||||
inline function getMap(map:Dynamic):IMap<Dynamic, Dynamic> {
|
||||
return cast(map, IMap<Dynamic, Dynamic>);
|
||||
}
|
||||
|
||||
inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
|
||||
return cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).get(key);
|
||||
return cast(map, IMap<Dynamic, Dynamic>).get(key);
|
||||
}
|
||||
|
||||
inline function setMapValue(map:Dynamic, key:Dynamic, value:Dynamic):Void {
|
||||
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
|
||||
cast(map, IMap<Dynamic, Dynamic>).set(key, value);
|
||||
}
|
||||
|
||||
public static var getRedirects:Map<String, Dynamic->String->Dynamic> = [];
|
||||
public static var setRedirects:Map<String, Dynamic->String->Dynamic->Dynamic> = [];
|
||||
|
||||
private static var _getRedirect:Dynamic->String->Dynamic;
|
||||
private static var _setRedirect:Dynamic->String->Dynamic->Dynamic;
|
||||
|
||||
public var useRedirects:Bool = false;
|
||||
|
||||
static function getClassType(o:Dynamic, ?cls:Class<Any>):Null<String> {
|
||||
return switch (Type.typeof(o)) {
|
||||
case TNull: "Null";
|
||||
case TInt: "Int";
|
||||
case TFloat: "Float";
|
||||
case TBool: "Bool";
|
||||
case _:
|
||||
if (cls == null)
|
||||
cls = Type.getClass(o);
|
||||
cls != null ? Type.getClassName(cls) : null;
|
||||
};
|
||||
}
|
||||
|
||||
function get(o:Dynamic, f:String):Dynamic {
|
||||
if (o == null)
|
||||
error(EInvalidAccess(f));
|
||||
return {
|
||||
var redirect:Dynamic->String->Dynamic = null;
|
||||
var cls = Type.getClass(o);
|
||||
var cl:Null<String> = switch (Type.typeof(o)) {
|
||||
case TNull: "Null";
|
||||
case TInt: "Int";
|
||||
case TFloat: "Float";
|
||||
case TBool: "Bool";
|
||||
case _: cls != null ? Type.getClassName(cls) : null;
|
||||
};
|
||||
if (cl != null && getRedirects.exists(cl) && (redirect = getRedirects[cl]) != null) {
|
||||
return redirect(o, f);
|
||||
} else if (o is IHScriptCustomBehaviour) {
|
||||
var obj = cast(o, IHScriptCustomBehaviour);
|
||||
return obj.hget(f);
|
||||
} else {
|
||||
var v = null;
|
||||
if(isBypassAccessor) {
|
||||
if ((v = Reflect.field(o, f)) == null)
|
||||
v = Reflect.field(cls, f);
|
||||
}
|
||||
|
||||
if(v == null) {
|
||||
if ((v = Reflect.getProperty(o, f)) == null)
|
||||
v = Reflect.getProperty(cls, f);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
var cls = Type.getClass(o);
|
||||
if (useRedirects && {
|
||||
var cl:Null<String> = getClassType(o, cls);
|
||||
cl != null && getRedirects.exists(cl) && (_getRedirect = getRedirects[cl]) != null;
|
||||
}) {
|
||||
return _getRedirect(o, f);
|
||||
} else if (o is IHScriptCustomBehaviour) {
|
||||
var obj = cast(o, IHScriptCustomBehaviour);
|
||||
return obj.hget(f);
|
||||
}
|
||||
var v = null;
|
||||
if(isBypassAccessor) {
|
||||
if ((v = UnsafeReflect.field(o, f)) == null)
|
||||
v = Reflect.field(cls, f);
|
||||
}
|
||||
|
||||
if(v == null) {
|
||||
if ((v = UnsafeReflect.getProperty(o, f)) == null)
|
||||
v = Reflect.getProperty(cls, f);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
function set(o:Dynamic, f:String, v:Dynamic):Dynamic {
|
||||
if (o == null)
|
||||
error(EInvalidAccess(f));
|
||||
|
||||
var redirect:Dynamic->String->Dynamic->Dynamic = null;
|
||||
var cls = Type.getClass(o);
|
||||
var cl:Null<String> = switch (Type.typeof(o)) {
|
||||
case TNull: "Null";
|
||||
case TInt: "Int";
|
||||
case TFloat: "Float";
|
||||
case TBool: "Bool";
|
||||
case _: cls != null ? Type.getClassName(cls) : null;
|
||||
};
|
||||
if (cl != null && setRedirects.exists(cl) && (redirect = setRedirects[cl]) != null)
|
||||
return redirect(o, f, v);
|
||||
if (useRedirects && {
|
||||
var cl:Null<String> = getClassType(o);
|
||||
cl != null && setRedirects.exists(cl) && (_setRedirect = setRedirects[cl]) != null;
|
||||
})
|
||||
return _setRedirect(o, f, v);
|
||||
else if (o is IHScriptCustomBehaviour) {
|
||||
var obj = cast(o, IHScriptCustomBehaviour);
|
||||
return obj.hset(f, v);
|
||||
}
|
||||
// Can use unsafe reflect here, since we checked for null above
|
||||
if(isBypassAccessor) {
|
||||
Reflect.setField(o, f, v);
|
||||
UnsafeReflect.setField(o, f, v);
|
||||
} else {
|
||||
Reflect.setProperty(o, f, v);
|
||||
UnsafeReflect.setProperty(o, f, v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic {
|
||||
if(o == CustomClassHandler.staticHandler && scriptObject != null) {
|
||||
return Reflect.callMethod(scriptObject, Reflect.field(scriptObject, "_HX_SUPER__" + f), args);
|
||||
if(_hasScriptObject && o == CustomClassHandler.staticHandler) {
|
||||
return UnsafeReflect.callMethodUnsafe(scriptObject, UnsafeReflect.field(scriptObject, "_HX_SUPER__" + f), args);
|
||||
}
|
||||
return call(o, get(o, f), args);
|
||||
}
|
||||
@@ -1052,11 +1172,10 @@ class Interp {
|
||||
if(f == CustomClassHandler.staticHandler) {
|
||||
return null;
|
||||
}
|
||||
return Reflect.callMethod(o, f, args);
|
||||
return UnsafeReflect.callMethodSafe(o, f, args);
|
||||
}
|
||||
|
||||
function cnew(cl:String, args:Array<Dynamic>):Dynamic {
|
||||
var cl:String = cast cl;
|
||||
var c:Dynamic = resolve(cl);
|
||||
if (c == null)
|
||||
c = Type.resolveClass(cl);
|
||||
|
||||
+10
-6
@@ -907,10 +907,12 @@ class Parser {
|
||||
|
||||
var fields = [];
|
||||
ensure(TBrOpen);
|
||||
while( !maybe(TBrClose) ) {
|
||||
if(token() == TSemicolon) continue;
|
||||
var a = parseExpr();
|
||||
fields.push(a);
|
||||
while( true ) {
|
||||
parseFullExpr(fields);
|
||||
tk = token();
|
||||
if( tk == TBrClose || (resumeErrors && tk == TEof) )
|
||||
break;
|
||||
push(tk);
|
||||
}
|
||||
|
||||
var tk = token();
|
||||
@@ -964,7 +966,7 @@ class Parser {
|
||||
var tk = token();
|
||||
switch( tk ) {
|
||||
case TId("case"):
|
||||
var c = { values : [], expr : null };
|
||||
var c:SwitchCase = { values : [], expr : null };
|
||||
cases.push(c);
|
||||
disableOrOp = true;
|
||||
while( true ) {
|
||||
@@ -1601,7 +1603,8 @@ class Parser {
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
function token(?infos : Null<haxe.PosInfos>) {
|
||||
function token() {
|
||||
//function token(?infos : Null<haxe.PosInfos>) {
|
||||
//function ttrace(v:Dynamic, ?infos : Null<haxe.PosInfos>) {
|
||||
// Sys.print(infos.fileName+":"+infos.lineNumber+": " + Std.string(v));
|
||||
// Sys.print("\r\n");
|
||||
@@ -1619,6 +1622,7 @@ class Parser {
|
||||
oldTokenMax = tokenMax;
|
||||
tokenMin = (this.char < 0) ? readPos : readPos - 1;
|
||||
var t = _token();
|
||||
//trace(t, infos);
|
||||
//ttrace(t, infos);
|
||||
tokenMax = (this.char < 0) ? readPos - 1 : readPos - 2;
|
||||
return t;
|
||||
|
||||
@@ -187,10 +187,12 @@ class ClassExtendMacro {
|
||||
overrideExpr = macro {
|
||||
var name:String = $v{name};
|
||||
|
||||
if (__interp != null) {
|
||||
var v:Dynamic = null;
|
||||
if (__interp.variables.exists(name) && Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||
return v($a{arguments});
|
||||
if (__custom__variables != null) {
|
||||
if(__custom__variables.exists(name)) {
|
||||
var v:Dynamic = null;
|
||||
if (Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||
return v($a{arguments});
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.$name($a{arguments});
|
||||
@@ -199,11 +201,13 @@ class ClassExtendMacro {
|
||||
overrideExpr = macro {
|
||||
var name:String = $v{name};
|
||||
|
||||
if (__interp != null) {
|
||||
var v:Dynamic = null;
|
||||
if (__interp != null && __interp.variables.exists(name) && Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||
v($a{arguments});
|
||||
return;
|
||||
if (__custom__variables != null) {
|
||||
if(__custom__variables.exists(name)) {
|
||||
var v:Dynamic = null;
|
||||
if (Reflect.isFunction(v = __custom__variables.get(name))) {
|
||||
v($a{arguments});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
super.$name($a{arguments});
|
||||
@@ -268,11 +272,13 @@ class ClassExtendMacro {
|
||||
pack: cl.pack.copy(),
|
||||
name: cl.name
|
||||
}, [
|
||||
{name: "IHScriptCustomBehaviour", pack: ["hscript"]}
|
||||
{name: "IHScriptCustomBehaviour", pack: ["hscript"]},
|
||||
{name: "IHScriptCustomClassBehaviour", pack: ["hscript"]}
|
||||
], false, true, false);
|
||||
shadowClass.name = '${cl.name}$CLASS_SUFFIX';
|
||||
var imports = Context.getLocalImports().copy();
|
||||
Utils.setupMetas(shadowClass, imports);
|
||||
Utils.processImport(imports, "hscript.utils.UnsafeReflect", "UnsafeReflect");
|
||||
|
||||
// Adding hscript getters and setters
|
||||
|
||||
@@ -282,7 +288,83 @@ class ClassExtendMacro {
|
||||
kind: FVar(TPath({
|
||||
pack: ['hscript'],
|
||||
name: 'Interp'
|
||||
}))
|
||||
})),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
shadowClass.fields.push({
|
||||
name: "__custom__variables",
|
||||
pos: Context.currentPos(),
|
||||
kind: FVar(TPath({
|
||||
pack: [],
|
||||
name: 'Map',
|
||||
params: [TPType(TPath({name: "String", pack: []})), TPType(TPath({name: "Dynamic", pack: []}))]
|
||||
})),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
shadowClass.fields.push({
|
||||
name: "__allowSetGet",
|
||||
pos: Context.currentPos(),
|
||||
kind: FVar(TPath({
|
||||
pack: [],
|
||||
name: 'Bool',
|
||||
}), macro true),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
shadowClass.fields.push({
|
||||
name: "__callGetter",
|
||||
pos: Context.currentPos(),
|
||||
kind: FFun({
|
||||
ret: TPath({name: 'Dynamic', pack: []}),
|
||||
params: [],
|
||||
expr: macro {
|
||||
__allowSetGet = false;
|
||||
var v = __custom__variables.get("get_" + name)();
|
||||
__allowSetGet = true;
|
||||
return v;
|
||||
},
|
||||
args: [
|
||||
{
|
||||
name: "name",
|
||||
opt: false,
|
||||
meta: [],
|
||||
type: TPath({name: "String", pack: []})
|
||||
}
|
||||
]
|
||||
}),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
shadowClass.fields.push({
|
||||
name: "__callSetter",
|
||||
pos: Context.currentPos(),
|
||||
kind: FFun({
|
||||
ret: TPath({name: 'Dynamic', pack: []}),
|
||||
params: [],
|
||||
expr: macro {
|
||||
__allowSetGet = false;
|
||||
var v = __custom__variables.get("set_" + name)(val);
|
||||
__allowSetGet = true;
|
||||
return v;
|
||||
},
|
||||
args: [
|
||||
{
|
||||
name: "name",
|
||||
opt: false,
|
||||
meta: [],
|
||||
type: TPath({name: "String", pack: []})
|
||||
},
|
||||
{
|
||||
name: "val",
|
||||
opt: false,
|
||||
meta: [],
|
||||
type: TPath({name: "Dynamic", pack: []})
|
||||
}
|
||||
]
|
||||
}),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
// Todo: make it possible to override
|
||||
@@ -327,44 +409,42 @@ class ClassExtendMacro {
|
||||
|
||||
var hgetField = if(hasHgetInSuper) {
|
||||
macro {
|
||||
if(this.__interp.variables.exists("get_" + name))
|
||||
return this.__interp.variables.get("get_" + name)();
|
||||
if (this.__interp.variables.exists(name))
|
||||
return this.__interp.variables.get(name);
|
||||
if(__allowSetGet && __custom__variables.exists("get_" + name))
|
||||
return __callGetter(name);
|
||||
if (__custom__variables.exists(name))
|
||||
return __custom__variables.get(name);
|
||||
return super.hget(name);
|
||||
}
|
||||
} else {
|
||||
macro {
|
||||
if(this.__interp.variables.exists("get_" + name))
|
||||
return this.__interp.variables.get("get_" + name)();
|
||||
if (this.__interp.variables.exists(name))
|
||||
return this.__interp.variables.get(name);
|
||||
return Reflect.getProperty(this, name);
|
||||
if(__allowSetGet && __custom__variables.exists("get_" + name))
|
||||
return __callGetter(name);
|
||||
if (__custom__variables.exists(name))
|
||||
return __custom__variables.get(name);
|
||||
return UnsafeReflect.getProperty(this, name);
|
||||
}
|
||||
}
|
||||
|
||||
var hsetField = if(hasHsetInSuper) {
|
||||
macro {
|
||||
if(this.__interp.variables.exists("set_" + name)) {
|
||||
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||
}
|
||||
if (this.__interp.variables.exists(name)) {
|
||||
this.__interp.variables.set(name, val);
|
||||
if(__allowSetGet && __custom__variables.exists("set_" + name))
|
||||
return __callSetter(name, val);
|
||||
if (__custom__variables.exists(name)) {
|
||||
__custom__variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
return super.hset(name, val);
|
||||
return super.hset(this, name);
|
||||
}
|
||||
} else {
|
||||
macro {
|
||||
if(this.__interp.variables.exists("set_" + name)) {
|
||||
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||
}
|
||||
if (this.__interp.variables.exists(name)) {
|
||||
this.__interp.variables.set(name, val);
|
||||
if(__allowSetGet && __custom__variables.exists("set_" + name))
|
||||
return __callSetter(name, val);
|
||||
if (__custom__variables.exists(name)) {
|
||||
__custom__variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
Reflect.setProperty(this, name, val);
|
||||
return Reflect.field(this, name);
|
||||
UnsafeReflect.setProperty(this, name, val);
|
||||
return UnsafeReflect.field(this, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
package hscript.utils;
|
||||
|
||||
#if cpp
|
||||
import cpp.ObjectType;
|
||||
#end
|
||||
|
||||
@:analyzer(ignore)
|
||||
class UnsafeReflect {
|
||||
public #if !cpp inline #end static function hasField(o:Dynamic, field:String):Bool {
|
||||
#if cpp
|
||||
untyped {
|
||||
return o.__HasField(field);
|
||||
}
|
||||
#else
|
||||
return Reflect.hasField(o, field);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function field(o:Dynamic, field:String):Dynamic {
|
||||
#if cpp
|
||||
untyped {
|
||||
return o.__Field(field, untyped __cpp__("::hx::paccNever"));
|
||||
}
|
||||
#else
|
||||
return Reflect.field(o, field);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function setField(o:Dynamic, field:String, value:Dynamic):Void {
|
||||
#if cpp
|
||||
untyped {
|
||||
o.__SetField(field, value, untyped __cpp__("::hx::paccNever"));
|
||||
}
|
||||
#else
|
||||
return Reflect.setField(o, field, value);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function getProperty(o:Dynamic, field:String):Dynamic {
|
||||
#if cpp
|
||||
untyped {
|
||||
return o.__Field(field, untyped __cpp__("::hx::paccAlways"));
|
||||
}
|
||||
#else
|
||||
return Reflect.getProperty(o, field);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function setProperty(o:Dynamic, field:String, value:Dynamic):Void {
|
||||
#if cpp
|
||||
untyped {
|
||||
o.__SetField(field, value, untyped __cpp__("::hx::paccAlways"));
|
||||
}
|
||||
#else
|
||||
Reflect.setProperty(o, field);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function callFieldUnsafe(o:Dynamic, field:String, args:Array<Dynamic>):Dynamic {
|
||||
#if cpp
|
||||
untyped {
|
||||
var func:Dynamic = o.__Field(field, untyped __cpp__("::hx::paccDynamic"));
|
||||
untyped func.__SetThis(o);
|
||||
return untyped func.__Run(args);
|
||||
}
|
||||
#else
|
||||
return Reflect.callMethod(o, func, args);
|
||||
#end
|
||||
}
|
||||
|
||||
public inline static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array<Dynamic>):Dynamic {
|
||||
return Reflect.callMethod(o, func, args);
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function callMethodSafe(o:Dynamic, func:haxe.Constraints.Function, args:Array<Dynamic>):Dynamic {
|
||||
#if cpp
|
||||
untyped {
|
||||
if (func == null)
|
||||
throw cpp.ErrorConstants.nullFunctionPointer;
|
||||
untyped func.__SetThis(o);
|
||||
return untyped func.__Run(args);
|
||||
}
|
||||
#else
|
||||
return Reflect.callMethod(o, func, args);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function callMethodUnsafe(o:Dynamic, func:haxe.Constraints.Function, args:Array<Dynamic>):Dynamic {
|
||||
#if cpp
|
||||
untyped {
|
||||
untyped func.__SetThis(o);
|
||||
return untyped func.__Run(args);
|
||||
}
|
||||
#else
|
||||
return Reflect.callMethod(o, func, args);
|
||||
#end
|
||||
}
|
||||
|
||||
public inline static function fields(o:Dynamic):Array<String>
|
||||
return Reflect.fields(o);
|
||||
/*untyped {
|
||||
if (o == null)
|
||||
return new Array();
|
||||
var a:Array<String> = [];
|
||||
o.__GetFields(a);
|
||||
return a;
|
||||
}*/
|
||||
|
||||
public #if !cpp inline #end static function isFunction(f:Dynamic):Bool
|
||||
#if cpp
|
||||
untyped {
|
||||
return f.__GetType() == ObjectType.vtFunction;
|
||||
}
|
||||
#else
|
||||
return Reflect.isFunction(f);
|
||||
#end
|
||||
|
||||
public inline static function compare<T>(a:T, b:T):Int {
|
||||
return Reflect.compare(a, b);
|
||||
//return (a == b) ? 0 : (((a : Dynamic) > (b : Dynamic)) ? 1 : -1);
|
||||
}
|
||||
|
||||
public inline static function compareMethods(f1:Dynamic, f2:Dynamic):Bool {
|
||||
return Reflect.compareMethods(f1, f2);
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function isObject(v:Dynamic):Bool {
|
||||
#if cpp
|
||||
untyped {
|
||||
var t:Int = v.__GetType();
|
||||
return t == ObjectType.vtObject || t == ObjectType.vtClass || t == ObjectType.vtString || t == ObjectType.vtArray;
|
||||
}
|
||||
#else
|
||||
return Reflect.isObject(v);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function isEnumValue(v:Dynamic):Bool {
|
||||
#if cpp
|
||||
untyped {
|
||||
return v.__GetType() == ObjectType.vtEnum;
|
||||
}
|
||||
#else
|
||||
return Reflect.isEnumValue(v);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function deleteField(o:Dynamic, field:String):Bool {
|
||||
#if cpp
|
||||
untyped {
|
||||
return untyped __global__.__hxcpp_anon_remove(o, field);
|
||||
}
|
||||
#else
|
||||
return Reflect.deleteField(o, field);
|
||||
#end
|
||||
}
|
||||
|
||||
public #if !cpp inline #end static function copy<T>(o:Null<T>):Null<T> {
|
||||
#if cpp
|
||||
if (o == null)
|
||||
return null;
|
||||
var t:Int = untyped o.__GetType();
|
||||
if (t == ObjectType.vtString)
|
||||
return o;
|
||||
if (t == ObjectType.vtArray)
|
||||
return untyped o.__Field("copy", untyped __cpp__("::hx::paccDynamic"))();
|
||||
var o2:Dynamic = {};
|
||||
for (f in UnsafeReflect.fields(o))
|
||||
UnsafeReflect.setField(o2, f, UnsafeReflect.field(o, f));
|
||||
return o2;
|
||||
#else
|
||||
return Reflect.copy(o);
|
||||
#end
|
||||
}
|
||||
|
||||
@:overload(function(f:Array<Dynamic>->Void):Dynamic {})
|
||||
public static function makeVarArgs(f:Array<Dynamic>->Dynamic):Dynamic {
|
||||
#if cpp
|
||||
return untyped __global__.__hxcpp_create_var_args(f);
|
||||
#else
|
||||
return inline Reflect.makeVarArgs(f);
|
||||
#end
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user