unwind-protect.ss
#lang scheme/base

(require (prefix-in finalize: "finalize.ss"))

(define (unwind-protect thunk cleanup)
  (call/cc
   (λ (continuation)
     (finalize:register continuation (λ (value) (cleanup)))
     (thunk))))

(define (rewind-protect thunk cleanup)
  (let ([re-entering? #f])
    (dynamic-wind
     (λ ()
       (when re-entering?
         (raise-user-error (format "~s has already been called ~s may not be entered again." cleanup thunk)))
       (set! re-entering? #t))
     thunk
     cleanup)))

(provide unwind-protect rewind-protect)