Calendar

July 2016
Mo Tu We Th Fr Sa Su
<< >>
123
45678910
11121314151617
18192021222324
25262728293031

Langs

Reification for Macros

Posted on Jun 17 2012

In case you don't know, Haxe has a power macro system which allows you to do a lot of compile-time checking and code generation. It's a really neat feature that enable you to extend the language in many different ways while still keeping the same syntax and being strictly typed.

But up to now it was quite difficult to write macros, since you had to construct the AST (which is the piece of Haxe code you want to generate) by-hand with enums. For instance let's say you want to generate a String "Hello World", you would have to write :

@:macro static function hello() {
    var pos = haxe.macro.Context.currentPosition();
    return { expr : EConst(CString("Hello World")), pos : pos };
}

And for a more complex for( x in 0...n ) loop :

// repeat the expression 'e' for 'n' times
@:macro static function repeat( e : Expr, n : Int ) {
    var pos = haxe.macro.Context.currentPosition();
    // 0...n
    var ezero = { expr : EConst(CInt(0)), pos : pos };
    var eN = { expr : EConst(CInt(n)), pos : pos };
    var iter = { expr : EBinop(OpInterval,ezero,eN), pos : pos };
    // x in n
    var ein = { expr : EIn({ expr : EConst(CIdent("x")), pos : pos },iter), pos : pos };
    return { expr : EFor(ein,e), pos : pos };
}

This looks quite hard to read, and while you can construct the whole language expressions this way, the more complex it become, the longer it takes.

Until today.

On SVN we have just added a new macro special word that will greatly simplify the task of writing macro, let's look at how the two previous examples are translated :

@:macro static function hello() {
    return macro "Hello World";
}
@:macro static function repeat( e : Expr, eN : Expr ) {
    return macro for( x in 0...$eN ) $e;
}

What macro does is to translate a Haxe expression into the corresponding AST enum, by also replacing all $-prefixed identifiers by the corresponding variable value.

I guess this way will make Haxe macros much more easy to write and maintain !

PS : we will make a 2.10 release of Haxe very soon, since we have many great things to share. This will be part of it.

12 comments
  • Jun 18, 2012 at 00:02

    Yes!

    This looks much easier :)

    I still need to get into the basics of Haxe macros. Up until now it has felt like a "dark art" that only a few understand, but I'm sure there are ways it could come in handy!

    I'm just keeping my eye out for the WWX presentations, so I can catch the HXCPP and Macro presentations I missed.

    Thanks!

  • EzeQL
    Jun 18, 2012 at 02:10

    Great. Much easier. No more eval playing.

  • Jason O'Neil
    Jun 18, 2012 at 03:41

    Looks so simple. Up until now I've only been able to do the most basic of macros, but hopefully with this I can attempt a whole lot more. Very powerful tool now a whole lot easier to use. Thanks very much!

    Jason

  • ex
    Jun 18, 2012 at 19:32

    This is pretty cool!
    I was doing some simple macros with a lot of pain before...
    What is the possible timeline for this to go mainstream and in Haxe NME?

  • Rytis
    Jun 19, 2012 at 12:26

    Sorry but those macros makes HaXe code unreadable. Best example is the great physics engine Nape that is full of macros. perhaps t is usefull only when you work alone.

  • Rytis
    Jun 19, 2012 at 12:28

    Ha, I just read in documentation that macros purpose is to make code unreadable... :)

  • Cauê Waneck
    Jun 19, 2012 at 17:42

    Rytis, actually Nape doesn't use Haxe macros. It uses its own preprocessor called CaXe; Haxe macros aren't like that.

  • Jun 19, 2012 at 21:44

    @ex : in 2.10, very soon

  • peterPh
    Jul 01, 2012 at 23:44

    hi

    i don't understand your for loop example...

    @:macro static function repeat( e : Expr, eN : Expr ) {
    return macro for( x in 0...$eN ) $e;
    }

    if i compile repeat(i++, 5)

    is $e expression repeated like this
    I++;I++;I++;I++;I++;

    or like this
    for( x in 0...5 ) i++;

    and in this case. how to make the fist result with this new keyword ?
    What is the scope of the keyword, macro scoped, apply only to the next exp ? can we use parenthesis ?

  • Rammserker
    Jul 12, 2012 at 19:22

    @peterPh: The second option

  • Ptg
    Jul 13, 2012 at 17:18

    So how would one use this with @:build and @:autoBuild type generators?

  • peterPh
    Aug 04, 2012 at 19:43

    @Rammserker thanks, i did some investigation since.

    not really happy with the syntax.. macro keyword for reification is stange. but it's a really good feature ! macro for everyone now !

    will prefer instead... (like string interpolation)

    return ${  for( x in 0...$eN ) $e; };  

Name : Email : Website : Message :