diff --git a/hscript/CustomClassHandler.hx b/hscript/CustomClassHandler.hx index cb8f59a..619699c 100644 --- a/hscript/CustomClassHandler.hx +++ b/hscript/CustomClassHandler.hx @@ -4,6 +4,7 @@ import hscript.Interp.DeclaredVar; import hscript.utils.UnsafeReflect; using StringTools; +@:deprecated('Switch to new Custom Class instead') class CustomClassHandler implements IHScriptCustomConstructor { public static var staticHandler = new StaticHandler(); diff --git a/hscript/Interp.hx b/hscript/Interp.hx index d32d1d4..ed87217 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -780,6 +780,11 @@ class Interp { return className; } + // Workaround for parsing custom classes if made inside of a script file + public var localImports:Map = new Map(); + public var localParsedClasses:Array = []; // Prevents duplicated classes + public var newCustomClass:Bool = true; // Temporary + public function expr(e:Expr):Dynamic { #if hscriptPos curExpr = e; @@ -788,16 +793,95 @@ class Interp { switch (e) { case EIgnore(_): case EClass(name, fields, extend, interfaces): //Not sure if leave the old system or implement the new one. - if (customClasses.exists(name)) - error(EAlreadyExistingClass(name)); - inline function importVar(thing:String):String { if (thing == null) return null; final variable:Class = variables.exists(thing) ? cast variables.get(thing) : null; return variable == null ? thing : Type.getClassName(variable); } - customClasses.set(name, new CustomClassHandler(this, name, fields, importVar(extend), [for (i in interfaces) importVar(i)])); + + if (!newCustomClass) { + if (customClasses.exists(name)) + error(EAlreadyExistingClass(name)); + + trace("WARNING: Old Custom Class system marked for removal.\n'newCustomClass = true' to use the new system (EXPERIMENTAL)"); + customClasses.set(name, new CustomClassHandler(this, name, fields, importVar(extend), [for (i in interfaces) importVar(i)])); + return null; + } + + // New Custom Class system + + if (localParsedClasses.contains(name)) + error(EAlreadyExistingClass(name)); + + var customClassFields:Array = []; + for (f in fields) { + switch (Tools.expr(f)) { + case EFunction(args, e, name, ret, isPublic, isStatic, isOverride, isPrivate, isFinal, isInline): + var fnAcc:Array = []; + if (isPublic) fnAcc.push(APublic); + if (isStatic) fnAcc.push(AStatic); + if (isOverride) fnAcc.push(AOverride); + + var fnd:FunctionDecl = { + args: args, + body: e, + ret: ret + }; + var fd:FieldDecl = { + name: name, + meta: [], + kind: KFunction(fnd), + access: fnAcc + }; + + customClassFields.push(fd); + case EVar(n, t, e, isPublic, isStatic, isPrivate, isFinal, isInline): + var varAcc:Array = []; + if (isPublic) varAcc.push(APublic); + if (isStatic) varAcc.push(AStatic); + + var vrd:VarDecl = { + get: null, + set: null, + expr: e, + type: t + }; + var fd:FieldDecl = { + name: n, + meta: [], + kind: KVar(vrd), + access: varAcc + }; + + customClassFields.push(fd); + default: + } + } + + var extendPath:Null = extend != null ? CTPath(importVar(extend).split(".")) : null; + var interfacesPaths:Array = [for (i in interfaces) CTPath(importVar(i).split("."))]; + + var classDecl:ClassDecl = { + name: name, + params: {}, // TODO: make it parse and ignore it + meta: [], + isPrivate: false, + extend: extendPath, + implement: interfacesPaths, + fields: customClassFields, + isExtern: false, + }; + + var customClassDecl:CustomClassDecl = { + classDecl: classDecl, + imports: localImports, + usings: [for(u in this.usings) u.name], + pkg: null + }; + + registerCustomClass(customClassDecl, null); + localParsedClasses.push(customClassDecl.classDecl.name); case EImport(c, n): if (!importEnabled) return null; @@ -808,6 +892,13 @@ class Interp { var oldClassName = realClassName; var oldSplitName = splitClassName.copy(); + var customImport:CustomClassImport = { + name: claVarName, + pkg: splitClassName, + fullPath: realClassName + }; + localImports.set(customImport.name, customImport); + if (variables.exists(toSetName)) // class is already imported return null;