簡単な自作言語のコンパイラをいろんな言語で書いてみるシリーズ 25番目の言語は C# です。
C# も以前から気にはなりつつ全然触れていなかったので、今回ちょっと雰囲気が知れてよかったです。
できたもの
サイズ
$ 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
動作例
$ 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 ...
移植元
こちらのコンパイラ部分が移植元です。
(追記 2023-12-29) step_66 の変更まで反映しました。
自分がコンパイラ実装に入門するために作った素朴なトイ言語 Mini Ruccola とその処理系です。簡単に概要を書くと下記のような感じ。
- 小規模: コンパイラ部分は 1,000 行程度
- 無理して短く書くようなことはせず、読みやすさ優先で素直に書いてこのくらい
- pure Ruby
- 標準ライブラリ以外のライブラリ不要。すべてを掌握できるように。
- x86風の自作VM向けにコンパイルする
- ライフゲームのために必要な機能だけ
- 変数宣言、代入、反復、条件分岐、関数定義
- 演算子:
+
,*
,==
,!=
のみ(優先順位は(
)
で明示) - 型なし(値は符号付き整数のみ) ... B言語や BCPL に似てる?
- 作ったときに書いた備忘記事
-
本体には含めていない後付けの機能など
- 真偽値リテラル / break / if/else / 単項マイナス / パーサの別実装 / 静的型検査 / etc.
-
セルフホスト版
- 育てていくとセルフホストまでできます
-
他言語への移植
- コンパイラ部分のみ
- Python, Java, PHP, TypeScript, Julia, Dart, OCaml, Haskell, Rust, Zig, V, Forth など、2023-07-02 の時点では 25言語
- 作り方は製作メモに全部書いています。
- この通りにやれば誰でも同じものが作れる、と言いたいところだけどいろいろ改善点が見えてきたので全体的に改訂したい……
- 凝ったことはしていないので Ruby を知らない人でも雰囲気くらいは分かるんじゃないかと。
これは Mini Ruccola 言語で書いたライフゲームを(コンパイル+アセンブルして)VM で実行している様子。コンパイルだけなら今回作った C# 版でも同様に行えます。
メモ
-
C#に入門してみた(Mini Ruccolaコンパイラを書くための下調べ)
- 別記事に分けてみました
- Java に似てるし 3, 4日くらいで書けた
- IDEなくても書けるくらいの簡単なものなので、今回も開発環境まわりは何も用意せず結局 Emacs(+ java-mode)で全部書いた
- mcs コマンド
-
--version
みたいなバージョン確認用オプションがなかったりして文化の違いを感じる - apt-get でインストールされるのはバージョンが古い?
- 今回はお試しみたいなものなので細かいことは気にしない。とりあえず一番めんどくさくなさそうな方法でインストールした。
-
- Java と違うところ
- プロパティ
- Java でも Lombock に頼らず簡易に getter/setter を書けたらいいなあと素朴に思うなど
- 組み込みでタプルがあって良い
-
==
,!=
で文字列の等値比較できて楽 - チェック例外がJavaにあってC#にない理由 - かとじゅんの技術日誌
- プロパティ
- ググると割とすぐ公式リファレンスに辿り着く。(たまに機械翻訳で変な記述になってる場合もあるけど)説明とサンプルコードが適度に用意されていて好印象。
この記事を読んだ人は(ひょっとしたら)こちらも読んでいます