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

时间:2016-06-25 14:55:24

标签: metaprogramming nim

假设我的类型定义如下:

type TMyStruct = object
    foo: int32
    bar: int16

我的目标是构建一个宏(或其他),给出一个简单的"像上面那样的对象类型,能够根据sizeof计算类型中每个字段的大小总和。在这种情况下,int32的大小为4,int16的大小为2,因此想法是

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

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

我尝试了许多事情并且失败了;我设法得到的最远的是检索字段名称" foo"和" bar"在AST中作为nnkSymNodes,但我无法检索有关其类型的任何信息。有意义的文档(在我的Nim专业水平上)很少到根本不存在。

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

由于

1 个答案:

答案 0 :(得分:1)

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)返回以下内容:

BracketExpr
  Sym "typeDesc"
  Sym "TMyStruct"

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

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

请注意,此处typed在宏中包含一个类型符号非常重要。