Mosh に例外システムを実装しました

R6RS Standard libraries Chapter 7 Exceptions and conditions に書かれている

  • (raise ...)
  • (raise-continuable ...)
  • (with-exception-handler ...)
  • (guard ...)

を実装しました。(コンディションは未実装)
trunk にコミットしてあります。

使用例 1

以前追加した REPL は以下のようなコードで動いています。

(define (repl . x)
  (define (rec)
    (display "mosh>")
    (print (eval (read (current-input-port)) '()))
    (rec))
  (rec))

(repl)

もしもユーザー入力のミスにより eval 内で何らかのエラーが起こった場合、デフォルトの例外ハンドラが exit していました。
つまりエラーが起きたらインタプリタが終了していました。


今回追加した guard を使えばエラーを catch して内容を表示し、また復帰することが出来ます。
try 〜 catch のようなものです。

(define (repl . x)
  (define (rec)
    (display "mosh>")
    (guard (e
            [e
             (print e)
             (rec)])
            (print (eval (read (current-input-port)) '())))
    (rec))
  (rec))

(repl)

使用例2

with-exception-handler は2つの手続きを引数にとります。
第1引数は例外ハンドラ、第2引数は実行する手続きです。


例えば

(with-exception-handler
  (lambda (e)
    "error")
  (lambda () "no-error"))

は第2引数の手続きが正常終了したので "no-error" が返ります


逆に

(with-exception-handler
  (lambda (e)
    e)
  (lambda () (raise "error") 5))

は "error" が返ります。
raise で送出されたエラーオブジェクトがエラーハンドラに渡り、エラーハンドラはそのオブジェクトをそのま返しています。