;; -*- Mode: Irken -*-

(include "lib/core.scm")
(include "lib/random.scm")

(define (base-exception-handler exn) : ((rsum 'a) -> 'b)
  (error1 "uncaught exception" exn))

(define *the-exception-handler* base-exception-handler)

(define (raise exn)
  (*the-exception-handler* exn)
  )

(defmacro try
  ;; done accumulating body parts, finish up.
  (try (begin body0 ...) <except> exn-match ...)
  -> (let/cc $exn-k
       (let (($old-hand *the-exception-handler*))
	 (set!
	  *the-exception-handler*
	  (lambda ($exn)
	    (set! *the-exception-handler* $old-hand)
	    ($exn-k
	     (match $exn with
	       exn-match ...
	       _ -> (raise $exn)))))
	 (let (($result (begin body0 ...)))
	   (set! *the-exception-handler* $old-hand)
	   $result)))
  ;; accumulating body parts...
  (try (begin body0 ...) body1 body2 ...) -> (try (begin body0 ... body1) body2 ...)
  ;; begin to accumulate...
  (try body0 body1 ...)                   -> (try (begin body0) body1 ...)
  )

(define (random-barf)
  (if (= (logand (random) 1) 1)
      (raise (:OtherException #t #t))
      7))

(define (thing)
  (try
   (let loop ((n 0))
     (if (= n 100)
         (raise (:MyException 12))
         (begin
           (random-barf)
           (loop (+ n 1)))))
   except
   (:MyException value) -> value
   (:OtherException x)  -> (+ x 9)
   ))

(thing)