RibbitでSchemeテストを通したい会

とりあえず面倒なところをScheme上で済ませてしまおうの会 ...CやJavaで実装するVMや標準ライブラリはたぶん1000行とかに収まるので。

import
をライブラリでも出力する
... これは逆に import
をプログラムでも出力しないようにした方が良いな。
これをやらないと、マクロ展開時にプログラムが依存しているライブラリを回収できない。

(integer? 1.0)
は真である
わりと忘れがちだけど、不正確数と正確数の両方をサポートしたScheme処理系では (integer? 1.0)
において小数点以下がゼロの数は真値を返却する。
$ gosh
gosh> (integer? 1.0)
#t
シリアライズ時に真の整数として処理したいのは正確数だけなので、一旦 exact?
を挟んでチェックする。そうでないと vector-ref
等にindexとして不正確数を渡してしまうことになる。

case
の実装
自前の標準ライブラリ実装が case
をimportしわすれていた。
この実装自体は割とテストしてるけど case
が無いScheme処理系で試したことが無かったんだな。。

when
と unless
もだった
when
はいわゆる 2-arm な if
で表現できるので厳密にはcore formじゃなかった。

可変長引数の実行がおかしい
(import (rvm-primitives))
(define (check a . b)
(if (eqv? '() b)
(error "OK" a)
(error "ERR" a)))
(check 12345)
これがVM内でクラッシュする。 (check 12345 1234)
のように、 b
が nil にならないようにすると正常に実行できる。
... 普通に実装漏れだった。
argnc
は "余り" 引数の数だが、可変長引数の手続きで argnc
がゼロになるケースは特別扱いしないといけないのを忘れてた。

unless
が正常に動かない
(define step1 'notyet)
(define step2 'notyet)
(define-syntax unless
(syntax-rules ()
((unless test result1 result2 ...)
(if (not test)
(begin result1 result2 ...)))))
(define (check x)
(unless x
(set! step1 'ok) ;; ★ ← これがスキップされる
(set! step2 'ok)))
これは if
の中に書かれた begin
が top-level の begin
だと判断されて消えるのが原因だった。そもそもtop-levelフラグを寝かす必要がある。

core0
のテストが通った
さてこれからひたすら欠けている機能を実装していかないといけないのか。。

テストを仕分け
通る:
通らない:
inexact1
(シリアライズで失敗する) みたいな奴は修正しないと不味いな。。逆に、syntax-rulesのテストみたいに現状のフロントエンドでは成功しないテストもある。

NaN
はハッシュテーブルに入れられない
NaN
と何かの比較は常に偽になるので、ハッシュテーブルに NaN
と紐付いたオブジェクトを入れても取り出す方法がない。特に NaN
!= NaN
なのに注意する。
NaNの替わりに別のオブジェクトを代表として使うことで回避した。。これで inexact1
が治った。

hashtablesを実装
hashtable-fold
とかは無くても良いかなぁ。。その替わり make-bytevector-hashtable
とかあっても良いんではないか説がある。 make-string-hashtable
は有るんだし。。
hashtable-update!
が何で必要なのかと思ったら、この形式のAPIがあるとキーのハッシュ値を1度だけ計算すれば良いからか。