Nim 在编译时反映类型的字段类型

Nim reflect on type's field types at compile-time

假设我有一个定义如下的类型:

type TMyStruct = object
    foo: int32
    bar: int16

我的目标是构建一个宏(或其他),给定一个像上面那样的 "simple" 对象类型,它能够计算该类型中每个字段的大小的总和,基于sizeof。在这种情况下,int32 的大小为 4,int16 的大小为 2,所以想法是

myMacro(TMyStruct)  # or, in the worst case, myMacro(x) where x is a TMyStruct

应该计算为 6 作为常量表达式。我想稍后将它扩展到嵌套对象,但是一旦基本版本工作,通过递归应该很容易。

我尝试了很多东西,但都失败了;我设法得到的最远的是检索 AST 中的字段名称 "foo" 和 "bar" 作为 nnkSymNodes,但我无法检索有关它们类型的任何信息。有意义的文档(以我的 Nim 专业水平)很少甚至不存在。

我问的是可能的吗,我需要使用什么 Nim 功能来实现它?

谢谢

import macros

type TMyStruct = object
  foo: int32
  bar: int16

macro sumSizes(t: typedesc): expr =
  result = nil
  let tDesc = getType(getType(t)[1])
  for field in tDesc[2].children:
    let sizeOfThis = newCall("sizeof", field)
    if isNil(result):
      result = sizeOfThis
    else:
      result = infix(result, "+", sizeOfThis)

echo sumSizes(TMyStruct)

有点奇怪,您必须在开头链接 getType 调用。这是因为 getType(t) returns 以下内容:

BracketExpr
  Sym "typeDesc"
  Sym "TMyStruct"

如果您想对类型的实例执行此操作,只需更改以下行:

macro sumSizes(e: typed): expr =
  result = nil
  let tDesc = getType(e)

请注意,typed 在宏中输入符号很重要。