OCaml 版を書いた勢いで Haskell にもババッと移植しました。いつもの通りでライフゲームのコンパイルだけ通ればヨシ、という程度の非常に雑なものです。
移植元
ライフゲームのプログラムだけコンパイルできれば OK という、ゆるくて簡単なコンパイラです。Ruby 版だとコンパイラ部分だけで 1000行くらい。
ベースになっているバージョンは ステップ 58 のあたり。
作り方はここに全部書いています(Ruby 版のものですが): vm2gol v2 製作メモ
メモ
主な部分のサイズ(行数)はこんな感じ。
$ wc -l *.hs lib/{Types,Utils}.hs 431 codegen.hs 142 lexer.hs 377 parser.hs 7 lib/Types.hs 27 lib/Utils.hs 984 合計
- Haskell はだいぶ前(メモを見返したら 9 年前だった)に本を 2, 3 冊流し読みしてちょっと手を動かした程度でそれっきり。なので、ほぼ忘れていて、今回はほぼゼロからの再入門……というのはウソで、前回とは違って今回は OCaml 版を作った直後なので、 その分のゲタを履いたところからのスタート。
- OCaml 版をほとんどそのまま移植する形で済み、3, 4 日(土日含む)で書き終わってしまった
- そもそも評価戦略が違うし結構いろんなところを書き直す必要がありそう、難航しそうと思っていたので予想外というか拍子抜けというか
- OCaml 版を割とそのまま移植しているので、あんまり Haskell っぽい書き方になっていないと思います
OCaml では、ある変数の値を加工して同じ変数に代入しなおすような書き方ができます(実際には値を更新しているのではなく新しい束縛で古いものをマスクしている感じ。たぶん)。
let () = print_int ( let x = 1 in let x = x + 1 in x )
Haskell では評価の仕方が違うのでこれはできなくて、実行時に無限ループになります。
main :: IO () main = do print ( let x = 1 in let x = x + 1 in x )
こういうことをやりたい場合は let x' = x + 1 in ...
のように別の名前にしないとダメ。
参考: debugging - Haskell program outputs <<loop>> - Stack Overflow
他の言語への移植
記事 | リポジトリ | 日付 |
---|---|---|
OCaml | github | 2021-06-26 |
Pascal | github | 2021-05-22 |
Julia | github | 2021-05-03 |
Rust | github | 2021-04-07 |
Crystal | github | 2021-03-27 |
セルフホスト | github | 2021-02-21 |
Kotlin | github | 2021-01-14 |
Zig | github | 2021-01-07 |
LibreOffice Basic | github | 2020-12-14 |
Go | github | 2020-09-25 |
PHP | github | 2020-09-18 |
C♭ | github | 2020-09-13 |
Perl | github | 2020-09-08 |
C | github | 2020-09-06 |
Java | github | 2020-08-30 |
Dart | github | 2020-08-22 |
Python | github | 2020-08-19 |
TypeScript (Deno) | github | 2020-08-15 |