Compare commits

..

2 Commits

Author SHA1 Message Date
Juraj Kirchheim
bc9f7460c2 Better, I guess. 2021-03-14 14:25:36 +01:00
Juraj Kirchheim
043df0f47d Try a more deterministic approach to build cache. 2021-03-14 14:11:35 +01:00
19 changed files with 129 additions and 310 deletions

View File

@@ -1,96 +0,0 @@
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.2.1",
"version": "4.0.5",
"resolveLibs": "scoped"
}

17
.vscode/tasks.json vendored
View File

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

View File

@@ -1,9 +1,7 @@
# Tinkerbell Macro Library
[![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)
[![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)
Explained in current marketing speak, `tink_macro` is *the* macro toolkit ;)

View File

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

View File

@@ -1,3 +1,3 @@
# @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
-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

View File

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

View File

@@ -1,6 +1,4 @@
# @install: lix --silent download "gh://github.com/haxetink/tink_streams#aa006c354e742164c4f7bc8ec4532bc9154fb0d0" into tink_streams/0.3.3/github/aa006c354e742164c4f7bc8ec4532bc9154fb0d0
-D tink_streams=0.2.1
# @install: lix --silent download "haxelib:/tink_streams#0.2.1" into tink_streams/0.2.1/haxelib
-lib tink_core
-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
-cp ${HAXE_LIBCACHE}/tink_streams/0.2.1/haxelib/src

View File

@@ -1,7 +1,6 @@
# @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
-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
-lib tink_cli
-cp ${HAXE_LIBCACHE}/travix/0.15.0/github/354c2b2a82cc3b03e2f87cc1b6f0ddc0a6a5c133/src
-D travix=0.15.0
--macro travix.Macro.setup()
-cp ${HAXE_LIBCACHE}/travix/0.12.2/github/7da3bf96717b52bf3c7e5d2273bf927a8cd7aeb5/src

View File

@@ -9,8 +9,8 @@
"contributors": [
"back2dos"
],
"version": "1.0.0",
"releasenote": "Let's just commit to the API and move on.",
"version": "0.22.0",
"releasenote": "Support Haxe 4.2",
"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,41 +29,35 @@ 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 static public macro function eval(f:Void->Dynamic) {
lastEvaled = f();
return macro null;
}
@:noUsing macro static public function catchBounce(id:Int)
@: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

