nim 宏中的标识符构造(而不是模板)

问题描述 投票:0回答:1

在 nim 中,如果我正在编写宏,如何从参数显式构造名称。具体来说,在 nim 手册中(参见here),我们有以下“标识符构造”的示例

template typedef(name: untyped, typ: typedesc) =
  type
    `T name`* {.inject.} = typ
    `P name`* {.inject.} = ref `T name`

typedef(myint, int)
var x: PMyInt

如果我希望 typedef 成为宏而不是模板,我怎样才能完成同样的事情?

macros nim-lang
1个回答
0
投票

任何模板都可以简单地成为宏。这里:

template typedef(name: untyped, typ: typedesc) =
  type
    `T name`* {.inject.} = typ
    `P name`* {.inject.} = ref `T name`

typedef(myint, int)
var x: PMyInt

import macros
import std/genasts
macro typedef2(name:untyped, typ:typedesc) =
  result = genast(name,typ):
    type
      `T name`* {.inject.} = typ
      `P name`* {.inject.} = ref `T name`

typedef2(yourint, int)
var y: PYourInt

x = new int
x[] = 3
y = x
assert (y[] == 3)

但这没有帮助。

如果您发现自己需要从模板升级到宏观领域,那是因为您需要直接操作 ast。所以你要做的第一件事就是弄清楚你想要的输出的 ast 是多少:

import macros
dumpTree: # dumpAstGen is also helpful
  type
    TMytype* = int
    PMytype* = ref TMytype
  TypeSection
    TypeDef
      Postfix
        Ident "*"
        Ident "Tmyname"
      Empty
      Ident "int"
    TypeDef
      Postfix
        Ident "*"
        Ident "Pmyname"
      Empty
      RefTy
        Ident "Tmyname"

dumpAstGen
将输出您需要放入宏中的确切代码,但视觉上不太清晰,所以我使用
dumpTree

现在我们创建一个宏来构造精确的 as:

macro typedef3(name: untyped, typ: typedesc) =
  result = nnkTypeSection.newNimNode()
  result.add nnkTypeDef.newTree(
    nnkPostfix.newTree(
      ident"*",
      ident "T" & name.strVal),
    newEmptyNode(),
    typ)

  result.add nnkTypeDef.newTree(
    nnkPostfix.newTree(
      ident"*",
      ident "P" & name.strVal),
    newEmptyNode(),
    nnkRefTy.newTree(typ))

  #echo result.treerepr

typedef3(yourtype, float)

最后我们回显我们刚刚制作的 ast,以便我们可以将其与我们的预期进行比较

这里是

echo result.repr
只是为了清楚起见:

type
  Tyourtype* = float
  Pyourtype* = ref float
© www.soinside.com 2019 - 2024. All rights reserved.