素朴な自作言語のコンパイラをC♭に移植した


移植まとめに戻る


やっつけなので汚いです。ライフゲームコンパイルが通ったのでヨシ、というレベルのものです。

github.com

C♭は書籍 『ふつうのコンパイラをつくろう』の題材として作られた、C によく似た言語です。コンパイラ cbcJava製。


移植元

memo88.hatenablog.com

ベースになっているバージョン: tag:49 のあたり

ただ、実質的には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 環境で動かしているせいかもしれません。