2016-06-25 19 views
1

コンパイル時に、型のフィールドタイプに反映:「シンプル」オブジェクト・タイプなどを与えられた、ニムは、私は次のように定義されたタイプがあるとし

type TMyStruct = object 
    foo: int32 
    bar: int16 

私の目標は、マクロ(またはそれ以外)を構築することであるが上の例では、sizeofに基づいて、型の各フィールドのサイズの合計を計算できます。この場合int32は、サイズ4を有するとint16のでアイデアが

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

が定数式として6に評価すべきであるということであるサイズ2を有します。後でネストされたオブジェクトに拡張したいが、基本バージョンが動作したら再帰を介して簡単にする必要があります。

私は多くのことを試みましたが恐ろしく失敗しました。私が得ることができた最も遠いのは、ASNのフィールド名 "foo"と "bar"をnnkSymNodesとして取り出すことでしたが、その型に関する情報を取得することができませんでした。意味のある文書化(私のNimの専門知識レベルで)は、存在しないことにはまばらです。

私は可能なことを聞​​いていますか、それを達成するためにNimの機能は何が必要ですか?

おかげ

答えて

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電話を持っていることを少し奇妙です。あなたはタイプのインスタンスでこれを行うにしたい場合は

BracketExpr 
    Sym "typeDesc" 
    Sym "TMyStruct" 

は、単にこれらの行を変更します:getType(t)は以下返すためです

typedが入力されたシンボルを持つことがここでは重要である。なお
macro sumSizes(e: typed): expr = 
    result = nil 
    let tDesc = getType(e) 

マクロの内部にある。

+0

非常に良い!ありがとう。私はちょうどASTの詳細を自分自身に熟達してマクロを書くのに慣れる必要があると思います:) – Thomas

関連する問題