CALL STACK を使いたい、のだけど
元々やりたいことは buffer にある expression を read して eval、的なこと。で condition を signal ったら CALL STACK を表示したい。
stack-trace という関数があって、呼び出すと CALL STACK を出力してくれる。のだけど、signal ったのを handler-case なりで拾って stack-trace すると、その時点での CALL STACK、つまり stack-trace の呼び出しのとこからになってしまう。
toggle-trace-on-error で、だと *Trace Output* に出力してくれちゃうので使いにくい、と思ったのだけど、xyzzy は si::*trace-on-error* が non-nil だったら *error-output* に CALL STACK を出力してるだけで、*error-output* を他の stream にしてしまえばそっちに出力させることができた。
(let ((si::*trace-on-error* t) (*error-output* *standard-output*)) (when :true (format nil "~A" (+ 33 (= :foo :bar))))) >CALL STACK 17: (= :foo :bar) >CALL STACK 16: (+ calculating arguments...) >CALL STACK 15: (format calculating arguments...) >CALL STACK 14: (progn ((format nil "~A" ...))) >CALL STACK 13: (if (:true (progn (format nil "~A" ...)))) >CALL STACK 12: (when (:true (format nil "~A" ...))) >CALL STACK 11: (let (((system:*trace-on-error* t) (*error-output* *standard-output*)) (when :true (format nil "~A" ...)))) >CALL STACK 10: (eval (let ((system:*trace-on-error* t) (*error-output* *standard-output*)) (when :true (format nil "~A" ...)))) >CALL STACK 9: (system:*byte-code ...) >CALL STACK 8: (eval-region 349 492 #<buffer stream 82383804>) >CALL STACK 7: (system:*byte-code ...) >CALL STACK 6: (editor::eval-last-print-sexp1 #<buffer stream 82383804> 349 492) >CALL STACK 5: (system:*byte-code ...) >CALL STACK 4: (eval-last-sexp #<buffer stream 82383804>) >CALL STACK 3: (system:*byte-code ...) >CALL STACK 2: (#<lexical-closure: eval-print-last-sexp>) >CALL STACK 1: (command-execute eval-print-last-sexp) 不正なデータ型です: :foo: number
後は
- handler-case なりで回復したら出力しなくていい。
- command-execute とか eval-expression とかまではいらない。上の例なら `(when :true ...)` のとこからでいい。
なんだけど、めんどいことになりそうだ。一旦 string-output-stream に出力させて string として取り出したのを parse(?)して、くらいしか思いつかん。