如何查看 NimNode 的内容?

huangapple go评论69阅读模式
英文:

How can I see the contents of a NimNode?

问题

我正在使用Nim编程语言,并进行一些元编程。

我想要编写一种DSL,以便生成procs。为此,我想要将一些Nim代码传递给宏(例如,一个proc定义),最终从中生成proc。

现在,我知道您可以使用以下语法在宏内捕获Nim代码:

macro generateMapper(body: untyped): untyped =
  echo body.repr


generateMapper():
  proc useThisToGenerateAProc(source: A, target: B)

这会将proc useThisToGenerateAProc(source: A, target: B)放入body,但是echo body.repr不显示任何内容。

我如何查看实际位于body或其他NimNodes中的NimNodes是什么?

英文:

I'm using the nim programming language and am doing some metaprogramming.

I want to write a DSL of some sorts that enables generating procs. For that I want to pass some nim-code into a macro (e.g. a proc definition) and eventually generate the proc from that.

Now I know you can capture nim-code inside of a macro with syntax such as this:

macro generateMapper(body: untyped): untyped =
  echo body.repr


generateMapper():
  proc useThisToGenerateAProc(source: A, target: B)

Which puts proc useThisToGenerateAProc(source: A, target: B) into body, but echo'ing body.repr doesn't show anything.

How can I see what NimNodes are actually inside body or other NimNodes in general etc.?

答案1

得分: 2

这些将在编译时为您打印出NimNode及其包含的所有内容的表示。

astGenRepr的示例:

macro generateMapper(body: untyped): untyped =
  echo body.astGenRepr

generateMapper():
  proc myMapProc(source: A, target: B): string

这会打印(带有我的注释):

nnkStmtList.newTree(           # 表示整行代码的一般“盒子”
  nnkProcDef.newTree(          # 表示整个过程定义的一般“盒子”
    newIdentNode("myMapProc"), # 过程的名称
    newEmptyNode(),
    newEmptyNode(),
    nnkFormalParams.newTree(   # 表示此过程所有参数的一般“盒子”
      newIdentNode("string"),  # 返回类型,在这种情况下是string。如果没有返回类型,则可以使用newEmptyNode()
      nnkIdentDefs.newTree(    # 表示第一个参数的一般“盒子”
        newIdentNode("source"),# 第一个参数的名称
        newIdentNode("A"),     # 第一个参数的类型
        newEmptyNode()
      ),
      nnkIdentDefs.newTree(    # 表示第二个参数的一般“盒子”
        newIdentNode("target"),# 第二个参数的名称
        newIdentNode("B"),     # 第二个参数的类型
        newEmptyNode()
      )
    ),
    newEmptyNode(),
    newEmptyNode(),
    newEmptyNode()
  )
)

与此相比,更紧凑的treeRepr

StmtList
  ProcDef
    Ident "myMapProc"
    Empty
    Empty
    FormalParams
      Ident "string"
      IdentDefs
        Ident "source"
        Ident "A"
        Empty
      IdentDefs
        Ident "target"
        Ident "B"
        Empty
    Empty
    Empty
    Empty

还有更紧凑的lisprepr

(StmtList (ProcDef (Ident "myMapProc") (Empty) (Empty) (FormalParams (Ident "string") (IdentDefs (Ident "source") (Ident "A") (Empty)) (IdentDefs (Ident "target") (Ident "B") (Empty))) (Empty) (Empty) (Empty)))
英文:

You'll want to use these procs from std/macros (in order of most verbose representation to least):

These will print you a representation at compile-time of the NimNode and everything it contains.
AstGenRepr of those 3 is the one that is closest to the code you'd actually write inside a macro where you deal with the Nodes yourself.

An example with astGenRepr:

macro generateMapper(body: untyped): untyped =
  echo body.astGenRepr

generateMapper():
  proc myMapProc(source: A, target: B): string

This prints (With comments from myself):

nnkStmtList.newTree(           # The general "box" representing the entire line of code
  nnkProcDef.newTree(          # The general "box" representing the entire proc definition
    newIdentNode("myMapProc"), # The name of the proc
    newEmptyNode(),
    newEmptyNode(),
    nnkFormalParams.newTree(   # The general "box" representing all parameters of this proc
      newIdentNode("string"),  # The return type, in this case string. Can be newEmptyNode() in case of no return type
      nnkIdentDefs.newTree(    # The general "box" representing the first parameter
        newIdentNode("source"),# Name of the first parameter
        newIdentNode("A"),     # Type of the first parameter
        newEmptyNode()
      ),
      nnkIdentDefs.newTree(    # The general "box" representing the second parameter
        newIdentNode("target"),# Name of the second parameter
        newIdentNode("B"),     # Type of the second parameter
        newEmptyNode()
      )
    ),
    newEmptyNode(),
    newEmptyNode(),
    newEmptyNode()
  )
)

Compared to that the more compact treeRepr:

StmtList
  ProcDef
    Ident "myMapProc"
    Empty
    Empty
    FormalParams
      Ident "string"
      IdentDefs
        Ident "source"
        Ident "A"
        Empty
      IdentDefs
        Ident "target"
        Ident "B"
        Empty
    Empty
    Empty
    Empty

And the even more compact lisprepr:

(StmtList (ProcDef (Ident "myMapProc") (Empty) (Empty) (FormalParams (Ident "string") (IdentDefs (Ident "source") (Ident "A") (Empty)) (IdentDefs (Ident "target") (Ident "B") (Empty))) (Empty) (Empty) (Empty)))

huangapple
  • 本文由 发表于 2023年8月5日 15:44:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76840619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定