debug 示例

下面的例子实现了一个接受可变参数的 debug 命令,功能强大:

  1. # 导入 `macros` 模块以获得操作 Nim 语法树所需要的 API
  2. import std/macros
  3. macro debug(args: varargs[untyped]): untyped =
  4. # `args` 是一个 `NimNode` 值列表,每个值对应一个传入参数的 AST
  5. # 宏总是需要返回一个 `NimNode`,本例子返回的是 `nnkStmtList` 节点
  6. result = nnkStmtList.newTree()
  7. # 遍历传入这个宏传递的所有参数:
  8. for n in args:
  9. # 为语句列表添加 write 调用;
  10. # `toStrLit` 将 AST 转换为字符串形式:
  11. result.add newCall("write", newIdentNode("stdout"), newLit(n.repr))
  12. # 为语句列表添加 write 调用,输出 ": "
  13. result.add newCall("write", newIdentNode("stdout"), newLit(": "))
  14. # 为语句列表添加 writeLine 调用,输出值并换行:
  15. result.add newCall("writeLine", newIdentNode("stdout"), n)
  16. var
  17. a: array[0..10, int]
  18. x = "some string"
  19. a[0] = 42
  20. a[1] = 45
  21. debug(a[0], a[1], x)

这个宏展开为以下代码:

  1. write(stdout, "a[0]")
  2. write(stdout, ": ")
  3. writeLine(stdout, a[0])
  4. write(stdout, "a[1]")
  5. write(stdout, ": ")
  6. writeLine(stdout, a[1])
  7. write(stdout, "x")
  8. write(stdout, ": ")
  9. writeLine(stdout, x)

传递给 varargs 的各参数被包装到数组构造函数表达式中。这就是 debug 能遍历所有 args 子节点的原因。