首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将复杂参数传递给Nimrod宏

将复杂参数传递给Nimrod宏
EN

Stack Overflow用户
提问于 2013-12-18 10:21:52
回答 3查看 337关注 0票数 0

我想将配置参数传递给宏。我已经有了一个基于这些参数(序列的元组)生成一串Nimrod代码的过程。我知道我可以传递一个字符串并使用strVal进行转换(如答案https://stackoverflow.com/a/19956317/334703所示)。对于更复杂的数据,我能做同样的事情吗?

或者,我可以在编译时过程中使用这串尼姆罗德代码,并调用诸如parseStmt这样的过程。

编辑: Nimrod代码的生成对测试我的想法很有用,我同意我应该直接生成AST。

这是我正在考虑的结构的一个例子。

代码语言:javascript
复制
type
  Tconfig = tuple
    letters: seq[string]
    numbers:seq[int]

var
  data = (@("aa", "bb"), @(11, 22))

macro mymacro(data: Tconfig): stmt =
   ...
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-12-18 19:38:32

如果需要或希望遍历宏中的数据结构,那么首先需要将变量设置为constvar用于运行时,因此宏将只获得一个nnkSym节点。一旦您将其设置为const,您就会得到相同的输入,就好像您在那里手动键入了该值一样。我将使用treeRepr宏和大量的echo来向您展示您得到的是什么类型的AST,以及如何遍历它:

代码语言:javascript
复制
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)

在编译该示例时,将得到以下输出:

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2014-03-09 15:29:43

如果宏需要处理传递给它的实际常量数据,建议的方法是使用静态参数:

代码语言:javascript
复制
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)输入param cfg将在宏体中具有TConfig类型,而不是获取原始AST,因此您可以更容易地访问其成员,如示例所示。

2)编译器将自动计算生成TConfig值的复杂表达式,当它们与宏一起使用时(例如mymacro(mergeConfigs(userConfig, systemConfig)),假设mergeConfigs是在编译时可以计算的某种proc )。

有关静态参数的更多信息,请参阅手册:

http://nim-lang.org/manual.html#static-t

票数 2
EN

Stack Overflow用户

发布于 2013-12-18 12:27:46

我不能百分之百肯定您的意思,但是从上下文来看,您需要的功能似乎是macros.toStrLit的功能,它从AST生成字符串文本节点。示例:

代码语言:javascript
复制
import macros, strutils

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

showExpr("x" & "y")

但是,可以考虑直接转换AST,因为将代码作为字符串生成和重新构造可能会导致引用(请注意上面的.escape )、缩进等方面的意外。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20655443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档