如何在宏中迭代元组/对象的字段(名称+类型)?

蓝注10

我想编写宏,它必须根据命名元组或对象的字段执行一些逻辑。我认为这最好通过将元组/对象作为typed参数传递给宏来实现。

问题是,我typed一般如何遍历参数的字段我基本上是在寻找forfieldPairs的等效项,即,与其采取具体的元组/对象,还不如对其进行操作,NimNode并同样返回字段名称/类型(以进一步生成AST)。

蓝注10

我找到了该问题的解决方案,它似乎工作正常,但我不确定是否有更好的替代方案。该解决方案是基于使用getTypeImpltyped参数。要了解它是如何工作的,查看t.getTypeImpl.treeRepr简单元组和对象的输出会有所帮助

  • 元组:例如类型 impl AST(x: 0, y: 1, name: "")看起来像这样:

    TupleTy
      IdentDefs
        Sym "x"
        Sym "int"
        Empty
      IdentDefs
        Sym "y"
        Sym "int"
        Empty
      IdentDefs
        Sym "name"
        Sym "string"
        Empty
    

    注:typeKindgetTypeImplISntyTuple

  • Object:具有相同结构的对象的类型 impl AST 将是:

    ObjectTy
      Empty
      Empty
      RecList
        IdentDefs
          Sym "x"
          Sym "int"
          Empty
        IdentDefs
          Sym "y"
          Sym "int"
          Empty
        IdentDefs
          Sym "name"
          Sym "string"
          Empty
    

    注:typeKindgetTypeImplISntyObject

这表明我们正在寻找的信息在IdentDefs. 我们只需要确保适当地处理元组和对象:对于元组,IdentDefs是的直接子级NimNode,而对于对象,IdentDefs将存储在索引2的子级中(索引0的子级包含编译指示信息,索引中的子级1 是关于父母的信息)。

总体而言,宏可能看起来像(添加了一些调试输出以进行说明):

macro iterateFields*(t: typed): untyped =
  echo "--------------------------------"

  # check type of t
  var tTypeImpl = t.getTypeImpl
  echo tTypeImpl.len
  echo tTypeImpl.kind
  echo tTypeImpl.typeKind
  echo tTypeImpl.treeRepr

  case tTypeImpl.typeKind:
  of ntyTuple:
    # For a tuple the IdentDefs are top level, no need to descent
    discard
  of ntyObject:
    # For an object we have to descent to the nnkRecList
    tTypeImpl = tTypeImpl[2]
  else:
    error "Not a tuple or object"

  # iterate over fields
  for child in tTypeImpl.children:
    if child.kind == nnkIdentDefs:
      let field = child[0] # first child of IdentDef is a Sym corresponding to field name
      let ftype = child[1] # second child is type
      echo "Iterating field: " & $field & " -> " & $ftype
    else:
      echo "Unexpected kind: " & child.kind.repr
      # Note that this can happen for an object with a case
      # fields, which would give a child of type nnkRecCase.
      # How to handle them depends on the use case.

# small test
type
  TestObj = object
    x: int
    y: int
    name: string

let t = (x: 0, y: 1, name: "")
let o = TestObj(x: 0, y: 1, name: "")

iterateFields(t)
iterateFields(o)    

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Haskell中访问名为元组字段的新类型

获取对象类型中属性或字段的名称

如何在Java中的字段中存储变量类型的对象?

如何在元组中重用休息类型?

如何在IntelliJ Idea中查看对象的全类型名称?

如何在解析中查询“对象”类型字段。

如何在 TypeScript 中访问对象的数组字段?类型“未知”必须有一个返回迭代器的“[Symbol.iterator]()”方法

元组类型的 usePreviousEffect 类型

如何在Ecto中更改字段类型?

如何在netsuite中更改字段类型?

如何从具有键数组的对象中获取元组类型

如何在具有相同名称成员的对象的构造函数中限定类型名称?

如何在程序中修复“类型错误:'float'对象不可迭代”?

在打字稿中,您如何表达其中一个字段是类型名称的对象的类型?

Scala:如何在函数中返回元组?“类型不匹配”

如何在JPA中接受Map <String,Object>类型的元组

如何在dotty中解开元组中元素的类型?

如何在F#中返回特定类型的元组?

如何在PySpark的UDF中返回“元组类型”?

如何在类型提示中定义元组或列表的大小

如何在宏中获取智能指针的类型?

如何在Rust宏中匹配表达式的类型?

如何在Scala宏中构造通配符类型?

如何在Scala的宏注释中访问通用类型?

如何在scala宏中获取类型较高的参数的树

如何在Rust过程宏中获取impl块的类型?

如何在Roslyn中查找具有特定名称的字段类型

如何在安全枚举类型中获取字段名称

如何从对象转换为元组(ValueTuple)类型?