C#でシンプルな自作言語のコンパイラを書いた

<!--
https://memo88.hatenablog.com/entry/mini_ruccola_compiler_csharp
-->

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/70a91ee7-2675-bb30-3df6-728d1609daa3.png)

[簡単な自作言語のコンパイラをいろんな言語で書いてみるシリーズ](https://memo88.hatenablog.com/entry/2020/08/30/132314) 25番目の言語は C# です。

C# も以前から気にはなりつつ全然触れていなかったので、今回ちょっと雰囲気が知れてよかったです。




# できたもの

https://github.com/sonota88/mini-ruccola-csharp


## サイズ

```terminal
  $ wc -l src/*.cs src/lib/{Types,Utils}.cs
  389 src/CodeGenerator.cs
   28 src/Compiler.cs
   70 src/Lexer.cs
  402 src/Parser.cs
  221 src/lib/Types.cs
   78 src/lib/Utils.cs
 1188 total
```


# 動作例

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

  func main() {
    call add(1, 2);
  }
' | mono bin/mrclc lex | mono bin/mrclc parse | mono bin/mrclc codegen

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

  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 ...
```




# 移植元

こちらのコンパイラ部分が移植元です。

https://github.com/sonota88/vm2gol-v2

（追記 2023-12-29） step_66 の変更まで反映しました。

自分がコンパイラ実装に入門するために作った素朴なトイ言語 Mini Ruccola とその処理系です。簡単に概要を書くと下記のような感じ。

- 小規模: コンパイラ部分は 1,000 行程度
  - 無理して短く書くようなことはせず、読みやすさ優先で素直に書いてこのくらい
- pure Ruby
  - 標準ライブラリ以外のライブラリ不要。すべてを掌握できるように。
- x86風の自作VM向けにコンパイルする
- ライフゲームのために必要な機能だけ
  - 変数宣言、代入、反復、条件分岐、関数定義
  - 演算子: `+`, `*`, `==`, `!=` のみ（優先順位は `(` `)` で明示）
  - 型なし（値は符号付き整数のみ） ... B言語や BCPL に似てる？
- 作ったときに書いた備忘記事
  - [RubyでオレオレVMとアセンブラとコード生成器を2週間で作ってライフゲームを動かした話](https://qiita.com/sonota88/items/f9cb3fc4a496b354b729)
  - [Rubyでかんたんな自作言語のコンパイラを作った](https://qiita.com/sonota88/items/2b95378b43a22109513c)
- [本体には含めていない後付けの機能など](https://memo88.hatenablog.com/entry/vm2gol_v2_additional_features)
    - 真偽値リテラル / break / if/else / 単項マイナス / パーサの別実装 / 静的型検査 / etc.
- [セルフホスト版](https://qiita.com/sonota88/items/1e683276541cf1b87b76)
    - 育てていくとセルフホストまでできます
- [他言語への移植](https://memo88.hatenablog.com/entry/2020/08/30/132314)
    - コンパイラ部分のみ
    - Python, Java, PHP, TypeScript, Julia, Dart, OCaml, Haskell, Rust, Zig, V, Forth など、2023-07-02 の時点では 25言語
- 作り方は[製作メモ](https://memo88.hatenablog.com/entry/2019/05/04/234516)に全部書いています。
  - この通りにやれば誰でも同じものが作れる、と言いたいところだけどいろいろ改善点が見えてきたので全体的に改訂したい……
  - 凝ったことはしていないので Ruby を知らない人でも雰囲気くらいは分かるんじゃないかと。

---

これは [Mini Ruccola 言語で書いたライフゲーム](https://github.com/sonota88/vm2gol-v2/blob/main/gol.mrcl)を（コンパイル＋アセンブルして）VM で実行している様子。コンパイルだけなら今回作った C# 版でも同様に行えます。
![Peek 2021-10-03 07-01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/98b4b4ad-da86-ca35-e578-20499277b42a.gif)




# メモ



- [C#に入門してみた（Mini Ruccolaコンパイラを書くための下調べ）](https://qiita.com/sonota88/items/25d08b0faafc3b4ccbab)
  - 別記事に分けてみました
- Java に似てるし 3, 4日くらいで書けた
- IDEなくても書けるくらいの簡単なものなので、今回も開発環境まわりは何も用意せず結局 Emacs（+ java-mode）で全部書いた
- mcs コマンド
  - `--version` みたいなバージョン確認用オプションがなかったりして文化の違いを感じる
  - apt-get でインストールされるのはバージョンが古い？
    - 今回はお試しみたいなものなので細かいことは気にしない。とりあえず一番めんどくさくなさそうな方法でインストールした。
- Java と違うところ
  - プロパティ
    - Java でも Lombock に頼らず簡易に getter/setter を書けたらいいなあと素朴に思うなど
  - 組み込みでタプルがあって良い
    - [タプル型 - C# リファレンス | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/value-tuples)
  - `==`, `!=` で文字列の等値比較できて楽
    - [文字列を比較する方法 - C# ガイド | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/csharp/how-to/compare-strings)
  - [チェック例外がJavaにあってC#にない理由 - かとじゅんの技術日誌](https://blog.j5ik2o.me/entry/20091017/1255799827)
- ググると割とすぐ公式リファレンスに辿り着く。（たまに機械翻訳で変な記述になってる場合もあるけど）説明とサンプルコードが適度に用意されていて好印象。





# この記事を読んだ人は（ひょっとしたら）こちらも読んでいます

<!-- 素朴な自作言語のコンパイラをJavaに移植した - memo486 -->
https://memo88.hatenablog.com/entry/2020/08/30/121437

<!-- Pascalでかんたんな自作言語のコンパイラを書いた - Qiita -->
https://qiita.com/sonota88/items/4d446b778ffbbaab267c

<!-- 素朴な自作言語のコンパイラをCに移植した - memo486 -->
https://memo88.hatenablog.com/entry/2020/09/06/043607