Ribbon: Cでプロトタイプする

いきなり C++ で作り出しても C++ のオーバーヘッドなのか自分の書いたコードが悪いのか区別が付かなそうなので、C++でやろうとしていることをCによる手動で実装しておくことにした。
アルゴリズムはC++でやろうとしているのと同じ、 リファレンスカウント + 循環参照検出 とする。ある程度できてきたら、Espuinoと同じ固定長オブジェクト方式の実装も用意したい。

ヒープの設計
数値型は32/64bitsの固定巾としてタグの埋め込みは行わず、型を表現するビット群は別の配列に確保することにする。これにより、浮動小数点数をヒープオブジェクトにする必要がなくなるが、型を他所のメモリに置くことでメモリ負荷(ポインタの演算負荷)が増えるというデメリットがある。
ヒープに置かれるオブジェクトは参照カウントのみのオブジェクト(文字列等)と、循環参照検出の対象になるオブジェクト(Vector等)に分かれることになる。
C言語にはスタック上の参照をスキャンするためのポータブルな方法は存在しないので、専用の 参照スタック を用意し、明示的に確保させる。Scheme側のヒープを参照するCコードは、
- スタックフレームの作成(enter)
- スタックフレームの破棄(leave)
の操作を関数の先頭および return
直前にやる必要がある。enterとleaveの数は1対1対応しなくても良い。例えば、 longjmp
で本来行われるleave処理を飛ばしてしまっても、自分が実施したenterまでのスタックは解放しても良いことが自明となる。 (C++では、longjmp
のかわりに try
〜 catch
を使えばデストラクタの呼出しで代替できる。)

要実装なプリミティブが103個もある
1個1分で実装しても1時間以上掛かるじゃないか。。

型のunwrap
ribに格納しなくても良い型は格納しないことにした。Scheme上なら良いけど、Cでいちいちribから実データを取り出すコードを書くのが面倒なため。
ただし、 vector?
はunwrapできない 。これはR7RS Schemeのtype disjointルールに因る。ある1つのオブジェクトについて、例えば同時に procedure?
と vector?
が真になってはいけない。
3.2. Disjointness of types
No object satisfies more than one of the following predicates:
boolean?
bytevector?
char?
eof-object?
null?
number?
pair?
port?
procedure?
string?
symbol?
vector?
Scheme上のVM実装では rib の表現にvectorを使用しているため、vectorをunwrapしてしまうと、全ての rib に格納されるタイプのオブジェクトについて vector?
が真になってしまう。
... いや vector だけは特別扱いしても良いかな。。

とりあえずGC以外のオブジェクトシステムを実装
シリアライズしたSchemeオブジェクトをヒープ上に展開するところまで実装しておいた。これにVMとプリミティブを付ければインタプリタになるはず。
すでに20KiB超えてんだけど。。しかも、ビルドは通るけど結構バグっている。
こんな激烈に間違っててエラーなく動いちゃうのか。。(実際のプログラムを流しているわけではないのでまだ間違った事が起きてそう)