Tried some fuckery
This commit is contained in:
+228
-109
@@ -18,15 +18,15 @@ class ClassExtendMacro {
|
||||
public static inline final FUNC_PREFIX = "_HX_SUPER__";
|
||||
public static inline final CLASS_SUFFIX = "_HSX";
|
||||
|
||||
public static var applyOn:Array<String> = ["flixel", "funkin"];
|
||||
|
||||
public function new(className:String, usedClass:Class<Dynamic>) {
|
||||
this.className = className;
|
||||
this.usedClass = usedClass;
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
//Compiler.addGlobalMetadata('funkin', '@:build(hscript.ClassExtendMacro.build())');
|
||||
Compiler.addGlobalMetadata('flixel', '@:build(hscript.ClassExtendMacro.build())');
|
||||
//Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())');
|
||||
trace("TEST");
|
||||
}
|
||||
|
||||
@@ -36,131 +36,250 @@ class ClassExtendMacro {
|
||||
if (clRef == null) return fields;
|
||||
var cl = clRef.get();
|
||||
|
||||
if (cl.isAbstract || cl.isExtern || cl.isFinal || cl.isInterface) return fields;
|
||||
if (!cl.name.endsWith("_Impl_") && !cl.name.endsWith(CLASS_SUFFIX) && !cl.name.endsWith("__Softcoded")) {//(/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType")) {
|
||||
var metas = cl.meta.get();
|
||||
|
||||
var hasInterp = false;
|
||||
if(cl.params.length > 0) {
|
||||
return fields;
|
||||
} else if (cl.superClass != null) {
|
||||
var sClass = cl;
|
||||
var inModifiedModule = false;
|
||||
while(sClass != null) {
|
||||
if (sClass.superClass != null) {
|
||||
if (sClass.superClass.params != null && sClass.superClass.params.length > 0)
|
||||
return fields;
|
||||
if (!inModifiedModule)
|
||||
for(e in applyOn)
|
||||
if (sClass.superClass.t.get().module.startsWith(e)) {
|
||||
inModifiedModule = true;
|
||||
hasInterp = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasInterp)
|
||||
for(f in sClass.fields.get())
|
||||
if (f.name == "__interp") {
|
||||
hasInterp = true;
|
||||
break;
|
||||
}
|
||||
sClass = sClass.superClass != null ? sClass.superClass.t.get() : null;
|
||||
|
||||
}
|
||||
if (sClass != null)
|
||||
return fields;
|
||||
}
|
||||
|
||||
var shadowClass = macro class {
|
||||
for(f in fields.copy()) {
|
||||
if (f.name == "new")
|
||||
continue;
|
||||
if (f.name.startsWith(FUNC_PREFIX))
|
||||
continue;
|
||||
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern) || f.access.contains(AInline))
|
||||
continue;
|
||||
|
||||
};
|
||||
shadowClass.params = switch(cl.params.length) {
|
||||
case 0:
|
||||
null;
|
||||
case 1:
|
||||
[
|
||||
{
|
||||
name: "T",
|
||||
}
|
||||
];
|
||||
default:
|
||||
[for(k=>e in cl.params) {
|
||||
name: "T" + Std.int(k+1)
|
||||
}];
|
||||
};
|
||||
shadowClass.name = cl.name + CLASS_SUFFIX; // Hscript Extra
|
||||
|
||||
var superClass:haxe.macro.TypePath = {
|
||||
pack: cl.pack,
|
||||
name: cl.name,
|
||||
//params: shadowClass.params
|
||||
}
|
||||
shadowClass.kind = TDClass(superClass, [], false, false, false);
|
||||
|
||||
var newFuncNames = [];
|
||||
|
||||
for(f in fields)
|
||||
switch(f.kind) {
|
||||
case FFun(fun):
|
||||
if (!f.access.contains(AStatic) && f.name != "new" && !f.access.contains(ADynamic)) { /* || !cl.name.endsWith(CLASS_SUFFIX)*/
|
||||
if (fun.params.length > 0) continue;
|
||||
if (fun.expr != null) {
|
||||
//trace(fun.expr);
|
||||
var newFuncName = FUNC_PREFIX + f.name;
|
||||
|
||||
var newAccess = f.access.copy();
|
||||
var needsOverride = false;
|
||||
for(cf in fields)
|
||||
switch(cf.kind) {
|
||||
case FFun(cfun):
|
||||
if (!cf.access.contains(AStatic)/* && cf.access.contains(AOverride)*/) {
|
||||
if(cf.name == newFuncName) {
|
||||
needsOverride = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
if(!needsOverride) { // by default contains AOverride, so we remove it if the class doesnt have the same name
|
||||
newAccess.remove(AOverride);
|
||||
}
|
||||
|
||||
var name = f.name;
|
||||
|
||||
//trace("");
|
||||
///trace(fun.args);
|
||||
|
||||
var myFunc:Function = null;
|
||||
|
||||
if(fun.ret.match(TPath({name: "Void"}))) {
|
||||
myFunc = {
|
||||
expr: macro super.$name(),
|
||||
ret: fun.ret,
|
||||
args: fun.args,
|
||||
params: fun.params,
|
||||
};
|
||||
|
||||
var arguments = myFunc.expr.expr.getParameters()[1];
|
||||
|
||||
for(i=>arg in fun.args) {
|
||||
arguments[i] = macro $i{arg.name};
|
||||
}
|
||||
} else {
|
||||
myFunc = {
|
||||
expr: macro return super.$name(),
|
||||
ret: fun.ret,
|
||||
args: fun.args,
|
||||
params: fun.params,
|
||||
};
|
||||
|
||||
var aa = myFunc.expr.expr.getParameters();
|
||||
var aa:ExprDef = cast aa[0].expr;
|
||||
var arguments = aa.getParameters()[1];
|
||||
|
||||
//trace(arguments);
|
||||
|
||||
for(i=>arg in fun.args) {
|
||||
arguments[i] = macro $i{arg.name};
|
||||
}
|
||||
}
|
||||
|
||||
newFuncNames.push(name);
|
||||
|
||||
var newField = {
|
||||
name: newFuncName,
|
||||
doc: null,
|
||||
meta: [],
|
||||
access: newAccess,
|
||||
kind: FFun(myFunc),
|
||||
var expr = fun.expr;
|
||||
var newExpr = fun.ret.match(TPath({name: "Void"})) ? (macro {
|
||||
var name = ${{
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CString(f.name, DoubleQuotes))
|
||||
}};
|
||||
var v:Dynamic;
|
||||
if (__interp != null && (v = __interp.resolve(name, false)) != null && Reflect.isFunction(v)) {
|
||||
${{
|
||||
expr: ECall({
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent("v"))
|
||||
}, fun.args != null ? [for(a in fun.args) {
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent(a.name))
|
||||
}] : []),
|
||||
pos: Context.currentPos()
|
||||
};
|
||||
shadowClass.fields.push(newField);
|
||||
}}
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
else {
|
||||
${{
|
||||
expr: ECall({
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent('$FUNC_PREFIX${f.name}'))
|
||||
}, fun.args != null ? [for(a in fun.args) {
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent(a.name))
|
||||
}] : []),
|
||||
pos: Context.currentPos()
|
||||
}}
|
||||
}
|
||||
}) : (macro {
|
||||
var name = ${{
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CString(f.name, DoubleQuotes))
|
||||
}};
|
||||
var v:Dynamic;
|
||||
if (__interp != null && (v = __interp.resolve(name, false)) != null && Reflect.isFunction(v)) {
|
||||
return ${{
|
||||
expr: ECall({
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent("v"))
|
||||
}, fun.args != null ? [for(a in fun.args) {
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent(a.name))
|
||||
}] : []),
|
||||
pos: Context.currentPos()
|
||||
}}
|
||||
}
|
||||
else {
|
||||
return ${{
|
||||
expr: ECall({
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent('$FUNC_PREFIX${f.name}'))
|
||||
}, fun.args != null ? [for(a in fun.args) {
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CIdent(a.name))
|
||||
}] : []),
|
||||
pos: Context.currentPos()
|
||||
}}
|
||||
}
|
||||
});
|
||||
fun.expr = newExpr;
|
||||
|
||||
if(shadowClass.fields.length > 0) {
|
||||
//trace("Defining Class: " + shadowClass.name + " containing " + newFuncNames);
|
||||
Context.defineModule(cl.module, [shadowClass], Context.getLocalImports());
|
||||
if (f.access.contains(AOverride) && hasInterp)
|
||||
cleanExpr(expr, f.name, '$FUNC_PREFIX${f.name}');
|
||||
|
||||
var newFunc:Function = {
|
||||
args: fun.args,
|
||||
ret: fun.ret,
|
||||
params: fun.params,
|
||||
expr: macro {
|
||||
@:privateAccess
|
||||
${expr}
|
||||
}
|
||||
};
|
||||
|
||||
fields.push({
|
||||
name: '$FUNC_PREFIX${f.name}',
|
||||
pos: f.pos,
|
||||
kind: FFun(newFunc),
|
||||
access: f.access.copy()
|
||||
});
|
||||
|
||||
if (!hasInterp)
|
||||
fields[fields.length - 1].access.remove(AOverride);
|
||||
default:
|
||||
// fuck off >:(
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasInterp) {
|
||||
fields.push({
|
||||
name: "__interp",
|
||||
pos: Context.currentPos(),
|
||||
kind: FVar(TPath({
|
||||
pack: ['hscript'],
|
||||
name: 'Interp'
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
public static function cleanExpr(expr:Expr, oldFunc:String, newFunc:String) {
|
||||
if (expr == null) return;
|
||||
if (expr.expr == null) return;
|
||||
switch(expr.expr) {
|
||||
case EConst(c):
|
||||
switch(c) {
|
||||
case CIdent(s):
|
||||
if (s == oldFunc)
|
||||
expr.expr = EConst(CIdent(newFunc));
|
||||
case CString(s, b):
|
||||
if (s == oldFunc)
|
||||
expr.expr = EConst(CString(s, b));
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
case EField(e, field):
|
||||
if (field == oldFunc && e != null) {
|
||||
switch(e.expr) {
|
||||
case EConst(c):
|
||||
switch(c) {
|
||||
case CIdent(s):
|
||||
if (s == "super")
|
||||
expr.expr = EField(e, newFunc);
|
||||
default:
|
||||
|
||||
}
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
case EParenthesis(e):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EObjectDecl(fields):
|
||||
for(f in fields) {
|
||||
cleanExpr(f.expr, oldFunc, newFunc);
|
||||
}
|
||||
case EArrayDecl(values):
|
||||
for(a in values) {
|
||||
cleanExpr(a, oldFunc, newFunc);
|
||||
}
|
||||
case ECall(e, params):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EBlock(exprs):
|
||||
for(e in exprs)
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EFor(it, expr):
|
||||
cleanExpr(it, oldFunc, newFunc);
|
||||
cleanExpr(expr, oldFunc, newFunc);
|
||||
case EIf(econd, eif, eelse):
|
||||
cleanExpr(econd, oldFunc, newFunc);
|
||||
cleanExpr(eif, oldFunc, newFunc);
|
||||
cleanExpr(eelse, oldFunc, newFunc);
|
||||
case EWhile(econd, e, normalWhile):
|
||||
cleanExpr(econd, oldFunc, newFunc);
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ECast(e, t):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ECheckType(e, t):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ETry(e, catches):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
for(c in catches) {
|
||||
cleanExpr(c.expr, oldFunc, newFunc);
|
||||
}
|
||||
case EThrow(e):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ETernary(econd, eif, eelse):
|
||||
cleanExpr(econd, oldFunc, newFunc);
|
||||
cleanExpr(eif, oldFunc, newFunc);
|
||||
cleanExpr(eelse, oldFunc, newFunc);
|
||||
case ESwitch(e, cases, edef):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
for(c in cases) {
|
||||
cleanExpr(c.expr, oldFunc, newFunc);
|
||||
}
|
||||
cleanExpr(edef, oldFunc, newFunc);
|
||||
case EReturn(e):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EIs(e, t):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EVars(vars):
|
||||
for(v in vars) {
|
||||
cleanExpr(v.expr, oldFunc, newFunc);
|
||||
}
|
||||
case ENew(t, params):
|
||||
for(p in params) {
|
||||
cleanExpr(p, oldFunc, newFunc);
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
class ClassExtendMacro {
|
||||
|
||||
@@ -24,11 +24,10 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
interp.execute(expr);
|
||||
}
|
||||
|
||||
var cl = extend == null ? TemplateClass : Type.resolveClass('${name}_HSX');
|
||||
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
||||
var _class = Type.createInstance(cl, args);
|
||||
//interp.variables.set("this", interp.variables);
|
||||
|
||||
_class.interp = interp;
|
||||
_class.__interp = interp;
|
||||
|
||||
var newFunc = interp.variables.get("new");
|
||||
if(newFunc != null) {
|
||||
@@ -49,23 +48,23 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
}
|
||||
|
||||
class TemplateClass implements IHScriptCustomBehaviour {
|
||||
public var interp:Interp;
|
||||
public var __interp:Interp;
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
if(Reflect.hasField(this, name)) {
|
||||
Reflect.setProperty(this, name, val);
|
||||
return Reflect.getProperty(this, name); // Incase it overwrites the return value
|
||||
}
|
||||
if(this.interp.variables.exists("set_" + name)) {
|
||||
return this.interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||
if(this.__interp.variables.exists("set_" + name)) {
|
||||
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||
}
|
||||
this.interp.variables.set(name, val);
|
||||
this.__interp.variables.set(name, val);
|
||||
return val;
|
||||
}
|
||||
public function hget(name:String):Dynamic {
|
||||
if(Reflect.hasField(this, name)) {
|
||||
return Reflect.getProperty(this, name);
|
||||
}
|
||||
return this.interp.variables.get(name);
|
||||
return this.__interp.variables.get(name);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -411,7 +411,7 @@ class Interp {
|
||||
#end
|
||||
}
|
||||
|
||||
function resolve(id:String, doException:Bool = true):Dynamic {
|
||||
public function resolve(id:String, doException:Bool = true):Dynamic {
|
||||
id = StringTools.trim(id);
|
||||
var l = locals.get(id);
|
||||
if (l != null)
|
||||
|
||||
Reference in New Issue
Block a user