bonotakeの日記

元・ソフトウェア工学系研究者、今・AI系エンジニア

ということで

上のエントリーの続き。インタプリタをちょっと改造してみた。

interpret :: Lang -> Lang -> Computer Lang
interpret m l = Run $ \p -> 
                let (p', l') = runner (run l) p in (I m p' l', m)

実行結果。

*Main> showComp (P S) $ return S >>= interpret T >>= interpret M
"(I M (P S) S,M)"
*Main> showComp (P S) $ return S >>= interpret T >>= interpret M >>= run
"(P S,S)"

何のことはなく、run を interpret の中に一個入れただけ。


コンパイラもさっきのだとまずかった。コンパイラコンパイルする、みたいなことをやると

*Main> showComp (P A) $ compile C B A >>= compile E D
"(I E (I D (I C (I B (P A) A) B) C) D,E)"

となって、run は4個必要だし、言語の適用の仕方もおかしくなる。
書き直してみると、こんな感じ。更に書き直しました。

compile :: Lang -> Lang -> Lang -> Computer Lang
compile m t s = Run $ \p ->
                let (p', s') = runner (run s) p in (I m (I t p' s') t, m)

で、実行結果。

*Main> showComp (P A) $ compile C B A >>= compile E D
"(I E (I D (I B (P A) A) B) D,E)"
*Main> showComp (P A) $ compile C B A >>= compile E D >>= run
"(I D (I B (P A) A) B,D)"
*Main> showComp (P A) $ compile C B A >>= compile E D >>= run >>= run
"(I B (P A) A,B)"
*Main> showComp (P A) $ compile C B A >>= compile E D >>= run >>= run >>= run
"(P A,A)"

Cで書かれた、AからBへのコンパイラを、Eで書かれた、CからDへのコンパイラコンパイルする。
これを実行すると(run一回適用)、Dで書かれた、AからBへのコンパイラができあがる。言語D上で2回目のrunを適用して、出てきたプログラム(Bで書かれている)を、B上でもう一度runすると、所望の動作が得られる。(更に続く


p.s. コンパイラの教科書に良く出てくる、T字型の図式(クロスコンパイルとか考えるときに使うやつ)って、なんていうんでしたっけ?(現在帰省中にて、手元に資料なし)あれ書きながら考えてたんですが、名前を失念しちゃいました。

注:bonotakeは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。