@@ -17,18 +17,18 @@ typedef BuildContextN = {
typedef BuildContext = {
pos:Position,
type:Type,
usings:Array<TypePath>,
name:String,
var pos(default, never):Position;
var type(default, never):Type;
var usings(default, never):Array<TypePath>;
var name(default, never):String;
}
typedef BuildContext2 = {>BuildContext,
type2:Type,
var type2(default, never):Type;
}
typedef BuildContext3 = {>BuildContext2,
type3:Type,
var type3(default, never):Type;
}
class BuildCache {
@@ -36,29 +36,20 @@ class BuildCache {
@:persistent static var cache = new Map();
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,
type3: types.t3,
return _getTypeN(name, 3, switch types {
case null: null;
case v: [types.t1, types.t2, types.t3];
}, pos, ctx -> build({
pos: ctx.pos,
name: ctx.name,
usings: ctx.usings
type: ctx.types[0],
type2: ctx.types[1],
type3: ctx.types[2],
usings: ctx.usings,
name: ctx.name
}), normalizer);
}
static public function getTypeN(name, ?types, ?pos:Position, build:BuildContextN->TypeDefinition, ?normalizer:Type->Type) {
static function _getTypeN(name, length, ?types, ?pos:Position, build:BuildContextN->TypeDefinition, ?normalizer:Type->Type) {
if (pos == null)
pos = Context.currentPos();
@@ -67,50 +58,37 @@ class BuildCache {
switch Context.getLocalType() {
case TInst(_.toString() == name => true, params):
types = params;
default:
throw 'assert';
case t:
pos.error('expected $name but found ${t.toString()}');
}
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), _):
TPath('tink.macro.ConstParam'.asTypePath([TPExpr(e)]));
case t: t.toComplex();
}),
}]).toType();
if (length != -1 && types.length != length)
pos.error('expected $length parameter${if (length == 1) '' else 's'}');
return getType(name, compound, pos, function (ctx) return build({
types: types,
pos: ctx.pos,
name: ctx.name,
usings: ctx.usings
}), 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 forName =
switch cache[name] {
case null: cache[name] = new Group(name);
case v: v;
}
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);
var ret = forName.get(types, pos.sanitize(), build, normalizer);
ret.getFields();// workaround for https://github.com/HaxeFoundation/haxe/issues/7905
return ret;
}
static public function getParams(name:String, ?pos:Position)
static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition, ?normalizer:Type->Type)
return _getTypeN(name, 2, switch types {
case null: null;
case v: [types.t1, types.t2];
}, pos, ctx -> build({
pos: ctx.pos,
type: ctx.types[0],
type2: ctx.types[1],
usings: ctx.usings,
name: ctx.name
}), normalizer);
static public function getParams(name:String, ?pos:Position, ?count:Int)
return
switch Context.getLocalType() {
case TInst(_.toString() == name => true, v):
@@ -131,70 +109,50 @@ class BuildCache {
});
static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition, ?normalizer:Type->Type) {
if (type == null)
type = getParam(name, pos).sure();
var forName =
switch cache[name] {
case null: cache[name] = new Group(name, normalizer);
case v: v;
}
var ret = forName.get(type, pos.sanitize(), build);
ret.getFields();// workaround for https://github.com/HaxeFoundation/haxe/issues/7905
return ret;
return _getTypeN(name, 1, switch type {
case null: null;
case v: [v];
}, pos, ctx -> build({
pos: ctx.pos,
type: ctx.types[0],
usings: ctx.usings,
name: ctx.name
}), normalizer);
}
}
private typedef Entry = {
name:String,
}
private class Group {
private class Group {//TODO: this is somewhat obsolete
var name:String;
var counter = 0;
var entries:TypeMap<Entry>;
public function new(name, ?normalizer) {
public function new(name) {
this.name = name;
this.entries = new TypeMap(normalizer);
}
public function get(type:Type, pos:Position, build:BuildContext->TypeDefinition):Type {
public function get(types:Array<Type>, pos:Position, build:BuildContextN->TypeDefinition, ?normalizer):Type {
function make(path:String) {
var usings = [];
var def = build({
pos: pos,
type: type,
usings: usings,
name: path.split('.').pop()
});
types = types.map(switch normalizer {
case null: function (t) return Context.follow(t);
case f: f;
});
entries.set(type, { name: path } );
Context.defineModule(path, [def], usings);
return Context.getType(path);
var retName = name + '_' + Context.signature(Sisyphus.exactParams(types));
return switch retName.definedType() {
case Some(v): v;
case None:
var usings = [];
var path = name.split('.');
var ret = build({
pos: pos,
types: types,
usings: usings,
name: retName.split('.').pop(),
});
Context.defineModule(retName, [ret], usings);
Context.getType(retName);
}
function doMake()
while (true)
switch '$name${counter++}' {
case _.definedType() => Some(_):
case v:
return make(v);
}
return
switch entries.get(type) {
case null:
doMake();
case v:
switch v.name.definedType() {
case Some(v): v;
default: doMake();
}
}
}
}

View File

@@ -48,11 +48,6 @@ 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

@@ -148,11 +148,7 @@ class Sisyphus {
return (
if (isMain) t.pack.concat([t.name]).join('.')
else t.module + '.' + t.name
) + switch params {
case []: '';
case params:
'<${params.map(toExactString).join(', ')}>';
}
) + exactParams(params);
}
static inline function isFinal(c:ClassField)
@@ -183,6 +179,12 @@ class Sisyphus {
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 exactParams(params:Array<Type>)
return switch params {
case []: '';
case params:
'<${params.map(toExactString).join(', ')}>';
}
static public function toExactString(t:Type)
return switch t {
case TMono(t): t.toString();

View File

@@ -1,6 +1,5 @@
package tink.macro;
import haxe.macro.Context;
import haxe.macro.Type;
import haxe.ds.Option;
using haxe.macro.Tools;
@@ -32,9 +31,6 @@ 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

@@ -14,7 +14,7 @@ import haxe.macro.Type.Ref;
class Types {
static public function definedType(typeName:String)
static public function definedType(typeName:String):Option<Type>
return
try {
Some(Context.getType(typeName));
@@ -41,10 +41,9 @@ class Types {
static public function accessToName(v:VarAccess, ?read = true)
return
switch (v) {
case AccNormal: 'default';
case AccInline: if (read) 'default' else 'never';
case AccNormal, AccInline: 'default';
case AccNo: 'null';
case AccNever #if haxe4 | AccCtor #end: 'never';
case AccNever: 'never';
case AccCall: if (read) 'get' else 'set';
default:
throw 'not implemented';

View File

@@ -16,46 +16,38 @@ 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);
@@ -65,10 +57,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(),
@@ -97,7 +89,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));