diff --git a/src/tink/macro/Bouncer.hx b/src/tink/macro/Bouncer.hx
index 10aa59b..99a20ba 100644
--- a/src/tink/macro/Bouncer.hx
+++ b/src/tink/macro/Bouncer.hx
@@ -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):Bouncer
+ @:noUsing static public function makeOuter(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);
}
\ No newline at end of file
diff --git a/src/tink/macro/Exprs.hx b/src/tink/macro/Exprs.hx
index b7ea55e..480bdc5 100644
--- a/src/tink/macro/Exprs.hx
+++ b/src/tink/macro/Exprs.hx
@@ -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, ?skipFields = false, ?callPos:PosInfos) {
if (nuPos == null)
nuPos = Context.currentPos();
diff --git a/src/tink/macro/TypedExprs.hx b/src/tink/macro/TypedExprs.hx
index 88bced6..4e3db6d 100644
--- a/src/tink/macro/TypedExprs.hx
+++ b/src/tink/macro/TypedExprs.hx
@@ -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;
diff --git a/tests/Exprs.hx b/tests/Exprs.hx
index 8cf88b4..f74abd3 100644
--- a/tests/Exprs.hx
+++ b/tests/Exprs.hx
@@ -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 = 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));