引き続き、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 の仕様が分からん系ではなくて、純粋に不具合だった。
だいたいのケースは
- 無限ループになる
- 例外を補足できない状態になる
のどちらかみたい。もうさすがに検証プログラムの仕組み自体を実行できないケースはないかな…【油断】