引き続き、ISLisp の検証プログラム対応を続けている
NG は多々あるんだけど、まずは、全ての検証式の処理以前に途中で止まってしまう問題をクリアしないといけない。でないと合格率も算出できない
だが、ここまで進んでいると、想像もしなかった ISLisp 仕様が登場してきて、なかなかおもしろくなってきた
(tagbody tag1 (tagbody tag2 (unwind-protect (go tag1) ;;; tag2 invalid (go tag2))))
当初、これが無限ループではなく、<control-error>
にならなきゃいけない理由が分からなかった
答えとしては、try〜finally 的な処理を行う (unwind-protect FORM CLEANUP-FORM)
の CLEANUP-FORM
部分では大域脱出的なことをしてはいけないから…らしい。上の場合だと (go tag2)
が <control-error>
になるということのようだ。
(defun if ())
という式があって、<program-error>
にしなければいけないというのは分かるんだが、なぜか (with-handler)
で補足できず、検証プログラム自体が NG 判定する前に止まってしまう
> NG: (+ (defdynamic *dynamic-2* 2)) -> *dynamic-2* [#<Error> <error>] > NG: (defun) -> #<Error> <error> [#<Error> <program-error>] > NG: (defun foo) -> #<Error> <error> [#<Error> <program-error>] > NG: (defun nil nil) -> #<Error> <domain-error> [nil] > NG: (defun t nil) -> #<Error> <domain-error> [t] too many arguments at if at tp-eval at setq at tp-$error-prim at tp-$error at case at while at let at for at with-open-input-file at with-standard-input at tp-main at while at let at for at let at tp-all Makefile:89: recipe for target 'verify' failed make: *** [verify] Error 1 exit status 2
しばらく悩んだが、(if)
の再定義ができてしまって、引数ゼロ個の関数になってしまっていて、それが検証プログラム本体の動作も変えてしまったせいらしい。
うける!
(defun foo-5 () 1) (flet ((foo-5 () (foo-5))) (foo-5))
無限ループになってしまった。でも、これは何が悪いか分かる。
(flet)
の定義するローカル関数はローカル関数自身からは見えないはずなので、無限ループになるはずがない。
が、末尾呼び出し最適化を施す際に、関数に自分の名前が分かるようにしてしまったんだよなー。 これは ISLisp の仕様が分からん系ではなくて、純粋に不具合だった。
だいたいのケースは
- 無限ループになる
- 例外を補足できない状態になる
のどちらかみたい。もうさすがに検証プログラムの仕組み自体を実行できないケースはないかな…【油断】