Compare commits

...

22 Commits

Author SHA1 Message Date
Juraj Kirchheim
32d711cd71 Release 1.0.0 2021-07-06 19:31:17 +02:00
Juraj Kirchheim
0947d1b916 Release 0.24.0 2021-06-02 10:23:41 +02:00
Juraj Kirchheim
aa186a1ec2 Add eval to Expr/TypedExpr. 2021-06-02 10:21:41 +02:00
Kevin Leung
40d7c2fbde Update badges 2021-05-22 12:07:27 +08:00
Kevin Leung
f1010a518f Bump dependency and fix haxe3 compatibility 2021-05-14 21:33:09 +08:00
Kevin Leung
54f592f14c Setup GitHub Actions 2021-05-14 21:29:25 +08:00
Juraj Kirchheim
e01bf6912a Improve VarAccess to String conversion. 2021-05-03 20:38:55 +02:00
Juraj Kirchheim
56fe8d7346 Release 0.23.0 2021-04-02 10:09:41 +02:00
Juraj Kirchheim
7e2dfad607 Make TypeMap work exacly with anons. 2021-03-14 13:25:20 +01:00
Juraj Kirchheim
94d02c91a8 Haxe 3 support. 2021-03-14 12:59:38 +01:00
Juraj Kirchheim
99a1fc3fa6 Exact type to string conversion. 2021-03-14 12:58:10 +01:00
Juraj Kirchheim
a383f7692b Argh ... 2021-02-25 11:37:04 +01:00
Juraj Kirchheim
5e5781e8bc Faster intersection for haxe4. 2021-02-25 11:36:26 +01:00
Juraj Kirchheim
63ce1853f5 Release 0.22.0 2021-02-22 11:46:09 +01:00
Juraj Kirchheim
f3ddaa6496 Merge pull request #33 from haxetink/deduce_common_type
Deduce common base type from a list of types
2020-12-23 09:32:31 +01:00
Kevin Leung
f46e49ce66 Fix haxe3 2020-12-22 17:15:28 +08:00
Kevin Leung
007c73d58e Deduce common base type from a list of types 2020-12-22 16:56:45 +08:00
Juraj Kirchheim
8c5903833c Merge pull request #32 from haxetink/isAbstract
haxe 4.2+ fix
2020-12-20 09:21:31 +01:00
Dan Korostelev
59d7407d1b haxe 4.2+ fix 2020-12-19 22:58:31 +01:00
Juraj Kirchheim
0680220a77 Release 0.21.1 2020-08-20 13:09:07 +02:00
Juraj Kirchheim
acaedc170a Fix issue with build field retrieval. 2020-08-20 13:08:28 +02:00
Juraj Kirchheim
8b9dbba624 Release 0.21.0 2020-08-20 12:47:53 +02:00
25 changed files with 377 additions and 75 deletions

