diff --git a/src/tink/macro/BuildCache.hx b/src/tink/macro/BuildCache.hx index 09b9e2e..7664655 100644 --- a/src/tink/macro/BuildCache.hx +++ b/src/tink/macro/BuildCache.hx @@ -31,23 +31,23 @@ typedef BuildContext3 = {>BuildContext2, type3:Type, } -class BuildCache { - +class BuildCache { + @:persistent static var cache = new Map(); - - static public function getType3(name, ?types, ?pos:Position, build:BuildContext3->TypeDefinition) { + + static public function getType3(name, ?types, ?pos:Position, build:BuildContext3->TypeDefinition, ?normalizer:Type->Type) { if (types == null) switch Context.getLocalType() { case TInst(_.toString() == name => true, [t1, t2, t3]): types = { t1: t1, t2: t2, t3: t3 }; default: throw 'assert'; - } - + } + var t1 = types.t1.toComplexType(), t2 = types.t2.toComplexType(), t3 = types.t2.toComplexType(); - + return getType(name, (macro : { t1: $t1, t2: $t2, t3: $t3 } ).toType(), pos, function (ctx) return build({ type: types.t1, type2: types.t2, @@ -55,62 +55,62 @@ class BuildCache { pos: ctx.pos, name: ctx.name, usings: ctx.usings - })); + }), normalizer); } - - static public function getTypeN(name, ?types, ?pos:Position, build:BuildContextN->TypeDefinition) { - + + static public function getTypeN(name, ?types, ?pos:Position, build:BuildContextN->TypeDefinition, ?normalizer:Type->Type) { + if (pos == null) pos = Context.currentPos(); - + if (types == null) switch Context.getLocalType() { case TInst(_.toString() == name => true, params): types = params; default: throw 'assert'; - } - + } + var compound = ComplexType.TAnonymous([for (i in 0...types.length) { name: 't$i', pos: pos, kind: FVar(switch types[i] { - case TInst(_.get().kind => KExpr(e), _): + case TInst(_.get().kind => KExpr(e), _): TPath('tink.macro.ConstParam'.asTypePath([TPExpr(e)])); case t: t.toComplex(); }), }]).toType(); - + return getType(name, compound, pos, function (ctx) return build({ types: types, pos: ctx.pos, name: ctx.name, usings: ctx.usings - })); - } - - static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition) { + }), normalizer); + } + + static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition, ?normalizer:Type->Type) { if (types == null) switch Context.getLocalType() { case TInst(_.toString() == name => true, [t1, t2]): types = { t1: t1, t2: t2 }; default: throw 'assert'; - } - + } + var t1 = types.t1.toComplexType(), t2 = types.t2.toComplexType(); - + return getType(name, (macro : { t1: $t1, t2: $t2 } ).toType(), pos, function (ctx) return build({ type: types.t1, type2: types.t2, pos: ctx.pos, name: ctx.name, usings: ctx.usings - })); + }), normalizer); } - static public function getParams(name:String, ?pos:Position) + static public function getParams(name:String, ?pos:Position) return switch Context.getLocalType() { case TInst(_.toString() == name => true, v): @@ -119,9 +119,9 @@ class BuildCache { pos.makeFailure('Expected $name'); case v: pos.makeFailure('$v should be a class'); - } + } - static public function getParam(name:String, ?pos:Position) + static public function getParam(name:String, ?pos:Position) return getParams(name, pos) .flatMap(function (args:Array) return switch args { @@ -130,18 +130,18 @@ class BuildCache { default: pos.makeFailure('too many parameters'); }); - static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition) { - + static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition, ?normalizer:Type->Type) { + if (type == null) type = getParam(name, pos).sure(); - - var forName = + + var forName = switch cache[name] { - case null: cache[name] = new Group(name); + case null: cache[name] = new Group(name, normalizer); case v: v; } - - var ret = forName.get(type, pos.sanitize(), build); + + var ret = forName.get(type, pos.sanitize(), build); ret.getFields();// workaround for https://github.com/HaxeFoundation/haxe/issues/7905 return ret; } @@ -152,23 +152,24 @@ private typedef Entry = { } private class Group { - + var name:String; var counter = 0; - var entries = new TypeMap(); - - public function new(name) { + var entries:TypeMap; + + public function new(name, ?normalizer) { this.name = name; + this.entries = new TypeMap(normalizer); } - + public function get(type:Type, pos:Position, build:BuildContext->TypeDefinition):Type { - + function make(path:String) { var usings = []; var def = build({ - pos: pos, - type: type, - usings: usings, + pos: pos, + type: type, + usings: usings, name: path.split('.').pop() }); @@ -177,15 +178,15 @@ private class Group { return Context.getType(path); } - function doMake() - while (true) + function doMake() + while (true) switch '$name${counter++}' { case _.definedType() => Some(_): case v: return make(v); - } + } - return + return switch entries.get(type) { case null: doMake(); diff --git a/tests/Run.hx b/tests/Run.hx index 7a16177..03b7515 100644 --- a/tests/Run.hx +++ b/tests/Run.hx @@ -3,8 +3,8 @@ package ; import haxe.unit.*; class Run { - #if !macro - static function main() + #if !macro + static function main() test();//It compiles ... #else static var cases:Array = [ @@ -19,12 +19,13 @@ class Run { macro static function test() { var runner = new TestRunner(); tink.macro.ClassBuilder; + tink.macro.BuildCache; for (c in cases) runner.add(c); runner.run(); if (!runner.result.success) haxe.macro.Context.error(runner.result.toString(), haxe.macro.Context.currentPos()); - + return macro { trace('Let\'s ship it!'); }