Refactor property fields
Now you can call directly the getter/setter functions without triggering them again.
This commit is contained in:
+37
-32
@@ -28,6 +28,7 @@
|
||||
*/
|
||||
package hscript;
|
||||
|
||||
import haxe.Exception;
|
||||
import haxe.ds.StringMap;
|
||||
import hscript.HEnum.HEnumValue;
|
||||
import haxe.CallStack;
|
||||
@@ -167,8 +168,12 @@ class Interp {
|
||||
|
||||
var usingHandler:UsingHandler;
|
||||
|
||||
var varLocationCache:Map<String, VarLocation> = new Map();
|
||||
var cacheValid:Bool = true;
|
||||
// TODO: separate cache into a class
|
||||
var varLocationCache:Map<String, VarLocation> = [];
|
||||
public var cacheValid(default, set):Bool = true;
|
||||
function set_cacheValid(valid:Bool):Bool {
|
||||
return cacheValid = valid;
|
||||
}
|
||||
|
||||
#if hscriptPos
|
||||
var curExpr:Expr;
|
||||
@@ -291,14 +296,16 @@ class Interp {
|
||||
var obj = resolve(id, false, false);
|
||||
if (obj != null && obj is Property) {
|
||||
var prop:Property = cast obj;
|
||||
return prop.callSetter(id, v);
|
||||
prop.__callingProperty = true;
|
||||
return prop.callSetter(v);
|
||||
}
|
||||
varLocationCache.remove(id);
|
||||
setVar(id, v);
|
||||
}
|
||||
} else if (l.r is Property) {
|
||||
var prop:Property = cast l.r;
|
||||
return prop.callSetter(id, v);
|
||||
prop.__callingProperty = true;
|
||||
return prop.callSetter(v);
|
||||
} else {
|
||||
l.r = v;
|
||||
if (l.depth == 0) {
|
||||
@@ -372,7 +379,8 @@ class Interp {
|
||||
var obj = resolve(id, true, false);
|
||||
if (obj != null && obj is Property) {
|
||||
var prop:Property = cast obj;
|
||||
return prop.callSetter(id, v);
|
||||
prop.__callingProperty = true;
|
||||
return prop.callSetter(v);
|
||||
}
|
||||
varLocationCache.remove(id);
|
||||
setVar(id, v);
|
||||
@@ -382,7 +390,8 @@ class Interp {
|
||||
var l = locals.get(id);
|
||||
if (l.r is Property) {
|
||||
var prop:Property = cast l.r;
|
||||
return prop.callSetter(id, v);
|
||||
prop.__callingProperty = true;
|
||||
return prop.callSetter(v);
|
||||
}
|
||||
l.r = v;
|
||||
if (l.depth == 0) {
|
||||
@@ -426,18 +435,19 @@ class Interp {
|
||||
var prop:Property = null;
|
||||
if (v is Property) {
|
||||
prop = cast v;
|
||||
v = prop.callGetter(id);
|
||||
prop.__callingProperty = true;
|
||||
v = prop.callGetter();
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v);
|
||||
prop.callSetter(v);
|
||||
else
|
||||
l.r = v;
|
||||
} else {
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v + delta);
|
||||
prop.callSetter(v + delta);
|
||||
else
|
||||
l.r = v + delta;
|
||||
}
|
||||
@@ -448,20 +458,21 @@ class Interp {
|
||||
var prop:Property = null;
|
||||
if (v is Property) {
|
||||
prop = cast v;
|
||||
v = prop.callGetter(id);
|
||||
prop.__callingProperty = true;
|
||||
v = prop.callGetter();
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v);
|
||||
prop.callSetter(v);
|
||||
else {
|
||||
varLocationCache.remove(id);
|
||||
setVar(id, v);
|
||||
}
|
||||
} else {
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v + delta);
|
||||
prop.callSetter(v + delta);
|
||||
else {
|
||||
varLocationCache.remove(id);
|
||||
setVar(id, v + delta);
|
||||
@@ -601,8 +612,11 @@ class Interp {
|
||||
}
|
||||
|
||||
inline function getProperty(o:Null<Dynamic>, n:String, allowProperty:Bool = true):Dynamic {
|
||||
if(allowProperty && o != null && o is Property)
|
||||
return cast(o, Property).callGetter(n);
|
||||
if(allowProperty && o != null && o is Property) {
|
||||
var prop:Property = cast o;
|
||||
prop.__callingProperty = true;
|
||||
return cast(o, Property).callGetter();
|
||||
}
|
||||
else
|
||||
return o;
|
||||
}
|
||||
@@ -725,14 +739,10 @@ class Interp {
|
||||
}
|
||||
|
||||
public function invalidateCache():Void {
|
||||
varLocationCache = new Map();
|
||||
varLocationCache.clear();
|
||||
cacheValid = true;
|
||||
}
|
||||
|
||||
public function setCacheValid(valid:Bool):Void {
|
||||
cacheValid = valid;
|
||||
}
|
||||
|
||||
public static var importRedirects:Map<String, String> = new Map();
|
||||
public static function getImportRedirect(className:String):String {
|
||||
return importRedirects.exists(className) ? importRedirects.get(className) : className;
|
||||
@@ -748,6 +758,7 @@ class Interp {
|
||||
return className;
|
||||
}
|
||||
|
||||
// TODO: separate large declarations (EClass, EEnum, etc...) into inline functions
|
||||
public function expr(e:Expr):Dynamic {
|
||||
#if hscriptPos
|
||||
curExpr = e;
|
||||
@@ -1001,20 +1012,14 @@ class Interp {
|
||||
return null;
|
||||
}
|
||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||
var r:Dynamic = (e == null) ? null : expr(e);
|
||||
var declProp:Property = null;
|
||||
if (hasGetSet) {
|
||||
declProp = {
|
||||
r: r,
|
||||
getter: getter,
|
||||
setter: setter,
|
||||
isVar: isVar,
|
||||
isStatic: isStatic,
|
||||
interp: this,
|
||||
}
|
||||
}
|
||||
var v:Dynamic = (e == null) ? null : expr(e);
|
||||
var r:Dynamic = null;
|
||||
if (hasGetSet)
|
||||
r = new Property(n, v, getter, setter, isVar, isStatic, this);
|
||||
else
|
||||
r = v;
|
||||
var declVar:DeclaredVar = {
|
||||
r: (!hasGetSet) ? r : declProp,
|
||||
r: r,
|
||||
depth: depth
|
||||
};
|
||||
locals.set(n, declVar);
|
||||
|
||||
+41
-6
@@ -26,11 +26,11 @@ import hscript.Expr.FieldPropertyAccess;
|
||||
* @see https://haxe.org/manual/class-field-property.html
|
||||
*/
|
||||
@:access(hscript.Interp)
|
||||
@:structInit
|
||||
class Property {
|
||||
private static inline var GET = 'get_';
|
||||
private static inline var SET = 'set_';
|
||||
|
||||
public var name:String;
|
||||
public var r:Dynamic;
|
||||
public var getter:FieldPropertyAccess;
|
||||
public var setter:FieldPropertyAccess;
|
||||
@@ -43,24 +43,54 @@ class Property {
|
||||
var isVar:Bool;
|
||||
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 function get_getterFunc():String {
|
||||
return '$GET$name';
|
||||
}
|
||||
|
||||
@:allow(hscript.Interp)
|
||||
private var setterFunc(get, never):String;
|
||||
private 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.getter = getter;
|
||||
this.setter = setter;
|
||||
this.isVar = isVar;
|
||||
this.__isStatic = isStatic;
|
||||
this.interp = interp;
|
||||
|
||||
setLookup();
|
||||
}
|
||||
|
||||
private inline function setLookup() {
|
||||
/*
|
||||
if(getter == AGet)
|
||||
interp.propertyLookup.set(getterFunc, {isStatic: isStatic, func: () -> return callGetter()});
|
||||
if(setter == ASet)
|
||||
interp.propertyLookup.set(setterFunc, {isStatic: isStatic, func: (v) -> return callSetter(v)});
|
||||
*/
|
||||
}
|
||||
|
||||
var __allowReadAccess:Bool = false;
|
||||
var __allowWriteAccess:Bool = false;
|
||||
var __allowSetGet:Null<Bool> = null;
|
||||
|
||||
@:allow(hscript.Interp)
|
||||
var __callingProperty:Bool = false; // flag to check if the get/set function hasn't been called directly
|
||||
|
||||
final __isStatic:Bool = false;
|
||||
|
||||
public function callGetter(name:String) {
|
||||
public function callGetter():Dynamic {
|
||||
switch (getter) {
|
||||
case AGet | ADynamic:
|
||||
var fName:String = '$GET$name';
|
||||
var fName:String = getterFunc;//'$GET$name';
|
||||
if(!__callingProperty)
|
||||
__allowReadAccess = true;
|
||||
if (!__allowReadAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
||||
if (varExists(fName)) {
|
||||
return callAccessor(fName);
|
||||
@@ -80,10 +110,12 @@ class Property {
|
||||
return r;
|
||||
}
|
||||
|
||||
public function callSetter(name:String, val:Dynamic) {
|
||||
public function callSetter(val:Dynamic):Dynamic {
|
||||
switch (setter) {
|
||||
case ASet | ADynamic:
|
||||
var fName:String = '$SET$name';
|
||||
var fName:String = setterFunc;//'$SET$name';
|
||||
if(!__callingProperty)
|
||||
__allowWriteAccess = true;
|
||||
if (!__allowWriteAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
||||
if (varExists(fName))
|
||||
return callAccessor(fName, [val], true);
|
||||
@@ -115,6 +147,9 @@ class Property {
|
||||
if (isWrite) __allowWriteAccess = false;
|
||||
else __allowReadAccess = false;
|
||||
|
||||
if(__callingProperty)
|
||||
__callingProperty = false;
|
||||
|
||||
return rt;
|
||||
} else
|
||||
interp.error(ECustom('Method $f required by property ${f.substr(3)} is missing'));
|
||||
|
||||
Reference in New Issue
Block a user