Compile-time macros

mu includes a compile-time macro system that rewrites the AST before bytecode is emitted. Macros are defined in mu, so you can extend the language without inflating the host runtime.

Define a macro

import "macro"

macro.define("identity", fn(call, value) {
  return value
})

Example: log + assert

import "macro"
import "ast"

macro.define("log", fn(_, value) {
  printlnCall := ast.callExpression(ast.identifier("println"), [
    ast.stringLiteral("[macro log]"),
    value,
  ])

  body := ast.blockStatement([
    ast.expressionStatement(printlnCall),
    ast.expressionStatement(value),
  ])

  fnLiteral := ast.functionLiteral([ast.identifier("__macro_value")], false, body)
  return ast.callExpression(fnLiteral, [value])
})

How it works

Read more in docs/Macros.md and docs/MacroTutorial.md.

Next steps