かんたんな自作言語のコンパイラをいろんな言語で書いてみるシリーズ 24番目の言語は V(V言語、vlang) です。
V を触り始めて1週間くらいの人が、理解は後回しにしてとにかく動くものを作るぞ、という方向性で書いたもの(そのくらいのノリで気軽に書けるコンパイラです)。
V のバージョンは 0.3.3(weekly.2023.14)。
できたもの
動かし方の例
$ echo ' func add(a, b) { return a + b; } func main() { call add(1, 2); } ' | bin/mrcl_lexer | bin/mrcl_parser | bin/mrcl_codegen # ↓アセンブリが出力される call main exit label add push bp cp sp bp cp [bp:2] reg_a push reg_a cp [bp:3] reg_a push reg_a pop reg_b pop reg_a add_ab cp bp sp pop bp ret label main push bp cp sp bp cp 2 reg_a push reg_a cp 1 reg_a push reg_a _cmt call~~add call add add_sp 2 cp bp sp pop bp ret (snip)
移植元
<自作言語処理系(Ruby版)の説明用テンプレ>
自分がコンパイラ実装に入門するために作った素朴なトイ言語 mini-ruccola とその処理系です。簡単に概要を書くと下記のような感じ。
- コンパクト: コンパイラ部分は 1,000 行程度
- 無理して短く書くようなことはせず、読みやすさ優先で素直に書いてこのくらい
- pure Ruby
- 標準ライブラリ以外のライブラリ不要。すべてを掌握できるように。
- x86風の自作VM向けにコンパイルする
- ライフゲームのために必要な機能だけ
- 変数の宣言・代入、反復、条件分岐、関数の定義・呼び出し
- 演算子:
+
,*
,==
,!=
のみ(優先順位は(
)
で明示) - 型なし(値は符号付き整数のみ) ... B言語や BCPL に似てる?
- 作ったときに書いた備忘記事
- 本体には含めていない後付けの機能など
- 真偽値リテラル / break / if/else / 単項マイナス / Racc などを使って書いたパーサの別実装 / etc.
- セルフホスト版
- さらに育てていくとセルフホストまでできます
- 作ったときの全過程を製作メモに書いています
- この通りにやれば誰でも作れる、と言いたいところだけどいろいろ改善点が見えてきたので全体的に改訂したい……
- 凝ったことはしていないので Ruby を知らない人でも雰囲気くらいは分かるんじゃないかと
<説明用テンプレおわり>
メモ
- 実質3, 4日くらいで移植完了
- ひっかかるところがほとんどなくて書くことがあまりない
- 参考にしたのはほぼこの2つのみ
- V Documentation
- ここを眺めれば基本的なところはだいたい分かる
- vlang リポジトリの vlib/ 以下
- 検索して使用例を見る
- V Documentation
- Go に似てる
- "V is very similar to Go. If you know Go, you already know ≈80% of V." (https://vlang.io/)と書かれている通り
- Go をよく知らないので詳しいことは書けませんが、見た目はたしかに似ていて、多値が返せたりする
- print が便利
- 構造体を print に渡すと中身を表示してくれる
- 文字列リテラルへの埋め込み
'...${x}...'
- mut にすれば
<<
で配列の末尾に要素を追加できる- ここだけ見た目がちょっと Ruby っぽい
- 今後 V言語を使う機会があったら今回作ったものから部品取りできる