BiwaSchemeで同期I/Oもしたい

ゲームの細かいデータハンドリングはSchemeで書いているので、Webアプリ側でも同じロジックを使いたい。というわけでBiwaSchemeにyuniを適当に移植した。で、適当に移植してみると、やっぱり普通のScheme処理系としても使えた方が便利...というわけでbytevectorや同期ファイルI/Oのような欠けている機能もyuniで使っているものは一通り実装した。
BiwaSchemeへのupstreamも意識して機能は基本的にJavaScript側に実装している。
非常に悩ましいのはJavaScriptは文字列がimmutableなため、R7RSで標準となっているmutable-stringsが実装できない点。専用の文字列ハンドルを導入して無理矢理実現するか、そもそも健全なプログラムはmutable-stringsを使うことは無いので実装しないかが悩みどころ。個人的にもmutable-stringsは殆ど使わない。
bytevectorはUint8Arrayで実装した( https://github.com/okuoku/biwasyuni/blob/5e93dc14f9901e0e20b90c56f4e037526f29b1d8/biwasyuni.js#L309 )。同期I/Oはどうせnode.jsでしか使わないのでBufferで良いような気もするが。。yuniではbytevectorのreadは必須でない(R6RSとR7RSで構文が違うので移植性が無い)ため、reader側はサポートを入れていない。
バイナリポートはget_bytes_at(bytevector指定箇所への読み取り)とget_bytes_all(内容全部の読み取り)を拡張している(https://github.com/okuoku/biwasyuni/blob/5e93dc14f9901e0e20b90c56f4e037526f29b1d8/biwasyuni.js#L137 )。openだけはyuniの側でScheme実装としている( https://github.com/okuoku/yuni/blob/7726eb4a0126c9585806160321f9e629e2a1ce2b/lib-runtime/biwascheme/prelib.scm#L12 )。これはbrowserfsがnode.jsと同じようなfsインターフェースをIndexedDBのようなブラウザ上のストレージに対して提供しているため、(current-port等と同じような感じで、)current-fsをオーバーライド可能にした方が良いかなという気がしていることに因る。
いくつかのBiwaScheme標準手続きはoverrideしている。例えばR6RSからR7RSで拡張されたstring-copy等の手続きはr6:string-copyにリネームしてyuniの標準ライブラリ側でR7RS版を実装した。また、yuniではloadは常にPauseを返し最終結果でresumeを呼ぶように修正している。

biwas.define_libfunc("load", 1, 1, function(ar){
    // Override: (load fn)
    // NB: Override load because we may return a Pause on load'ed code.
    // FIXME: Parhaps it's same for scheme-eval...
    var pth = ar[0];
    var src = fs.readFileSync(pth, "utf8"); // FIXME: Make this async.
    return new biwas.Pause(function(pause){
        var interp2 = new biwas.Interpreter(interp, this.on_error);
        interp2.evaluate(src, pause.resume);
    });
});

標準のloadは手続きがPauseを返すことを想定していないため、loadしたスクリプトがPauseを返すと異常な挙動になってしまう。このようにすることで、browserfs等を使ってブラウザ上でもファイルのload等をローカルストレージから実施できるように拡張できる可能性がある。PauseオブジェクトはBiwaSchemeの便利な機能で、継続をwrapしたJavaScriptオブジェクトとしてPauseオブジェクトを生成でき、手続きから返すことでVMの実行を一時中断できる。これによりJavaScript界ではよくある、コールバック駆動の非同期処理を同期処理のように記述することができる。

Isomorphic プログラム環境として実は有望なのではないか

yuniにとって、BiwaSchemeはs7に続く2つめのGeneric runtime処理系となっている。というわけで、yuniのランタイムをロードした状態であれば、擬似的なSyntax-rules( http://d.hatena.ne.jp/mjt/20180521/p1 )やyuniのR6RS-liteライブラリ機構を使えるので、BiwaSchemeと他のScheme処理系で同じように動作するプログラムを容易に組むことができる。(まだFFIが無いので現状実用的でもないが)
Scheme環境の他所に無い特徴として、Gambitのような実用的かつ静的な最適化コンパイラの存在がある。ランタイムサイズを極限まで絞った環境と同じコードがJavaScriptJavaでも動作するので、今までに無いIsomorphicアプリケーションが考えられるかもしれない。