Custom Classes rework progress - 2
This commit is contained in:
+185
-86
@@ -2,9 +2,11 @@ package hscript;
|
||||
|
||||
import hscript.utils.UnsafeReflect;
|
||||
import haxe.Constraints.Function;
|
||||
|
||||
using Lambda;
|
||||
|
||||
// TODO
|
||||
|
||||
/**
|
||||
* The Custom Class core.
|
||||
*
|
||||
@@ -13,117 +15,214 @@ using Lambda;
|
||||
* @author Jamextreme140
|
||||
*/
|
||||
@:access(hscript.CustomClassHandler)
|
||||
class CustomClass implements IHScriptCustomClassBehaviour{
|
||||
@:access(hscript.Property)
|
||||
class CustomClass implements IHScriptCustomClassBehaviour {
|
||||
public var className(get, never):String;
|
||||
|
||||
public var className(get, never):String;
|
||||
private function get_className():String
|
||||
return __class.name;
|
||||
private function get_className():String
|
||||
return __class.name;
|
||||
|
||||
public var __interp:Interp;
|
||||
public var __custom__variables:Map<String, Dynamic>; // TODO: remove this
|
||||
public var __real_fields:Array<String>;
|
||||
public var __class__fields:Array<String>; // Declared fields
|
||||
public var __interp:Interp;
|
||||
public var __real_fields:Array<String> = []; // UNUSED
|
||||
public var __class__fields:Array<String> = []; // Declared fields
|
||||
|
||||
public var __allowSetGet:Bool = true;
|
||||
public var __allowSetGet:Bool = true;
|
||||
|
||||
var __class:CustomClassHandler;
|
||||
var __superClass:IHScriptCustomClassBehaviour;
|
||||
var __constructor:Function;
|
||||
var fields:Array<Expr>;
|
||||
|
||||
public function new(__class:CustomClassHandler, args:Array<Dynamic>) {
|
||||
this.__class = __class;
|
||||
var __class:CustomClassHandler;
|
||||
var __superClass:IHScriptCustomClassBehaviour;
|
||||
var __constructor:Function;
|
||||
var fields:Array<Expr>;
|
||||
|
||||
__interp = new Interp();
|
||||
__interp.errorHandler = __class.staticInterp.errorHandler;
|
||||
__interp.importFailedCallback = __class.staticInterp.importFailedCallback;
|
||||
public function new(__class:CustomClassHandler, args:Array<Dynamic>) {
|
||||
this.__class = __class;
|
||||
|
||||
__interp.variables = __class.staticInterp.variables; // This will access to static fields
|
||||
__interp.allowPublicVariables = __class.ogInterp.allowPublicVariables;
|
||||
__interp.publicVariables = __class.ogInterp.publicVariables;
|
||||
__interp.allowStaticVariables = __class.ogInterp.allowStaticVariables;
|
||||
__interp.staticVariables = __class.ogInterp.staticVariables;
|
||||
__interp = new Interp();
|
||||
__interp.errorHandler = __class.staticInterp.errorHandler;
|
||||
__interp.importFailedCallback = __class.staticInterp.importFailedCallback;
|
||||
|
||||
__interp.scriptObject = this;
|
||||
__interp.variables = __class.staticInterp.variables; // This will access to static fields
|
||||
__interp.publicVariables = __class.ogInterp.publicVariables;
|
||||
__interp.staticVariables = __class.ogInterp.staticVariables;
|
||||
|
||||
this.fields = __class.fields;
|
||||
for(f in fields) {
|
||||
switch(Tools.expr(f)) {
|
||||
case EVar(n):
|
||||
__class__fields.push(n);
|
||||
case EFunction(_, _, n):
|
||||
__class__fields.push(n);
|
||||
default:
|
||||
}
|
||||
@:privateAccess __interp.exprReturn(f);
|
||||
}
|
||||
this.fields = __class.fields;
|
||||
for (f in fields) {
|
||||
switch (Tools.expr(f)) {
|
||||
case EVar(n):
|
||||
__class__fields.push(n);
|
||||
case EFunction(_, _, n):
|
||||
__class__fields.push(n);
|
||||
default:
|
||||
}
|
||||
@:privateAccess __interp.exprReturn(f);
|
||||
}
|
||||
|
||||
if(hasField('new')) {
|
||||
buildConstructor();
|
||||
call('new', args);
|
||||
__interp.scriptObject = this;
|
||||
|
||||
if(this.__superClass == null && __class.extend != null)
|
||||
__interp.error(ECustom("super() not called"));
|
||||
}
|
||||
else if(__class.extend != null) {
|
||||
buildSuperClass(args);
|
||||
}
|
||||
|
||||
}
|
||||
if (hasField('new')) {
|
||||
buildConstructor();
|
||||
call('new', args);
|
||||
|
||||
function buildConstructor() {
|
||||
__constructor = Reflect.makeVarArgs(buildSuperClass);
|
||||
}
|
||||
if (this.__superClass == null && __class.extend != null)
|
||||
__interp.error(ECustom("super() not called"));
|
||||
} else if (__class.extend != null) {
|
||||
buildSuperClass(args);
|
||||
}
|
||||
}
|
||||
|
||||
function buildSuperClass(?args:Array<Dynamic>) {
|
||||
if(args == null)
|
||||
args = [];
|
||||
function buildConstructor() {
|
||||
__constructor = Reflect.makeVarArgs(buildSuperClass);
|
||||
}
|
||||
|
||||
if(__class.cl == null) __interp.error(ECustom('Current class does not have a super'));
|
||||
function buildSuperClass(?args:Array<Dynamic>) {
|
||||
if (args == null)
|
||||
args = [];
|
||||
|
||||
if (__class.cl == null) {
|
||||
__interp.error(ECustom('Current class does not have a super'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (__class.cl == CustomClassHandler) {
|
||||
__superClass = new CustomClass(__class.cl, args);
|
||||
@:privateAccess
|
||||
__interp.__instanceFields.concat(__superClass.__class__fields);
|
||||
} else {
|
||||
var disallowCopy = Type.getInstanceFields(__class.cl);
|
||||
__superClass = Type.createInstance(__class.cl, args);
|
||||
__superClass.__real_fields = disallowCopy;
|
||||
__superClass.__interp = this.__interp;
|
||||
__superClass.__class__fields = this.__class__fields;
|
||||
__superClass.__interp = this.__interp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function call(name:String, ?args:Array<Dynamic>):Dynamic {
|
||||
var fn = __interp.variables.get(name);
|
||||
if(fn != null && Reflect.isFunction(fn))
|
||||
return UnsafeReflect.callMethodUnsafe(null, fn, (args == null) ? [] : args);
|
||||
|
||||
__interp.error(ECustom('$name is not a function'));
|
||||
return null;
|
||||
}
|
||||
public function call(name:String, ?args:Array<Dynamic>):Dynamic {
|
||||
var fn = __interp.variables.get(name);
|
||||
if (fn != null && Reflect.isFunction(fn))
|
||||
return UnsafeReflect.callMethodUnsafe(null, fn, (args == null) ? [] : args);
|
||||
else
|
||||
__interp.error(ECustom('$name is not a function'));
|
||||
return null;
|
||||
}
|
||||
|
||||
function hasField(name:String) {
|
||||
return __interp.variables.exists(name);
|
||||
}
|
||||
function hasField(name:String) {
|
||||
// return __interp.variables.exists(name);
|
||||
return __class__fields.contains(name);
|
||||
}
|
||||
|
||||
public function hget(name:String):Dynamic {
|
||||
switch (name) {
|
||||
case 'superClass': return __superClass;
|
||||
case 'superConstructor': return __constructor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function getField(name:String, allowProperty:Bool = true):Dynamic {
|
||||
var f = __interp.variables.get(name);
|
||||
if (allowProperty && f is Property) {
|
||||
var prop:Property = cast f;
|
||||
prop.__allowSetGet = this.__allowSetGet;
|
||||
var r = prop.callGetter(name);
|
||||
prop.__allowSetGet = null;
|
||||
return r;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public function __callGetter(name:String):Dynamic {
|
||||
return null;
|
||||
}
|
||||
function setField(name:String, val:Dynamic):Dynamic {
|
||||
var f = getField(name, false);
|
||||
if (f is Property) {
|
||||
var prop:Property = cast f;
|
||||
prop.__allowSetGet = this.__allowSetGet;
|
||||
var r = prop.callSetter(name, val);
|
||||
prop.__allowSetGet = null;
|
||||
return r;
|
||||
}
|
||||
__interp.variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
return null;
|
||||
}
|
||||
function superHasField(name:String) {
|
||||
if (__superClass == null)
|
||||
return false;
|
||||
|
||||
public function __callSetter(name:String, val:Dynamic):Dynamic {
|
||||
return null;
|
||||
}
|
||||
var realFieldExists = __superClass.__real_fields != null && __superClass.__real_fields.contains(name);
|
||||
var classFieldExists = __superClass.__class__fields != null && __superClass.__class__fields.contains(name);
|
||||
|
||||
public function toString():String
|
||||
return className;
|
||||
}
|
||||
return realFieldExists || classFieldExists;
|
||||
}
|
||||
|
||||
public function hget(name:String):Dynamic {
|
||||
switch (name) {
|
||||
case 'superClass': return __superClass;
|
||||
case 'superConstructor': return __constructor;
|
||||
default:
|
||||
if (hasField(name))
|
||||
return getField(name);
|
||||
|
||||
if (__superClass != null) {
|
||||
if (superHasField(name)) {
|
||||
__superClass.__allowSetGet = this.__allowSetGet;
|
||||
return __superClass.hget(name);
|
||||
}
|
||||
}
|
||||
|
||||
throw "field '"
|
||||
+ name
|
||||
+ "' does not exist in custom class '"
|
||||
+ this.className
|
||||
+ "'"
|
||||
+ (__superClass != null ? "' or super class '" + Type.getClassName(Type.getClass(this.__superClass)) + "'" : "");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
if (hasField(name)) {
|
||||
return setField(name, val);
|
||||
}
|
||||
|
||||
if (__superClass != null) {
|
||||
if (superHasField(name)) {
|
||||
__superClass.__allowSetGet = this.__allowSetGet;
|
||||
return __superClass.hset(name, val);
|
||||
}
|
||||
}
|
||||
|
||||
throw "field '"
|
||||
+ name
|
||||
+ "' does not exist in custom class '"
|
||||
+ this.className
|
||||
+ "'"
|
||||
+ (__superClass != null ? "' or super class '" + Type.getClassName(Type.getClass(this.__superClass)) + "'" : "");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// UNUSED
|
||||
public function __callGetter(name:String):Dynamic {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __callSetter(name:String, val:Dynamic):Dynamic {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the real superClass if the Custom Class
|
||||
* extends another Custom Class, and so on until
|
||||
* it reaches a real class, otherwise it will
|
||||
* return the last fetched Custom Class
|
||||
* @return Null<Dynamic>
|
||||
*/
|
||||
public function getSuperclass():IHScriptCustomClassBehaviour {
|
||||
var cls:Null<IHScriptCustomClassBehaviour> = this.__superClass;
|
||||
|
||||
// Check if the superClass is another custom class,
|
||||
// so it will find for a real class, otherwise
|
||||
// returns the last super CustomClass parent.
|
||||
while (cls != null && cls is CustomClass) {
|
||||
var next = cast(cls, CustomClass).__superClass;
|
||||
if (next == null)
|
||||
break; // Return the Custom Class itself
|
||||
cls = next;
|
||||
}
|
||||
|
||||
return cls;
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
return className;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ using StringTools;
|
||||
/**
|
||||
* Provides handlers for static custom class fields and instantiation.
|
||||
*/
|
||||
class CustomClassHandler implements IHScriptCustomConstructor implements IHScriptCustomBehaviour{
|
||||
@:access(hscript.Property)
|
||||
class CustomClassHandler implements IHScriptCustomConstructor implements IHScriptCustomAccessBehaviour{
|
||||
public static var staticHandler = new StaticHandler();
|
||||
|
||||
public var __allowSetGet:Bool = true;
|
||||
@@ -36,10 +37,11 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
||||
this.cl = ogInterp.customClasses.get(extend);
|
||||
else
|
||||
this.cl = Type.resolveClass('${extend}_HSX');
|
||||
|
||||
if(cl == null)
|
||||
ogInterp.error(EInvalidClass(extend));
|
||||
}
|
||||
//this.cl = extend == null ? CustomTemplateClass : Type.resolveClass('${extend}_HSX');
|
||||
//if(cl == null)
|
||||
// ogInterp.error(EInvalidClass(extend));
|
||||
|
||||
initStatic();
|
||||
}
|
||||
@@ -51,28 +53,30 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
||||
staticInterp.importFailedCallback = ogInterp.importFailedCallback;
|
||||
|
||||
staticInterp.variables = ogInterp.variables;
|
||||
staticInterp.allowPublicVariables = ogInterp.allowPublicVariables;
|
||||
staticInterp.publicVariables = ogInterp.publicVariables;
|
||||
staticInterp.allowStaticVariables = ogInterp.allowStaticVariables;
|
||||
staticInterp.staticVariables = ogInterp.staticVariables;
|
||||
|
||||
// TODO: optimize this
|
||||
for(ex in fields) {
|
||||
var varOrFunction:Int = -1; // 0 - variable | 1 - function
|
||||
var staticField:Bool = false;
|
||||
var fieldName:String = "";
|
||||
switch (Tools.expr(ex)) {
|
||||
case EVar(n, _, _, _, isStatic, _, _, _, _, _, _):
|
||||
if(isStatic) {
|
||||
staticInterp.exprReturn(ex);
|
||||
staticFields.push(n);
|
||||
fields.remove(ex);
|
||||
}
|
||||
varOrFunction = 0;
|
||||
staticField = isStatic;
|
||||
fieldName = n;
|
||||
case EFunction(_, _, n, _, _, isStatic, _, _, _, _):
|
||||
if(isStatic) {
|
||||
staticInterp.exprReturn(ex);
|
||||
staticFields.push(n);
|
||||
fields.remove(ex);
|
||||
}
|
||||
varOrFunction = 1;
|
||||
staticField = isStatic;
|
||||
fieldName = n;
|
||||
default:
|
||||
}
|
||||
|
||||
if(staticField && varOrFunction > -1) {
|
||||
staticInterp.exprReturn(ex);
|
||||
staticFields.push(fieldName);
|
||||
fields.remove(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,19 +199,58 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
||||
}
|
||||
*/
|
||||
|
||||
// I can't believe all these lines of code above got reduced to this sentence.
|
||||
var _class = new CustomClass(this, args);
|
||||
|
||||
return _class;
|
||||
}
|
||||
|
||||
function hasField(name:String) {
|
||||
return staticFields.contains(name);
|
||||
}
|
||||
|
||||
function getField(name:String, allowProperty:Bool = true):Dynamic {
|
||||
var f = staticInterp.variables.get(name);
|
||||
if(f is Property && allowProperty) {
|
||||
var prop:Property = cast f;
|
||||
prop.__allowSetGet = this.__allowSetGet;
|
||||
var r = prop.callGetter(name);
|
||||
prop.__allowSetGet = null;
|
||||
return r;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
function setField(name:String, val:Dynamic):Dynamic {
|
||||
var f = getField(name, false);
|
||||
if(f is Property) {
|
||||
var prop:Property = cast f;
|
||||
prop.__allowSetGet = this.__allowSetGet;
|
||||
var r = prop.callSetter(name, val);
|
||||
prop.__allowSetGet = null;
|
||||
return r;
|
||||
}
|
||||
staticInterp.variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
public function hget(name:String):Dynamic {
|
||||
if(hasField(name)) {
|
||||
return getField(name);
|
||||
}
|
||||
throw "field '"+ name+ "' does not exist in class '"+ this.name+ "'";
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
if(hasField(name))
|
||||
return setField(name, val);
|
||||
|
||||
throw "field '"+ name+ "' does not exist in class '"+ this.name+ "'";
|
||||
return null;
|
||||
}
|
||||
|
||||
// UNUSED
|
||||
public function __callGetter(name:String):Dynamic {
|
||||
return null;
|
||||
}
|
||||
@@ -220,7 +263,7 @@ class CustomClassHandler implements IHScriptCustomConstructor implements IHScrip
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
class CustomTemplateClass implements IHScriptCustomClassBehaviour {
|
||||
public var __interp:Interp;
|
||||
public var __allowSetGet:Bool = true;
|
||||
@@ -265,7 +308,7 @@ class CustomTemplateClass implements IHScriptCustomClassBehaviour {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is for backwards compatibility with old hscript-improved, since some scripts use it
|
||||
|
||||
@@ -2,7 +2,6 @@ package hscript;
|
||||
|
||||
interface IHScriptCustomClassBehaviour extends IHScriptCustomAccessBehaviour{
|
||||
public var __interp:Interp;
|
||||
public var __custom__variables:Map<String, Dynamic>;
|
||||
public var __real_fields:Array<String>;
|
||||
public var __class__fields:Array<String>;
|
||||
|
||||
|
||||
+46
-15
@@ -65,6 +65,7 @@ class RedeclaredVar {
|
||||
public var depth:Int;
|
||||
}
|
||||
|
||||
@:access(hscript.CustomClass)
|
||||
@:analyzer(optimize, local_dce, fusion, user_var_fusion)
|
||||
class Interp {
|
||||
private var hasScriptObject(get, never):Bool;
|
||||
@@ -117,7 +118,7 @@ class Interp {
|
||||
public var errorHandler:Error->Void;
|
||||
public var importFailedCallback:Array<String>->Bool;
|
||||
|
||||
public var customClasses:Map<String, CustomClassHandler>; // make this static ???
|
||||
public var customClasses:Map<String, CustomClassHandler>;
|
||||
public var variables:Map<String, Dynamic>;
|
||||
public var publicVariables:Map<String, Dynamic>;
|
||||
public var staticVariables:Map<String, Dynamic>;
|
||||
@@ -587,7 +588,7 @@ class Interp {
|
||||
#end
|
||||
}
|
||||
|
||||
public function resolve(id:String, doException:Bool = true, getProperty:Bool = true):Dynamic {
|
||||
public function resolve(id:String, doException:Bool = true, allowProperty:Bool = true):Dynamic {
|
||||
if (id == null)
|
||||
return null;
|
||||
id = StringTools.trim(id);
|
||||
@@ -601,7 +602,7 @@ class Interp {
|
||||
if (locals.exists(id)) {
|
||||
var l = locals.get(id);
|
||||
if(l != null) {
|
||||
if(l.r != null && l.r is Property && getProperty)
|
||||
if(l.r != null && l.r is Property && allowProperty)
|
||||
return cast(l.r, Property).callGetter(id);
|
||||
else
|
||||
return l.r;
|
||||
@@ -618,7 +619,7 @@ class Interp {
|
||||
r = staticVariables.get(id);
|
||||
|
||||
if(r != null) {
|
||||
if(r is Property && getProperty)
|
||||
if(r is Property && allowProperty)
|
||||
return cast(r, Property).callGetter(id);
|
||||
else
|
||||
return r;
|
||||
@@ -846,7 +847,7 @@ class Interp {
|
||||
error(EInvalidOp(op));
|
||||
}
|
||||
case ECall(e, params):
|
||||
var args:Array<Dynamic> = [for(p in params) expr(p)];
|
||||
var args:Array<Dynamic> = makeArgs(params);
|
||||
|
||||
switch (Tools.expr(e)) {
|
||||
case EField(e, f, s):
|
||||
@@ -1063,10 +1064,7 @@ class Interp {
|
||||
return arr[index];
|
||||
}
|
||||
case ENew(cl, params):
|
||||
var a = [];
|
||||
for (e in params)
|
||||
a.push(expr(e));
|
||||
return cnew(cl, a);
|
||||
return cnew(cl, makeArgs(params));
|
||||
case EThrow(e):
|
||||
throw expr(e);
|
||||
case ETry(e, n, _, ecatch):
|
||||
@@ -1189,6 +1187,26 @@ class Interp {
|
||||
return v;
|
||||
}
|
||||
|
||||
function makeArgs(params:Array<Expr>):Array<Dynamic> {
|
||||
var args:Array<Dynamic> = [];
|
||||
for (p in params) {
|
||||
switch (Tools.expr(p)) {
|
||||
case EIdent(id):
|
||||
var ident = resolve(id);
|
||||
if (ident is CustomClass) {
|
||||
var customClass:CustomClass = cast ident; // Pass the underlying superclass if exist
|
||||
args.push(customClass.__superClass != null ? customClass.getSuperclass() : customClass);
|
||||
} else {
|
||||
args.push(ident);
|
||||
}
|
||||
default:
|
||||
args.push(expr(p));
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
function forLoop(n:String, it:Expr, e:Expr, ?ithv:String):Void {
|
||||
var isKeyValue = ithv != null;
|
||||
var old = declared.length;
|
||||
@@ -1333,16 +1351,29 @@ class Interp {
|
||||
}
|
||||
|
||||
function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic {
|
||||
if(hasScriptObject && o == CustomClassHandler.staticHandler) {
|
||||
return UnsafeReflect.callMethodUnsafe(scriptObject, UnsafeReflect.field(scriptObject, "_HX_SUPER__" + f), args);
|
||||
// Custom logic to handle super calls to prevent infinite recursion
|
||||
if(inCustomClass) {
|
||||
if (o == scriptObject.__superClass) {
|
||||
if (scriptObject.__superClass is CustomClass)
|
||||
return cast(scriptObject.__superClass, CustomClass).call(f, args);
|
||||
else
|
||||
return return UnsafeReflect.callMethodUnsafe(scriptObject.__superClass, UnsafeReflect.field(scriptObject.__superClass, '_HX_SUPER__$f'), args);
|
||||
}
|
||||
}
|
||||
return call(o, get(o, f), args);
|
||||
|
||||
var func = get(o, f);
|
||||
// Workaround for an HTML5-specific issue.
|
||||
// https://github.com/HaxeFoundation/haxe/issues/11298
|
||||
#if js
|
||||
if (func == null && f == "contains") {
|
||||
func = get(o, "includes");
|
||||
}
|
||||
#end
|
||||
|
||||
return call(o, func, args);
|
||||
}
|
||||
|
||||
function call(o:Dynamic, f:Dynamic, args:Array<Dynamic>):Dynamic {
|
||||
if(f == CustomClassHandler.staticHandler) {
|
||||
return null;
|
||||
}
|
||||
return UnsafeReflect.callMethodSafe(o, f, args);
|
||||
}
|
||||
|
||||
|
||||
+12
-2
@@ -465,15 +465,25 @@ class Parser {
|
||||
case TBkOpen:
|
||||
var a = [];
|
||||
tk = token();
|
||||
var first = true;
|
||||
while( tk != TBkClose && (!resumeErrors || tk != TEof) ) {
|
||||
if (!first) {
|
||||
if (tk != TComma)
|
||||
unexpected(tk);
|
||||
else {
|
||||
tk = token();
|
||||
if (tk == TBkClose)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
first = false;
|
||||
push(tk);
|
||||
var oldoo = disableOrOp;
|
||||
disableOrOp = false;
|
||||
a.push(parseExpr());
|
||||
disableOrOp = oldoo;
|
||||
tk = token();
|
||||
if( tk == TComma )
|
||||
tk = token();
|
||||
}
|
||||
if( a.length == 1 && a[0] != null ) // What is this for???
|
||||
switch( expr(a[0]) ) {
|
||||
|
||||
+3
-2
@@ -16,12 +16,13 @@ class Property {
|
||||
|
||||
var __allowReadAccess:Bool = false;
|
||||
var __allowWriteAccess:Bool = false;
|
||||
var __allowSetGet:Null<Bool> = null;
|
||||
|
||||
public function callGetter(name:String) {
|
||||
switch (getter) {
|
||||
case AGet | ADynamic:
|
||||
var fName:String = 'get_$name';
|
||||
if (!__allowReadAccess && !interp.isBypassAccessor) {
|
||||
if (!__allowReadAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
||||
if (interp.varExists(fName)) {
|
||||
return callAccessor(fName);
|
||||
} else
|
||||
@@ -44,7 +45,7 @@ class Property {
|
||||
switch (setter) {
|
||||
case ASet | ADynamic:
|
||||
var fName:String = 'set_$name';
|
||||
if (!__allowWriteAccess && !interp.isBypassAccessor) {
|
||||
if (!__allowWriteAccess && (__allowSetGet != null && __allowSetGet || !interp.isBypassAccessor)) {
|
||||
if (interp.varExists(fName))
|
||||
return callAccessor(fName, [val], true);
|
||||
else
|
||||
|
||||
@@ -61,6 +61,7 @@ class ClassExtendMacro {
|
||||
if(key == "away3d.tools.commands.Weld") return fields; // Error: Unknown identifier
|
||||
if(fkey == "hscript.CustomClassHandler.TemplateClass") return fields; // Error: Redefined
|
||||
if(fkey == "hscript.CustomClassHandler.CustomTemplateClass") return fields; // Error: Redefined
|
||||
if(fkey == "hscript.CustomClass") return fields; // Error: Redefined
|
||||
if(key == "sys.thread.EventLoop") return fields; // Error: cant override force inlined
|
||||
if(Config.DISALLOW_CUSTOM_CLASSES.contains(cl.module) || Config.DISALLOW_CUSTOM_CLASSES.contains(fkey)) return fields;
|
||||
if(cl.module.contains("_")) return fields; // Weird issue, sorry
|
||||
@@ -210,7 +211,15 @@ class ClassExtendMacro {
|
||||
if (f == null)
|
||||
continue;
|
||||
if (f.name == "new") {
|
||||
hasNew = true;
|
||||
switch (f.kind) {
|
||||
case FFun(fn):
|
||||
var constructor:Field = buildConstructor(fn.args);
|
||||
|
||||
shadowClass.fields.push(constructor);
|
||||
definedFields.push(f.name);
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (f.name.startsWith(FUNC_PREFIX))
|
||||
@@ -245,7 +254,7 @@ class ClassExtendMacro {
|
||||
if (returns) {
|
||||
overrideExpr = macro {
|
||||
var name:String = $v{name};
|
||||
|
||||
/*
|
||||
if (__custom__variables != null) {
|
||||
if(__custom__variables.exists(name)) {
|
||||
var v:Dynamic = null;
|
||||
@@ -254,12 +263,20 @@ class ClassExtendMacro {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (__interp != null && __class__fields.contains(name)) {
|
||||
var v:Dynamic = null;
|
||||
if (Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||
return v($a{arguments});
|
||||
}
|
||||
}
|
||||
|
||||
return super.$name($a{arguments});
|
||||
};
|
||||
} else {
|
||||
overrideExpr = macro {
|
||||
var name:String = $v{name};
|
||||
|
||||
/*
|
||||
if (__custom__variables != null) {
|
||||
if(__custom__variables.exists(name)) {
|
||||
var v:Dynamic = null;
|
||||
@@ -269,6 +286,14 @@ class ClassExtendMacro {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (__interp != null && __class__fields.contains(name)) {
|
||||
var v:Dynamic = null;
|
||||
if (Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||
v($a{arguments});
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.$name($a{arguments});
|
||||
};
|
||||
}
|
||||
@@ -331,7 +356,6 @@ class ClassExtendMacro {
|
||||
pack: cl.pack.copy(),
|
||||
name: cl.name
|
||||
}, [
|
||||
{name: "IHScriptCustomAccessBehaviour", pack: ["hscript"]},
|
||||
{name: "IHScriptCustomClassBehaviour", pack: ["hscript"]}
|
||||
], false, true, false);
|
||||
shadowClass.name = '${cl.name}$CLASS_SUFFIX';
|
||||
@@ -347,14 +371,14 @@ class ClassExtendMacro {
|
||||
kind: FVar(macro: hscript.Interp),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
/*
|
||||
shadowClass.fields.push({
|
||||
name: "__custom__variables",
|
||||
pos: Context.currentPos(),
|
||||
kind: FVar(macro: Map<String, Dynamic>),
|
||||
access: [APublic]
|
||||
});
|
||||
|
||||
*/
|
||||
shadowClass.fields.push({
|
||||
name: "__allowSetGet",
|
||||
pos: Context.currentPos(),
|
||||
@@ -384,7 +408,7 @@ class ClassExtendMacro {
|
||||
params: [],
|
||||
expr: macro {
|
||||
__allowSetGet = false;
|
||||
var v = __custom__variables.get("get_" + name)();
|
||||
//var v = __custom__variables.get("get_" + name)();
|
||||
__allowSetGet = true;
|
||||
return v;
|
||||
},
|
||||
@@ -408,7 +432,7 @@ class ClassExtendMacro {
|
||||
params: [],
|
||||
expr: macro {
|
||||
__allowSetGet = false;
|
||||
var v = __custom__variables.get("set_" + name)(val);
|
||||
//var v = __custom__variables.get("set_" + name)(val);
|
||||
__allowSetGet = true;
|
||||
return v;
|
||||
},
|
||||
@@ -472,30 +496,16 @@ class ClassExtendMacro {
|
||||
|
||||
var hgetField = if(hasHgetInSuper) {
|
||||
macro {
|
||||
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(__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(__allowSetGet && __custom__variables.exists("set_" + name))
|
||||
return __callSetter(name, val);
|
||||
if (__custom__variables.exists(name)) {
|
||||
__custom__variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
if(__real_fields.contains(name)) {
|
||||
UnsafeReflect.setProperty(this, name, val);
|
||||
return UnsafeReflect.field(this, name);
|
||||
@@ -504,17 +514,11 @@ class ClassExtendMacro {
|
||||
}
|
||||
} else {
|
||||
macro {
|
||||
if(__allowSetGet && __custom__variables.exists("set_" + name))
|
||||
return __callSetter(name, val);
|
||||
if (__custom__variables.exists(name)) {
|
||||
__custom__variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
if(__real_fields.contains(name)) {
|
||||
UnsafeReflect.setProperty(this, name, val);
|
||||
return UnsafeReflect.field(this, name);
|
||||
}
|
||||
__custom__variables.set(name, val);
|
||||
//__custom__variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -579,6 +583,23 @@ class ClassExtendMacro {
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
static function buildConstructor(constArgs:Array<FunctionArg>):Field {
|
||||
var superCallArgs:Array<Expr> = [for (arg in constArgs) macro $i{arg.name}];
|
||||
|
||||
return {
|
||||
name: 'new',
|
||||
access: [APublic],
|
||||
pos: Context.currentPos(),
|
||||
kind: FFun({
|
||||
args: constArgs,
|
||||
expr: macro {
|
||||
// Call the super constructor with appropriate args
|
||||
super($a{superCallArgs});
|
||||
}
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
#else
|
||||
class ClassExtendMacro {
|
||||
|
||||
Reference in New Issue
Block a user