diff --git a/src/tink/macro/Sisyphus.hx b/src/tink/macro/Sisyphus.hx index 81364a4..fba3fb9 100644 --- a/src/tink/macro/Sisyphus.hx +++ b/src/tink/macro/Sisyphus.hx @@ -138,7 +138,7 @@ class Sisyphus { } } - static function exactBase(r:haxe.macro.Type.Ref, params:Array) { + static function exactBase(r:Ref, params:Array) { var t = r.get(); var isMain = !t.isPrivate && switch t.pack { case []: t.module == t.name || t.module == 'StdTypes'; @@ -197,4 +197,29 @@ class Sisyphus { case TLazy(f): toExactString(f()); } + static function eager(t:Type) + return switch t { + case TLazy(f): eager(f()); + default: t; + } + + static public function compare(t1:Type, t2:Type, ?follow:Bool = true) { + if (follow) { + t1 = t1.reduce(); + t2 = t2.reduce(); + } + else { + t1 = eager(t1); + t2 = eager(t2); + } + + return switch t1.getIndex() - t2.getIndex() { + case 0: + switch Reflect.compare(t1.toString(), t2.toString()) { + case 0: Reflect.compare(t1.toExactString(), t2.toExactString()); + case v: v; + } + case v: v; + } + } } diff --git a/src/tink/macro/Types.hx b/src/tink/macro/Types.hx index 988ac1d..634cfbd 100644 --- a/src/tink/macro/Types.hx +++ b/src/tink/macro/Types.hx @@ -10,6 +10,8 @@ using haxe.macro.Tools; using tink.MacroApi; using tink.CoreApi; +import haxe.macro.Type.Ref; + class Types { static public function definedType(typeName:String) @@ -355,18 +357,8 @@ class Types { throw 'assert'; } - static public function compare(t1:Type, t2:Type, ?follow:Bool = true) { - if (follow) { - t1 = t1.reduce(); - t2 = t2.reduce(); - } - - return switch t1.getIndex() - t2.getIndex() { - case 0: - Reflect.compare(t1.toString(), t2.toString());//much to my surprise, this actually seems to work (at least with 3.4) - case v: v; - } - } + static public function compare(t1:Type, t2:Type, ?follow:Bool = true) + return Sisyphus.compare(t1, t2, follow); static var SUGGESTIONS = ~/ \(Suggestions?: .*\)$/; diff --git a/tests/ExactStrings.hx b/tests/ExactStrings.hx index c2c5172..082159a 100644 --- a/tests/ExactStrings.hx +++ b/tests/ExactStrings.hx @@ -1,4 +1,3 @@ -import haxe.macro.Context; import haxe.macro.Context.typeof; using tink.MacroApi; @@ -12,6 +11,8 @@ class ExactStrings extends Base { expect('Dummy.Private', macro Dummy.p); expect('nested.Dummy.Private', macro nested.Dummy.p); expect('{ @foo var x:Int; }', macro (null:{@foo var x:Int;})); + expect('{ @foo @bar var x:Int; }', macro (null:{@foo @bar var x:Int;})); + expect('{ @bar @foo var x:Int; }', macro (null:{@bar @foo var x:Int;}));// not 100% sure this is always the best choice, but let's roll with it expect('{ @bar var x:Int; }', macro (null:{@bar var x:Int;})); expect('{ var x:Int; var y:Int; }', macro (null:{x:Int,y:Int})); expect('{ var x:Int; var y:Int; }', macro (null:{y:Int,x:Int})); diff --git a/tests/TypeMapTest.hx b/tests/TypeMapTest.hx index 201dd9c..0f17235 100644 --- a/tests/TypeMapTest.hx +++ b/tests/TypeMapTest.hx @@ -11,6 +11,8 @@ class TypeMapTest extends TestCase { var t = new TypeMap(); var t1 = (macro [{ foo: [{ bar: '5' }]}]).typeof().sure(); var t2 = (macro [{ foo: [{ bar: 5 }]}]).typeof().sure(); + var t3 = (macro [{ foo: [{ bar: 5 }]}]).typeof().sure(); + var t4 = (macro [{ foo: [({ bar: 5 }:{ @foo var bar:Int; })]}]).typeof().sure(); t.set(t1, 0); assertEquals(Lambda.count(t), 1); @@ -19,7 +21,10 @@ class TypeMapTest extends TestCase { t.set(t1, 2); assertEquals(Lambda.count(t), 2); t.set(t2, 3); + t.set(t3, 3); assertEquals(Lambda.count(t), 2); + t.set(t4, 4); + assertEquals(Lambda.count(t), 3); assertEquals(t.get(t1), 2); assertEquals(t.get(t2), 3); diff --git a/tests/Types.hx b/tests/Types.hx index 9a602bf..54d4846 100644 --- a/tests/Types.hx +++ b/tests/Types.hx @@ -10,36 +10,35 @@ using tink.MacroApi; class Types extends Base { function type(c:ComplexType) return c.toType().sure(); - + function resolve(type:String) return Context.getType(type); - + inline function assertSuccess(o:Outcome) assertTrue(o.isSuccess()); - + inline function assertFailure(o:Outcome) assertFalse(o.isSuccess()); - + function testIs() { - assertSuccess(resolve('Int').isSubTypeOf(resolve('Float'))); assertFailure(resolve('Float').isSubTypeOf(resolve('Int'))); - } - + } + function testFields() { var expected = type(macro : Void -> Iterator), iterator = type(macro : haxe.ds.StringMap).getFields(true).sure().filter(function (c) return c.name == 'iterator')[0]; - + assertSuccess(iterator.type.isSubTypeOf(expected)); assertSuccess(expected.isSubTypeOf(iterator.type)); } - + function testConvert() { assertSuccess((macro : Int).toType()); assertFailure((macro : Tni).toType()); function blank() return type(MacroApi.pos().makeBlankType()); - + var bool = type(macro : Bool); assertTrue(blank().isSubTypeOf(bool).isSuccess()); assertTrue(bool.isSubTypeOf(blank()).isSuccess()); @@ -65,7 +64,7 @@ class Types extends Base { assertEquals('String', Context.getType('String').toComplex().toString()); assertEquals('tink.CoreApi.Noise', Context.getType('tink.CoreApi.Noise').toComplex().toString()); } - + function testDeduceCommonType() { function ct2t(ct:ComplexType) return ct.toType().sure(); assertEquals('StdTypes.Float', tink.macro.Types.deduceCommonType([(macro:Float), (macro:Int)].map(ct2t)).sure().toComplex().toString());