#lang scheme

(define test-expr
  (lambda (make-lit make-sub make-catch make-throw make-both)
    (make-sub (make-catch (make-sub (make-both 4 3) (make-lit 1)))
              (make-catch (make-sub (make-throw (make-lit 2)) (make-lit 1))))))

(define eval-big
  (lambda (e)
    (e (lambda (n)
         (lambda (c) (c n)))
       (lambda (e1 e2)
         (lambda (c) (e1 (lambda (n1) (e2 (lambda (n2) (c (- n1 n2))))))))
       (lambda (e1)
         (lambda (c) (c (e1 (lambda (n) n)))))
       (lambda (e1)
         (lambda (c) (e1 (lambda (n) n))))
       (lambda (n1 n2)
         (lambda (c) (* (c n1) (c n2)))))))

; Try: ((eval-big test-expr) (lambda (n) n))

(require (only-in scheme/control reset abort shift))

(define eval-meta
  (lambda (e)
    (e (lambda (n)
         (lambda () n))
       (lambda (e1 e2)
         (lambda () (- (e1) (e2))))
       (lambda (e1)
         (lambda () (reset (e1))))
       (lambda (e1)
         (lambda () (abort (e1))))
       (lambda (n1 n2)
         (lambda () (shift c (* (c n1) (c n2))))))))

; Try: ((eval-meta test-expr))
