Skip to content

Instantly share code, notes, and snippets.

@dpeek
Last active May 3, 2019 19:30
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save dpeek/7476625 to your computer and use it in GitHub Desktop.
Save dpeek/7476625 to your computer and use it in GitHub Desktop.
import haxe.macro.Expr;
class FTW
{
public static function build()
{
return haxe.macro.Context.getBuildFields().map(transformField);
}
static function transformField(field:Field)
{
switch (field.kind)
{
case FFun(f): transformExpr(f.expr);
default:
}
return field;
}
static function transformExpr(expr:Expr) switch (expr)
{
case macro @for($init, $cond, $incr) $block:
transformExpr(block);
expr.expr = makeLoop(init, cond, incr, block).expr;
default:
haxe.macro.ExprTools.iter(expr, transformExpr);
}
static function makeLoop(init:Expr, cond:Expr, incr:Expr, block:Expr) return macro
{
$init;
while ($cond)
{
$block;
$incr;
}
}
}
@:build(FTW.build())
class Main
{
static function main()
{
@for(var i = 0, i < 10, i++)
{
trace('ftw: $i');
}
}
}
@dpeek
Copy link
Author

dpeek commented Nov 20, 2013

@YellowAfterlife we could add a helper that allowed you to do: --macro FTW.build('package.name')

@bamtang-dev
Copy link

One question in the line: macro @for($init , $cond , $incr) $block:
is there some way to tell Haxe to accept: @for($init EConst(';') $cond EConst(';') $incr) $block:

@player-03
Copy link

Possible workaround allowing both continue and break:

static function makeLoop(init:Expr, cond:Expr, incr:Expr, block:Expr) return macro
{
    $init;
    if ($cond)
    {
        do
        {
            $block;
        } while ({ $incr; $cond; });
    }
}

(Untested.)

@player-03
Copy link

@YellowAfterlife
Copy link

player-03: Your version combines duplicating code (slightly larger output size) with creating anonymous functions (or even whole classes, if it's C#/Java) on most targets. It's an arguable advancement. Example: http://try.haxe.org/#7F556

@player-03
Copy link

A year and a half later, I finally noticed your comment. Sorry for the late response!

Anyway, I figured out that you meant to include a continue statement in your example, because that's what causes duplicate code. (Or maybe you did include one and try.haxe.org didn't save it. Or maybe Haxe improved over the past 1.5 years, and now it optimizes your example better.)

Whichever it was, I've fixed the issue. My code checks for the existence of continue and break statements, and uses the simplest possible loop. Even in the most complicated case, the only code that gets duplicated is "shouldBreak = false," not any anonymous functions or classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment