Skip to content
Draft

V1 #53

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ jobs:
haxe-version:
- stable
- nightly
target:
target:
- interp
- interp -D function_sugar
- interp -D deprecated_function_sugar
- neko
- node
- python
Expand All @@ -26,7 +28,7 @@ jobs:
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)"
Expand All @@ -38,34 +40,34 @@ jobs:
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-

- name: Cache Haxe
uses: actions/cache@v1
with:
path: ${{ startsWith(runner.os, 'windows') && '%AppData%' || '~/haxe' }}
key: ${{ runner.os }}-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)"
Expand All @@ -77,24 +79,23 @@ jobs:
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-

- name: Cache Haxe
uses: actions/cache@v1
with:
path: ${{ startsWith(runner.os, 'windows') && '%AppData%' || '~/haxe' }}
key: ${{ runner.os }}-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 }}

2 changes: 1 addition & 1 deletion .haxerc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version": "4.2.0",
"version": "4.3.6",
"resolveLibs": "scoped"
}
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ hxx('

## Implicit function syntax

For attributes that are functions with 0 or 1 argument, you may write the function body directly:
With `using tink.hxx.FunctionSugar;` (which can be placed in [`import.hx`](https://haxe.org/manual/type-system-import-defaults.html)), for attributes that are functions with 0 or 1 argument, you may write the function body directly:

```haxe
hxx('
Expand All @@ -514,6 +514,14 @@ hxx('

Note that if there's exactly one argument, it will be called "event".

Up until version 0.25 this has been a standard feature, but it has been relegated to an opt-in (via `using`) for a few reasons:

1. some users - especially new comers - consider it confusing rather than convenient (that is left for you to judge)
2. it's hard to implement in a way that works well with IDE services (this may change in the future though)
3. it makes code harder to port to JSX, should the need arise

If you have exisiting code relying on this feature but wish to migrate away from it, you may use `using tink.hxx.DeprecatedFunctionSyntax;` instead, which will also activate the feature, but produces warnings anywhere it is used.

## Whitespace

The treatment of whitespace depends on whether the generated structure even has any notion of whitespace or not. The default HXX flavor uses the JSX style whitespace explained below.
Expand Down Expand Up @@ -548,7 +556,7 @@ Example:

```

The first version will retain the white space between the two spans, the second one will not.
The first version will retain the white space between the two spans, the second one will not.

To enforce a whitspace, `${' '}` can be used, e.g.:

Expand Down
4 changes: 2 additions & 2 deletions haxe_libraries/tink_anon.hxml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @install: lix --silent download "gh://github.com/haxetink/tink_anon#ef441a73a41f9ae4ca0f060035ff2c188618df4c" into tink_anon/0.7.0/github/ef441a73a41f9ae4ca0f060035ff2c188618df4c
# @install: lix --silent download "gh://github.com/haxetink/tink_anon#0277e6e3f97a7878f1aa9aeeccc4b7be0e9c82bc" into tink_anon/0.7.0/github/0277e6e3f97a7878f1aa9aeeccc4b7be0e9c82bc
-lib tink_macro
-cp ${HAXE_LIBCACHE}/tink_anon/0.7.0/github/ef441a73a41f9ae4ca0f060035ff2c188618df4c/src
-cp ${HAXE_LIBCACHE}/tink_anon/0.7.0/github/0277e6e3f97a7878f1aa9aeeccc4b7be0e9c82bc/src
-D tink_anon=0.7.0
4 changes: 2 additions & 2 deletions haxe_libraries/tink_core.hxml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# @install: lix --silent download "gh://github.com/haxetink/tink_core#d74b0e03d7f9efcf2c2b73fecd99d240dd6d57ff" into tink_core/2.0.2/github/d74b0e03d7f9efcf2c2b73fecd99d240dd6d57ff
-cp ${HAXE_LIBCACHE}/tink_core/2.0.2/github/d74b0e03d7f9efcf2c2b73fecd99d240dd6d57ff/src
# @install: lix --silent download "gh://github.com/haxetink/tink_core#f500203b657859bfde36c49e54f95a0b1fc2b165" into tink_core/2.0.2/github/f500203b657859bfde36c49e54f95a0b1fc2b165
-cp ${HAXE_LIBCACHE}/tink_core/2.0.2/github/f500203b657859bfde36c49e54f95a0b1fc2b165/src
-D tink_core=2.0.2
3 changes: 3 additions & 0 deletions src/tink/hxx/DeprecatedFunctionSugar.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package tink.hxx;

extern class DeprecatedFunctionSugar {}
5 changes: 5 additions & 0 deletions src/tink/hxx/Expression.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package tink.hxx;

@:callable @:transitive
abstract Expression<T>(()->T) from ()->T to ()->T {
}
3 changes: 3 additions & 0 deletions src/tink/hxx/FunctionSugar.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package tink.hxx;

extern class FunctionSugar {}
119 changes: 42 additions & 77 deletions src/tink/hxx/Generator.hx
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@ class Generator {
dynamic function adjustFormattingPos(pos:Position)
return pos;

public var defaults(default, null):Lazy<Array<Named<Position->Tag>>>;

public function new(?defaults) {
this.defaults = switch defaults {
case null: [];
case v: v;
}

public function new() {
var shift = {
var pos = (macro null).pos;
Context.getPosInfos(('foo'.formatString(pos):Expr).pos).min - Context.getPosInfos(pos).min;
Expand All @@ -51,9 +44,10 @@ class Generator {
}

function tag(n:Node, tag:Tag, pos:Position) {
var paramatrized = tag.parametrized();

var aliases = tag.args.aliases,
children = tag.args.children,
children:Type = paramatrized.children,//tag.args.children,
fields = tag.args.fields,
fieldsType = tag.args.fieldsType,
childrenAttribute = tag.args.childrenAttribute;
Expand Down Expand Up @@ -129,7 +123,7 @@ class Generator {
case l:

function get()
return applyCustomRules(tag.args.children, this.childList.bind(l, _));
return applyCustomRules(children, this.childList.bind(l, _));

switch childrenAttribute {
case null:
Expand All @@ -151,7 +145,6 @@ class Generator {

args.unshift(
compute(function () {
var paramatrized = tag.parametrized();
var attrType = paramatrized.fieldsType;

return mergeParts(
Expand All @@ -178,6 +171,13 @@ class Generator {
},
duplicateField: function (name) return 'duplicate attribute $name',
missingField: function (f) return 'missing attribute ${f.name}',//TODO: might be nice to put type here
},
(owner, field) -> {
var e = owner.field(field.name, owner.pos);
switch field.type.get() {
case None: e;
case Some(t): applyCustomRules(t, _ -> e);
}
}
);
})
Expand All @@ -189,8 +189,8 @@ class Generator {
return invoke({ value: tag.realPath, pos: tagName.pos }, tag.create, args, tagName.pos);
}

function later(fn:Void->Expr)
return withTags.bind(localTags, fn).bounce();
inline function later(fn:Void->Expr)
return fn.bounce();

function makePart(name:StringAt, value:Expr, ?quotes):Part
return {
Expand All @@ -213,16 +213,14 @@ class Generator {
}
};

function applyCustomRules(t, getValue:Type->Expr) {
var transform = getTransform(t);
t = transform.reduced.or(t);
var e = getValue(t);
return switch transform.postprocessor {
case PTyped(f): f.bind(e).bounce();
case PUntyped(f): f(e);
default: e;
function applyCustomRules(t:Type, getValue:Type->Expr)
return switch t.reduce() {
case TAbstract(_.toString() => 'tink.hxx.Expression', [t]):
var ret = applyCustomRules(t, getValue);
ret = macro @:pos(ret.pos) function () return $ret;
default:
getTransform(t)(getValue(t));
}
}

function invoke(name:StringAt, create:TagCreate, args:Array<Expr>, pos:Position)
return
Expand Down Expand Up @@ -251,7 +249,6 @@ class Generator {
return !Context.unify(Context.getType('Array'), t.reduce());

function complexAttribute(n:Node):Part {
var localTags = localTags;
return {
name: n.name.value,
pos: n.name.pos,
Expand Down Expand Up @@ -298,32 +295,11 @@ class Generator {
return this.childList(n.children, ret);

var body =
if (splat) {
var tags = switch requiredArgs[0].t.getFields() {
case Success(fields):
var ret =
#if haxe4
localTags.copy();
#else
[for (t in localTags.keys()) t => localTags[t]];
#end

for (c in fields)
ret[c.name] = Tag.declaration.bind(c.name, _, c.type, c.params);

ret;
default:
localTags;
}

if (splat)
macro @:pos(n.name.pos) {
tink.Anon.splat(__data__);
return ${
if (tags != localTags) withTags(tags, getBody)
else later(withTags.bind(tags, getBody))
};
return ${later(getBody)};
}
}
else getBody();
body.func(args).asExpr();
default:
Expand Down Expand Up @@ -352,6 +328,7 @@ class Generator {
throw 'assert';
}
}
else if (c == null || c.value.length == 0) macro ([]:$ct);
else macro {
var __r = [];
if (false) (__r:$ct);
Expand Down Expand Up @@ -501,42 +478,30 @@ class Generator {
}

function node(n, pos)
return tag(n, getTag(n.name), pos);

function getTag(name:StringAt):Tag
return Tag.resolve(localTags, name).sure();

var localTags:Map<String, Position->Tag>;
return tag(n, Tag.resolve(n.name), pos);

var postProcess:Expr->Expr = function (e) return e;

function withTags<T>(tags, f:Void->T) {
#if tink_syntaxhub var lastFn = postProcess; #end

var last = localTags;
return tink.core.Error.tryFinally(
function () {
localTags = tags;
#if tink_syntaxhub
postProcess = switch tink.SyntaxHub.exprLevel.appliedTo(new ClassBuilder()) {
case Some(f): f;
case None: function (e) return e;
}
#end
return f();
},
function () {
localTags = last;
#if tink_syntaxhub postProcess = lastFn; #end
}
);
}

public function createContext():GeneratorContext {
var tags = Tag.getAllInScope(defaults);
return {
isVoid: function (name) return Tag.resolve(tags, name).match(Success({ isVoid: true })),
generateRoot: function (root:Children) return withTags(tags, function () return children(root)),
isVoid: function (name) return false,
generateRoot: function (root:Children) {
#if tink_syntaxhub
var lastFn = postProcess;
return tink.core.Error.tryFinally(
function () {
postProcess = switch tink.SyntaxHub.exprLevel.appliedTo(new ClassBuilder()) {
case Some(f): f;
case None: function (e) return e;
}
return children(root);
},
function () postProcess = lastFn
);
#else
return children(root);
#end
}
}
}

Expand Down
Loading
Loading