0

我想将配置参数传递给宏。我已经有一个基于这些参数(序列元组)生成一串 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 =
   ...
4

3 回答 3

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)

这种方法有很多好处:

cfg1) 输入参数将TConfig在宏体内具有类型,而不是获取原始 AST,因此您可以更轻松地访问其成员,如示例所示。

2) 编译器将自动评估产生TConfig值的复杂表达式,当它们与宏一起使用时(例如mymacro(mergeConfigs(userConfig, systemConfig)),假设这mergeConfigs是一些可以在编译时评估的过程)。

有关静态参数的更多信息,请参阅手册: http:
//nim-lang.org/manual.html#static-t

于 2014-03-09T15:29:43.903 回答
1

我不是 100% 确定您的意思,但从上下文来看,您需要的功能似乎是macros.toStrLit,它从 AST 生成字符串文字节点。例子:

import macros, strutils

macro showExpr(x: expr): stmt =
  parseStmt("echo(" & x.toStrLit.strVal.escape & ")")

showExpr("x" & "y")

不过,请考虑直接转换 AST,因为将代码生成和重新解析为字符串可能会导致引用(注意.escape上述内容)、缩进等意外。

于 2013-12-18T12:27:46.237 回答
1

如果需要或想要遍历宏中数据的结构,首先需要将变量 a constvar用于运行时,所以宏只会得到一个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
于 2013-12-18T19:38:32.837 回答