Locationでは、グローバル変数・自動変数・文字列定数の割り付けを行っています。
このコードを書き始めたのは完成の前日で、あわてて書いていたのでコードが適当になってきています。
FrameEnvironment
フレームというか、中かっこ文ごとの、「今のSPがBPからどれだけ離れているか」と「中かっこを脱出した時に戻すべきSPのBP相対値」、「スコープに入っている自動変数のBP相対値の辞書」をまとめたものです。
ParseSize
sizeof演算子やalignof演算子の結果を計算するような部分です。FunctionのSizeが0であるのは、関数がスタックに取られたりすることはないためで、変数ではない証になっています。
add_global_environment
GlobalEnvironmentは、グローバル変数・関数定義の情報を収集して入れておくものですが、これに情報を追加します。この時、Sizeが0のものは変数ではなく関数の前方宣言なので、追加しません。
add_flame_environment
FrameEnvironmentに新たな自動変数を付け加えます(ブロック先頭以外での変数宣言も可能なので、途中でSPの値が変わり得ます)。また、アライン要求の一番大きな4Byteに強制的に揃えます。
StringPool, StringRef
文字列定数は、出現するたびにスタックに積むわけではなく、グローバル領域にその情報が置かれています。StringPoolはその情報を収集して入れておくもので、StringRefはそれを示す一種のポインタになる、StringPoolの先頭から何番目に存在するかを示す整数を保持します。
Locate
各式について、割り付けを行います。変数ならFlamePositionに変換し、文字列定数ならばStringRefに変換したうえでStringPoolに追加します。ほかの式の場合は、各部分式についてこれを再帰的に行います。 BinaryNodeは抽象化されていますが、他の部分は抽象化しておらず完全にコピペコードになっています。
あれ、これではグローバル変数が来た時にエラーになってしまうような……。
StatementFold
各文について、必要ならば再帰的にLocateを行います。TypeAnalysisでやったものと同じようなコードが並んでいます。
makeReturn
関数の終了には、暗黙的にreturn
文が存在します。void
型であれば何も問題なく、int
型などであれば偶然残っていたゴミが返されることになります。そのreturn
文を追加します。
GlobalStatementFold
グローバル領域に現れる文すべてについて、変数宣言ならGlobalEnvironmentに加える、関数定義なら中身をStatementFoldにかけたうえでGlobalEnvironmentに加える、ということを行います。
Fold
いつもの、線形再帰にならないようにタプルを分割しながら再帰するものです。
おわりに
Locationはほとんど自明な変換しか行っていないのであまり説明することがありませんでした。
あまり関係ない話
何とは言いませんが締切がせまってきていて、ltmpcをいじる暇が全くなくなってしまっています。はやくいろいろ改修したいです……。