Pythonでかんたんな自作言語のコンパイラを書いた


移植一覧に戻る


Python で書いてみました。やっつけなので汚いです。Python よく知らないけどライフゲームが動いたのでヨシ、という程度の雑なものです。

github.com

移植元

github.com

<自作言語処理系(Ruby版)の説明用テンプレ>

自分がコンパイラ実装に入門するために作った素朴なトイ言語とその処理系です。

何ヶ月もかけてCコンパイラを作るのが「100 の労力で 100 を得る」だとしたら、このプロジェクトは「まず 5 の労力で 20 を得よう」みたいな方向性です。得られるものは 100 ではありませんが短期間で完成させることができます。

<説明用テンプレおわり>

ベースになっているバージョン: ステップ45 のあたり
(追記 2023-11-19 ステップ66 まで反映しました)

動かし方の例

$ echo '
  func add(a, b) {
    return a + b;
  }

  func main() {
    call add(1, 2);
  }
' | python3 mrcl_lexer.py | python3 mrcl_parser.py | python3 mrcl_codegen.py


# ↓アセンブリが出力される

  call main
  exit

label add
  push bp
  mov bp sp

  # 関数の処理本体
  mov reg_a [bp:2]
  push reg_a
  mov reg_a [bp:3]
  push reg_a
  pop reg_b
  pop reg_a
  add reg_a reg_b

  mov sp bp
  pop bp
  ret

  mov sp bp
  pop bp
  ret

label main
  push bp
  mov bp sp

  # 関数の処理本体
  mov reg_a 2
  push reg_a
  mov reg_a 1
  push reg_a
  _cmt call~~add
  call add
  add sp 2

  mov sp bp
  pop bp
  ret

(snip)

ライフゲームコンパイルして実行

(2024-01-06 追記)

run_game_of_life.sh を追加しました。 ライフゲームのプログラムをコンパイルアセンブルし、VM で実行します。

他の人によって書かれた Python 版移植

ご興味ある方はぜひどうぞ!

github.com

メモ

アセンブラVM は移植対象から外しました。Ruby 版のものを使います。

(2024-01-06 追記)Python で書いたアセンブラVM も追加しました。


トークナイザは今のところ大した量もないのでパーサと同じファイルに書いていますが、やっぱり分けようかなという気分になりました。


移植版は今後も継続してメンテするわけではなくババッと作って気が済んだら終わりというものなので、 Ruby 版にそのうち入れるかもしれない修正を気軽に・実験的に試してみようかと。

高水準言語部分の文法をやっぱり Ruby っぽくしようかなと考えていて、今回はそれを一部試してみました。

(2021-06-05 追記: その後の修正を加えるために以下の修正はいったん取り消しましたが、一応 trial ブランチに残してあります。)

funcdef に変えて、 { ... }... end に変えて、行コメントの開始文字を # に変えて……と修正していって、下記のような怪しい見た目になりました。varset なんかはまだ残っています。

def calc_next_gen(current_val, count)
  # 注目しているセルの次世代の生死
  var next_val = 0;

  case
  when (current_val == 0)
    case
    when (count == 3)
      set next_val = 1;
    end
  when (0 == 0)
    case
    when (count == 2)
      set next_val = 1;
    when (count == 3)
      set next_val = 1;
    end
  end
  
  return next_val;
end

怪しいですが ruby -c test/*.vg.txt で文法チェックすると OK と出ます。

Ruby で実行するとさすがに何かしらエラーになるだろう……と思って試してみたら正常終了しました。 最初は意外な感じがしましたが、メソッドの定義しかしてない(実行していない)ため実行時エラーも出ない、ということのようです。なるほど。