やっつけなので汚いです。ライフゲームのコンパイルが通ったのでヨシ、というレベルのものです。
C♭は書籍 『ふつうのコンパイラをつくろう』の題材として作られた、C によく似た言語です。コンパイラ cbc は Java製。
移植元
ベースになっているバージョン: tag:49 のあたり
- (追記 2022-03-27)Docker 化しました
ただ、実質的にはC言語版 からの移植です。 そのままコピーしてきて、cbc でコンパイルできるように修正しました。
メモ
- cbc のコンパイルについては前回書いたとおり
- ほぼC言語なので細かい部分の直しだけで済み、 ライフゲームのコードをコンパイルできるところまで2日程度で持っていけた
- いろいろあって適当なプリプロセッサを作り、
必要なファイルを全部1ファイルにまとめて cbc に渡すようにした
- 行番号が変わってしまうのでこれはこれでめんどくさいのですが……
- 単純なマクロの置換もここで処理
- substring (lib/utils.cb) のバグというか実装が雑だったので ちゃんと文字列終端を見て止めるように修正。 まあそもそもがやっつけなのでそういうのあるだろうなと思ってました。 やっぱりあった。
- sscanf がなかったため 文字列から int に変換する処理だけ自前で追加
- ためしに Names だけ連結リストにしてみた
以下、移植で変更が必要だった部分についてのメモ。 Cの仕様にも詳しくないので「そもそもCでもダメだけどたまたま動いていた」みたいなパターンもある気がします。
引数がない関数の場合は void
が必須。
int foo_func(void) { // snip } // foo_func() とした場合のエラーメッセージ: //=> cbc: error: Encountered " ")" ") "" at line 849, column 34.
for 文でイテレータ変数の変数宣言はダメ。 C89/90 だとそうなんでしたっけ……(記憶がうっすら)。
for (int i = 0; i < 10; i++) { // snip } //=> cbc: error: Encountered " "int" "int "" at line 767, column 35.
for (;;) ...
はダメ。
これは while (1) ...
に書き換えればOK。
ポインタの配列の宣言の書式はこう。
Foo*[1024] foo_array;
文字の比較
int main(void) { char* str = "fdsa"; if (str[0] == 'f') { printf("equal\n"); } else { printf("not equal\n"); } return 0; } //=> not equal
(int)str[0] == 'f'
のように int にキャストすると equal になる。
詳しく調べていませんが、 64bit 環境で動かしているせいかもしれません。