Nim Expert · Lesson 1 · On the house

Building ASTs in macros

Construct NimNodes with newTree, newCall, ident, and newLit, and walk typed arguments. Lesson 1 is free — on the house.

Lessons · Nim Expert · Lesson 1 of 10 · On the house

Building ASTs in macros

Construct NimNodes with newTree, newCall, ident, and newLit, and walk typed arguments.

Illustration for Nim
Lesson 1 is on the house.

Macros can build code node by node: newCall(ident"echo", newLit("hi")) equals echo "hi".

newTree(nnkInfix, ident"+", a, b) builds a + b; newStmtList() collects statements; result.add appends.

Iterate children with for child in node: and inspect node.kind, node.len, node[i], node.strVal, node.intVal.

typed parameters are semantically checked first, so you can call getType/getTypeImpl to read object fields.

expandMacros: or echo result.repr at the end of a macro shows the generated code while debugging.

AST building

import std/macros

macro sumLits(args: varargs[untyped]): untyped =
  result = newLit(0)
  for a in args:
    result = newTree(nnkInfix, ident"+", result, a)

macro fieldNames(T: typedesc): untyped =
  let impl = T.getTypeInst[1].getImpl
  var names = newSeq[string]()
  for def in impl[2][2]:
    for i in 0 ..< def.len - 2:
      names.add $def[i]
  newLit(names)

macro echoEach(args: varargs[untyped]): untyped =
  result = newStmtList()
  for a in args:
    result.add newCall(ident"echo", newLit(a.repr & " = "), a)

type Order = object
  id: int
  total, tax: float

echo sumLits(1, 2, 3, 4)
echo fieldNames(Order)
let x = 6
echoEach(x * 7, x div 4)
Match this when you type.

Quiz

What does newCall(ident"echo", newLit("hi")) represent?

Quiz

What does a typed macro parameter allow?

Quiz

How do you see a macro's generated code?

Quiz

What does sumLits(1, 2, 3, 4) evaluate to?

Check

Match the still for: Building ASTs in macros.

Open-book: the answers are on this page. Pass every quiz and check (5) to mark the lesson done. This visit: 0/5.