私は最近、テンプレートとマクロを使用していますが、これらの重要なタイプに関する情報はほとんど見つかりませんでした。これは私の表面的な理解です:
- typed/expr は事前に存在している必要がありますが、.immediate を使用できます。それらを克服するために。
- untyped/stmt は、以前に定義されていないもの/1 つ以上のステートメントです。
これは、タイプの非常に漠然とした概念です。どのタイプを戻り値として使用する必要があるかなど、それらについてのより良い説明が必要です。
これらのさまざまなパラメーター タイプの目的は、コンパイラーがマクロへのパラメーターとして受け入れる必要があるものを指定する際に、精度を高めるいくつかのレベルを提供することです。
数式を解く仮想マクロを想像してみましょう。次のように使用されます。
solve(x + 10 = 25) # figures out that the correct value for x is 15
ここで、マクロは、提供された AST ツリーの構造を気にします。同じツリーが現在のスコープで有効な式である必要はありません (つまり、x
定義されているなど)。このマクロは、ほとんどの数式をデコードして AST ツリーを扱いやすいものに変換できる Nim パーサーを利用するだけです。そのためのuntyped
パラメーターです。それらは意味的にチェックされず、生の AST を取得します。
精度ラダーの次のステップはtyped
パラメータです。現在のスコープで適切な意味を持っている (つまり、その型を決定できる) 限り、任意の式を受け入れる汎用的な種類のマクロを記述できます。macros.getType
エラーを早期にキャッチするだけでなく、マクロ本体内の式の型を ( procを使用して) 処理できるという利点もあります。
特定の型 (具象型または型クラス/概念) の式を要求することで、さらに正確にすることができます。マクロは、通常のプロシージャのようにオーバーロードの解決に参加できるようになりました。コンパイル時に評価できる式と実行時にのみ評価できる式の両方を受け入れるため、マクロは引き続き AST ツリーを受け取ることを理解することが重要です。
最後に、コンパイル時に提供される特定の型の値をマクロが受け取るように要求できます。マクロは、この値を使用してコード生成をパラメータ化できます。これは静的パラメータの領域です。マクロの本体内では、それらはもはや AST ツリーではなく、適切に型指定された通常の値です。
これまでは式についてのみ説明してきましたが、Nim のマクロはブロックを受け入れて生成することもできます。これは、制御できる 2 番目の軸です。expr
一般に、 は単一の式を意味し、一方stmt
は式のリストを示します (歴史的に、その名前は、Nim で式とステートメントが統合される前に別の概念として存在していた StatementList に由来します)。
この違いは、テンプレートの戻り値の型で最も簡単に説明できます。newException
system モジュールのテンプレートを考えてみましょう:
template newException*(exceptn: typedesc, message: string): expr =
## creates an exception object of type ``exceptn`` and sets its ``msg`` field
## to `message`. Returns the new exception object.
var
e: ref exceptn
new(e)
e.msg = message
e
例外を作成するにはいくつかの手順が必要ですexpr
が、テンプレートの戻り値の型として指定することで、最後の式のみがテンプレートの戻り値と見なされることをコンパイラに伝えます。残りのステートメントはインライン化されますが、呼び出しコードから巧妙に隠されています。
別の例として、C/C++ のセマンティクスをエミュレートできる特別な代入演算子を定義して、if ステートメント内で代入を許可してみましょう。
template `:=` (a: untyped, b: typed): bool =
var a = b
a != nil
if f := open("foo"):
...
具象型の指定は、 を使用するのと同じセマンティクスを持ちexpr
ます。代わりにデフォルトのstmt
戻り値の型を使用していた場合、if ステートメントは明らかに単一の式を想定しているため、コンパイラは「式のリスト」を渡すことを許可しませんでした。
.immediate.
テンプレートとマクロがオーバーロードの解決に関与していなかった過去からの遺産です。最初に型システムを認識させたとき、多くのコードが現在のuntyped
パラメーターを必要としていましたが、最初からそれらを導入するようにコンパイラーをリファクタリングするのは非常に困難でした。代わりに.immediate.
、下位互換性の動作を強制する方法としてプラグマを追加しました。マクロ/テンプレート全体。
ではtyped/untyped
、マクロの個々のパラメータをより細かく制御でき、.immediate.
プラグマは段階的に廃止され、非推奨になります。