読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

アセンブリでLISP開発日誌 (2)

前回からとにかくVM命令を追加していった。さらにSchemeで作ったVM側でコンパイラを作っていた(後述)。現時点でアセンブリで2500行ほど。

github.com

Forth処理系を作った経験から、

  • とにかく早めに色がついたREPLを作る
  • 内部情報をイイカンジに出力する
  • できるだけ自動テスト書く

ようにするとかなりやる気が出るのがわかってたので、ちょっとだけ力入れた。

f:id:phaendal:20160306160806p:plain

アセンブリで書いたVMの上で〜みたいにいちいち書くの面倒なんだけど、Lispkit Lispと呼んだ方がいいのかな、正式な用語調べるのがちょっと億劫だし、気合い入れたいので名前をつけていく。

  • S式で書かれたSECDマシンのVM命令(LISPではない)のことはS-CODEと呼ぶ。上の (LDF (LDE (0 . 0)みたいなの。
  • その上で動かしたいオリジナルのLISP方言をAmeLisp、又は単にAmeと呼ぶ。
  • 最初にSchemeで書いたSECD VMVM/S
  • アセンブリで書いてるVMVM/A(Linux x86_64)

次の大きい目標はVM/A上でAmeのREPLを動かすこと。しかしAme→S-CODEコンパイラアセンブリで書く気はさすがに無い。

なのでまずVM/S上のAmeでAme→S-CODEコンパイラ(Compiler/Ame)を書く。簡単なREPLも。それにCompiler/Ame自身を食わせて、CompilerのS-CODEを作らせる。そのS-CODEをVM/Aで読み込んで目標を達成する。

VM/Aの命令は継続と限定継続以外は多分できた。この2つはコンパイラには使わないけど、SECDマシンなら楽に実装できるのでやってしまおう。

それからVM/A上にCONS,CAR,EQ?などのプリミティブ命令を追加する必要がある。最低限何が必要かは、VM/S上でCompiler/Ameを書いているうちにわかる。

といってもCompiler/Ameも結構できてきた。(githubscheme/builtin.lispにある) 今のところ簡単な命令だけでいけそうな雰囲気。

最初はScheme#t#fをそのまま使ってたんだけど、好みでnil true false undefを使うことにした。SELはfalseとundefで偽と判定する。ここの書き換えを適当にやったので、変なバグ出るかもしれなくてちょっと怖い。

VM/Sの方は2,3日で動いたんだけど、VM/Aは2/26から始めて9日、ようやく体力勝負に持ち込めるとこに来た。やっぱりGCレジスタ書き換え周りのバグが追うのキツい。ランボー怒りのプリントデバッグじゃなくて、デバッガの上手い使い方練習しないとなあ……

広告を非表示にする