使用 nnkDotExpr 在 Nim 中创建 ident

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

我尝试在宏中使用 nnkDotExpr 并收到错误。具体来说,我正在尝试编写一个宏,它将编写一个返回特定字段的过程。我尝试了三种方法,但似乎都失败了,我不知道为什么。

这是我的代码。

import macros 

type
    Test_Type = object of RootObj
        Name_HIDDEN: string

macro Name_MacroA*(vType: untyped): untyped =
    var tName = nnkDotExpr(ident("self"), ident("Name_HIDDEN"))
    
    quote do:
        proc Name*(self: var `vType`): string =
            return `tName`

macro Name_MacroB*(vType: untyped): untyped =
    var tName = newNimNode(nnkDotExpr)
    tName.add(ident("self"))
    tName.add(ident("Name_HIDDEN"))

    quote do:
        proc Name*(self: var `vType`): string =
            return `tName`

macro Name_MacroC*(vType: untyped): untyped =
    var tName = nnkDotExpr.newTree(ident("self"), ident("Name_HIDDEN"))

    quote do:
        proc Name*(self: var `vType`): string =
            return `tName`

Name_MacroB(Test_Type)

var tTest: Test_Type
tTest.Name_HIDDEN = "Hello"
echo tTest.Name

当我使用 Name_MacroA 时,出现错误:

Error: attempting to call routine: 'nnkDotExpr'
  found 'nnkDotExpr' [enumField declared in /usr/local/Cellar/nim/2.0.0_1/nim/lib/core/macros.nim(45, 5)]

Name_MacroA 尝试匹配 nnkDotExpr 引用中的代码 尼姆宏

当我使用 Name_MacroB 或 Name_MacroC 时,出现错误:

template/generic instantiation of `Name_MacroB` from here test4.nim(17, 20) Error: undeclared identifier: 'self'
candidates (edit distance, scope distance); see '--spellSuggest': 
 (2, 4): 'del'
 (2, 4): 'ref'
 (2, 4): 'send'

Name_MacroB 是尝试匹配来自 Nim Macros

的代码

Name_MacroC 尝试匹配来自 Nim Macros

的代码
macros nim-lang
1个回答
0
投票

第一个问题是,当它是一个枚举时,您试图调用

nnkDotExpr
。对于 NimNodeKind 就像
nnkDotExpr
,你需要使用 newTree

第二个问题是

quote do
正在为
self
参数生成一个唯一的符号,因此您需要让它像这样使用您自己的身份

    # Create your own ident
    let selfIdent = ident"self"
    # Can use genSym if you think there might be conflicts
    # let selfIdent = genSym(nskParam, "self")
    tName.add(selfIdent) 
    tName.add(ident("Name_HIDDEN"))

    quote do:
        # Now it uses your symbol here instead of making a new one
        proc Name*(`selfIdent`: var `vType`): string =
            return `tName`

还有 newDotExpr 使创建点表达式变得更简单

© www.soinside.com 2019 - 2024. All rights reserved.