When running the r5rs-tests.scm attached, the dynamic-wind test #163 results in:
Error: (tests/r5rs-tests.scm : 472) illegal function
The test is:
(let ((path '())
(c #f))
(let ((add (lambda (s)
(set! path (cons s path)))))
(dynamic-wind
(lambda () (add 'connect))
(lambda ()
(add (call-with-current-continuation
(lambda (c0)
(set! c c0)
'talk1))))
(lambda () (add 'disconnect)))
(if (< (length path) 4)
(c 'talk2)
(reverse path))))
This is similar to the result I get when trying to execute the last form in r5rs_pitfall.scm
;;Not really an error to fail this (Matthias Radestock)
;;If this returns (0 1 0), your map isn't call/cc safe, but is probably
;;tail-recursive. If its (0 0 0), the opposite is true.
(let ((result
(let ()
(define executed-k #f)
(define cont #f)
(define res1 #f)
(define res2 #f)
(set! res1 (map (lambda (x)
(if (= x 0)
(call/cc (lambda (k) (set! cont k) 0))
0))
'(1 0 2)))
(if (not executed-k)
(begin (set! executed-k #t)
(set! res2 res1)
(cont 1)))
res2)))
(if (equal? result '(0 0 0))
(display "Map is call/cc safe, but probably not tail recursive or inefficient.")
(display "Map is not call/cc safe, but probably tail recursive and efficient."))
(newline))
I tried running tinyscheme without the dynamic-wind code in init.scm, and it didn't seem to make a difference for this test.
r5rs test script
the pitfalls source
I've boiled this down to a simple test; without dynamic-wind defined:
trunk e$ rlwrap ./scheme
TinyScheme 1.40
(define cont #f)
cont
ts>
(+ 1 (call/cc (lambda (k) (set! cont k) 0)))
1
ts> cont
#<CONTINUATION>
ts> (cont 2)
Error: illegal function
ts>
;; with dynamic-wind (doesn't matter)
trunk e$ rlwrap ./scheme
TinyScheme 1.40
(define cont #f)
cont
ts>
(+ 1 (call/cc (lambda (k) (set! cont k) 0)))
1
ts> cont
#<CLOSURE>
ts> (cont 2)
Error: illegal function
ts>
Bisecting the repository, it seems the call/cc bug was introduced in checkin 15 which brought the version number to 1.32. I have tracked it down to the use of reverse_in_place(). The following uses of reverse_in_place() are not compatible with call/cc:
OP_E1ARGS -- this causes the "simple test" problem in comment #1
OP_LET1 -- this causes the failure in r5rs-tests.scm dynamic-wind test #163
OP_LET1REC -- not OK based on the similarity with OP_LET1
By replacing these three occurrences of
reverse_in_place(sc, sc->NIL, sc->args);
with
reverse(sc, sc->args);
I have eliminated the call/cc test failures.
The other instances of reverse_in_place() seem OK:
OP_LET2 -- reverses a list created locally for named let and not captured
OP_RDLIST & OP_RDDOT -- were in 1.30 and (read) internals not subject to capture by call/cc
main() -- used for *args*, cannot be captured by call/cc
-- e