Haxe Code Cookbook
Haxe programming cookbookMacrosGenerating code in a macro

Generating code in a macro

This example shows:

  • How Haxe code can be generated by using either the Context.parse() API or the macro keyword for expression reification.
  • The difference between code that's executed at compile time (calculating the buildTime timestamp in the macro function) and code that's executed at run time (calculating the runTime timestamp in expressions returned from the macro.)
  • How generated code is inlined in place of a macro function call.
import haxe.macro.Context;
class Test {
  public static function main() {
    // The expressions returned form the macros are injected here in main()
    trace_build_age_with_parse();
    trace_build_age_with_reification();
  }

  // This macro generates code using Context.parse()
  public static macro function trace_build_age_with_parse() {
    var buildTime = Math.floor(Date.now().getTime() / 1000);

    var code = '{
      var runTime = Math.floor(Date.now().getTime() / 1000);
      var age = runTime - $buildTime;
      trace("Right now it\'s "+runTime+", and this build is "+age+" seconds old");
    }';

    return Context.parse(code, Context.currentPos());
  }

  // This macro generates the same code using the macro keyword (expressions reification)
  public static macro function trace_build_age_with_reification() {
    var buildTime = Math.floor(Date.now().getTime() / 1000);

    var e = macro {
      var runTime = Math.floor(Date.now().getTime() / 1000);
      var age = runTime - $v{ buildTime };
      trace("Right now it's "+runTime+", and this build is "+age+" seconds old");
    };

    return e;
  }
}

Usage

Compile this example to Neko with:

haxe -main Test -neko test.n

Run the program with neko test.n and observe the output:

Test.hx:6: Right now it's 1466034708, and this build is 3 seconds old
Test.hx:32: Right now it's 1466034708, and this build is 3 seconds old

Wait a few seconds and run it again:

Test.hx:6: Right now it's 1466034711, and this build is 6 seconds old
Test.hx:32: Right now it's 1466034711, and this build is 6 seconds old

Also, you can compile it to JavaScript and observe how the expressions the macro returned are indeed inlined directly in the main() function. The buildTime timestamp is now simply a literal:

Test.main = function() {
  var runTime = Math.floor(new Date().getTime() / 1000);
  var age = runTime - 1466034832;
  console.log("Right now it's " + runTime + ", and this build is " + age + " seconds old");
  var runTime1 = Math.floor(new Date().getTime() / 1000);
  var age1 = runTime1 - 1466034832;
  console.log("Right now it's " + runTime1 + ", and this build is " + age1 + " seconds old");
};

Contributors:
Last modified:
Created:
Category:  Macros