Started working on the abstract parser macro

This commit is contained in:
NeeEoo
2024-04-26 20:19:47 +02:00
parent 19021058c4
commit 1892f0793f
10 changed files with 1498 additions and 1 deletions
+1
View File
@@ -1,4 +1,5 @@
--macro keep('IntIterator')
--macro hscript.macros.UsingHandler.init()
--macro hscript.macros.ClassExtendMacro.init()
--macro hscript.macros.AbstractHandler.init()
--define HSCRIPT_NEW
+426
View File
@@ -0,0 +1,426 @@
package hscript.macros;
#if macro
import Type.ValueType;
import haxe.macro.ComplexTypeTools;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxe.macro.Context;
import haxe.macro.Printer;
import haxe.macro.Compiler;
import haxe.macro.ComplexTypeTools;
using StringTools;
using haxe.macro.PositionTools;
class AbstractHandler {
public static inline final CLASS_SUFFIX = "_HSA";
public static function init() {
#if !display
if(Context.defined("display")) return;
//for(apply in Config.ALLOWED_ABSTRACT_AND_ENUM) {
//}
Compiler.addGlobalMetadata("", '@:build(hscript.macros.AbstractHandler.build())');
//var module = cl.module + cl.name;
#end
}
static var abstracts = new Map<String, {
}>();
static function finalizeAbstract(a:AbstractType) {
var name = a.name;
if(name.endsWith(CLASS_SUFFIX)) return; // !name.endsWith("_Impl_") ||
if(name != "NodeListAccess") return;
Sys.println("");
Sys.println("");
Sys.println("");
Sys.println("");
Sys.println("");
//Sys.println("name: " + a.name);
//Sys.println("module: " + a.module);
Sys.println(MacroPrinter.convertAbstractTypeToString(a));
//trace("buildAbstract", a);
}
static var currentSelf = "";
static function oldTypeToString(t:Type, selfCheck:String = null):String {
var str = switch(t) {
case TInst(_.get() => t, params):
var str = "";
if(t.pack.length > 0) {
str += t.pack.join(".") + ".";
}
str += t.name;
if(t.params != null && t.params.length > 0) {
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
}
//if(t.params.length > 0) {
// throw "Params not supported yet " + t.name + " " + t.params;
//}
str;
case TAbstract(_.get() => t, params):
var str = "";
if(t.pack.length > 0) {
str += t.pack.join(".") + ".";
}
str += t.name;
if(t.params != null && t.params.length > 0) {
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
}
//if(t.params.length > 0) {
// throw "Params not supported yet " + t.name + " " + t.params;
//}
str;
case TEnum(_.get() => t, params):
var str = "";
if(t.pack.length > 0) {
str += t.pack.join(".") + ".";
}
str += t.name;
if(t.params != null && t.params.length > 0) {
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
}
//if(t.params.length > 0) {
// throw "Params not supported yet " + t.name + " " + t.params;
//}
str;
case TType(_.get() => t, params):
var str = "";
if(t.pack.length > 0) {
str += t.pack.join(".") + ".";
}
str += t.name;
if(t.params != null && t.params.length > 0) {
str += "<" + t.params.map((v)->oldTypeToString(v.t, t.name + "." + v.name)).join(", ") + ">";
//trace("TType", str);
}
str;
case TAnonymous(_.get() => t):
//var str = "Dynamic {"+t.fields.map((f)->f.name).join(", ")+"}";
//str += t.name;
var str = "{ ";
var first = true;
for(f in t.fields) {
if(!first) str += ", ";
first = false;
str += f.name + ":" + oldTypeToString(f.type);
}
str += " }";
//trace("TAnonymous", str);
str;
case TDynamic(t):
var str = "Dynamic";
if(t != null) {
str += "<" + oldTypeToString(t) + ">";
}
str;
default:
Sys.println("Unknown type " + Std.string(t));
null;
}
if(selfCheck != null) {
if(str == selfCheck) {
return selfCheck;
//return currentSelf;
}
}
return str;
}
static function getResolvedType(t:ComplexType):String {
if(t == null) return null;
try {
//var type = Context.getType(checkType);
var paramFree = switch(t) {
case TPath(t):
//trace(t);
TPath({
name: t.name,
pack: t.pack,
params: t.params,
sub: t.sub
});
case TAnonymous(a):
t;
case TFunction(args, ret):
t;
default:
trace("");
trace(ComplexTypeTools.toString(t));
throw "Unknown type " + Std.string(t);
}
var type = ComplexTypeTools.toType(paramFree);
var strType = oldTypeToString(type);
if(strType != null) return strType;
} catch(e:Dynamic) {
Sys.println(e);
Sys.println(ComplexTypeTools.toString(t));
Sys.println(haxe.CallStack.toString(haxe.CallStack.exceptionStack()));
}
return MacroPrinter.typeToString(t);
}
public static function build():Array<Field> {
var fields = Context.getBuildFields();
var clRef = Context.getLocalClass();
if (clRef == null) return fields;
var cl = clRef.get();
if(cl.isExtern) return fields;
//if(cl.name != "Access_Impl_") return fields;
//if(cl.name != "DrawQuadsView_Impl_") return fields;
if(cl.name.endsWith("_Impl_") && !cl.name.endsWith(CLASS_SUFFIX)) // && ["Access_Impl_", "AttribAccess_Impl_"].contains(cl.name))
{
//if(!initialized) {
// initialized = true;
// Context.onAfterTyping(function(mods) {
// for(mod in mods) {
// switch(mod) {
// case TAbstract(_.get() => a):
// //trace("onAfterTyping", a);
// finalizeAbstract(a);
// //ab = a;
// default:
// // return;
// }
// }
// });
//}
currentSelf = cl.name.substr(0, cl.name.length - "_Impl_".length);
var funcInfos = [];
//for(f in fields) {
// trace(f.name, f.kind);
//}
for(f in fields) {
if(f.name.startsWith("__abstract_helper"))
continue;
//if(f.name != "escapes")
// continue;
//trace(f);
//trace(
//MacroPrinter.convertFieldToString(f, cl.module + "." + cl.name)
//);
//trace();
//continue;
switch(f.kind) {
case FFun(fun):
if(fun.expr != null) {
var obj:Dynamic = {
name: f.name,
args: [for(a in fun.args) {
name: a.name,
opt: a.opt,
type: getResolvedType(a.type),
//value: a.value,
//meta: a.meta,
}],
ret: fun.ret,
op: {
var op = null;
//trace("");
//trace("");
//trace("");
//trace(f.name, f.meta);
//trace(f.name, fun);
for(m in f.meta) {
if(m.name == ":op") {
switch (m.params[0].expr) {
case EField(_.expr => EConst(CIdent("a")), "b"):
op = "a.b";
case EArrayDecl([]):
op = "[]";
case EUnop(o, suffix, _.expr => EConst(CIdent("A"))):
var opStr = switch(o) {
case OpNeg: "-";
case OpIncrement: "++";
case OpDecrement: "--";
case OpNot: "!";
case OpNegBits: "~";
case OpSpread: "...";
}
if(suffix) {
op = "A" + opStr;
} else {
op = opStr + "A";
}
case EBinop(o, _.expr => EConst(CIdent("A")), _.expr => EConst(CIdent("B"))):
var opStr = getBinopStr(o);
op = "A " + opStr + " B";
#if (haxe >= "4.3.0")
case ECall(_.expr => EConst(CIdent("a")), []):
op = "a()";
#end
default:
trace(f.name, cl.module);
throw "Unknown op " + MacroPrinter.convertExprToString(m.params[0]) + "\n in " + f.name + " in " + cl.module;
}
//trace(op, convertExprToString(m.params[0]));
//trace(Type.typeof(m.params[0]));
//switch (m.params[0].expr) {
// case EConst(CIdent(_i)):
// id = _i;
// default:
//}
}
}
op;
}
}
if(obj.ret == null && f.name.startsWith("get_")) {
var v = getVarFromFields(fields, f.name.substr(4));
var type = getTypeFromField(v);
//Sys.println("getter " + f.name + " " + getResolvedType(type) + " " + type);
obj.ret = type;
} else if(obj.ret == null && f.name.startsWith("set_")) {
var v = getVarFromFields(fields, f.name.substr(4));
var type = getTypeFromField(v);
//Sys.println("setter " + f.name + " " + getResolvedType(type) + " " + type);
obj.ret = type;
} else {
if(obj.ret != null) {
//Sys.println("normal field " + f.name + " " + getResolvedType(obj.ret) + " " + obj.ret);
}
}
if(obj.name == "_new")
obj.name = "new";
obj.ret = getResolvedType(obj.ret);
trace("FFun", obj);
funcInfos.push(obj);
//trace(cl.name, obj);
}
default:
}
//funcInfos.push([f.name, ]);
}
//trace(funcInfos);
//trace(cl.pos);
var shadowClass = macro class {
};
shadowClass.kind = TDClass(null, [
//{name: "IHScriptCustomBehaviour", pack: ["hscript"]},
//{name: "IHScriptCustomClassBehaviour", pack: ["hscript"]}
], false, true, false);
shadowClass.name = '${cl.name.substr(0, cl.name.length - "_Impl_".length)}$CLASS_SUFFIX';
//trace(shadowClass.name);
var imports = Context.getLocalImports().copy();
Utils.setupMetas(shadowClass, [], false);
//Utils.processImport(imports, "hscript.utils.UnsafeReflect", "UnsafeReflect");
shadowClass.fields.push({
name: "__abstract_helper",
pos: cl.pos,
access: [APublic, AStatic],
kind: FFun({
ret: TPath({name: 'Dynamic', pack: []}),
params: [],
expr: macro {
return {
funcs: $v{funcInfos}
};
},
args: [
]
})
});
//trace(cl.name, fields.length);
var moduleName = cl.module;
//if(cl.module.lastIndexOf(".") > 0) {
// moduleName += cl.module.substr(0, cl.module.lastIndexOf(".")) + ".";
//}
//moduleName += "_" + cl.module.split(".").pop();
Context.defineModule(moduleName, [shadowClass], imports);
//trace(moduleName);
var printer = new haxe.macro.Printer();
var code = printer.printTypeDefinition(shadowClass);
//trace(code);
return fields;
}
return fields;
}
static var initialized = false;
static function getBinopStr(op:Binop):String {
return switch(op) {
case OpAdd: "+";
case OpSub: "-";
case OpMult: "*";
case OpDiv: "/";
case OpMod: "%";
case OpEq: "==";
case OpNotEq: "!=";
case OpGt: ">";
case OpGte: ">=";
case OpLt: "<";
case OpLte: "<=";
case OpAnd: "&";
case OpOr: "|";
case OpXor: "^";
case OpShl: "<<";
case OpShr: ">>";
case OpUShr: ">>>";
case OpBoolAnd: "&&";
case OpBoolOr: "||";
case OpAssign: "=";
case OpArrow: "=>";
case OpAssignOp(op):
getBinopStr(op) + "=";
case OpIn: "in";
case OpInterval: "...";
}
}
static function getVarFromFields(fields:Array<Field>, name:String):Field {
for(f in fields) {
if(f.name == name) {
switch(f.kind) {
case FProp(_, _, _, _):
return f;
default:
}
}
}
return null;
}
static function getTypeFromField(field:Field):ComplexType {
//if(field == null) return null;
return switch(field.kind) {
case FProp(_, _, t, _): t;
case FVar(t, _): t;
case FFun(f): f.ret;
default: null;
}
}
}
#end
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -25,10 +25,11 @@ class Utils {
return type;
}
public static function setupMetas(shadowClass:TypeDefinition, imports) {
public static function setupMetas(shadowClass:TypeDefinition, imports:Array<ImportExpr>, doImports:Bool = true) {
shadowClass.meta = [];
shadowClass.meta.push({name: ":dox", params: [macro hide], pos: Context.currentPos()});
shadowClass.meta.push({name: ":noCompletion", params: [], pos: Context.currentPos()});
if(!doImports) return;
var module = Context.getModule(Context.getLocalModule());
for(t in module) {
switch(t) {
+5
View File
@@ -17,6 +17,11 @@
# File Specific Defines
--define linux
--macro keep('IntIterator')
# --macro hscript.macros.UsingHandler.init()
# --macro hscript.macros.ClassExtendMacro.init()
--macro hscript.macros.AbstractHandler.init()
# Copying the assets from source code to bin folder
--cmd rm -rf bin/cpp/assets
--cmd cp -r assets bin/cpp/assets
+1
View File
@@ -24,6 +24,7 @@
--macro keep('IntIterator')
# --macro hscript.macros.UsingHandler.init()
# --macro hscript.macros.ClassExtendMacro.init()
--macro hscript.macros.AbstractHandler.init()
# Copying the assets from source code to bin folder
+1
View File
@@ -40,6 +40,7 @@ class Main {
// TODO: UnicodeCase.hx?
// TODO: UnicodeStringCase.hx?
runTest("Final", new FinalCase());
runTest("Abstract", new AbstractCase());
Util.printTestResults();
#end
}
+54
View File
@@ -0,0 +1,54 @@
package tests;
import haxe.xml.Access;
import Xml;
class AbstractCase extends TestCase {
override function setup() {
super.setup();
}
override function run() {
var access = new Access(Xml.parse("<test test=\"cool\"><hello>world</hello></test>").firstElement());
trace(access.att.test);
getNewInterp().execute(Util.parse("
// Converts to
import haxe.xml._Access.Access_Impl_;
import haxe.xml._Access.AttribAccess_Impl_;
var access = Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement();
trace(AttribAccess_Impl_.resolve(Access_Impl_.get_att(access), 'test'));
// trace(Access_Impl_.get_att(access));
//abstract import haxe.xml.Access;
//import haxe.xml.Access with Abstract;
import haxe.xml.Access;
var access = new Access(Xml.parse('<test test=\"cool\"><hello>world</hello></test>').firstElement());
trace(access.att.test);
"));
}
override function teardown() {
super.teardown();
}
}
abstract TestAbstract(Int)
{
//public static inline var TRANSPARENT:TestAbstract = 0x00000000;
//public static inline var WHITE:TestAbstract = 0xFFFFFFFF;
//public static inline var GRAY:TestAbstract = 0xFF808080;
//public static inline var BLACK:TestAbstract = 0xFF000000;
}
enum abstract TestEnumAbstract(Int) {
}
+2
View File
@@ -126,6 +126,8 @@ class FinalCase extends TestCase {
import Math.round;
round(1.9);", Math.round(1.9));
trace(Type.resolveClass("hscript._Error.ErrorMessage_Impl_"));
// Test EOF with preprocessor
}
+5
View File
@@ -18,6 +18,11 @@
# File Specific Defines
--define windows
--macro keep('IntIterator')
# --macro hscript.macros.UsingHandler.init()
# --macro hscript.macros.ClassExtendMacro.init()
--macro hscript.macros.AbstractHandler.init()
# Copying the assets from source code to bin folder
# --cmd Xcopy assets\ bin\cpp\assets\ /E /H /C /I /Y
--cpp bin/cpp