Source Edit

This module implements AST generation using captured variables for macros.

Imports

macros

Types

  1. GenAstOpt = enum
  2. kDirtyTemplate, kNoNewLit

Source Edit

Macros

  1. macro genAstOpt(options: static set[GenAstOpt]; args: varargs[untyped]): untyped

Accepts a list of captured variables a=b or a and a block and returns the AST that represents it. Local {.inject.} symbols (e.g. procs) are captured unless kDirtyTemplate in options.

Example:

  1. # This example shows how one could write a simplified version of `unittest.check`.
  2. import std/[macros, strutils]
  3. macro check2(cond: bool): untyped =
  4. assert cond.kind == nnkInfix, "$# not implemented" % $cond.kind
  5. result = genAst(cond, s = repr(cond), lhs = cond[1], rhs = cond[2]):
  6. # each local symbol we access must be explicitly captured
  7. if not cond:
  8. doAssert false, "'$#'' failed: lhs: '$#', rhs: '$#'" % [s, $lhs, $rhs]
  9. let a = 3
  10. check2 a*2 == a+3
  11. if false: check2 a*2 < a+1 # would error with: 'a * 2 < a + 1'' failed: lhs: '6', rhs: '4'

Example:

  1. # This example goes in more details about the capture semantics.
  2. macro fun(a: string, b: static bool): untyped =
  3. let c = 'z'
  4. var d = 11 # implicitly {.gensym.} and needs to be captured for use in `genAst`.
  5. proc localFun(): auto = 12 # implicitly {.inject.}, doesn't need to be captured.
  6. genAst(a, b, c = true):
  7. # `a`, `b` are captured explicitly, `c` is a local definition masking `c = 'z'`.
  8. const b2 = b # macro static param `b` is forwarded here as a static param.
  9. # `echo d` would give: `var not init` because `d` is not captured.
  10. (a & a, b, c, localFun()) # localFun can be called without capture.
  11. assert fun("ab", false) == ("abab", false, true, 12)

Source Edit

Templates

  1. template genAst(args: varargs[untyped]): untyped

Convenience wrapper around genAstOpt. Source Edit