# Chapter 33. AST introspection The mapping from Nim’s syntax to syntax trees is rather subtle. While the syntax is optimized for readability and conciseness the syntax trees are designed for ease of construction and traversal. Like in Lisp the tree consists of nested nodes where each node is of a certain "kind" such as "if statement" (nnkIfStmt) or "routine call" (nnkCall). The mapping can easily be seen with treeRepr: import std / macros macro investigate(body: untyped) = 1 echo treeRepr body 2 investigate: if undeclaredIdentifier == 3: echo "3" else: echo "not 3" 1 Declares a macro called investigate that works on untyped trees. 2 Calls treeRepr which produces a debug string of body. Because macro expansion happens at compile time this program produces at compile time: 229 StmtList IfStmt ElifBranch Infix Ident "==" Ident "undeclaredIdentifier" IntLit 3 StmtList Command Ident "echo" StrLit "3" Else StmtList Command Ident "echo" StrLit "not 3" We can see that a list of statements StmtList is passed to investigate. In order to create a StmtList one can use newTree(nnkStmtList, ). 33.1. Typed vs untyped ASTs The difference between typed and unytyped parameters is important for templates and it is even more important for macros. The AST that is passed to a typed macro parameter can differ significantly from an AST that is passed to an untyped macro parameter. For example: import std / macros macro investigateTyped(body: typed) = echo treeRepr body var needsToBeDeclaredIdentifier = 0 investigateTyped: if needsToBeDeclaredIdentifier == 3: echo "3" else: echo "not 3" This program produces at compile time: 230 StmtList IfStmt ElifBranch Infix Sym "==" Sym "needsToBeDeclaredIdentifier" IntLit 3 Command Sym "echo" HiddenStdConv Empty Bracket StrLit "3" Else Command Sym "echo" HiddenStdConv Empty Bracket StrLit "not 3" Note how symbol lookups happened producing nnkSym nodes and the echo calls have mysterious hidden conversion nodes containing an nnkBracket node. In other words, echo "3" was transformed into echo ["3"] because echo uses a varargs parameter. Many details like these have to be understood before one can write a macro operating on typed ASTs. For this reason most of the following examples operate on untyped ASTs.