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


かんたんな自作言語のコンパイラをいろんな言語で書いてみるシリーズ 12回目は Kotlin です。

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

github.com

移植元

memo88.hatenablog.com

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

メモ


今回の実験は配列変数の宣言。 trial ブランチで試してみました。

確認用のコードです。今回の実験ではとりあえずこれだけコンパイルできれば OK。

// declare_array.vg.txt

func main() {
  var xs[22];
}

AST がこんな感じ。お試しなので適当。

$ ( \
>   cat declare_array.vg.txt \
>   | ./run.sh tokenize \
>   | ./run.sh parse \
> ) 2>/dev/null
[
  "top_stmts",
  [
    "func",
    "main",
    [

    ],
    [
      [
        "var_array",
        "xs",
        22
      ]
    ]
  ]
]

アセンブリコードがこんな感じ。

$ ( \
>   cat declare_array.vg.txt \
>   | ./run.sh tokenize \
>   | ./run.sh parse \
>   | ./run.sh codegen \
> ) 2>/dev/null
  call main
  exit

label main
  push bp
  cp sp bp

  # 関数の処理本体
  sub_sp 22 # ... 配列のサイズ分の領域をスタック上に確保する

  cp bp sp
  pop bp
  ret

これだけだったら少し修正するだけで済みました。

次のようなコードはまだ正しく動くようにコンパイルできません。

func main() {
  var xs[22];
  var a = 11;
}

配列がスタック上で占有している幅を考慮しないといけないのに、それをまだやってないからです。 これをやろうとするとたぶんあちこち修正しないといけなくなるので、それはまた今度ということで。

vm2gol v2 (51) 機械語コードのフォーマットを固定長風に変更



これまで機械語コードのフォーマットはこのような YAML ファイルにしていました。 (以下便宜的に「可変長風」と呼びます)

---
- call
- 1029
- exit
- label
- vram_set
- push
- bp
...

これを変更して、1行あたり1命令となるようにして、行ごとに JSON.parse でパースできるようにしました。 (以下便宜的に「固定長風」と呼びます)

["call", 1029]
["exit"]
["label", "vram_set"]
["push", "bp"]
...

どの命令でもメモリ上で占める幅が 1 になったため Vm.num_args_for も不要になってすっきりしました。

また、YAML への依存がなくなり JSON への依存に一本化できました。 Ruby でやる分には何でもいいのですが、他の言語に移植するときに若干めんどくさかったので。これでちょっと簡単になるはず。

その他の変更

メモ

元の YAML のように 1命令が複数の行(可変)となるようにしていたのは、機械語といってもバイナリではなくテキストにした上にさらに固定長風にしてしまうとさすがに簡略化しすぎで勉強にならないのではないか、みたいなことを考えていたからでした。たしか。

しかし、今になってみると別にこだわるところではなかったように思えます。こだわる必要がないのであれば簡単な方がよい、というわけで変えてしまうことにしました。

あとは 1行1命令にするとアセンブリコードとの違いがさらに小さくなってアセンブラが仕事してない感じになってしまうけどこれでいいの? ということが気になっていたのですが、そこも気にしないことにしました。


全体で 50行弱減って今このくらいの行数。

   14 common.rb
   58 vgasm.rb
  555 vgcg.rb
  509 vgparser.rb
  513 vgvm.rb
 1649 合計


memo88の2020年ブックマークランキング

blog.sushi.money

やってみました。調べてないけど9割方セルクマ 😅

ブクマしてくださった方、ありがとうございます。

memo88の2020年ブックマークランキングベスト24(累計30ブックマーク)

# タイトル
1位 きしださんのかわいいリレーショナルデータベースをRubyで写経した - memo88
2位 リレー式論理回路シミュレータを自作して1bit CPUまで動かした - memo88
3位 Rubyで素朴な自作言語のコンパイラを作った - memo88
4位 LibreOffice Drawのodgファイルから図形の情報を抜き出して使う - memo88
5位 kairo-gokko 製作メモ - memo88
6位 Ruby/Racc: パースに失敗した位置(行、桁)を得る - memo88
7位 素朴な自作言語のコンパイラをGoに移植した - memo88
8位 kairo-gokko (35) 1bit CPU 2 - memo88
9位 kairo-gokko (34) 1bit CPU 1 - memo88
10位 素朴な自作言語のコンパイラをPHPに移植した - memo88
11位 HiveQL テスト 自動化 メモ - memo88
12位 kairo-gokko (33) Dフリップフロップ 2 - memo88
13位 DockerでDigdagサーバを動かす(クライアントの簡単な動作確認用、PostgreSQL不使用) - memo88
14位 素朴な自作言語のコンパイラをPerlに移植した - memo88
15位 素朴な自作言語のコンパイラをCに移植した - memo88
16位 失敗したタスクの情報をdigdagコマンドとシェルスクリプトで取得する - memo88
17位 Ubuntu 18.04にJupyter NotebookとIRubyをインストール(pyenv, rbenv を使用) - memo88
18位 hive.server2.enable.doAs がよく分からなかったので Apache Bigtop で調べてみた - memo88
19位 素朴な自作言語のコンパイラをJavaに移植した - memo88
20位 正規表現エンジン(ロブ・パイクのバックトラック実装)をRubyで写経した - memo88
21位 素朴な自作言語のコンパイラをTypeScript(Deno)に移植した - memo88
22位 素朴な自作言語のコンパイラをDartに移植した - memo88
23位 素朴な自作言語のコンパイラをC♭に移植した - memo88
24位 素朴な自作言語のコンパイラをPythonに移植した - memo88

generated by 年間ブックマークランキングジェネレーター