2008-12-28

昼はクリパ

クリパ

勉強

今,課題でコンパイラを作っていて,最終段階なわけだが,web上にも資料が少ないことに愕然とした.いや,あるにはあるんだけど,難しすぎて全然分からない.様々な最適化手法などが沢山あるとは思うんだけど,とりあえず,思いつく原始的な方法でやることにする.暇があれば,今までの授業で習ったことをまとめたページも作ってみたいなあ.以下の文章は,一般の方*1には意味不明だろうが,詳しくはおいおい*2解説したい

*1 コンピュータが大体分かってるぐらいのレベルの人を指す

*2 ぼくに余裕が出来たら(^_^;)

コンパイラの方針

さて,今までやってきたフェーズでの主な作業は次の通りだ.

  • 構文チェック
    • EBNFに従っているか逐次*1検査
    • 先読みする必要があるとき*2の対処
  • 意味チェック
    • 名前の管理
      • グローバル変数・ローカル変数・仮引数の「名前」と「型情報」の管理
      • 手続き*3の「名前」と「引数情報」の管理
    • 型の検査
      • 「式」内部での型の検査(=演算子のオペランドとしての妥当性の判定)
      • 「文」の「引数」の妥当性の検査

んで,次にする作業は

  • コード生成
    • 変数の読み書き(メモリアクセス)
      • メモリ上に変数領域確保
      • その領域のアドレスの受け渡し(例えば,先頭アドレスを特定のレジスタに入れ,変位*4を見ていく)
    • 「式」の値*5の取得(例えば,演算結果を特定のレジスタに入れて処理していくなど)
    • 基本文の処理
      • 手続き呼び出し
      • 入出力文

といったところだろう.

こういう風に「問題」を,適当なサイズの問題に分割統治するってのは大切だ.それに,こうしてみると案外簡単にできそうだ.

あと1つ考えるとしたら,「実際にコード出力するタイミング」だろうか.あとで,最適化するなら,コードを都度ファイルに出力せず,スタック上に積んでいった方が良さそうだ.

*1 後戻りする必要がない言語仕様なので,前から順に一回だけ見ていくだけで出来るようになっている

*2 「代入文」と「手続き呼び出し文」はどちらも先頭のトークンが「名前」のため

*3 今回の課題で「関数」は扱わない

*4 これはコンパイル時に決定できる

*5 コンパイル時に(静的に)どのような値になるかは,一般には分からない

今日の作業終了

今日の作業は終了.

意外とバグが残っていて,冷や汗..ただ,リファクタリング途中でバグが混入したとき,SVNを使ってて心底良かったと思った.すぐに原因の分析ができるからね.大体,設計は頭の中でやったので,

あとは,実際にコーディングだね.