標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

引き続き、ISLisp 検証パズルを進めてる

引き続き、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 の仕様が分からん系ではなくて、純粋に不具合だった。


だいたいのケースは

  • 無限ループになる
  • 例外を補足できない状態になる

のどちらかみたい。もうさすがに検証プログラムの仕組み自体を実行できないケースはないかな…【油断】