diff --git a/hscript/CustomClass.hx b/hscript/CustomClass.hx index dd31206..63162e0 100644 --- a/hscript/CustomClass.hx +++ b/hscript/CustomClass.hx @@ -1,5 +1,7 @@ package hscript; +import hscript.utils.UnsafeReflect; +import haxe.Constraints.Function; using Lambda; // TODO @@ -11,40 +13,115 @@ using Lambda; * @author Jamextreme140 */ @:access(hscript.CustomClassHandler) -class CustomClass /*implements IHScriptCustomClassBehaviour*/{ +class CustomClass implements IHScriptCustomClassBehaviour{ public var className(get, never):String; private function get_className():String return __class.name; - var interp:Interp; + public var __interp:Interp; + public var __custom__variables:Map; // TODO: remove this + public var __real_fields:Array; + public var __class__fields:Array; // Declared fields + + public var __allowSetGet:Bool = true; + var __class:CustomClassHandler; + var __superClass:IHScriptCustomClassBehaviour; + var __constructor:Function; var fields:Array; - public function new(__class:CustomClassHandler) { + public function new(__class:CustomClassHandler, args:Array) { this.__class = __class; - interp = new Interp(); - interp.errorHandler = __class.staticInterp.errorHandler; - interp.scriptObject = this; + __interp = new Interp(); + __interp.errorHandler = __class.staticInterp.errorHandler; + __interp.importFailedCallback = __class.staticInterp.importFailedCallback; - fields = []; - /* - for(e in __class.fields) { - switch (Tools.expr(e)) { - case EVar(n, _, e, _, isStatic, _, isFinal, _, get, set, isVar): - if(!isStatic) - fields.push(e); - case EFunction(args, e, name, ret, _, isStatic, _, _, isFinal, _): - if(!isStatic) - fields.push(e); + __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.scriptObject = this; + + 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); } - */ - for(f in fields) - @:privateAccess interp.exprReturn(f); + if(hasField('new')) { + buildConstructor(); + call('new', args); + + if(this.__superClass == null && __class.extend != null) + __interp.error(ECustom("super() not called")); + } + else if(__class.extend != null) { + buildSuperClass(args); + } + + } + + function buildConstructor() { + __constructor = Reflect.makeVarArgs(buildSuperClass); + } + + function buildSuperClass(?args:Array) { + if(args == null) + args = []; + + if(__class.cl == null) __interp.error(ECustom('Current class does not have a super')); + + if (__class.cl == CustomClassHandler) { + __superClass = new CustomClass(__class.cl, args); + } else { + var disallowCopy = Type.getInstanceFields(__class.cl); + __superClass = Type.createInstance(__class.cl, args); + __superClass.__real_fields = disallowCopy; + __superClass.__interp = this.__interp; + } + } + + function call(name:String, ?args:Array):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; + } + + function hasField(name:String) { + return __interp.variables.exists(name); + } + + public function hget(name:String):Dynamic { + switch (name) { + case 'superClass': return __superClass; + case 'superConstructor': return __constructor; + } + return null; + } + + public function __callGetter(name:String):Dynamic { + return null; + } + + public function hset(name:String, val:Dynamic):Dynamic { + return null; + } + + public function __callSetter(name:String, val:Dynamic):Dynamic { + return null; } public function toString():String diff --git a/hscript/CustomClassHandler.hx b/hscript/CustomClassHandler.hx index b42cfda..4beaa82 100644 --- a/hscript/CustomClassHandler.hx +++ b/hscript/CustomClassHandler.hx @@ -8,18 +8,21 @@ using StringTools; /** * Provides handlers for static custom class fields and instantiation. */ -class CustomClassHandler implements IHScriptCustomConstructor { +class CustomClassHandler implements IHScriptCustomConstructor implements IHScriptCustomBehaviour{ public static var staticHandler = new StaticHandler(); + public var __allowSetGet:Bool = true; + public var ogInterp:Interp; public var name:String; public var fields:Array; - public var extend:String; + public var extend:Null; public var interfaces:Array; - public var cl:Class; + public var cl:Dynamic; private var staticInterp:Interp; + private var staticFields:Array; public function new(ogInterp:Interp, name:String, fields:Array, ?extend:String, ?interfaces:Array) { this.ogInterp = ogInterp; @@ -28,17 +31,55 @@ class CustomClassHandler implements IHScriptCustomConstructor { this.extend = extend; this.interfaces = interfaces; - this.cl = extend == null ? CustomTemplateClass : Type.resolveClass('${extend}_HSX'); - if(cl == null) - ogInterp.error(EInvalidClass(extend)); + if(extend != null) { + if(ogInterp.customClasses.exists(extend)) + this.cl = ogInterp.customClasses.get(extend); + else + this.cl = Type.resolveClass('${extend}_HSX'); + } + //this.cl = extend == null ? CustomTemplateClass : Type.resolveClass('${extend}_HSX'); + //if(cl == null) + // ogInterp.error(EInvalidClass(extend)); + initStatic(); + } + + @:access(hscript.Interp) + function initStatic() { staticInterp = new Interp(); staticInterp.errorHandler = ogInterp.errorHandler; + 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) { + switch (Tools.expr(ex)) { + case EVar(n, _, _, _, isStatic, _, _, _, _, _, _): + if(isStatic) { + staticInterp.exprReturn(ex); + staticFields.push(n); + fields.remove(ex); + } + case EFunction(_, _, n, _, _, isStatic, _, _, _, _): + if(isStatic) { + staticInterp.exprReturn(ex); + staticFields.push(n); + fields.remove(ex); + } + default: + } + } } public function hnew(args:Array):Dynamic { // TODO: clean this up, it sucks, i hate it // TODO: make static vars work correctly + /* var interp = new Interp(); interp.errorHandler = ogInterp.errorHandler; @@ -152,11 +193,29 @@ class CustomClassHandler implements IHScriptCustomConstructor { } } } - + */ + + var _class = new CustomClass(this, args); return _class; } + public function hget(name:String):Dynamic { + return null; + } + + public function hset(name:String, val:Dynamic):Dynamic { + return null; + } + + public function __callGetter(name:String):Dynamic { + return null; + } + + public function __callSetter(name:String, val:Dynamic):Dynamic { + return null; + } + public function toString():String { return name; } diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 822652e..41d3237 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -592,6 +592,12 @@ class Interp { return null; id = StringTools.trim(id); + if(inCustomClass && id == 'super') { + var customClass:IHScriptCustomClassBehaviour = cast scriptObject; + var superClass = customClass.hget('superClass'); + return superClass == null ? customClass.hget('superConstructor') : superClass; + } + if (locals.exists(id)) { var l = locals.get(id); if(l != null) {