1:
2:
3:
4:
5:
6:
7: (use gauche.test)
8:
9: (test-start "dynamic-wind and call/cc")
10:
11: (define c #f)
12:
13:
14:
15:
16: (define (callcc-test1)
17: (let ((r '()))
18: (let ((w (let ((v 1))
19: (set! v (+ (call-with-current-continuation
20: (lambda (c0) (set! c c0) v))
21: v))
22: (set! r (cons v r))
23: v)))
24: (if (<= w 1024) (c w) r))))
25:
26: (test "call/cc (env)" '(2048 1024 512 256 128 64 32 16 8 4 2)
27: callcc-test1)
28:
29:
30:
31: (test* "call/cc (values)" '(1 2 3)
32: (receive x (call-with-current-continuation
33: (lambda (c) (c 1 2 3)))
34: x))
35:
36: (test* "call/cc (values2)" '(1 2 3)
37: (receive (x y z) (call-with-current-continuation
38: (lambda (c) (c 1 2 3)))
39: (list x y z)))
40:
41: (test* "call/cc (values3)" '(1 2 (3))
42: (receive (x y . z)
43: (call-with-current-continuation
44: (lambda (c) (c 1 2 3)))
45: (list x y z)))
46:
47: (test* "call/cc (values4)" *test-error*
48: (receive (x y)
49: (call-with-current-continuation
50: (lambda (c) (c 1 2 3)))
51: (list x y)))
52:
53:
54:
55:
56: (define (callcc-test2)
57: (let ((cc #f)
58: (r '()))
59: (let ((s (list 1 2 3 4 (call/cc (lambda (c) (set! cc c) 5)) 6 7 8)))
60: (if (null? r)
61: (begin (set! r s) (cc -1))
62: (list r s)))))
63:
64: (test "call/cc (inline)" '((1 2 3 4 5 6 7 8) (1 2 3 4 -1 6 7 8))
65: callcc-test2)
66:
67:
68:
69:
70: (test "call/cc (do)" 6
71: (lambda ()
72: (do ((x 0 (+ x 1))
73: (y 0 (call/cc (lambda (c) c))))
74: ((> x 5) x)
75: #f)))
76:
77:
78:
79:
80:
81:
82:
83:
84:
85: (define (callcc-over-cstack)
86: (call-with-current-continuation
87: (lambda (c)
88: (sort '(1 2 3 4 5 6) (lambda (a b) (c 10))))))
89:
90: (test "call/cc (cstack)" 10 callcc-over-cstack)
91:
92: (test "call/cc (cstack2)" '(10 . 11)
93: (lambda () (cons (callcc-over-cstack) 11)))
94:
95: (test "call/cc (cstack, values)" '(10 11)
96: (lambda ()
97: (receive x
98: (call-with-current-continuation
99: (lambda (c)
100: (sort '(1 2 3 4 5 6)
101: (lambda (a b) (c 10 11)))))
102: x)))
103:
104: (test "call/cc (cstack, two level)" '(10 . 11)
105: (lambda ()
106: (cons (call-with-current-continuation
107: (lambda (c)
108: (sort '(1 2 3 4 5 6)
109: (lambda (a b)
110: (sort '(1 2 3 4 5 6)
111: (lambda (a b) (c 10)))))))
112: 11)))
113:
114: (test "call/cc (cstack, two level, two hop)" '(11 . 11)
115: (lambda ()
116: (cons (call-with-current-continuation
117: (lambda (c)
118: (sort '(1 2 3 4 5 6)
119: (lambda (a b)
120: (c (+ (call-with-current-continuation
121: (lambda (d)
122: (sort '(1 2 3 4 5 6)
123: (lambda (a b) (d 10)))))
124: 1))))))
125: 11)))
126:
127:
128:
129: (test "call/cc & dynwind (cstack)" '(a b c)
130: (lambda ()
131: (let ((x '()))
132: (call-with-current-continuation
133: (lambda (c)
134: (dynamic-wind
135: (lambda () (set! x (cons 'c x)))
136: (lambda ()
137: (sort '(1 2 3 4 5 6)
138: (lambda (a b)
139: (set! x (cons 'b x))
140: (c 0)))
141: (set! x (cons 'z x))
142: )
143: (lambda () (set! x (cons 'a x))))))
144: x)))
145:
146:
147:
148:
149:
150: (define (dynwind-test1)
151: (let ((path '()))
152: (let ((add (lambda (s) (set! path (cons s path)))))
153: (dynamic-wind
154: (lambda () (add 'connect))
155: (lambda ()
156: (add (call-with-current-continuation
157: (lambda (c0) (set! c c0) 'talk1))))
158: (lambda () (add 'disconnect)))
159: (if (< (length path) 4)
160: (c 'talk2)
161: (reverse path)))))
162:
163: (test "dynamic-wind"
164: '(connect talk1 disconnect connect talk2 disconnect)
165: dynwind-test1)
166:
167:
168: (define (dynwind-test2)
169: (let ((path '()))
170: (dynamic-wind
171: (lambda () (set! path (cons 1 path)))
172: (lambda () (set! path (append (dynwind-test1) path)))
173: (lambda () (set! path (cons 3 path))))
174: path))
175:
176: (test "dynamic-wind"
177: '(3 connect talk1 disconnect connect talk2 disconnect 1)
178: dynwind-test2)
179:
180: (test "dynamic-wind" '(a b c d e f g b c d e f g h)
181: (lambda ()
182: (let ((x '())
183: (c #f))
184: (dynamic-wind
185: (lambda () (push! x 'a))
186: (lambda ()
187: (dynamic-wind
188: (lambda () (push! x 'b))
189: (lambda ()
190: (dynamic-wind
191: (lambda () (push! x 'c))
192: (lambda () (set! c (call/cc identity)))
193: (lambda () (push! x 'd))))
194: (lambda () (push! x 'e)))
195: (dynamic-wind
196: (lambda () (push! x 'f))
197: (lambda () (when c (c #f)))
198: (lambda () (push! x 'g))))
199: (lambda () (push! x 'h)))
200: (reverse x))))
201:
202:
203: (test "dynamic-wind (multival)" '(a b c)
204: (lambda ()
205: (receive x
206: (dynamic-wind (lambda () #f)
207: (lambda () (values 'a 'b 'c))
208: (lambda () #f))
209: x)))
210:
211: (test "dynamic-wind (multival)" '()
212: (lambda ()
213: (receive x
214: (dynamic-wind (lambda () #f)
215: (lambda () (values))
216: (lambda () #f))
217: x)))
218:
219:
220: (test "dynamic-wind - error in before thunk"
221: '(a b c d h)
222: (lambda ()
223: (let ((k '()))
224: (with-error-handler (lambda (e) #f)
225: (lambda ()
226: (push! k 'a)
227: (dynamic-wind
228: (lambda () (push! k 'b))
229: (lambda ()
230: (push! k 'c)
231: (dynamic-wind
232: (lambda () (push! k 'd) (error "ho"))
233: (lambda () (push! k 'e))
234: (lambda () (push! k 'f)))
235: (push! k 'g))
236: (lambda () (push! k 'h)))
237: (push! k 'i)))
238: (reverse k))))
239:
240: (test "dynamic-wind - error in after thunk"
241: '(a b c d e f h)
242: (lambda ()
243: (let ((k '()))
244: (with-error-handler (lambda (e) #f)
245: (lambda ()
246: (push! k 'a)
247: (dynamic-wind
248: (lambda () (push! k 'b))
249: (lambda ()
250: (push! k 'c)
251: (dynamic-wind
252: (lambda () (push! k 'd))
253: (lambda () (push! k 'e))
254: (lambda () (push! k 'f) (error "ho")))
255: (push! k 'g))
256: (lambda () (push! k 'h)))
257: (push! k 'i)))
258: (reverse k))))
259:
260:
261:
262:
263: (define (test-thunk body)
264: (let ((x '()))
265: (with-error-handler
266: (lambda (e) (push! x 'x))
267: (lambda ()
268: (call/cc
269: (lambda (c)
270: (dynamic-wind
271: (lambda () (push! x 'a))
272: (lambda ()
273: (dynamic-wind
274: (lambda () (push! x 'b))
275: (lambda () (body c))
276: (lambda () (push! x 'c) (car 3))))
277: (lambda () (push! x 'd)))))))
278: (reverse x)))
279:
280: (test* "restart & dynamic-wind with error(1)" '(a b c x d)
281: (test-thunk (lambda (cont) (cont #t))))
282:
283: (test* "restart & dynamic-wind with error(2)" '(a b c x d)
284: (test-thunk (lambda (cont)
285: (with-error-handler
286: (lambda (e) (cont #t))
287: (lambda () (car 3))))))
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299: (define (sum-rec n)
300: (if (> n 0)
301: (+ n (sum-rec (- n 1)))
302: 0))
303:
304: (test "stack overflow" (/ (* 1000 1001) 2)
305: (lambda () (sum-rec 1000)))
306:
307: (test "stack overflow" (/ (* 4000 4001) 2)
308: (lambda () (sum-rec 4000)))
309:
310: (define (sum-rec-apply n)
311: (if (> n 0)
312: (apply + n (apply sum-rec (- n 1) '()) '())
313: 0))
314:
315: (test "stack overflow (apply)" (/ (* 2000 2001) 2)
316: (lambda () (sum-rec-apply 2000)))
317:
318: (test "stack overflow (apply)" (/ (* 3000 3001) 2)
319: (lambda () (sum-rec-apply 3000)))
320:
321:
322:
323:
324: (test "call-with-output-file -> port-closed?"
325: #t
326: (lambda ()
327: (let ((p #f))
328: (call-with-output-file
329: "tmp1.o"
330: (lambda (port)
331: (write '(a b c d e) port)
332: (set! p port)))
333: (port-closed? p))))
334:
335: (test "call-with-input-file -> port-closed?"
336: '(#t a b c d e)
337: (lambda ()
338: (let* ((p #f)
339: (r (call-with-input-file "tmp1.o"
340: (lambda (port)
341: (set! p port)
342: (read port)))))
343: (cons (port-closed? p) r))))
344:
345: (test "with-output-to-file -> port-closed?"
346: '(#t #f)
347: (lambda ()
348: (let ((p #f))
349: (with-output-to-file "tmp1.o"
350: (lambda ()
351: (set! p (current-output-port))
352: (write '(a b c d e))))
353: (list (port-closed? p)
354: (eq? p (current-output-port))))))
355:
356: (test "with-input-from-file -> port-closed?"
357: '(#t #f)
358: (lambda ()
359: (let* ((p #f)
360: (r (with-input-from-file "tmp1.o"
361: (lambda ()
362: (set! p (current-input-port))
363: (read)))))
364: (list (port-closed? p)
365: (eq? p (current-input-port))))))
366:
367:
368:
369:
370:
371: (test "Al's call/cc test" 1
372: (lambda () (call/cc (lambda (c) (0 (c 1))))))
373:
374: (test-end)