96
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,96 @@
name: CI
on:
push:
pull_request:
branches: [ master ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
haxe-version:
- "3.4.7"
- stable
- nightly
target:
- node
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache Yarn
uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Cache Haxe
uses: actions/cache@v1
with:
path: ~/haxe
key: haxe
- name: Install Lix
uses: lix-pm/setup-lix@master
- name: Install Haxe
run: lix install haxe ${{ matrix.haxe-version }}
- name: Install Haxe Libraries
run: lix download
- name: Run Test
run: lix run travix ${{ matrix.target }}
release:
runs-on: ubuntu-latest
needs: test
if: startsWith(github.ref, 'refs/tags/') # consider using the "release" event. see: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#release
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache Yarn
uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Cache Haxe
uses: actions/cache@v1
with:
path: ~/haxe
key: haxe
- name: Install Lix
uses: lix-pm/setup-lix@master
- name: Install Haxe
run: lix install haxe stable
- name: Install Haxe Libraries
run: lix download
- name: Release to Haxelib
run: lix run travix release
env:
HAXELIB_AUTH: ${{ secrets.HAXELIB_AUTH }}

View File

@@ -1,4 +1,4 @@
{
"version": "4.0.5",
"version": "4.2.1",
"resolveLibs": "scoped"
}

17
.vscode/tasks.json vendored
View File

@@ -1,6 +1,19 @@
{
"version": "0.1.0",
"version": "2.0.0",
"command": "haxelib",
"args": ["run", "travix", "node"],
"problemMatcher": "$haxe"
"problemMatcher": "$haxe",
"tasks": [
{
"label": "haxelib",
"command": "haxelib",
"args": [
"run",
"travix",
"node"
],
"problemMatcher": "$haxe",
"group": "build"
}
]
}

View File

@@ -1,7 +1,9 @@
# Tinkerbell Macro Library
[![Build Status](https://travis-ci.org/haxetink/tink_macro.svg?branch=master)](https://travis-ci.org/haxetink/tink_macro)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/haxetink/public)
[![Build Status](https://github.com/haxetink/tink_macro/actions/workflows/ci.yml/badge.svg)](https://github.com/haxetink/tink_macro/actions)
[![Gitter](https://img.shields.io/gitter/room/haxetink/public?logo=gitter&)](https://gitter.im/haxetink/public)
[![Discord](https://img.shields.io/discord/162395145352904705.svg?logo=discord)](https://discord.com/channels/162395145352904705/579634919576436736)
Explained in current marketing speak, `tink_macro` is *the* macro toolkit ;)

View File

@@ -0,0 +1,3 @@
# @install: lix --silent download "gh://github.com/haxetink/tink_chunk#f095072a029f1f50ce5f2cc0a690c3e834298d96" into tink_chunk/0.3.1/github/f095072a029f1f50ce5f2cc0a690c3e834298d96
-cp ${HAXE_LIBCACHE}/tink_chunk/0.3.1/github/f095072a029f1f50ce5f2cc0a690c3e834298d96/src
-D tink_chunk=0.3.1

View File

@@ -1,8 +1,8 @@
-D tink_cli=0.3.1
# @install: lix --silent download "haxelib:/tink_cli#0.3.1" into tink_cli/0.3.1/haxelib
# @install: lix --silent download "gh://github.com/haxetink/tink_cli#1278ad2a34fd5e2403e414aefe09bb938d0c8825" into tink_cli/0.5.1/github/1278ad2a34fd5e2403e414aefe09bb938d0c8825
-lib tink_io
-lib tink_stringly
-lib tink_macro
-cp ${HAXE_LIBCACHE}/tink_cli/0.3.1/haxelib/src
-lib tink_stringly
-cp ${HAXE_LIBCACHE}/tink_cli/0.5.1/github/1278ad2a34fd5e2403e414aefe09bb938d0c8825/src
-D tink_cli=0.5.1
# Make sure docs are generated
-D use-rtti-doc

View File

@@ -1,3 +1,3 @@
-D tink_core=1.24.0
# @install: lix --silent download "haxelib:/tink_core#1.24.0" into tink_core/1.24.0/haxelib
-cp ${HAXE_LIBCACHE}/tink_core/1.24.0/haxelib/src
# @install: lix --silent download "gh://github.com/haxetink/tink_core#abee932c4e724517090238b6527eac28874c0354" into tink_core/1.27.1/github/abee932c4e724517090238b6527eac28874c0354
-cp ${HAXE_LIBCACHE}/tink_core/1.27.1/github/abee932c4e724517090238b6527eac28874c0354/src
-D tink_core=1.27.1

View File

@@ -1,5 +1,5 @@
-D tink_io=0.5.0
# @install: lix --silent download "haxelib:/tink_io#0.5.0" into tink_io/0.5.0/haxelib
# @install: lix --silent download "gh://github.com/haxetink/tink_io#e4a92421865adfd7037474937cffacaa1abd4338" into tink_io/0.8.0/github/e4a92421865adfd7037474937cffacaa1abd4338
-lib tink_chunk
-lib tink_streams
-lib tink_core
-cp ${HAXE_LIBCACHE}/tink_io/0.5.0/haxelib/src
-cp ${HAXE_LIBCACHE}/tink_io/0.8.0/github/e4a92421865adfd7037474937cffacaa1abd4338/src
-D tink_io=0.8.0

View File

@@ -1,4 +1,6 @@
-D tink_streams=0.2.1
# @install: lix --silent download "haxelib:/tink_streams#0.2.1" into tink_streams/0.2.1/haxelib
# @install: lix --silent download "gh://github.com/haxetink/tink_streams#aa006c354e742164c4f7bc8ec4532bc9154fb0d0" into tink_streams/0.3.3/github/aa006c354e742164c4f7bc8ec4532bc9154fb0d0
-lib tink_core
-cp ${HAXE_LIBCACHE}/tink_streams/0.2.1/haxelib/src
-cp ${HAXE_LIBCACHE}/tink_streams/0.3.3/github/aa006c354e742164c4f7bc8ec4532bc9154fb0d0/src
-D tink_streams=0.3.3
# temp for development, delete this file when pure branch merged
-D pure

View File

@@ -1,6 +1,7 @@
-D travix=0.12.2
# @install: lix --silent download "gh://github.com/back2dos/travix#7da3bf96717b52bf3c7e5d2273bf927a8cd7aeb5" into travix/0.12.2/github/7da3bf96717b52bf3c7e5d2273bf927a8cd7aeb5
# @post-install: cd ${HAXE_LIBCACHE}/travix/0.12.2/github/7da3bf96717b52bf3c7e5d2273bf927a8cd7aeb5 && haxe -cp src --run travix.PostDownload
# @run: haxelib run-dir travix ${HAXE_LIBCACHE}/travix/0.12.2/github/7da3bf96717b52bf3c7e5d2273bf927a8cd7aeb5
# @install: lix --silent download "gh://github.com/back2dos/travix#354c2b2a82cc3b03e2f87cc1b6f0ddc0a6a5c133" into travix/0.15.0/github/354c2b2a82cc3b03e2f87cc1b6f0ddc0a6a5c133
# @post-install: cd ${HAXE_LIBCACHE}/travix/0.15.0/github/354c2b2a82cc3b03e2f87cc1b6f0ddc0a6a5c133 && haxe -cp src --run travix.PostDownload
# @run: haxelib run-dir travix ${HAXE_LIBCACHE}/travix/0.15.0/github/354c2b2a82cc3b03e2f87cc1b6f0ddc0a6a5c133
-lib tink_cli
-cp ${HAXE_LIBCACHE}/travix/0.12.2/github/7da3bf96717b52bf3c7e5d2273bf927a8cd7aeb5/src
-cp ${HAXE_LIBCACHE}/travix/0.15.0/github/354c2b2a82cc3b03e2f87cc1b6f0ddc0a6a5c133/src
-D travix=0.15.0
--macro travix.Macro.setup()

View File

@@ -9,8 +9,8 @@
"contributors": [
"back2dos"
],
"version": "0.20.2",
"releasenote": "Expose autocompletion contents. Work around metadata completion issue.",
"version": "1.0.0",
"releasenote": "Let's just commit to the API and move on.",
"tags": [
"tink",
"macro",

View File

@@ -3,7 +3,7 @@ package tink.macro;
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
using tink.macro.Positions;
using tink.macro.Exprs;
#end
@@ -15,7 +15,7 @@ package tink.macro;
static public function bounceExpr(e:Expr, transform:Expr->Expr) {
var id = idCounter++,
pos = e.pos;
outerMap.set(id, transform);
outerMap.set(id, transform);
return macro @:pos(e.pos) tink.macro.Bouncer.catchBounceExpr($e, $v{id});
}
static public function bounce(f:Void->Expr, ?pos:Position) {
@@ -29,35 +29,41 @@ package tink.macro;
pos = e.pos;
outerMap.set(id, transform);
return macro @:pos(e.pos) tink.macro.Bouncer.makeOuter($e).andBounce($v{id});
}
}
static function doOuter(id:Int, e:Expr) {
return
if (outerMap.exists(id))
if (outerMap.exists(id))
outerMap.get(id)(e);
else
Context.currentPos().error('unknown id ' + id);
Context.currentPos().error('unknown id ' + id);
}
static function doBounce(id:Int) {
return
if (bounceMap.exists(id))
if (bounceMap.exists(id))
bounceMap.get(id)();
else
Context.currentPos().error('unknown id ' + id);
Context.currentPos().error('unknown id ' + id);
}
static public var lastEvaled(default, null):Dynamic;
#else
@:noUsing static public function makeOuter<A>(a:A):Bouncer
@:noUsing static public function makeOuter<A>(a:A):Bouncer
return null;
#end
@:noUsing macro public function andBounce(ethis:Expr, id:Int)
@:noUsing macro public function andBounce(ethis:Expr, id:Int)
return
switch (ethis.expr) {
case ECall(_, params): doOuter(id, params[0]);
default: ethis.reject();
}
@:noUsing macro static public function catchBounce(id:Int)
@:noUsing static public macro function eval(f:Void->Dynamic) {
lastEvaled = f();
return macro null;
}
@:noUsing macro static public function catchBounce(id:Int)
return doBounce(id);
@:noUsing macro static public function catchBounceExpr(e:Expr, id:Int)
return doOuter(id, e);
}

View File

@@ -23,9 +23,9 @@ class ClassBuilder {
target = Context.getLocalClass().get();
if (fields == null)
switch MacroApi.getBuildFields() {
fields = switch MacroApi.getBuildFields() {
case None: target.pos.error('Impossible to get builds fields now. Possible cause: https://github.com/HaxeFoundation/haxe/issues/9853');
case Some(_):
case Some(v): v;
}
this.initializeFrom = fields;

View File

@@ -48,6 +48,11 @@ class Exprs {
static public inline function as(e:Expr, c:ComplexType)
return ECheckType(e, c).at(e.pos);
static public function eval(e:Expr):Dynamic {
Context.typeof(macro tink.macro.Bouncer.eval(function () return $e));
return Bouncer.lastEvaled;
}
static public function finalize(e:Expr, ?nuPos:Position, ?rules:Dict<String>, ?skipFields = false, ?callPos:PosInfos) {
if (nuPos == null)
nuPos = Context.currentPos();

View File

@@ -2,6 +2,8 @@ package tink.macro;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
using tink.MacroApi;
class Sisyphus {
@@ -61,8 +63,7 @@ class Sisyphus {
}
}
public static function toComplexType(type : Null<Type>) : Null<ComplexType> return {
static public function toComplexType(type : Null<Type>) : Null<ComplexType> return {
inline function direct()
return Types.toComplex(type, { direct: true });
switch (type) {
@@ -136,4 +137,89 @@ class Sisyphus {
}],
}
}
static function exactBase<T:BaseType>(r:Ref<T>, params:Array<Type>) {
var t = r.get();
var isMain = !t.isPrivate && switch t.pack {
case []: t.module == t.name || t.module == 'StdTypes';
default: StringTools.endsWith(t.module, '.${t.name}');
}
return (
if (isMain) t.pack.concat([t.name]).join('.')
else t.module + '.' + t.name
) + switch params {
case []: '';
case params:
'<${params.map(toExactString).join(', ')}>';
}
}
static inline function isFinal(c:ClassField)
return #if haxe4 c.isFinal #else false #end;
static function exactAnonField(c:ClassField) {
var kw =
switch c.kind {
case FMethod(_): 'function';
case FVar(_):
if (isFinal(c)) 'final' else 'var';
}
return [for (m in c.meta.get()) m.toString() + ' '].join('') + '$kw ${c.name}' + (switch c.kind {
case FVar(read, write):
(
if (isFinal(c) || (read == AccNormal && write == AccNormal)) ''
else '(${read.accessToName()}, ${read.accessToName(false)})'
) + ':' + c.type.toExactString();
case FMethod(_):
switch haxe.macro.Context.follow(c.type) {
case TFun(arg, ret): exactSig(arg, ret, ':');
default: throw 'assert';
}
}) + ';';
}
static function exactSig(args:Array<{name:String, opt:Bool, t:Type}>, ret:Type, sep:String)
return '(${[for (a in args) (if (a.opt) '?' else '') + a.name + ':' + toExactString(a.t)].join(', ')})$sep${toExactString(ret)}';
static public function toExactString(t:Type)
return switch t {
case TMono(t): t.toString();
case TEnum(r, params): exactBase(r, params);
case TInst(r, params): exactBase(r, params);
case TType(r, params): exactBase(r, params);
case TAbstract(r, params): exactBase(r, params);
case TFun(args, ret): exactSig(args, ret, '->');
case TAnonymous(a): '{ ${[for (f in a.get().fields) exactAnonField(f)].join(' ')} }';
case TDynamic(null): 'Dynamic';
case TDynamic(t): 'Dynamic<${toExactString(t)}>';
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;
}
}
}

View File

@@ -1,5 +1,6 @@
package tink.macro;
import haxe.macro.Context;
import haxe.macro.Type;
import haxe.ds.Option;
using haxe.macro.Tools;
@@ -31,6 +32,9 @@ class TypedExprs {
return None;
}
static public function eval(t:TypedExpr)
return Exprs.eval(Context.storeTypedExpr(t));
static public function isThis(t:TypedExpr):Bool
return switch t {
case null: false;

View File

@@ -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)
@@ -39,9 +41,10 @@ class Types {
static public function accessToName(v:VarAccess, ?read = true)
return
switch (v) {
case AccNormal, AccInline: 'default';
case AccNormal: 'default';
case AccInline: if (read) 'default' else 'never';
case AccNo: 'null';
case AccNever: 'never';
case AccNever #if haxe4 | AccCtor #end: 'never';
case AccCall: if (read) 'get' else 'set';
default:
throw 'not implemented';
@@ -172,6 +175,9 @@ class Types {
#if haxe4
isExtern: field.isExtern,
isFinal: field.isFinal,
#if (haxe >= version("4.2.0-rc.1"))
isAbstract: field.isAbstract,
#end
#end
}:ClassField)
]);
@@ -205,7 +211,22 @@ class Types {
default: Failure('type "$t" has no position');
}
static public function deduceCommonType(types:Array<Type>):Outcome<Type, Error> {
var exprs = types.map(function(t) {
var ct = t.toComplex();
return macro (null:$ct);
});
return switch (macro $a{exprs}).typeof() {
case Success(TInst(_, [v])): Success(v);
case Success(_): throw 'unreachable';
case Failure(e): Failure(new Error('Unable to deduce common type among $types'));
}
}
/// like haxe.macro.TypeTools.toString, but not lossy
static public function toExactString(t:Type)
return Sisyphus.toExactString(t);
static public function toString(t:ComplexType)
return new Printer().printComplexType(t);
@@ -293,6 +314,9 @@ class Types {
if (types.length == 1) return Success(types[1]);
#if haxe4
return Success(TIntersection(types));
#end
var paths = [],
fields = [];
@@ -334,18 +358,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?: .*\)$/;

8
tests/Dummy.hx Normal file
View File

@@ -0,0 +1,8 @@
class Dummy {
public function new() {}
static public var p(default, never) = new Private();
}
private class Private {
public function new() {}
}

21
tests/ExactStrings.hx Normal file
View File

@@ -0,0 +1,21 @@
import haxe.macro.Context.typeof;
using tink.MacroApi;
class ExactStrings extends Base {
function test() {
function expect(s:String, e, ?pos)
assertEquals(s, typeof(e).toExactString(), pos);
expect('Dummy', macro new Dummy());
expect('nested.Dummy', macro new nested.Dummy());
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}));
expect('{ function foo(x:Int, ?y:Int):Void; }', macro (null:{ function foo(x:Int, ?y:Int):Void; }));
}
}

View File

@@ -16,38 +16,46 @@ class Exprs extends Base {
assertTrue(id.length <= 3);
}
}
function testEval() {
var expr = macro (untyped {foo:[{bar:234},'bar']});
var str = Std.string(untyped {foo:[{bar:234},'bar']});
assertEquals(Std.string(expr.eval()), Std.string(untyped {foo:[{bar:234},'bar']}));
assertEquals(Std.string(Context.typeExpr(expr).eval()), Std.string(untyped {foo:[{bar:234},'bar']}));
}
function testGet() {
assertEquals('foo', (macro foo).getIdent().sure());
assertEquals('foo', (macro "foo").getString().sure());
assertEquals('foo', (macro foo).getName().sure());
assertEquals('foo', (macro "foo").getName().sure());
assertEquals(5, (macro 5).getInt().sure());
exprEq(macro [a, b, c], (macro function (a, b, c) [a, b, c]).getFunction().sure().expr);
assertEquals('a,b,c', [for (arg in (macro function (a, b, c) [a, b, c]).getFunction().sure().args) arg.name].join(','));
assertFalse((macro 'foo').getIdent().isSuccess());
assertFalse((macro foo).getString().isSuccess());
assertFalse((macro 5).getName().isSuccess());
assertFalse((macro 5.1).getInt().isSuccess());
assertFalse((macro foo).getFunction().isSuccess());
}
function testShortcuts() {
assertTrue(true);
}
function testIterType() {
assertEquals('Int', (macro [1, 2]).getIterType().sure().getID());
assertEquals('Int', (macro [1, 2].iterator()).getIterType().sure().getID());
assertEquals('Int', ECheckType(macro null, macro: Arrayish).at().getIterType().sure().getID());
}
function testYield() {
function yielder(e) return macro @yield $e;
function test(x:Expr, e:Expr, ?options)
exprEq(x, e.yield(yielder, options));
test(macro @yield foo, macro foo);
test(macro @yield (foo), macro (foo));
test(macro for (_) @yield foo, macro for (_) foo);
@@ -57,10 +65,10 @@ class Exprs extends Base {
}
function testSubstitute() {
exprEq(
macro foo.call(arg1, arg2),
macro foo.call(arg1, arg2),
(macro bar.call(x, y)).substitute({ x: macro arg1, y: macro arg2, bar: macro foo })
);
exprEq(
macro {
var x:Map<Int, String> = new Map(),
@@ -89,7 +97,7 @@ class Exprs extends Base {
])
);
}
function testConcat() {
exprEq(macro {a; b;}, (macro a).concat(macro b));
exprEq(macro {a; b; c;}, (macro {a; b;}).concat(macro c));

View File

@@ -1,6 +1,9 @@
package ;
import haxe.unit.*;
#if macro
using haxe.macro.Tools;
#end
class Run {
#if !macro
@@ -14,6 +17,7 @@ class Run {
new TypeMapTest(),
new Functions(),
new Misc(),
new ExactStrings(),
];
#end
macro static function test() {

View File

@@ -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);

View File

@@ -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<S, F>(o:Outcome<S, F>)
assertTrue(o.isSuccess());
inline function assertFailure<S, F>(o:Outcome<S, F>)
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<Arrayish>),
iterator = type(macro : haxe.ds.StringMap<Arrayish>).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,5 +64,20 @@ 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());
assertEquals('Types.CommonI1', tink.macro.Types.deduceCommonType([(macro:Types.CommonA), (macro:Types.CommonB), (macro:Types.CommonC)].map(ct2t)).sure().toComplex().toString());
assertEquals('Types.CommonI2', tink.macro.Types.deduceCommonType([(macro:Types.CommonB), (macro:Types.CommonC)].map(ct2t)).sure().toComplex().toString());
// assertEquals('Types.CommonI3', tink.macro.Types.deduceCommonType([(macro:Types.CommonC)].map(ct2t)).sure().toComplex().toString());
}
}
#end
#end
interface CommonI1 {}
interface CommonI2 {}
interface CommonI3 {}
class CommonA implements CommonI1 {}
class CommonB implements CommonI2 implements CommonI1 {}
class CommonC implements CommonI3 implements CommonI2 implements CommonI1 {}

10
tests/nested/Dummy.hx Normal file
View File

@@ -0,0 +1,10 @@
package nested;
class Dummy {
public function new() {}
static public var p(default, never) = new Private();
}
private class Private {
public function new() {}
}