构建你的第一个宏
为了给写宏一个开始,我们展示如何实现之前提到的 myDebug 宏。 首先要构建一个宏使用的示例,接着打印实参。这可以看出一个正确的实参是什么样子。
- import macros
- macro myAssert(arg: untyped): untyped =
- echo arg.treeRepr
- let a = 1
- let b = 2
- myAssert(a != b)
- Infix
- Ident "!="
- Ident "a"
- Ident "b"
从输出可以看出实参信息是一个中缀操作符(节点类型是"Infix"), 两个操作数在索引1和2的位置。用这个信息可以写真正的宏。
- import macros
- macro myAssert(arg: untyped): untyped =
- # 所有节点类型标识符用前缀 "nnk"
- arg.expectKind nnkInfix
- arg.expectLen 3
- # 操作符作字符串字面值
- let op = newLit(" " & arg[0].repr & " ")
- let lhs = arg[1]
- let rhs = arg[2]
- result = quote do:
- if not `arg`:
- raise newException(AssertionError,$`lhs` & `op` & $`rhs`)
- let a = 1
- let b = 2
- myAssert(a != b)
- myAssert(a == b)
这是即将生成的代码。 调试生成的宏可以在宏最后一行用 echo result.repr 语句。它也是用于获取此输出的语句。
- if not (a != b):
- raise newException(AssertionError, $a & " != " & $b)