我想将配置参数传递给宏。我已经有一个基于这些参数(一个序列元组)产生一串Nimrod代码的过程。 我知道我可以传递一个字符串并将其转换为strVal(如答案https://stackoverflow.com/a/19956317/334703所示)。我可以用更复杂的数据做同样的事吗?
或者,我可以在编译时程序中使用此字符串的Nimrod代码,并调用parseStmt等过程吗?
编辑: Nimrod代码的生成对于测试我的想法很有用,我同意我应该直接生成AST。
以下是我正在考虑的结构示例。
type
Tconfig = tuple
letters: seq[string]
numbers:seq[int]
var
data = (@("aa", "bb"), @(11, 22))
macro mymacro(data: Tconfig): stmt =
...
答案 0 :(得分:2)
如果你的宏需要处理传递给它的实际常量数据,推荐的方法是使用静态参数:
type
TConfig = tuple
letters: seq[string]
numbers:seq[int]
const data = (@["aa", "bb"], @[11, 22])
macro mymacro(cfg: static[TConfig]): stmt =
echo "letters"
for s in cfg.letters:
echo s
echo "numbers"
for n in cfg.numbers:
echo n
mymacro(data)
这种方法有很多好处:
1)输入参数cfg
不是获取原始AST,而是在宏体内部具有TConfig
类型,因此您可以更轻松地访问其成员,如示例所示。
2)编译器将自动评估产生TConfig
值的复杂表达式,当它们与宏一起使用时(例如mymacro(mergeConfigs(userConfig, systemConfig))
,假设mergeConfigs
是一些可以评估的proc在编译时。)
有关静态参数的更多信息,请参阅手册:
http://nim-lang.org/manual.html#static-t
答案 1 :(得分:1)
我不是100%肯定你的意思,但从上下文来看,你看起来好像你需要的功能是macros.toStrLit
,它从AST生成一个字符串文字节点。例如:
import macros, strutils
macro showExpr(x: expr): stmt =
parseStmt("echo(" & x.toStrLit.strVal.escape & ")")
showExpr("x" & "y")
考虑直接转换AST,因为生成和重新分析代码作为字符串可能会引发意外(请注意上面的.escape
),缩进等。
答案 2 :(得分:1)
如果您需要或想要遍历宏中数据的结构,首先需要将变量设为const
。 var
用于运行时,因此宏将获得nnkSym
节点。一旦你创建了const
,就会获得相同的输入,就像你在那里手动输入值一样。我将使用treeRepr
宏和大量echo
来向您展示您获得的AST类型以及如何使用它:
import macros
type
Tconfig = tuple
letters: seq[string]
numbers:seq[int]
const data: Tconfig = (@["aa", "bb"], @[11, 22])
macro mymacro(data: Tconfig): stmt =
echo "AST being passed in:\n", treeRepr(data)
echo "root type is ", data.kind
echo "number of children ", len(data)
let n1 = data[0]
echo "first child is ", n1.kind
echo "first child children ", len(n1)
let e2 = n1[1]
echo "second exp child is ", e2.kind
echo "second exp child children ", len(e2)
let v1 = e2[0]
echo "first seq value is ", v1.kind
echo "first seq value children ", len(v1)
echo "Final literal is ", v1.strVal
when isMainModule:
mymacro(data)
当我编译该示例时,我得到以下输出:
AST being passed in:
Par
ExprColonExpr
Sym "letters"
Bracket
StrLit aa
StrLit bb
ExprColonExpr
Sym "numbers"
Bracket
IntLit 11
IntLit 22
root type is nnkPar
number of children 2
first child is nnkExprColonExpr
first child children 2
second exp child is nnkBracket
second exp child children 2
first seq value is nnkStrLit
first seq value children 0
Final literal is aa