diff --git a/extraParams.hxml b/extraParams.hxml index e68718c..d5f836c 100644 --- a/extraParams.hxml +++ b/extraParams.hxml @@ -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 diff --git a/hscript/macros/AbstractHandler.hx b/hscript/macros/AbstractHandler.hx new file mode 100644 index 0000000..ecedb77 --- /dev/null +++ b/hscript/macros/AbstractHandler.hx @@ -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(); + + 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 { + 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, 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 \ No newline at end of file diff --git a/hscript/macros/MacroPrinter.hx b/hscript/macros/MacroPrinter.hx new file mode 100644 index 0000000..4676244 --- /dev/null +++ b/hscript/macros/MacroPrinter.hx @@ -0,0 +1,1001 @@ +package hscript.macros; + +#if macro +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type; +import haxe.macro.TypeTools; + +class MacroPrinter { + public static function convertTypePathToString(t:TypePath):String { + //trace(t); + // TODO: handle pack from files in same module; + //trace(t); + var type = t.name; + if(t.pack != null && t.pack.length > 0) { + type = t.pack.join(".") + "." + type; + //Sys.println(t); + } + + if(t.params != null && t.params.length > 0) + type += "<" + t.params.map(function(p) return typeParamToString(p)).join(", ") + ">"; + + return type; + } + + public static function typeToString(t:ComplexType):String { + if(t == null) return "null"; + return switch(t) { + case TPath(p): + convertTypePathToString(p); + //case TAnonymous(a): a.get().fields.map(function(f) return f.name).join(", "); + //case TInst(c, _): c.toString(); + //case TEnum(e, _): e.toString(); + //case TAbstract(a, _): a.toString(); + //case TType(t, _): t.toString(); + //case TFun(args, ret): args.map(function(a) return a.name).join(", ") + " -> " + typeToString(ret); + default: null; + } + } + + public static function typeParamToString(t:TypeParam):String { + return switch(t) { + case TPType(t): typeToString(t); + case TPExpr(e): null; + default: null; + } + } + + public static function getIndentation(tabs:Int):String { + var s = new StringBuf(); + for(i in 0...tabs) s.add(" "); + return s.toString(); + } + + public static function convertFieldToString(f:Field, tabs:Int = 0, module:String = null):String { + var s = new StringBuf(); + s.add("Field("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: \""); + s.add(f.name); + s.add("\",\n"); + if(module != null) { + s.add(getIndentation(tabs+1)); + s.add("module: \""); + s.add(module); + s.add("\",\n"); + } + if(f.access != null && f.access.length > 0) { + s.add(getIndentation(tabs+1)); + s.add("access: ["); + var first = true; + for(a in f.access) { + if(!first) { + s.add(", "); + } + s.add(Std.string(a)); + first = false; + } + s.add("],\n"); + } + s.add(getIndentation(tabs+1)); + s.add("kind: "); + switch(f.kind) { + case FVar(t, e): + s.add("FVar("); + s.add(typeToString(t)); + s.add(", "); + s.add(convertExprToString(e, tabs)); + s.add(")"); + case FProp(get, set, t, e): + s.add("FProp("); + s.add(Std.string(get)); + s.add(", "); + s.add(Std.string(set)); + s.add(", "); + s.add(typeToString(t)); + s.add(", "); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + case FFun(fun): + s.add("FFun("); + s.add(convertFunctionToString(fun, tabs + 1)); + s.add(")"); + default: throw "Unknown field kind " + Std.string(f.kind); + } + if(f.meta.length > 0) { + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("meta: "); + s.add(convertMetaToString(f.meta, tabs+1)); + } + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + public static function convertFunctionToString(fun:Function, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("{"); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("args: ["); + var first = true; + if(fun.args.length > 0) { + s.add("\n"); + } + for(a in fun.args) { + if(!first) { + s.add(",\n"); + } + s.add(getIndentation(tabs+2)); + s.add(convertArgToString(a, tabs+2)); + //if(first) { + // s.add("\n"); + //} + first = false; + } + if(!first) { + s.add("\n"); + s.add(getIndentation(tabs+1)); + } + s.add("],\n"); + s.add(getIndentation(tabs+1)); + s.add("ret: "); + s.add(typeToString(fun.ret)); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add("}"); + + return s.toString(); + } + + public static function convertArgToString(a:FunctionArg, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("{"); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: \""); + s.add(a.name); + s.add("\",\n"); + s.add(getIndentation(tabs+1)); + s.add("opt: "); + s.add(Std.string(a.opt)); + if(a.type != null) { + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("type: "); + s.add(typeToString(a.type)); + } + if(a.value != null) { + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("value: "); + s.add(convertExprToString(a.value, tabs+1)); + } + if(a.meta.length > 0) { + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("meta: "); + s.add(convertMetaToString(a.meta, tabs+1)); + } + s.add("\n"); + s.add(getIndentation(tabs)); + s.add("}"); + + return s.toString(); + } + + public static function convertMetaEntryToString(m:MetadataEntry, tabs:Int = 0):String { + var s = new StringBuf(); + + s.add("MetadataEntry("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: "); + s.add(m.name); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("params: ["); + var first = true; + for(param in m.params) { + if(!first) { + s.add(",\n"); + s.add(getIndentation(tabs+2)); + } + first = false; + s.add(convertExprToString(param, tabs+2)); + } + s.add("]\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + public static function convertMetaToString(m:Metadata, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("Metadata(["); + if(m.length > 0) { + s.add("\n"); + s.add(getIndentation(tabs+1)); + var first = true; + for(entry in m) { + if(!first) { + s.add(",\n"); + s.add(getIndentation(tabs+1)); + } + first = false; + s.add(convertMetaEntryToString(entry, tabs + 1)); + } + s.add("\n"); + s.add(getIndentation(tabs)); + } + s.add("])"); + + return s.toString(); + } + + public static function convertExprToString(e:Expr, tabs:Int = 0):String { + if(e == null) return "null"; + var s = new StringBuf(); + switch(e.expr) { + case EConst(c): + s.add("EConst("); + s.add(Std.string(c)); + s.add(")"); + case EField(e, f): + s.add("EField("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", "); + s.add(f); + s.add(")"); + case EBlock(exprs): + s.add("EBlock(["); + var first = true; + for(e in exprs) { + if(!first) { + s.add(","); + } + first = false; + s.add("\n"); + s.add(getIndentation(tabs + 2)); + s.add(convertExprToString(e, tabs + 1)); + } + s.add("\n"); + s.add(getIndentation(tabs + 1)); + s.add("])"); + case EIf(econd, eif, eelse): + s.add("EIf("); + s.add(convertExprToString(econd, tabs + 1)); + s.add(", "); + s.add(convertExprToString(eif, tabs + 1)); + s.add(", "); + s.add(convertExprToString(eelse, tabs + 1)); + s.add(")"); + case EWhile(econd, e, normalWhile): + s.add("EWhile("); + s.add(convertExprToString(econd, tabs + 1)); + s.add(", "); + s.add(convertExprToString(e, tabs + 1)); + s.add(", "); + s.add(Std.string(normalWhile)); + s.add(")"); + case EFor(it, expr): + s.add("EFor("); + s.add(convertExprToString(it, tabs + 1)); + s.add(", "); + s.add(convertExprToString(expr, tabs + 1)); + s.add(")"); + case EBreak: + s.add("EBreak"); + case EContinue: + s.add("EContinue"); + case EArrayDecl(values): + s.add("EArrayDecl(["); + var first = true; + for(v in values) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertExprToString(v, tabs + 1)); + } + s.add("])"); + case EUnop(op, postFix, e): + s.add("EUnop("); + s.add(Std.string(op)); + s.add(", "); + s.add(Std.string(postFix)); + s.add(", "); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + case EBinop(op, e1, e2): + s.add("EBinop("); + s.add(Std.string(op)); + s.add(", "); + s.add(convertExprToString(e1, tabs + 1)); + s.add(", "); + s.add(convertExprToString(e2, tabs + 1)); + s.add(")"); + case ENew(t, params): + s.add("ENew("); + s.add(convertTypePathToString(t)); + s.add(", ["); + var first = true; + for(p in params) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertExprToString(p, tabs + 1)); + } + s.add("])"); + case ECast(e, t): + s.add("ECast("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", "); + s.add(typeToString(t)); + s.add(")"); + case EFunction(name, f): + s.add("EFunction("); + s.add(name); + s.add(", "); + s.add(convertFunctionToString(f, tabs + 1)); + s.add(")"); + case EVars(vars): + s.add("EVars(["); + var first = true; + for(v in vars) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertVarToString(v, tabs + 1)); + } + s.add("])"); + case ECall(e, params): + s.add("ECall("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", ["); + var first = true; + for(p in params) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertExprToString(p, tabs + 1)); + } + s.add("])"); + case EMeta(m, e): + s.add("EMeta("); + s.add(convertMetaEntryToString(m, tabs + 1)); + s.add(", "); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + case EParenthesis(e): + s.add("EParenthesis("); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + case EObjectDecl(fields): + s.add("EObjectDecl(["); + var first = true; + for(f in fields) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertObjectFieldToString(f, tabs + 1)); + } + s.add("])"); + case ETernary(econd, eif, eelse): + s.add("ETernary("); + s.add(convertExprToString(econd, tabs + 1)); + s.add(", "); + s.add(convertExprToString(eif, tabs + 1)); + s.add(", "); + s.add(convertExprToString(eelse, tabs + 1)); + s.add(")"); + case EArray(e1, e2): + s.add("EArray("); + s.add(convertExprToString(e1, tabs + 1)); + s.add(", "); + s.add(convertExprToString(e2, tabs + 1)); + s.add(")"); + case ECheckType(e, t): + s.add("ECheckType("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", "); + s.add(typeToString(t)); + s.add(")"); + case EDisplay(e, d): + s.add("EDisplay("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", "); + s.add(Std.string(d)); + s.add(")"); + case EThrow(e): + s.add("EThrow("); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + case ETry(e, catches): + s.add("ETry("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", ["); + var first = true; + for(c in catches) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertCatchToString(c, tabs + 1)); + } + s.add("])"); + case EDisplayNew(t): + s.add("EDisplayNew("); + s.add(convertTypePathToString(t)); + s.add(")"); + case EIs(e1, t): + s.add("EIs("); + s.add(convertExprToString(e1, tabs + 1)); + s.add(", "); + s.add(typeToString(t)); + s.add(")"); + case ESwitch(e, cases, edef): + s.add("ESwitch("); + s.add(convertExprToString(e, tabs + 1)); + s.add(", ["); + var first = true; + for(c in cases) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertSwitchCaseToString(c, tabs + 1)); + } + s.add("], "); + s.add(convertExprToString(edef, tabs + 1)); + s.add(")"); + case EUntyped(e): + s.add("EUntyped("); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + case EReturn(e): + s.add("EReturn("); + s.add(convertExprToString(e, tabs + 1)); + s.add(")"); + default: + s.add("Unknown expr " + Std.string(e.expr)); + } + + return s.toString(); + } + + public static function convertSwitchCaseToString(c:Case, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("Case("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("expr: "); + s.add(convertExprToString(c.expr, tabs+1)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("guard: "); + s.add(convertExprToString(c.guard, tabs+1)); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + public static function convertCatchToString(c:Catch, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("Catch("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("type: "); + s.add(typeToString(c.type)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("expr: "); + s.add(convertExprToString(c.expr, tabs+1)); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + public static function convertObjectFieldToString(f:ObjectField, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("ObjectField("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + if(f.quotes == Quoted) { + s.add("field: \""); + s.add(f.field); + s.add("\",\n"); + } else { + s.add("field: "); + s.add(f.field); + s.add(",\n"); + } + s.add(getIndentation(tabs+1)); + s.add("expr: "); + s.add(convertExprToString(f.expr, tabs+1)); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + public static function convertVarToString(v:Var, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("Var("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: \""); + s.add(v.name); + s.add("\",\n"); + s.add(getIndentation(tabs+1)); + s.add("type: "); + s.add(typeToString(v.type)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("expr: "); + s.add(convertExprToString(v.expr, tabs+1)); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + + // AbstractType + + public static function convertAbstractTypeToString(a:AbstractType, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("AbstractType("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: "); + s.add(a.name); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("pack: ["); + s.add(a.pack.join(", ")); + s.add("],\n"); + s.add(getIndentation(tabs+1)); + s.add("isExtern: "); + s.add(Std.string(a.isExtern)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("isPrivate: "); + s.add(Std.string(a.isPrivate)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("from: "); + s.add(convertToFromToString(a.from, tabs+1)); + //s.add(a.from.map(function(f) return convertTypePathToString(f)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("to: "); + s.add(convertToFromToString(a.to, tabs+1)); + //s.add(",\n"); + /*s.add(getIndentation(tabs+1)); + s.add("params: "); + s.add(a.params.map(function(p) return convertTypeParamToString(p)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("meta: "); + s.add(a.meta.map(function(m) return convertMetaToString(m)).join(", ")); + s.add(",\n");*/ + //s.add(getIndentation(tabs+1)); + //s.add("fields: ["); + //var first = true; + //for(f in a.fields()) { + // if(!first) { + // s.add(", "); + // } + // first = false; + // s.add(convertClassFieldToString(f, tabs+1)); + //} + //s.add("],\n"); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + + return s.toString(); + } + + public static function convertToFromToString(t:Array<{t:Type, field:Null}>, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("["); + var first = true; + for(t in t) { + if(!first) { + s.add(",\n"); + s.add(getIndentation(tabs+1)); + } + first = false; + + //s.add("\n"); + //s.add(getIndentation(tabs+0)); + s.add("{\n"); + s.add(getIndentation(tabs+1)); + s.add("field: "); + s.add(t.field == null ? "null" : t.field.name); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("t: "); + s.add(convertTypeToString(t.t, tabs+1)); + s.add("\n"); + s.add(getIndentation(tabs+0)); + s.add("}"); + } + s.add("]"); + + return s.toString(); + } + + public static function convertEnumTypeToString(t:haxe.macro.Type.EnumType, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("EnumType("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: "); + s.add(t.name); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("pack: ["); + s.add(t.pack.join(", ")); + s.add("]\n"); + //s.add(getIndentation(tabs+1)); + //s.add("params: "); + //s.add(t.params.map(function(p) return convertTypeParamToString(p)).join(", ")); + //s.add(",\n"); + //s.add(getIndentation(tabs)); + + //s.add("meta: "); + //s.add(t.meta.map(function(m) return convertMetaToString(m)).join(", ")); + //s.add(",\n"); + //s.add(getIndentation(tabs)); + //s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + return s.toString(); + } + + public static function convertClassTypeToString(t:haxe.macro.Type.ClassType, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("ClassType("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: "); + s.add(t.name); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("pack: ["); + s.add(t.pack.join(", ")); + s.add("]\n"); + /*s.add(getIndentation(tabs)); + s.add("params: "); + s.add(t.params.map(function(p) return convertTypeParamToString(p)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs)); + s.add("meta: "); + s.add(t.meta.map(function(m) return convertMetaToString(m)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs)); + s.add("\n");*/ + s.add(getIndentation(tabs)); + s.add(")"); + return s.toString(); + } + + public static function convertDefTypeToString(t:haxe.macro.Type.DefType, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("DefType("); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add("name: "); + s.add(t.name); + s.add(",\n"); + s.add(getIndentation(tabs)); + s.add("pack: ["); + s.add(t.pack.join(", ")); + s.add("],\n"); + /*s.add(getIndentation(tabs)); + s.add("params: "); + s.add(t.params.map(function(p) return convertTypeParamToString(p)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs)); + s.add("meta: "); + s.add(t.meta.map(function(m) return convertMetaToString(m)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs)); + s.add("\n");*/ + s.add(getIndentation(tabs)); + s.add(")"); + return s.toString(); + } + + public static function convertFunctionTypeToString(t:Array<{name:String, opt:Bool, t:Type}>, ret:Type, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("TFun("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("args: ["); + var first = true; + for(a in t) { + if(!first) { + s.add(", "); + } + first = false; + s.add("{"); + s.add("\n"); + s.add(getIndentation(tabs+2)); + s.add("name: "); + s.add(a.name); + s.add(",\n"); + s.add(getIndentation(tabs+2)); + s.add("opt: "); + s.add(Std.string(a.opt)); + s.add(",\n"); + s.add(getIndentation(tabs+2)); + s.add("t: "); + s.add(convertTypeToString(a.t, tabs+2)); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("}"); + } + s.add("],\n"); + s.add(getIndentation(tabs+1)); + s.add("ret: "); + s.add(convertTypeToString(ret, tabs+1)); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + return s.toString(); + } + + public static function convertAnonTypeToString(t:haxe.macro.Type.AnonType, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("AnonType("); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add("fields: ["); + var first = true; + for(f in t.fields) { + if(!first) { + s.add(", "); + } + first = false; + s.add(convertClassFieldToString(f, tabs)); + } + s.add("],\n"); + s.add(getIndentation(tabs)); + s.add(")"); + return s.toString(); + } + + public static function convertClassFieldToString(f:haxe.macro.Type.ClassField, tabs:Int = 0):String { + var s = new StringBuf(); + s.add("ClassField("); + s.add("\n"); + s.add(getIndentation(tabs+1)); + s.add("name: "); + s.add(f.name); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("type: "); + s.add(convertTypeToString(f.type, tabs+1)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("isPublic: "); + s.add(Std.string(f.isPublic)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("isExtern: "); + s.add(Std.string(f.isExtern)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("isFinal: "); + s.add(Std.string(f.isFinal)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("isAbstract: "); + s.add(Std.string(f.isAbstract)); + s.add(",\n"); + /*s.add(getIndentation(tabs+1)); + s.add("params: "); + s.add(f.params.map(function(p) return convertTypeParamToString(p)).join(", ")); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("meta: "); + s.add(f.meta.map(function(m) return convertMetaToString(m)).join(", ")); + s.add(",\n");*/ + s.add(getIndentation(tabs+1)); + s.add("kind: "); + s.add(Std.string(f.kind)); + s.add(",\n"); + //s.add(getIndentation(tabs+1)); + //s.add("expr: "); + //s.add(convertExprToString(f.expr, tabs+1)); + //s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("overloads: "); + s.add(f.overloads.get().map(function(o) return convertClassFieldToString(o, tabs+1)).join(", ")); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + return s.toString(); + } + + public static function printableBaseType(t:haxe.macro.Type.BaseType):String { + var name = t.name; + if(t.pack != null && t.pack.length > 0) { + name = t.pack.join(".") + "." + name; + } + + if(t.params != null && t.params.length > 0) { + name += "<" + t.params.map(function(p) return typeParameterToString(p)).join(", ") + ">"; + } + + trace(t); + + return name; + } + + public static function printableClassType(t:ClassType):String { + /*var name = t.name; + if(t.pack.length > 0) { + name = t.pack.join(".") + "." + name; + } + + if(t.params != null && t.params.length > 0) { + name += "<" + t.params.map(function(p) return typeToString(p)).join(", ") + ">"; + }*/ + + return printableBaseType(t); + } + + public static function typeParameterToString(t:TypeParameter):String { + var name = t.name; + //if(t.t != null) { + // name += "<" + printTypeOld(t.t) + ">"; + //} + return name; + } + + public static function printTypeOld(t:haxe.macro.Type.Type):String { + if(t == null) return "null"; + var str = ""; + switch(t) { + case TMono(t): + str = printTypeOld(t.get()); + case TEnum(t, params): + str = printableBaseType(t.get()); + if(params != null && params.length > 0) { + str += "<" + params.map(printTypeOld).join(", ") + ">"; + } + case TInst(t, params): + str = printableClassType(t.get()); + if(params != null && params.length > 0) { + str += "<" + params.map(printTypeOld).join(", ") + ">"; + } + //case TExtend(t, params): + // str = printableBaseType(t.get()); + // if(params != null && params.length > 0) { + // str += "<" + params.map(printTypeOld).join(", ") + ">"; + // } + case TType(t, params): + str = printableBaseType(t.get()); + if(params != null && params.length > 0) { + str += "<" + params.map(printTypeOld).join(", ") + ">"; + } + case TFun(args, ret): + str = args.map(function(a) return a.name).join(", ") + " -> " + printTypeOld(ret); + case TAnonymous(a): + str = a.get().fields.map(function(f) return f.name).join(", "); + case TDynamic(t): + str = "Dynamic"; + case TLazy(f): + str = "Lazy"; + case TAbstract(t, params): + str = printableBaseType(t.get()) + "<" + params.map(function(p) return printTypeOld(p)).join(", ") + ">"; + } + return str; + } + + public static function convertTypeToString(t:haxe.macro.Type.Type, tabs:Int = 0):String { + var s = new StringBuf(); + switch(t) { + case TMono(t): + s.add("TMono("); + s.add(convertTypeToString(t.get(), tabs)); + s.add(")"); + case TEnum(t, params): + s.add("TEnum("); + s.add(convertEnumTypeToString(t.get(), tabs)); + s.add(", ["); + var first = true; + for(p in params) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertTypeToString(p, tabs)); + } + s.add("])"); + case TInst(t, params): + s.add(printableClassType(t.get())); + //s.add("TInst("); + //s.add(convertClassTypeToString(t.get(), tabs)); + //s.add(", ["); + //var first = true; + //for(p in params) { + // if(!first) { + // s.add(","); + // } + // first = false; + // s.add(convertTypeToString(p, tabs)); + //} + //s.add("])"); + case TType(t, params): + s.add("TType("); + s.add(convertDefTypeToString(t.get(), tabs)); + s.add(", ["); + var first = true; + for(p in params) { + if(!first) { + s.add(","); + } + first = false; + s.add(convertTypeToString(p, tabs)); + } + s.add("])"); + case TFun(args, ret): + s.add(convertFunctionTypeToString(args, ret, tabs)); + case TAnonymous(a): + s.add("TAnonymous("); + s.add(convertAnonTypeToString(a.get(), tabs)); + s.add(")"); + case TDynamic(t): + s.add("TDynamic("); + s.add(convertTypeToString(t, tabs)); + s.add(")"); + case TLazy(f): + s.add("TLazy("); + s.add(f); + s.add(")"); + case TAbstract(t, params): + s.add("TAbstract(\n"); + s.add(getIndentation(tabs+1)); + s.add(convertAbstractTypeToString(t.get(), tabs+1)); + s.add(",\n"); + s.add(getIndentation(tabs+1)); + s.add("["); + var first = true; + for(p in params) { + if(!first) { + s.add(",\n"); + } + s.add(convertTypeToString(p, tabs+1)); + first = false; + } + s.add("]"); + s.add("\n"); + s.add(getIndentation(tabs)); + s.add(")"); + } + return s.toString(); + } +} +#end \ No newline at end of file diff --git a/hscript/macros/Utils.hx b/hscript/macros/Utils.hx index cbf7ac8..d6d96ff 100644 --- a/hscript/macros/Utils.hx +++ b/hscript/macros/Utils.hx @@ -25,10 +25,11 @@ class Utils { return type; } - public static function setupMetas(shadowClass:TypeDefinition, imports) { + public static function setupMetas(shadowClass:TypeDefinition, imports:Array, 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) { diff --git a/tests/linux.hxml b/tests/linux.hxml index 85d775a..9c692f7 100644 --- a/tests/linux.hxml +++ b/tests/linux.hxml @@ -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 diff --git a/tests/mac.hxml b/tests/mac.hxml index 3ec74d6..e42e5e9 100644 --- a/tests/mac.hxml +++ b/tests/mac.hxml @@ -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 diff --git a/tests/src/Main.hx b/tests/src/Main.hx index c665d31..870197e 100644 --- a/tests/src/Main.hx +++ b/tests/src/Main.hx @@ -40,6 +40,7 @@ class Main { // TODO: UnicodeCase.hx? // TODO: UnicodeStringCase.hx? runTest("Final", new FinalCase()); + runTest("Abstract", new AbstractCase()); Util.printTestResults(); #end } diff --git a/tests/src/tests/AbstractCase.hx b/tests/src/tests/AbstractCase.hx new file mode 100644 index 0000000..5bf37e5 --- /dev/null +++ b/tests/src/tests/AbstractCase.hx @@ -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("world").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('world').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('world').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) { + +} \ No newline at end of file diff --git a/tests/src/tests/FinalCase.hx b/tests/src/tests/FinalCase.hx index 74acc3f..9c507ae 100644 --- a/tests/src/tests/FinalCase.hx +++ b/tests/src/tests/FinalCase.hx @@ -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 } diff --git a/tests/windows.hxml b/tests/windows.hxml index efbdd02..ebf4bce 100644 --- a/tests/windows.hxml +++ b/tests/windows.hxml @@ -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