Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
328a8476a5 | ||
![]() |
1589665652 | ||
![]() |
08f15a6739 | ||
![]() |
b5e992b820 | ||
![]() |
8c50dcf04b | ||
![]() |
4bc63c6eb0 | ||
![]() |
acb7237ae4 | ||
![]() |
e3bac681ce | ||
![]() |
34516086c9 |
@@ -15,14 +15,14 @@ os:
|
||||
env:
|
||||
- HAXE_VERSION=3.4.7
|
||||
- HAXE_VERSION=edge
|
||||
|
||||
|
||||
install:
|
||||
- npm i -g lix@15.5.4
|
||||
- lix install haxe $HAXE_VERSION
|
||||
- lix download
|
||||
|
||||
script:
|
||||
- lix run travix node -lib hx3compat
|
||||
- lix run travix node
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
@@ -1,3 +1,3 @@
|
||||
-D hx3compat=1.0.0
|
||||
# @install: lix --silent download "haxelib:/hx3compat#1.0.0" into hx3compat/1.0.0/haxelib
|
||||
-cp ${HAXE_LIBCACHE}/hx3compat/1.0.0/haxelib/std
|
||||
# @install: lix --silent download "haxelib:/hx3compat#1.0.3" into hx3compat/1.0.3/haxelib
|
||||
-cp ${HAXE_LIBCACHE}/hx3compat/1.0.3/haxelib/std
|
||||
-D hx3compat=1.0.3
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# @install: lix --silent download "haxelib:hxnodejs#4.0.9" into hxnodejs/4.0.9/haxelib
|
||||
-D hxnodejs=4.0.9
|
||||
-cp ${HAXESHIM_LIBCACHE}/hxnodejs/4.0.9/haxelib/src
|
||||
-D nodejs
|
||||
# @install: lix --silent download "haxelib:/hxnodejs#12.0.0" into hxnodejs/12.0.0/haxelib
|
||||
-cp ${HAXE_LIBCACHE}/hxnodejs/12.0.0/haxelib/src
|
||||
-D hxnodejs=12.0.0
|
||||
--macro allowPackage('sys')
|
||||
--macro _hxnodejs.VersionWarning.include()
|
||||
# should behave like other target defines and not be defined in macro context
|
||||
--macro define('nodejs')
|
||||
|
24
haxelib.json
24
haxelib.json
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"name": "tink_macro",
|
||||
"license": "MIT",
|
||||
"description": "The macro toolkit ;)",
|
||||
"classPath": "src",
|
||||
"dependencies": {
|
||||
"tink_core": ""
|
||||
},
|
||||
"url": "https://github.com/haxetink/tink_macro",
|
||||
"contributors": [
|
||||
"back2dos"
|
||||
],
|
||||
"version": "0.19.3",
|
||||
"releasenote": "Fix issues in ComplexType -> Type conversion for functions.",
|
||||
"tags": [
|
||||
"tink",
|
||||
"macro",
|
||||
"utility"
|
||||
],
|
||||
"classPath": "src",
|
||||
"description": "The macro toolkit ;)",
|
||||
"contributors": [
|
||||
"back2dos"
|
||||
],
|
||||
"releasenote": "Internal refactor: remove reflections",
|
||||
"version": "0.19.0",
|
||||
"url": "http://haxetink.org/tink_macro",
|
||||
"dependencies": {
|
||||
"tink_core": ""
|
||||
}
|
||||
"license": "MIT"
|
||||
}
|
@@ -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<Type>) 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<Entry>();
|
||||
|
||||
public function new(name) {
|
||||
var entries:TypeMap<Entry>;
|
||||
|
||||
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();
|
||||
|
@@ -23,8 +23,8 @@ class Sisyphus {
|
||||
if (cf.params.length == 0) {
|
||||
name: cf.name,
|
||||
doc: cf.doc,
|
||||
access:
|
||||
(cf.isPublic ? [ APublic ] : [ APrivate ])
|
||||
access:
|
||||
(cf.isPublic ? [ APublic ] : [ APrivate ])
|
||||
#if haxe4 .concat(if (cf.isFinal) [AFinal] else []) #end
|
||||
,
|
||||
kind: switch([ cf.kind, cf.type ]) {
|
||||
@@ -84,7 +84,7 @@ class Sisyphus {
|
||||
cl.kind.match(KTypeParameter(_))
|
||||
&& cl.module == classType.module
|
||||
&& cl.pack.join('.') == classType.pack.join('.')
|
||||
): ct;
|
||||
): ct;
|
||||
default:
|
||||
direct();
|
||||
}
|
||||
@@ -95,8 +95,12 @@ class Sisyphus {
|
||||
TPath(toTypePath(baseType, params));
|
||||
case TFun(args, ret):
|
||||
TFunction(
|
||||
[ for (a in args) a.opt ? nullable(toComplexType(a.t)) : toComplexType(a.t) ],
|
||||
toComplexType(ret));
|
||||
[for (a in args) {
|
||||
var t = #if haxe4 TNamed(a.name, #else ( #end toComplexType(a.t));
|
||||
if (a.opt) TOptional(t) else t;
|
||||
}],
|
||||
toComplexType(ret)
|
||||
);
|
||||
case TAnonymous(_.get() => { fields: fields }):
|
||||
TAnonymous([ for (cf in fields) toField(cf) ]);
|
||||
case TDynamic(t):
|
||||
@@ -121,7 +125,7 @@ class Sisyphus {
|
||||
case _ == name => true: null;
|
||||
case v: v;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
pack: baseType.pack,
|
||||
name: name,
|
||||
|
@@ -8,14 +8,33 @@ import haxe.macro.Type;
|
||||
using tink.MacroApi;
|
||||
|
||||
class TypeMap<V> extends BalancedTree<Type, V> implements IMap<Type, V> {
|
||||
var follow:Bool;
|
||||
|
||||
public function new(?noFollow:Bool) {
|
||||
this.follow = noFollow != true;
|
||||
var normalize:Type->Type;
|
||||
|
||||
public function new(?normalize:Type->Type) {
|
||||
this.normalize = switch normalize {
|
||||
case null: function (t) return t.reduce();
|
||||
case fn: fn;
|
||||
}
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
override function compare(k1:Type, k2:Type):Int
|
||||
return k1.compare(k2, follow);
|
||||
|
||||
return normalize(k1).compare(normalize(k2), false);
|
||||
|
||||
static public function noFollow(t:Type)
|
||||
return t;
|
||||
|
||||
static public function keepNull(t:Type):Type
|
||||
return switch t {
|
||||
case TAbstract(_.get() => { name: 'Null', pack: [] }, [t])
|
||||
#if !haxe4 | TType(_.get() => { name: 'Null', pack: []}, [t]) #end
|
||||
:
|
||||
var ct = keepNull(t).toComplex({ direct: true });
|
||||
(macro : Null<$ct>).toType().sure();
|
||||
|
||||
case TLazy(f): keepNull(f());
|
||||
case TType(_, _): keepNull(Context.follow(t, true));
|
||||
default: t;
|
||||
}
|
||||
|
||||
}
|
@@ -1,2 +1,3 @@
|
||||
-cp tests
|
||||
-lib hx3compat
|
||||
-main Run
|
1
tests/MyString.hx
Normal file
1
tests/MyString.hx
Normal file
@@ -0,0 +1 @@
|
||||
typedef MyString = String;
|
@@ -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<TestCase> = [
|
||||
@@ -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!');
|
||||
}
|
||||
|
@@ -1,17 +1,17 @@
|
||||
package;
|
||||
|
||||
import haxe.unit.TestCase;
|
||||
import haxe.macro.Expr;
|
||||
|
||||
import tink.macro.TypeMap;
|
||||
using haxe.macro.Context;
|
||||
using tink.MacroApi;
|
||||
|
||||
class TypeMapTest extends TestCase {
|
||||
|
||||
function testMap() {
|
||||
var t = new TypeMap();
|
||||
var t1 = (macro [{ foo: [{ bar: '5' }]}]).typeof();
|
||||
var t2 = (macro [{ foo: [{ bar: 5 }]}]).typeof();
|
||||
|
||||
var t1 = (macro [{ foo: [{ bar: '5' }]}]).typeof().sure();
|
||||
var t2 = (macro [{ foo: [{ bar: 5 }]}]).typeof().sure();
|
||||
|
||||
t.set(t1, 0);
|
||||
assertEquals(Lambda.count(t), 1);
|
||||
t.set(t2, 1);
|
||||
@@ -20,11 +20,29 @@ class TypeMapTest extends TestCase {
|
||||
assertEquals(Lambda.count(t), 2);
|
||||
t.set(t2, 3);
|
||||
assertEquals(Lambda.count(t), 2);
|
||||
|
||||
|
||||
assertEquals(t.get(t1), 2);
|
||||
assertEquals(t.get(t2), 3);
|
||||
|
||||
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
|
||||
function testNormalization() {
|
||||
for (settings in [
|
||||
{ count: 4, map: new TypeMap(TypeMap.noFollow)},
|
||||
{ count: 2, map: new TypeMap(TypeMap.keepNull)},
|
||||
{ count: 1, map: new TypeMap()},
|
||||
]) {
|
||||
|
||||
function set(ct:ComplexType)
|
||||
settings.map.set(ct.toType().sure(), ct);
|
||||
|
||||
set(macro : String);
|
||||
set(macro : MyString);
|
||||
set(macro : Null<String>);
|
||||
set(macro : Null<MyString>);
|
||||
|
||||
assertEquals(settings.count, Lambda.count(settings.map));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user