Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75a21abecd | ||
|
|
763999c376 | ||
|
|
c1b23320c3 | ||
|
|
266bb67c93 | ||
|
|
6276ddfc2c | ||
|
|
b8ead38556 | ||
|
|
1972ae6a82 |
@@ -21,4 +21,9 @@ class Config {
|
|||||||
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@:unreflective
|
||||||
|
public static final IMPORT_BLACKLIST:Array<String> = [
|
||||||
|
// "flixel.FlxG"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,6 @@ using Lambda;
|
|||||||
* @author Jamextreme140
|
* @author Jamextreme140
|
||||||
*/
|
*/
|
||||||
@:access(hscript.CustomClassHandler)
|
@:access(hscript.CustomClassHandler)
|
||||||
@:access(hscript.Property)
|
|
||||||
class CustomClass implements IHScriptCustomClassBehaviour {
|
class CustomClass implements IHScriptCustomClassBehaviour {
|
||||||
public var className(get, never):String;
|
public var className(get, never):String;
|
||||||
|
|
||||||
@@ -174,9 +173,9 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
var f = __interp.variables.get(name);
|
var f = __interp.variables.get(name);
|
||||||
if (f != null && allowProperty && f is Property) {
|
if (f != null && allowProperty && f is Property) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callGetter(name);
|
var r = prop.get(!__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@@ -186,9 +185,9 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
var f = getField(name, false);
|
var f = getField(name, false);
|
||||||
if (f != null && f is Property) {
|
if (f != null && f is Property) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callSetter(name, val);
|
var r = prop.set(val, !__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
@@ -354,6 +353,7 @@ class CustomClass implements IHScriptCustomClassBehaviour {
|
|||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: scriptable "toString" function
|
||||||
public function toString():String
|
public function toString():String
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,23 +60,19 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
if(!__interp.variables.exists(f))
|
if(!__interp.variables.exists(f))
|
||||||
__interp.variables.set(f, v);
|
__interp.variables.set(f, v);
|
||||||
|
|
||||||
for(e in fields.copy()) {
|
for(i => e in fields.copy()) {
|
||||||
var validField:Bool = false;
|
var isValid:Bool = false;
|
||||||
var staticField:Bool = false;
|
var staticField:Bool = false;
|
||||||
var fieldName:String = "";
|
var fieldName:String = null;
|
||||||
switch (Tools.expr(e)) {
|
switch (Tools.expr(e)) {
|
||||||
case EVar(n, _, _, _, isStatic):
|
case EVar(n, _, _, _, isStatic) | EFunction(_, _, n, _, _, isStatic):
|
||||||
validField = true;
|
isValid = true;
|
||||||
staticField = isStatic;
|
|
||||||
fieldName = n;
|
|
||||||
case EFunction(_, _, n, _, _, isStatic, _, _, _, _):
|
|
||||||
validField = true;
|
|
||||||
staticField = isStatic;
|
staticField = isStatic;
|
||||||
fieldName = n;
|
fieldName = n;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(staticField && validField) {
|
if(staticField && isValid) {
|
||||||
__interp.exprReturn(e);
|
__interp.exprReturn(e);
|
||||||
__staticFields.push(fieldName);
|
__staticFields.push(fieldName);
|
||||||
fields.remove(e);
|
fields.remove(e);
|
||||||
@@ -88,7 +84,7 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
return new CustomClass(this, args);
|
return new CustomClass(this, args);
|
||||||
|
|
||||||
@:allow(hscript.Interp)
|
@:allow(hscript.Interp)
|
||||||
function hasField(name:String) {
|
inline function hasField(name:String) {
|
||||||
return __staticFields.contains(name);
|
return __staticFields.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,9 +92,9 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
var f = __interp.variables.get(name);
|
var f = __interp.variables.get(name);
|
||||||
if(f is Property && allowProperty) {
|
if(f is Property && allowProperty) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callGetter(name);
|
var r = prop.get(!__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@@ -108,9 +104,9 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
var f = getField(name, false);
|
var f = getField(name, false);
|
||||||
if(f is Property) {
|
if(f is Property) {
|
||||||
var prop:Property = cast f;
|
var prop:Property = cast f;
|
||||||
prop.__allowSetGet = this.__allowSetGet;
|
//prop.__allowSetGet = this.__allowSetGet;
|
||||||
var r = prop.callSetter(name, val);
|
var r = prop.set(val, !__allowSetGet);
|
||||||
prop.__allowSetGet = null;
|
//prop.__allowSetGet = true;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
@@ -119,10 +115,9 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
|||||||
|
|
||||||
public function hget(name:String):Dynamic {
|
public function hget(name:String):Dynamic {
|
||||||
if(name == 'new') {
|
if(name == 'new') {
|
||||||
var __constructor = Reflect.makeVarArgs(function(args:Array<Dynamic>) {
|
return Reflect.makeVarArgs(function(args:Array<Dynamic>):Dynamic {
|
||||||
return this.hnew(args);
|
return inline this.hnew(args);
|
||||||
});
|
});
|
||||||
return __constructor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasField(name)) {
|
if(hasField(name)) {
|
||||||
|
|||||||
+2
-2
@@ -106,7 +106,7 @@ enum abstract Binop(Int) from Int to Int {
|
|||||||
case "<<=": OpShlAssign;
|
case "<<=": OpShlAssign;
|
||||||
case ">>=": OpShrAssign;
|
case ">>=": OpShrAssign;
|
||||||
case ">>>=": OpUshrAssign;
|
case ">>>=": OpUshrAssign;
|
||||||
case "??=": OpNcoalAssign;
|
case _ if (s == "??" + "="): OpNcoalAssign;
|
||||||
default: -1;
|
default: -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ enum abstract Binop(Int) from Int to Int {
|
|||||||
case OpShlAssign: "<<=";
|
case OpShlAssign: "<<=";
|
||||||
case OpShrAssign: ">>=";
|
case OpShrAssign: ">>=";
|
||||||
case OpUshrAssign: ">>>=";
|
case OpUshrAssign: ">>>=";
|
||||||
case OpNcoalAssign: "??=";
|
case OpNcoalAssign: "??" + "=";
|
||||||
default: "?";
|
default: "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-49
@@ -28,6 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
|
|
||||||
|
import haxe.Exception;
|
||||||
import haxe.ds.StringMap;
|
import haxe.ds.StringMap;
|
||||||
import hscript.HEnum.HEnumValue;
|
import hscript.HEnum.HEnumValue;
|
||||||
import haxe.CallStack;
|
import haxe.CallStack;
|
||||||
@@ -135,11 +136,16 @@ class Interp {
|
|||||||
|
|
||||||
public var errorHandler:Error->Void;
|
public var errorHandler:Error->Void;
|
||||||
public var warnHandler:Error->Void;
|
public var warnHandler:Error->Void;
|
||||||
|
// TODO: set this callback as a Global Resolver
|
||||||
|
/**
|
||||||
|
* Custom Import resolver. It's called when an import couldn't be resolved.
|
||||||
|
*/
|
||||||
public var importFailedCallback:Array<String>->Null<String>->Bool;
|
public var importFailedCallback:Array<String>->Null<String>->Bool;
|
||||||
|
|
||||||
public var customClasses:Map<String, CustomClassHandler>;
|
public var customClasses:Map<String, CustomClassHandler>;
|
||||||
public var variables:Map<String, Dynamic>;
|
public var variables:Map<String, Dynamic>;
|
||||||
public var publicVariables:Map<String, Dynamic>;
|
public var publicVariables:Map<String, Dynamic>;
|
||||||
|
// TODO: maybe turn this completely static
|
||||||
public var staticVariables:Map<String, Dynamic>;
|
public var staticVariables:Map<String, Dynamic>;
|
||||||
|
|
||||||
// warning can be null
|
// warning can be null
|
||||||
@@ -160,15 +166,19 @@ class Interp {
|
|||||||
public var allowStaticVariables:Bool = false;
|
public var allowStaticVariables:Bool = false;
|
||||||
public var allowPublicVariables:Bool = false;
|
public var allowPublicVariables:Bool = false;
|
||||||
|
|
||||||
// TODO: move this to an external class
|
public var importBlocklist(get, never):Array<String>;
|
||||||
public var importBlocklist:Array<String> = [
|
private inline function get_importBlocklist():Array<String> {
|
||||||
// "flixel.FlxG"
|
return Config.IMPORT_BLACKLIST;
|
||||||
];
|
}
|
||||||
|
|
||||||
var usingHandler:UsingHandler;
|
var usingHandler:UsingHandler;
|
||||||
|
|
||||||
var varLocationCache:Map<String, VarLocation> = new Map();
|
// TODO: separate cache into a class
|
||||||
var cacheValid:Bool = true;
|
var varLocationCache:Map<String, VarLocation> = [];
|
||||||
|
public var cacheValid(default, set):Bool = true;
|
||||||
|
function set_cacheValid(valid:Bool):Bool {
|
||||||
|
return cacheValid = valid;
|
||||||
|
}
|
||||||
|
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
var curExpr:Expr;
|
var curExpr:Expr;
|
||||||
@@ -291,14 +301,14 @@ class Interp {
|
|||||||
var obj = resolve(id, false, false);
|
var obj = resolve(id, false, false);
|
||||||
if (obj != null && obj is Property) {
|
if (obj != null && obj is Property) {
|
||||||
var prop:Property = cast obj;
|
var prop:Property = cast obj;
|
||||||
return prop.callSetter(id, v);
|
return prop.set(v, isBypassAccessor);
|
||||||
}
|
}
|
||||||
varLocationCache.remove(id);
|
varLocationCache.remove(id);
|
||||||
setVar(id, v);
|
setVar(id, v);
|
||||||
}
|
}
|
||||||
} else if (l.r is Property) {
|
} else if (l.r is Property) {
|
||||||
var prop:Property = cast l.r;
|
var prop:Property = cast l.r;
|
||||||
return prop.callSetter(id, v);
|
return prop.set(v, isBypassAccessor);
|
||||||
} else {
|
} else {
|
||||||
l.r = v;
|
l.r = v;
|
||||||
if (l.depth == 0) {
|
if (l.depth == 0) {
|
||||||
@@ -372,7 +382,7 @@ class Interp {
|
|||||||
var obj = resolve(id, true, false);
|
var obj = resolve(id, true, false);
|
||||||
if (obj != null && obj is Property) {
|
if (obj != null && obj is Property) {
|
||||||
var prop:Property = cast obj;
|
var prop:Property = cast obj;
|
||||||
return prop.callSetter(id, v);
|
return prop.set(v, isBypassAccessor);
|
||||||
}
|
}
|
||||||
varLocationCache.remove(id);
|
varLocationCache.remove(id);
|
||||||
setVar(id, v);
|
setVar(id, v);
|
||||||
@@ -382,7 +392,7 @@ class Interp {
|
|||||||
var l = locals.get(id);
|
var l = locals.get(id);
|
||||||
if (l.r is Property) {
|
if (l.r is Property) {
|
||||||
var prop:Property = cast l.r;
|
var prop:Property = cast l.r;
|
||||||
return prop.callSetter(id, v);
|
return prop.set(v, isBypassAccessor);
|
||||||
}
|
}
|
||||||
l.r = v;
|
l.r = v;
|
||||||
if (l.depth == 0) {
|
if (l.depth == 0) {
|
||||||
@@ -426,18 +436,18 @@ class Interp {
|
|||||||
var prop:Property = null;
|
var prop:Property = null;
|
||||||
if (v is Property) {
|
if (v is Property) {
|
||||||
prop = cast v;
|
prop = cast v;
|
||||||
v = prop.callGetter(id);
|
v = prop.get(isBypassAccessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
if (prop != null)
|
if (prop != null)
|
||||||
prop.callSetter(id, v);
|
prop.set(v, isBypassAccessor);
|
||||||
else
|
else
|
||||||
l.r = v;
|
l.r = v;
|
||||||
} else {
|
} else {
|
||||||
if (prop != null)
|
if (prop != null)
|
||||||
prop.callSetter(id, v + delta);
|
prop.set(v + delta, isBypassAccessor);
|
||||||
else
|
else
|
||||||
l.r = v + delta;
|
l.r = v + delta;
|
||||||
}
|
}
|
||||||
@@ -448,20 +458,20 @@ class Interp {
|
|||||||
var prop:Property = null;
|
var prop:Property = null;
|
||||||
if (v is Property) {
|
if (v is Property) {
|
||||||
prop = cast v;
|
prop = cast v;
|
||||||
v = prop.callGetter(id);
|
v = prop.get(isBypassAccessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
if (prop != null)
|
if (prop != null)
|
||||||
prop.callSetter(id, v);
|
prop.set(v, isBypassAccessor);
|
||||||
else {
|
else {
|
||||||
varLocationCache.remove(id);
|
varLocationCache.remove(id);
|
||||||
setVar(id, v);
|
setVar(id, v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (prop != null)
|
if (prop != null)
|
||||||
prop.callSetter(id, v + delta);
|
prop.set(v + delta, isBypassAccessor);
|
||||||
else {
|
else {
|
||||||
varLocationCache.remove(id);
|
varLocationCache.remove(id);
|
||||||
setVar(id, v + delta);
|
setVar(id, v + delta);
|
||||||
@@ -601,8 +611,10 @@ class Interp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline function getProperty(o:Null<Dynamic>, n:String, allowProperty:Bool = true):Dynamic {
|
inline function getProperty(o:Null<Dynamic>, n:String, allowProperty:Bool = true):Dynamic {
|
||||||
if(allowProperty && o != null && o is Property)
|
if(allowProperty && o != null && o is Property) {
|
||||||
return cast(o, Property).callGetter(n);
|
var prop:Property = cast o;
|
||||||
|
return prop.get(isBypassAccessor);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -631,7 +643,7 @@ class Interp {
|
|||||||
case VPublic: getProperty(publicVariables.get(id), id, allowProperty);
|
case VPublic: getProperty(publicVariables.get(id), id, allowProperty);
|
||||||
case VStatic: getProperty(staticVariables.get(id), id, allowProperty);
|
case VStatic: getProperty(staticVariables.get(id), id, allowProperty);
|
||||||
case VScriptObject: isBypassAccessor ? UnsafeReflect.field(scriptObject, id) : UnsafeReflect.getProperty(scriptObject, id);
|
case VScriptObject: isBypassAccessor ? UnsafeReflect.field(scriptObject, id) : UnsafeReflect.getProperty(scriptObject, id);
|
||||||
case VScriptObjectGetter: UnsafeReflect.getProperty(scriptObject, 'get_$id')();
|
case VScriptObjectGetter: UnsafeReflect.callFieldUnsafe(scriptObject, 'get_$id', []);
|
||||||
case VCustomClass: (cast scriptObject:IHScriptCustomAccessBehaviour).hget(id);
|
case VCustomClass: (cast scriptObject:IHScriptCustomAccessBehaviour).hget(id);
|
||||||
case VCustomClassBypass:
|
case VCustomClassBypass:
|
||||||
var obj:IHScriptCustomAccessBehaviour = cast scriptObject;
|
var obj:IHScriptCustomAccessBehaviour = cast scriptObject;
|
||||||
@@ -709,9 +721,10 @@ class Interp {
|
|||||||
varLocationCache.set(id, VScriptObject);
|
varLocationCache.set(id, VScriptObject);
|
||||||
return UnsafeReflect.getProperty(scriptObject, id);
|
return UnsafeReflect.getProperty(scriptObject, id);
|
||||||
}
|
}
|
||||||
} else if (__instanceFields.contains('get_$id')) { // getter
|
} else if (__instanceFields.contains('get_$id')) { // getter
|
||||||
return UnsafeReflect.getProperty(scriptObject, 'get_$id')();
|
varLocationCache.set(id, VScriptObjectGetter);
|
||||||
}
|
return UnsafeReflect.callFieldUnsafe(scriptObject, 'get_$id', []);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
varLocationCache.set(id, VNotFound);
|
varLocationCache.set(id, VNotFound);
|
||||||
@@ -725,14 +738,10 @@ class Interp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function invalidateCache():Void {
|
public function invalidateCache():Void {
|
||||||
varLocationCache = new Map();
|
varLocationCache.clear();
|
||||||
cacheValid = true;
|
cacheValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCacheValid(valid:Bool):Void {
|
|
||||||
cacheValid = valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var importRedirects:Map<String, String> = new Map();
|
public static var importRedirects:Map<String, String> = new Map();
|
||||||
public static function getImportRedirect(className:String):String {
|
public static function getImportRedirect(className:String):String {
|
||||||
return importRedirects.exists(className) ? importRedirects.get(className) : className;
|
return importRedirects.exists(className) ? importRedirects.get(className) : className;
|
||||||
@@ -748,6 +757,7 @@ class Interp {
|
|||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: separate large declarations (EClass, EEnum, etc...) into inline functions
|
||||||
public function expr(e:Expr):Dynamic {
|
public function expr(e:Expr):Dynamic {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
curExpr = e;
|
curExpr = e;
|
||||||
@@ -808,7 +818,6 @@ class Interp {
|
|||||||
|
|
||||||
function importResolve(__clsName:String):Null<Dynamic> {
|
function importResolve(__clsName:String):Null<Dynamic> {
|
||||||
var _realClassName = getLocalImportRedirect(__clsName);
|
var _realClassName = getLocalImportRedirect(__clsName);
|
||||||
if(importBlocklist.contains(_realClassName)) return null;
|
|
||||||
|
|
||||||
var _cl = Type.resolveClass(_realClassName);
|
var _cl = Type.resolveClass(_realClassName);
|
||||||
if(_cl == null) _cl = Type.resolveClass('${_realClassName}_HSC');
|
if(_cl == null) _cl = Type.resolveClass('${_realClassName}_HSC');
|
||||||
@@ -1001,20 +1010,14 @@ class Interp {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||||
var r:Dynamic = (e == null) ? null : expr(e);
|
var v:Dynamic = (e == null) ? null : expr(e);
|
||||||
var declProp:Property = null;
|
var r:Dynamic = null;
|
||||||
if (hasGetSet) {
|
if (hasGetSet)
|
||||||
declProp = {
|
r = new Property(n, v, getter, setter, isVar, isStatic, this);
|
||||||
r: r,
|
else
|
||||||
getter: getter,
|
r = v;
|
||||||
setter: setter,
|
|
||||||
isVar: isVar,
|
|
||||||
isStatic: isStatic,
|
|
||||||
interp: this,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var declVar:DeclaredVar = {
|
var declVar:DeclaredVar = {
|
||||||
r: (!hasGetSet) ? r : declProp,
|
r: r,
|
||||||
depth: depth
|
depth: depth
|
||||||
};
|
};
|
||||||
locals.set(n, declVar);
|
locals.set(n, declVar);
|
||||||
@@ -1131,7 +1134,7 @@ class Interp {
|
|||||||
}
|
}
|
||||||
return fcall(obj, f, args);
|
return fcall(obj, f, args);
|
||||||
default:
|
default:
|
||||||
return call(null, expr(e), args);
|
return call(hasScriptObject ? scriptObject : null, expr(e), args);
|
||||||
}
|
}
|
||||||
case EIf(econd, e1, e2):
|
case EIf(econd, e1, e2):
|
||||||
return if (expr(econd) == true) expr(e1) else if (e2 == null) null else expr(e2);
|
return if (expr(econd) == true) expr(e1) else if (e2 == null) null else expr(e2);
|
||||||
@@ -1400,12 +1403,12 @@ class Interp {
|
|||||||
for (i => p in params) {
|
for (i => p in params) {
|
||||||
switch (Tools.expr(p)) {
|
switch (Tools.expr(p)) {
|
||||||
case EIdent(n):
|
case EIdent(n):
|
||||||
declared.push({
|
declared.push({
|
||||||
n: n,
|
n: n,
|
||||||
old: {r: locals.get(n), depth: depth},
|
old: {r: locals.get(n), depth: depth},
|
||||||
depth: depth
|
depth: depth
|
||||||
});
|
});
|
||||||
locals.set(n, {r: valParams[i], depth: depth});
|
locals.set(n, {r: valParams[i], depth: depth});
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1798,6 +1801,7 @@ class Interp {
|
|||||||
if (usingHandler.usingEntries.iterator().hasNext()) { // If is not empty
|
if (usingHandler.usingEntries.iterator().hasNext()) { // If is not empty
|
||||||
var v:Dynamic = null;
|
var v:Dynamic = null;
|
||||||
var clsName:String = o is CustomClassHandler ? cast(o, CustomClassHandler).name : Type.getClassName(Type.getClass(o));
|
var clsName:String = o is CustomClassHandler ? cast(o, CustomClassHandler).name : Type.getClassName(Type.getClass(o));
|
||||||
|
// TODO: optimize this
|
||||||
if(!usingHandler.entryExists(clsName)) {
|
if(!usingHandler.entryExists(clsName)) {
|
||||||
for (n => us in usingHandler.usingEntries) {
|
for (n => us in usingHandler.usingEntries) {
|
||||||
if (us.hasField(f)) {
|
if (us.hasField(f)) {
|
||||||
@@ -1835,4 +1839,4 @@ class Interp {
|
|||||||
|
|
||||||
return Type.createInstance(c, args);
|
return Type.createInstance(c, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+68
-18
@@ -26,15 +26,33 @@ import hscript.Expr.FieldPropertyAccess;
|
|||||||
* @see https://haxe.org/manual/class-field-property.html
|
* @see https://haxe.org/manual/class-field-property.html
|
||||||
*/
|
*/
|
||||||
@:access(hscript.Interp)
|
@:access(hscript.Interp)
|
||||||
@:structInit
|
|
||||||
class Property {
|
class Property {
|
||||||
private static inline var GET = 'get_';
|
private static inline var GET = 'get_';
|
||||||
private static inline var SET = 'set_';
|
private static inline var SET = 'set_';
|
||||||
|
|
||||||
public var r:Dynamic;
|
/**
|
||||||
public var getter:FieldPropertyAccess;
|
* Name of the attached field.
|
||||||
public var setter:FieldPropertyAccess;
|
*/
|
||||||
|
public final name:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current value. If isn't initialized, it's always `null`.
|
||||||
|
*/
|
||||||
|
public var r:Dynamic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The getter property kind
|
||||||
|
*/
|
||||||
|
public final getter:FieldPropertyAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The setter property kind
|
||||||
|
*/
|
||||||
|
public final setter:FieldPropertyAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the field is declared as static.
|
||||||
|
*/
|
||||||
public var isStatic(get, never):Bool;
|
public var isStatic(get, never):Bool;
|
||||||
function get_isStatic() {
|
function get_isStatic() {
|
||||||
return __isStatic && interp.allowStaticVariables;
|
return __isStatic && interp.allowStaticVariables;
|
||||||
@@ -43,7 +61,20 @@ class Property {
|
|||||||
var isVar:Bool;
|
var isVar:Bool;
|
||||||
var interp:Interp;
|
var interp:Interp;
|
||||||
|
|
||||||
public function new(r:Dynamic, getter:FieldPropertyAccess, setter:FieldPropertyAccess, isVar:Bool, isStatic:Bool, interp:Interp) {
|
@:allow(hscript.Interp)
|
||||||
|
private var getterFunc(get, never):String;
|
||||||
|
private inline function get_getterFunc():String {
|
||||||
|
return '$GET$name';
|
||||||
|
}
|
||||||
|
|
||||||
|
@:allow(hscript.Interp)
|
||||||
|
private var setterFunc(get, never):String;
|
||||||
|
private inline function get_setterFunc():String {
|
||||||
|
return '$SET$name';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function new(name:String, r:Dynamic, getter:FieldPropertyAccess, setter:FieldPropertyAccess, isVar:Bool, isStatic:Bool, interp:Interp) {
|
||||||
|
this.name = name;
|
||||||
this.r = r;
|
this.r = r;
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
@@ -52,23 +83,41 @@ class Property {
|
|||||||
this.interp = interp;
|
this.interp = interp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal flags to gain access to the current field value (if isn't a property field)
|
||||||
var __allowReadAccess:Bool = false;
|
var __allowReadAccess:Bool = false;
|
||||||
var __allowWriteAccess:Bool = false;
|
var __allowWriteAccess:Bool = false;
|
||||||
var __allowSetGet:Null<Bool> = null;
|
// Internal flag to gain access if the field is accessed with @:bypassAccessor
|
||||||
|
var __allowSetGet:Bool = true;
|
||||||
|
|
||||||
final __isStatic:Bool = false;
|
final __isStatic:Bool = false;
|
||||||
|
|
||||||
public function callGetter(name:String) {
|
public function get(isBypassAccessor:Bool) {
|
||||||
|
if(isBypassAccessor) __allowSetGet = false;
|
||||||
|
var r:Dynamic = callGetter();
|
||||||
|
if(isBypassAccessor) __allowSetGet = true;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(value:Dynamic, isBypassAccessor:Bool) {
|
||||||
|
if(isBypassAccessor) __allowSetGet = false;
|
||||||
|
var r:Dynamic = callSetter(value);
|
||||||
|
if(isBypassAccessor) __allowSetGet = true;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function callGetter():Dynamic {
|
||||||
switch (getter) {
|
switch (getter) {
|
||||||
case AGet | ADynamic:
|
case AGet | ADynamic:
|
||||||
var fName:String = '$GET$name';
|
var fName:String = getterFunc;
|
||||||
if (!__allowReadAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
if (!__allowReadAccess && __allowSetGet) {
|
||||||
if (varExists(fName)) {
|
if (varExists(fName)) {
|
||||||
return callAccessor(fName);
|
return callAccessor(fName);
|
||||||
} else
|
} else
|
||||||
interp.error(ECustom('Method $fName required by property $name is missing'));
|
interp.error(ECustom('Method $fName required by property $name is missing'));
|
||||||
} else {
|
} else {
|
||||||
if ((setter == ADefault || setter == ANull) || isVar)
|
if ((setter == ADefault || setter == ANull) || isVar) {
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
||||||
}
|
}
|
||||||
@@ -80,18 +129,19 @@ class Property {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function callSetter(name:String, val:Dynamic) {
|
private function callSetter(val:Dynamic):Dynamic {
|
||||||
switch (setter) {
|
switch (setter) {
|
||||||
case ASet | ADynamic:
|
case ASet | ADynamic:
|
||||||
var fName:String = '$SET$name';
|
var fName:String = setterFunc;
|
||||||
if (!__allowWriteAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
if (!__allowWriteAccess && __allowSetGet) {
|
||||||
if (varExists(fName))
|
if (varExists(fName))
|
||||||
return callAccessor(fName, [val], true);
|
return callAccessor(fName, true, val);
|
||||||
else
|
else
|
||||||
interp.error(ECustom('Method $fName required by property $name is missing'));
|
interp.error(ECustom('Method $fName required by property $name is missing'));
|
||||||
} else {
|
} else {
|
||||||
if ((getter == ADefault || getter == ANull) || isVar)
|
if ((getter == ADefault || getter == ANull) || isVar) {
|
||||||
return r = val;
|
return r = val;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
||||||
}
|
}
|
||||||
@@ -103,14 +153,14 @@ class Property {
|
|||||||
return r = val;
|
return r = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function callAccessor(f:String, ?args:Array<Dynamic>, isWrite:Bool = false):Dynamic {
|
private function callAccessor(f:String, isWrite:Bool = false, ?value:Dynamic):Dynamic {
|
||||||
var fn = isStatic ? interp.staticVariables.get(f) : interp.variables.get(f);
|
var fn = isStatic ? interp.staticVariables.get(f) : interp.variables.get(f);
|
||||||
var rt:Dynamic = null;
|
var rt:Dynamic = null;
|
||||||
if (fn != null && Reflect.isFunction(fn)) {
|
if (fn != null && Reflect.isFunction(fn)) {
|
||||||
if (isWrite) __allowWriteAccess = true;
|
if (isWrite) __allowWriteAccess = true;
|
||||||
else __allowReadAccess = true;
|
else __allowReadAccess = true;
|
||||||
|
|
||||||
rt = UnsafeReflect.callMethodUnsafe(null, fn, args == null ? [] : args);
|
rt = UnsafeReflect.callMethodUnsafe(null, fn, isWrite ? [value] : []);
|
||||||
|
|
||||||
if (isWrite) __allowWriteAccess = false;
|
if (isWrite) __allowWriteAccess = false;
|
||||||
else __allowReadAccess = false;
|
else __allowReadAccess = false;
|
||||||
@@ -122,7 +172,7 @@ class Property {
|
|||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function varExists(n:String) {
|
private inline function varExists(n:String) {
|
||||||
return isStatic ? interp.staticVariables.exists(n) : interp.variables.exists(n);
|
return isStatic ? interp.staticVariables.exists(n) : interp.variables.exists(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -483,8 +483,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callGetter(name);
|
return cast(v, hscript.Property).get(ba);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
else @:privateAccess {
|
else @:privateAccess {
|
||||||
@@ -508,8 +509,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callGetter(name);
|
return cast(v, hscript.Property).get(ba);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
else @:privateAccess {
|
else @:privateAccess {
|
||||||
@@ -535,8 +537,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callSetter(name, val);
|
return cast(v, hscript.Property).set(val, ba);
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -565,8 +568,9 @@ class ClassExtendMacro {
|
|||||||
if (__interp != null) {
|
if (__interp != null) {
|
||||||
if(__class__fields.contains(name)) {
|
if(__class__fields.contains(name)) {
|
||||||
var v:Dynamic = __interp.variables.get(name);
|
var v:Dynamic = __interp.variables.get(name);
|
||||||
|
var ba:Bool = @:privateAccess __interp.isBypassAccessor;
|
||||||
if(v != null && v is hscript.Property)
|
if(v != null && v is hscript.Property)
|
||||||
return cast(v, hscript.Property).callSetter(name, val);
|
return cast(v, hscript.Property).set(val, ba);
|
||||||
__interp.variables.set(name, val);
|
__interp.variables.set(name, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user