4

私はイテレーターをしばらく使用しており、私はそれらを愛しています。イテレータを認識するコンパイラはどのように実装できますか?

しかし、私はそれについて懸念していましたが、「イテレータを認識するコンパイラがどのように実装されるか」を理解できませんでした。私はそれについても研究しましたが、コンパイラ設計の状況を説明するリソースは見つかりませんでした。

説明すると、反復子に関する記事のほとんどは、希望の動作を実装する何らかの「魔法」があることを暗示しています。彼らは、コンパイラが、実行がどこにあるかに従うためにステートマシンを維持することを提案しています(最後の「利回り」が見られる場所)。私は怠惰な評価を可能にするイテレータのこのプロパティに特に興味があります。

ところで、私はどのような状態マシンが、コンパイラデザインコースを取って、ドラゴンブックを学んだのか知っています。しかし、明らかに、私が学んだことをcscの「魔法」に関連付けることはできません。

あらゆる知識や差別化された考えが認められます。

+0

もう少し説明できますか?たとえば、コンパイラが認識するのが非常に難しいと思うソースコードの例がありますか? – Thilo

+0

また、あなたが話している言語 - たとえば「yeild」は何ですか? –

+0

C#には "yield returns"構文があります。 –

答えて

5

それはそれよりも簡単です。コンパイラは反復子関数を個々のチャンクに分解できます。チャンクはyieldステートメントで分割されます。

ステートマシンは、現在のチャンクを追跡するだけで済みます。イテレータの次の呼び出し時に、このチャンクに直接ジャンプします。また、すべてのローカル変数を追跡する必要があります(もちろん)。

次に、いくつかの特別なケース、特にyieldを含むループを考慮する必要があります。幸いにも、IL(ただしC#ではなく)ではgotoのループをループにジャンプさせて再開させます。

非常に複雑なエッジケースがあることに注意してください。 C#はyieldfinallyブロックに入れません。yieldに関数を残すことは非常に困難(不可能です)し、後で機能を再開し、クリーンアップを実行して例外を再スローします。はスタックトレースを保持します。

Eric Lippertが処理のin-depth descriptionを転記しました。(彼がリンクしている記事も読んでください!)

1

私がしようとしていることの1つは、C#で簡単な例を書いてコンパイルし、それにReflectorを使用することです。私は、この "yield return"は構文砂糖だけだと思う​​ので、コンパイラーが逆アセンブラーの出力でどのようにそれを処理するかを見ることができます。

しかし、まあ、私はこれらのことについてはあまりよく知らないので、私は完全に間違っているかもしれません。