2021-03-22に更新

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


移植一覧に戻る


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

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


移植元

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

  • 追記 2021-03-21: Dart のバージョンアップ(2.9.1 => 2.12.0)に合わせて修正
    • null safety まわりを適当に修正
  • 追記 2021-03-21: ステップ56 の修正まで適用しました

メモ

  • アセンブラ・VM は移植対象から外しました。Ruby 版のものを使います。
  • トークナイザとパーサを分けてみた
  • テストのステップを細かくした
  • ファイルを直接まじめに読まなくても、 標準入力が読めればあとはシェルスクリプトでラップしてあげたりすればいいので、 もうそれでいいかなという気持ちになった。

Dart でプログラムを書くのは今回初めてでしたが、JavaScript と Java あたりを知っていればかなりスムーズに書き始められるなーという感想でした。引っかかるところがほとんどなかったです(今回書いた範囲では)。適当にググりながら 1日で書けてしまいました。


今回の実験的な要素としては、パーサをいじって set を不要にしてみました。

(追記 2021-03-21: この修正はいったん revert しましたが、一応 trial ブランチに残してあります。)

 func main() {
   var a;
-  set a = 42;
+  a = 42;
 }

文の先頭の set で判別するのをやめて、識別子だったら parseSet_v2() を呼ぶ。もうちょっとめんどくさいかなと思ってましたが、これだけだったら意外と簡単ですね。

List parseSet_v2() {
  // consume("set"); ... これが不要になる
  final t = peek();
  pos++;
  final varName = t.value;
  consume("=");
  final expr = parseExpr();
  consume(";");
  return ["set", varName, expr];
}

List parseStmt() {
  final t = peek();

  if (t.value == "}") {
    return null;
  }

  if      (t.value == "func"    ) { return parseFunc();      } 
  // ...
  // else if (t.value == "set"     ) { return parseSet();       }
  // ...
  else if (t.value == "_cmt"    ) { return parseVmComment(); }
  else {
    if (t.type == "ident") {
      return parseSet_v2();
    } else {
      throw notYetImpl([ t ]);
    }
  }
}

Originally published at memo88.hatenablog.com
ツイッターでシェア
みんなに共有、忘れないようにメモ

sonota88

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント