From f43221c3bbd9d8499550cfbec50626d7a265f692 Mon Sep 17 00:00:00 2001 From: Jaime Humberto Macias Bustamante Date: Thu, 27 Mar 2025 16:02:06 -0700 Subject: [PATCH] "Type" for Custom Classes - Part II - Move the superClass instantiation to CustomClassDecl - Imported classes available for Static Functions Warning: untested code. --- hscript/Interp.hx | 3 +- hscript/customclass/CustomClass.hx | 24 ++++++++---- hscript/customclass/CustomClassDecl.hx | 54 +++++++++++++++++++++++++- hscript/proxy/ProxyType.hx | 20 +++++----- 4 files changed, 82 insertions(+), 19 deletions(-) diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 950cc5d..975487a 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -1881,7 +1881,8 @@ class Interp { classDecl: classDecl, imports: imports, usings: usings, - pkg: pkg + pkg: pkg, + ogInterp: this } //customClassDecl.cacheFields(); registerCustomClass(customClassDecl, !regAlias ? as : null, _inCustomClass); diff --git a/hscript/customclass/CustomClass.hx b/hscript/customclass/CustomClass.hx index aa36720..0a48c31 100644 --- a/hscript/customclass/CustomClass.hx +++ b/hscript/customclass/CustomClass.hx @@ -23,16 +23,12 @@ class CustomClass implements IHScriptCustomAccessBehaviour { public var superClass:Dynamic; public var superConstructor(default, null):Dynamic; - + // TODO: move this to CustomClassDecl public var className(get, never):String; private function get_className():String { - // TODO: simplify this - var name = ""; - if (__class.pkg != null) { - name += __class.pkg.join("."); - } - name += __class.classDecl.name; - return name; + var pkg = __class.pkg != null ? '${__class.pkg.join(".")}.' : ""; + var name = __class.classDecl.name; + return '$pkg$name'; } private var __class:CustomClassDecl; @@ -128,6 +124,17 @@ class CustomClass implements IHScriptCustomAccessBehaviour { if (args == null) args = []; + if(__class.superClassDecl is CustomClassDecl) + superClass = new CustomClass(__class.superClassDecl, args, _cachedFieldDecls, this.interp); + else { + if (_cachedSuperFields != null) { + Reflect.setField(__class.superClassDecl, "__cachedFields", _cachedSuperFields); // Static field + } + superClass = Type.createInstance(__class.superClassDecl, args); + superClass.__customClass = this; + superClass.__real_fields = Type.getInstanceFields(__class.superClassDecl); + } + /* var extendString = new Printer().typeToString(__class.classDecl.extend); if (__class.pkg != null && extendString.indexOf(".") == -1) { extendString = __class.pkg.join(".") + "." + extendString; @@ -149,6 +156,7 @@ class CustomClass implements IHScriptCustomAccessBehaviour { superClass.__customClass = this; superClass.__real_fields = Type.getInstanceFields(c); } + */ } function buildImports() { diff --git a/hscript/customclass/CustomClassDecl.hx b/hscript/customclass/CustomClassDecl.hx index eb06e62..7e3da30 100644 --- a/hscript/customclass/CustomClassDecl.hx +++ b/hscript/customclass/CustomClassDecl.hx @@ -1,5 +1,6 @@ package hscript.customclass; +import hscript.proxy.ProxyType; import hscript.customclass.utils.FunctionUtils; import haxe.Constraints.Function; import hscript.Expr.FieldDecl; @@ -13,23 +14,63 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour { public var imports:Map; public var usings:Array; public var pkg:Null> = null; + public var ogInterp:Interp = null; public var staticInterp:Interp = new Interp(); + public var superClassDecl(default, null):Dynamic = null; //This holds the super class reference. + var _cachedStaticFields:Map = []; var _cachedStaticFunctions:Map = []; var _cachedStaticVariables:Map = []; public var __allowSetGet:Bool = true; - public function new(classDecl:Expr.ClassDecl, imports:Map, usings:Array, pkg:Null>) { + public function new(classDecl:Expr.ClassDecl, imports:Map, usings:Array, pkg:Null>, ogInterp:Interp = null) { this.classDecl = classDecl; this.imports = imports; this.usings = usings; this.pkg = pkg; + this.ogInterp = ogInterp; + if(ogInterp != null && ogInterp.importFailedCallback != null && ogInterp.errorHandler != null) { + staticInterp.importFailedCallback = ogInterp.importFailedCallback; + staticInterp.errorHandler = ogInterp.errorHandler; + staticInterp.allowStaticVariables = ogInterp.allowStaticVariables; + staticInterp.staticVariables = ogInterp.staticVariables; + } + + cacheImports(); cacheFields(); processUsings(); + if(classDecl.extend != null) + buildSuperClass(); + } + + function cacheImports() { + // This will make imported classes available for Static Functions + for(i => imp in imports) { + var importedClass = imp.fullPath; + var importAlias = imp.as; + + if (Interp.customClassExist(importedClass) && this.staticInterp.importFailedCallback != null) { + this.staticInterp.importFailedCallback(importedClass.split("."), importAlias); + continue; + } + + #if hscriptPos + var e:Expr = { + e: ExprDef.EImport(importedClass, importAlias), + pmin: 0, + pmax: 0, + origin: this.className, + line: i + }; + #else + var e = Expr.EImport(importedClass, importAlias); + #end + this.staticInterp.expr(e); + } } function cacheFields() { @@ -69,6 +110,17 @@ class CustomClassDecl implements IHScriptCustomAccessBehaviour { } } + function buildSuperClass() { + var extendString = new Printer().typeToString(classDecl.extend); + if (this.pkg != null && extendString.indexOf(".") == -1) { + extendString = this.pkg.join(".") + "." + extendString; + } + + superClassDecl = ProxyType.resolveClass(extendString); + if(superClassDecl == null) + staticInterp.error(ECustom("could not resolve super class: " + extendString)); + } + public function callFunction(name:String, ?args:Array):Dynamic { var func:Function = getFunction(name); diff --git a/hscript/proxy/ProxyType.hx b/hscript/proxy/ProxyType.hx index b8bc940..c043e5e 100644 --- a/hscript/proxy/ProxyType.hx +++ b/hscript/proxy/ProxyType.hx @@ -7,6 +7,8 @@ import hscript.Tools.EnumValue as HScriptEnumValue; abstract OneOfTwo(Dynamic) from T1 from T2 to T1 to T2 {} +@:allow(hscript.customclass.CustomClass) +@:allow(hscript.customclass.CustomClassDecl) class ProxyType { /** Returns the class of `o`, if `o` is a class instance. @@ -49,9 +51,11 @@ class ProxyType { In general, type parameter information cannot be obtained at runtime. **/ - inline static function getSuperClass(c:Class):Class { - // TODO: SuperClass declaration on CustomClassDecl instead of CustomClass - return Type.getSuperClass(c); + inline static function getSuperClass(c:OneOfTwo, CustomClassDecl>):Dynamic { + if(c is CustomClassDecl) { + return cast(c, CustomClassDecl).superClassDecl; + } + return Type.getSuperClass(cast c); } /** @@ -73,9 +77,8 @@ class ProxyType { if(c is CustomClassDecl) { var cls:CustomClassDecl = cast c; var name = cls.classDecl.name; - if(cls.pkg != null) - name = cls.pkg.join('.') + name; - return name; + var pkg = cls.pkg != null ? '${cls.pkg.join(".")}.' : ""; + return '$pkg$name'; } return Type.getClassName(cast c); } @@ -115,7 +118,6 @@ class ProxyType { The class name must not include any type parameters. **/ inline static function resolveClass(name:String):Dynamic { - // Dynamic to no mess with casting if(Interp.customClassExist(name)) { return Interp.getCustomClass(name); } @@ -350,13 +352,13 @@ class ProxyType { If `e` is null, the result is unspecified. **/ - inline static function allEnums(e:Enum):Array { + inline static function allEnums(e:OneOfTwo, HScriptEnum>):Array { // TODO: SUPPORT HSCRIPT ENUMS var isScripted:Bool = Std.isOfType(e, HScriptEnum); if(isScripted) { var hEnum:HScriptEnum = cast e; return [for(en in Reflect.fields(hEnum.enumValues)) Reflect.field(hEnum, en)]; } - return Type.allEnums(e); + return Type.allEnums(cast e); } }