; "dynwind.scm", wind-unwind-protect for Scheme ; Copyright (c) 1992, 1993 Aubrey Jaffer ; ;Permission to copy this software, to modify it, to redistribute it, ;to distribute modified versions, and to use it for any purpose is ;granted, subject to the following restrictions and understandings. ; ;1. Any copy made of this software must include this copyright notice ;in full. ; ;2. I have made no warranty or representation that the operation of ;this software will be error-free, and I am under no obligation to ;provide any services, by way of maintenance, update, or otherwise. ; ;3. In conjunction with products arising from the use of this ;material, there shall be no use of my name in any advertising, ;promotional, or sales literature without prior written consent in ;each case. ;This facility is a generalization of Common Lisp `unwind-protect', ;designed to take into account the fact that continuations produced by ;CALL-WITH-CURRENT-CONTINUATION may be reentered. ; (dynamic-wind ) procedure ;The arguments , , and must all be procedures ;of no arguments (thunks). ;DYNAMIC-WIND calls , , and then . The value ;returned by is returned as the result of DYNAMIC-WIND. ; is also called just before control leaves the dynamic ;context of by calling a continuation created outside that ;context. Furthermore, is called before reentering the ;dynamic context of by calling a continuation created inside ;that context. (Control is inside the context of if ;is on the current return stack). ;;;WARNING: This code has no provision for dealing with errors or ;;;interrupts. If an error or interrupt occurs while using ;;;dynamic-wind, the dynamic environment will be that in effect at the ;;;time of the error or interrupt. (define dynamic:winds '()) ;@ (define (dynamic-wind ) () (set! dynamic:winds (cons (cons ) dynamic:winds)) (let ((ans ())) (set! dynamic:winds (cdr dynamic:winds)) () ans)) ;@ (define call-with-current-continuation (let ((oldcc call-with-current-continuation)) (lambda (proc) (let ((winds dynamic:winds)) (oldcc (lambda (cont) (proc (lambda (c2) (dynamic:do-winds winds (- (length dynamic:winds) (length winds))) (cont c2))))))))) (define (dynamic:do-winds to delta) (cond ((eq? dynamic:winds to)) ((negative? delta) (dynamic:do-winds (cdr to) (+ 1 delta)) ((caar to)) (set! dynamic:winds to)) (else (let ((from (cdar dynamic:winds))) (set! dynamic:winds (cdr dynamic:winds)) (from) (dynamic:do-winds to (+ -1 delta))))))