3imp 伝統的マクロとバイトコードの変換
伝統的マクロ
VMの方は触らずに,コンパイラの方だけを修正した. マクロ展開時と定義時にマクロテーブルに追加したり,参照したりするようにしている. トップレベル変数とは名前空間が違うけど,これでいいよな… ということで以下のようにletとかbeginとかいろいろ自由に拡張できるようになった. また時間があれば他のマクロシステムも増やしたい.
|
|
バイトコードをかっこよく
今までのバイトコードは下のような感じで,次の命令を繋げていく構造だった. schemeで扱うには適しているようなだけど,後々VMをCで書きたいのでもっと線形な感じにしたい.
|
|
こんな感じにした. これでCとのインターフェイスも簡単にかけそう.
|
|
この作業はなかなか大変だった. 問題点はclosureだった. closureをトップレベル変数に束縛しない限りは,そのclosureに対応するバイトコードが存在するから, closureオブジェクトには単純に,#(開始番地 終了番地)を入れておけばいい. しかし,トップレベル変数に束縛した場合は,呼び出し時には開始番地や終了番地が分かったところでそのバイトコードの自体がないので,呼び出せない. 色々考えてみる
- 組み込み関数(+,-,…)のclosureは命令コードをまた別の場所においておかねば
- それに,defineでclosureを定義するときにも気をつけないと
- closure生成時に本体の命令コードを全部RAMに突っ込んで,アドレスだけ書いておけば動くだろう
- いや,トップレベルに束縛される可能性のないclosureをRAMに移動させるのはコストがかかる
- よし.必要なclosureだけRAMに移動させよう
- 必要な時ってのはset!かdefineでトップレベルに束縛されるとき
(ただし,コンパイラが吐いた命令コードの領域をROM,VM自身が後から追加した命令コードの領域をRAMと 勝手に呼んでる)
まだ考えることはある
- close,test,frameは命令のアドレス(分岐先とか返り番地とか)を含んでいるので,そのアドレスをちゃんと変換せねば. - 最初油断してた - これは,再帰的に書いていけば解決できた
- 継続はどうするんや - 継続は結局中身はスタックの情報を含んだclosureオブジェクトなので大丈夫のはず - 大丈夫だった
この変換プログラムとVMコードを書き直した. 無駄にRAMを使わないようになったので,よかったよかった. VMは方は前よりも簡単になった. こんな感じになった.
|
|