Property Variables
Now property variables fully works.
This commit is contained in:
+86
-18
@@ -107,7 +107,7 @@ class Interp {
|
||||
public var errorHandler:Error->Void;
|
||||
public var importFailedCallback:Array<String>->Bool;
|
||||
|
||||
public var customClasses:Map<String, Dynamic>;
|
||||
public var customClasses:Map<String, CustomClassHandler>;
|
||||
public var variables:Map<String, Dynamic>;
|
||||
public var publicVariables:Map<String, Dynamic>;
|
||||
public var staticVariables:Map<String, Dynamic>;
|
||||
@@ -145,7 +145,7 @@ class Interp {
|
||||
}
|
||||
|
||||
private function resetVariables():Void {
|
||||
customClasses = new Map<String, Dynamic>();
|
||||
customClasses = new Map<String, CustomClassHandler>();
|
||||
variables = new Map<String, Dynamic>();
|
||||
publicVariables = new Map<String, Dynamic>();
|
||||
staticVariables = new Map<String, Dynamic>();
|
||||
@@ -281,8 +281,16 @@ class Interp {
|
||||
setVar(id, v);
|
||||
}
|
||||
} else {
|
||||
var obj = resolve(id, false, false);
|
||||
if (obj != null && obj is Property) {
|
||||
var prop:Property = cast obj;
|
||||
return prop.callSetter(id, v);
|
||||
}
|
||||
setVar(id, v);
|
||||
}
|
||||
} else if (l.r is Property) {
|
||||
var prop:Property = cast l.r;
|
||||
return prop.callSetter(id, v);
|
||||
} else {
|
||||
l.r = v;
|
||||
if (l.depth == 0) {
|
||||
@@ -356,11 +364,20 @@ class Interp {
|
||||
setVar(id, v);
|
||||
}
|
||||
} else {
|
||||
var obj = resolve(id, true, false);
|
||||
if (obj != null && obj is Property) {
|
||||
var prop:Property = cast obj;
|
||||
return prop.callSetter(id, v);
|
||||
}
|
||||
setVar(id, v);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var l = locals.get(id);
|
||||
if (l.r is Property) {
|
||||
var prop:Property = cast l.r;
|
||||
return prop.callSetter(id, v);
|
||||
}
|
||||
l.r = v;
|
||||
if (l.depth == 0) {
|
||||
setVar(id, v);
|
||||
@@ -399,19 +416,45 @@ class Interp {
|
||||
var l = locals.get(id);
|
||||
if(l != null) {
|
||||
var v:Dynamic = l.r;
|
||||
var prop:Property = null;
|
||||
if (v is Property) {
|
||||
prop = cast v;
|
||||
v = prop.callGetter(id);
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
l.r = v;
|
||||
} else
|
||||
l.r = v + delta;
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v);
|
||||
else
|
||||
l.r = v;
|
||||
} else {
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v + delta);
|
||||
else
|
||||
l.r = v + delta;
|
||||
}
|
||||
return v;
|
||||
} else {
|
||||
var v:Dynamic = resolve(id);
|
||||
var v:Dynamic = resolve(id, true, false);
|
||||
var prop:Property = null;
|
||||
if (v is Property) {
|
||||
prop = cast v;
|
||||
v = prop.callGetter(id);
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
v += delta;
|
||||
setVar(id, v);
|
||||
} else
|
||||
setVar(id, v + delta);
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v);
|
||||
else
|
||||
setVar(id, v);
|
||||
} else {
|
||||
if (prop != null)
|
||||
prop.callSetter(id, v + delta);
|
||||
else
|
||||
setVar(id, v + delta);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
case EField(e, f, s):
|
||||
@@ -533,23 +576,37 @@ class Interp {
|
||||
#end
|
||||
}
|
||||
|
||||
public function resolve(id:String, doException:Bool = true):Dynamic {
|
||||
public function resolve(id:String, doException:Bool = true, getProperty:Bool = true):Dynamic {
|
||||
if (id == null)
|
||||
return null;
|
||||
id = StringTools.trim(id);
|
||||
|
||||
if (locals.exists(id)) {
|
||||
var l = locals.get(id);
|
||||
if(l != null)
|
||||
return l.r;
|
||||
if(l != null) {
|
||||
if(l.r != null && l.r is Property && getProperty)
|
||||
return cast(l.r, Property).callGetter(id);
|
||||
else
|
||||
return l.r;
|
||||
}
|
||||
}
|
||||
|
||||
var r:Dynamic = null;
|
||||
|
||||
if(variables.exists(id))
|
||||
return variables.get(id);
|
||||
if(publicVariables.exists(id))
|
||||
return publicVariables.get(id);
|
||||
if(staticVariables.exists(id))
|
||||
return staticVariables.get(id);
|
||||
r = variables.get(id);
|
||||
else if(publicVariables.exists(id))
|
||||
r = publicVariables.get(id);
|
||||
else if(staticVariables.exists(id))
|
||||
r = staticVariables.get(id);
|
||||
|
||||
if(r != null) {
|
||||
if(r is Property && getProperty)
|
||||
return cast(r, Property).callGetter(id);
|
||||
else
|
||||
return r;
|
||||
}
|
||||
|
||||
if(customClasses.exists(id))
|
||||
return customClasses.get(id);
|
||||
|
||||
@@ -710,8 +767,19 @@ 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,
|
||||
interp: this,
|
||||
}
|
||||
}
|
||||
var declVar:DeclaredVar = {
|
||||
r: (e == null) ? null : expr(e),
|
||||
r: (declProp == null) ? r : declProp,
|
||||
depth: depth
|
||||
};
|
||||
locals.set(n, declVar);
|
||||
|
||||
+4
-3
@@ -832,7 +832,8 @@ class Parser {
|
||||
}
|
||||
}
|
||||
var ident = getIdent();
|
||||
var get = ADefault, set = ADefault;
|
||||
var get:Null<FieldPropertyAccess> = null;
|
||||
var set:Null<FieldPropertyAccess> = null;
|
||||
var hasGetSet:Bool = false;
|
||||
var oldIsVar:Bool = isVar;
|
||||
|
||||
@@ -843,7 +844,7 @@ class Parser {
|
||||
|
||||
var getId = getIdent();
|
||||
switch (getId) {
|
||||
case 'default': // Do nothing
|
||||
case 'default': get = ADefault;
|
||||
case 'get': get = AGet;
|
||||
case 'null': get = ANull;
|
||||
case 'dynamic': get = ADynamic;
|
||||
@@ -853,7 +854,7 @@ class Parser {
|
||||
ensure(TComma);
|
||||
var setId = getIdent();
|
||||
switch (setId) {
|
||||
case 'default': // Do nothing
|
||||
case 'default': set = ADefault;
|
||||
case 'set': set = ASet;
|
||||
case 'null': set = ANull;
|
||||
case 'dynamic': set = ADynamic;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package hscript;
|
||||
|
||||
import hscript.utils.UnsafeReflect;
|
||||
import hscript.Interp;
|
||||
import hscript.Expr.FieldPropertyAccess;
|
||||
|
||||
@:access(hscript.Interp)
|
||||
@:structInit
|
||||
class Property {
|
||||
public var r:Dynamic;
|
||||
public var getter:FieldPropertyAccess;
|
||||
public var setter:FieldPropertyAccess;
|
||||
|
||||
var isVar:Bool;
|
||||
var interp:Interp;
|
||||
|
||||
var __allowReadAccess:Bool = false;
|
||||
var __allowWriteAccess:Bool = false;
|
||||
|
||||
public function callGetter(name:String) {
|
||||
switch (getter) {
|
||||
case AGet | ADynamic:
|
||||
var fName:String = 'get_$name';
|
||||
if (!__allowReadAccess && !interp.isBypassAccessor) {
|
||||
if (interp.varExists(fName)) {
|
||||
return callAccessor(fName);
|
||||
} else
|
||||
interp.error(ECustom('Method $fName required by property $name is missing'));
|
||||
} else {
|
||||
if ((setter == ADefault || setter == ANull) || isVar)
|
||||
return r;
|
||||
else
|
||||
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
||||
}
|
||||
case ANever:
|
||||
interp.error(ECustom('This expression cannot be accessed for reading'));
|
||||
default:
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public function callSetter(name:String, val:Dynamic) {
|
||||
switch (setter) {
|
||||
case ASet | ADynamic:
|
||||
var fName:String = 'set_$name';
|
||||
if (!__allowWriteAccess && !interp.isBypassAccessor) {
|
||||
if (interp.varExists(fName))
|
||||
return callAccessor(fName, [val], true);
|
||||
else
|
||||
interp.error(ECustom('Method $fName required by property $name is missing'));
|
||||
} else {
|
||||
if ((getter == ADefault || getter == ANull) || isVar)
|
||||
return r = val;
|
||||
else
|
||||
interp.error(ECustom('Field $name cannot be accessed because it is not a real variable${interp.isBypassAccessor ? '. Add @:isVar to enable it' : ''}'));
|
||||
}
|
||||
case ANever:
|
||||
interp.error(ECustom('This expression cannot be accessed for writing'));
|
||||
default:
|
||||
}
|
||||
|
||||
return r = val;
|
||||
}
|
||||
|
||||
private function callAccessor(f:String, ?args:Array<Dynamic>, isWrite:Bool = false):Dynamic {
|
||||
var fn = interp.variables.get(f);
|
||||
var rt:Dynamic = null;
|
||||
if (fn != null && Reflect.isFunction(fn)) {
|
||||
if (isWrite) __allowWriteAccess = true;
|
||||
else __allowReadAccess = true;
|
||||
|
||||
rt = UnsafeReflect.callMethodUnsafe(null, fn, args == null ? [] : args);
|
||||
|
||||
if (isWrite) __allowWriteAccess = false;
|
||||
else __allowReadAccess = false;
|
||||
|
||||
return rt;
|
||||
} else
|
||||
interp.error(ECustom('Method $f required by property ${f.substr(3)} is missing'));
|
||||
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user