"Type" for Custom Classes - Part II

- Move the superClass instantiation to CustomClassDecl
- Imported classes available for Static Functions

Warning: untested code.
This commit is contained in:
Jaime Humberto Macias Bustamante
2025-03-27 16:02:06 -07:00
parent e71f5a0471
commit f43221c3bb
4 changed files with 82 additions and 19 deletions
+2 -1
View File
@@ -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);
+16 -8
View File
@@ -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() {
+53 -1
View File
@@ -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<String, CustomClassImport>;
public var usings:Array<String>;
public var pkg:Null<Array<String>> = 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<String, FieldDecl> = [];
var _cachedStaticFunctions:Map<String, FunctionDecl> = [];
var _cachedStaticVariables:Map<String, VarDecl> = [];
public var __allowSetGet:Bool = true;
public function new(classDecl:Expr.ClassDecl, imports:Map<String, CustomClassImport>, usings:Array<String>, pkg:Null<Array<String>>) {
public function new(classDecl:Expr.ClassDecl, imports:Map<String, CustomClassImport>, usings:Array<String>, pkg:Null<Array<String>>, 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>):Dynamic {
var func:Function = getFunction(name);
+11 -9
View File
@@ -7,6 +7,8 @@ import hscript.Tools.EnumValue as HScriptEnumValue;
abstract OneOfTwo<T1, T2>(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<Dynamic>):Class<Dynamic> {
// TODO: SuperClass declaration on CustomClassDecl instead of CustomClass
return Type.getSuperClass(c);
inline static function getSuperClass(c:OneOfTwo<Class<Dynamic>, 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<T>(e:Enum<T>):Array<T> {
inline static function allEnums<T>(e:OneOfTwo<Enum<T>, HScriptEnum>):Array<T> {
// 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);
}
}