/collects/tests/racket/prompt-tests.rktl

http://github.com/gmarceau/PLT · Racket · 2306 lines · 2035 code · 121 blank · 150 comment · 69 complexity · b940c6f53da740af690c14e4011ee153 MD5 · raw file

Large files are truncated click here to view the full file

  1. (let ([try
  2. (lambda (thread m-top n-top do-mid-stream do-abort)
  3. (let ([result #f])
  4. (thread-wait
  5. (thread
  6. (lambda ()
  7. (set! result
  8. (let pre-loop ([m m-top])
  9. (if (zero? m)
  10. (list
  11. (do-mid-stream
  12. (lambda ()
  13. (call-with-continuation-prompt
  14. (lambda ()
  15. (let loop ([n n-top])
  16. (if (zero? n)
  17. (do-abort
  18. (lambda ()
  19. (abort-current-continuation
  20. (default-continuation-prompt-tag)
  21. (lambda () 5000))))
  22. (+ (loop (sub1 n))))))))))
  23. (list (car (pre-loop (sub1 m))))))))))
  24. (test '(5000) values result)))])
  25. (try thread 5000 10000 (lambda (mid) (mid))
  26. (lambda (abort) (((call/cc
  27. (lambda (k) (lambda () k))))
  28. (lambda () (lambda (x) 5000))))))
  29. (test-breaks-ok)
  30. ;;----------------------------------------
  31. ;; Prompt escapes
  32. ;; Simple return
  33. (test 10 call-with-continuation-prompt
  34. (lambda () 10))
  35. (test-values '(10 11) (lambda ()
  36. (call-with-continuation-prompt
  37. (lambda () (values 10 11)))))
  38. (test-values '() (lambda ()
  39. (call-with-continuation-prompt
  40. (lambda () (values)))))
  41. ;; Aborts
  42. (test 11 call-with-continuation-prompt
  43. (lambda () (abort-current-continuation
  44. (default-continuation-prompt-tag)
  45. 11))
  46. (default-continuation-prompt-tag)
  47. values)
  48. (test 11 call-with-continuation-prompt
  49. (lambda () (abort-current-continuation
  50. (default-continuation-prompt-tag)
  51. (lambda () 11))))
  52. (test 12 call-with-continuation-prompt
  53. (lambda () (abort-current-continuation
  54. (default-continuation-prompt-tag)
  55. 12))
  56. (default-continuation-prompt-tag)
  57. values)
  58. (test 12 call-with-continuation-prompt
  59. (lambda () (abort-current-continuation
  60. (default-continuation-prompt-tag)
  61. (lambda () 12)))
  62. (default-continuation-prompt-tag))
  63. (test-values '(11 12)
  64. (lambda ()
  65. (call-with-continuation-prompt
  66. (lambda () (abort-current-continuation
  67. (default-continuation-prompt-tag)
  68. 11
  69. 12))
  70. (default-continuation-prompt-tag)
  71. values)))
  72. (test-values '(11 12)
  73. (lambda ()
  74. (call-with-continuation-prompt
  75. (lambda () (abort-current-continuation
  76. (default-continuation-prompt-tag)
  77. (lambda () (values 11
  78. 12)))))))
  79. (test 8 call-with-continuation-prompt
  80. (lambda () (+ 17
  81. (abort-current-continuation
  82. (default-continuation-prompt-tag)
  83. (lambda () 8)))))
  84. (test 81 call-with-continuation-prompt
  85. (lambda () (+ 17
  86. (call-with-continuation-prompt
  87. (lambda ()
  88. (abort-current-continuation
  89. (default-continuation-prompt-tag)
  90. (lambda () 81)))
  91. (make-continuation-prompt-tag)))))
  92. (let ([p (make-continuation-prompt-tag)])
  93. (test 810 call-with-continuation-prompt
  94. (lambda () (+ 17
  95. (call-with-continuation-prompt
  96. (lambda ()
  97. (abort-current-continuation
  98. p
  99. 810))
  100. (make-continuation-prompt-tag))))
  101. p
  102. values))
  103. ;; Aborts with handler
  104. (test 110 call-with-continuation-prompt
  105. (lambda () (abort-current-continuation
  106. (default-continuation-prompt-tag)
  107. 11))
  108. (default-continuation-prompt-tag)
  109. (lambda (x) (* x 10)))
  110. (test 23
  111. call-with-continuation-prompt
  112. (lambda () (abort-current-continuation
  113. (default-continuation-prompt-tag)
  114. 11
  115. 12))
  116. (default-continuation-prompt-tag)
  117. (lambda (x y) (+ x y)))
  118. ;; Handler in tail position:
  119. (test '(11 12 17)
  120. 'handler-in-tail-position
  121. (with-continuation-mark
  122. 'x 16
  123. (call-with-continuation-prompt
  124. (lambda () (abort-current-continuation
  125. (default-continuation-prompt-tag)
  126. 11
  127. 12))
  128. (default-continuation-prompt-tag)
  129. (lambda (x y)
  130. (with-continuation-mark
  131. 'x 17
  132. (list* x y
  133. (continuation-mark-set->list
  134. (current-continuation-marks)
  135. 'x)))))))
  136. (test-breaks-ok)
  137. ;; Abort to a prompt in a d-w post that is deeper than a
  138. ;; prompt with the same tag at the continuation-jump site:
  139. (test 0
  140. values
  141. (let ([p1 (make-continuation-prompt-tag)]
  142. [p2 (make-continuation-prompt-tag)])
  143. (let/cc k
  144. (call-with-continuation-prompt
  145. (lambda ()
  146. (call-with-continuation-prompt
  147. (lambda ()
  148. (dynamic-wind
  149. void
  150. (lambda ()
  151. (call-with-continuation-prompt
  152. (lambda ()
  153. (k 0))
  154. p2))
  155. (lambda ()
  156. (abort-current-continuation p1 (lambda () 0)))))
  157. p1))
  158. p2))))
  159. ;; ----------------------------------------
  160. ;; Continuations
  161. (with-cc-variants
  162. (test -17
  163. call-with-continuation-prompt
  164. (lambda () -17)))
  165. (with-cc-variants
  166. (test 17
  167. call-with-continuation-prompt
  168. (lambda ()
  169. (let/cc k
  170. (k 17)))))
  171. (test-breaks-ok)
  172. (with-cc-variants
  173. (test 29
  174. 'in-other-prompt1
  175. (let ([retry #f])
  176. (test 35
  177. call-with-continuation-prompt
  178. (lambda ()
  179. (+ 18
  180. (let/cc k
  181. (set! retry k)
  182. 17))))
  183. (+ 1 (call-with-continuation-prompt
  184. (lambda ()
  185. (retry 10)))))))
  186. (with-cc-variants
  187. (test 60
  188. 'in-other-prompt2
  189. (let ([retry #f])
  190. (test 35
  191. call-with-continuation-prompt
  192. (lambda ()
  193. (+ 18
  194. (let/cc k
  195. (set! retry k)
  196. 17))))
  197. (+ 1 (call-with-continuation-prompt
  198. (lambda ()
  199. (+ (call-with-continuation-prompt
  200. (lambda ()
  201. (retry 12)))
  202. (call-with-continuation-prompt
  203. (lambda ()
  204. (retry 11))))))))))
  205. (with-cc-variants
  206. (test '(#f #t)
  207. 'in-other-thread1
  208. (let ([retry #f]
  209. [result #f]
  210. [did? #f])
  211. (call-with-continuation-prompt
  212. (lambda ()
  213. (+ 18
  214. (begin0
  215. (let/cc k
  216. (set! retry k)
  217. 17)
  218. (set! did? #t)))))
  219. (set! did? #f)
  220. (thread-wait
  221. (thread (lambda ()
  222. (set! result (retry 0)))))
  223. (list result did?))))
  224. (with-cc-variants
  225. (test 18
  226. 'in-other-thread2
  227. (let ([retry #f]
  228. [result #f])
  229. (call-with-continuation-prompt
  230. (lambda ()
  231. (+ 18
  232. (let/cc k
  233. (set! retry k)
  234. 17))))
  235. (thread-wait
  236. (thread (lambda ()
  237. (set! result
  238. (call-with-continuation-prompt
  239. (lambda ()
  240. (retry 0)))))))
  241. result)))
  242. (with-cc-variants
  243. (test 25
  244. 'back-in-original-thread
  245. (let ([retry #f]
  246. [result #f])
  247. (thread-wait
  248. (thread
  249. (lambda ()
  250. (+ 18
  251. (let/cc k
  252. (set! retry k)
  253. 17)))))
  254. (call-with-continuation-prompt
  255. (lambda ()
  256. (retry 7))))))
  257. (test-breaks-ok)
  258. ;; Catch continuation in composed continuation:
  259. (with-cc-variants
  260. (test 89
  261. 'catch-composed
  262. (let ([k (call-with-continuation-prompt
  263. (lambda ()
  264. ((let/cc k (lambda () k)))))])
  265. (let ([k2 (call-with-continuation-prompt
  266. (lambda ()
  267. (k (lambda ()
  268. (car (let/cc k2 (list k2)))))))])
  269. (call-with-continuation-prompt
  270. (lambda ()
  271. (k2 '(89))))))))
  272. ;; Grab continuation shallow inside meta-prompt with
  273. ;; delimiting prompt deep in a different meta-prompt.
  274. (with-cc-variants
  275. (let ([k (call-with-continuation-prompt
  276. (lambda ()
  277. ((call/cc
  278. (lambda (k) (lambda () k))))))])
  279. (test 10 call-with-continuation-prompt
  280. (lambda ()
  281. (let loop ([n 300])
  282. (if (zero? n)
  283. (k (lambda ()
  284. (let/cc k2 (k2 10))))
  285. (cons n (loop (sub1 n)))))))))
  286. ;; Grab continuation deep inside meta-prompt with
  287. ;; delimiting prompt shallow in a different meta-prompt.
  288. (with-cc-variants
  289. (let ([k (call-with-continuation-prompt
  290. (lambda ()
  291. (let loop ([n 12])
  292. (if (zero? n)
  293. ((call/cc
  294. (lambda (k) (lambda () k))))
  295. (cons 1 (loop (sub1 n)))))))])
  296. (test '(1 1 1 1 1 1 1 1 1 1 1 1 . 10) call-with-continuation-prompt
  297. (lambda ()
  298. ((list-tail k 12)
  299. (lambda ()
  300. (let/cc k2 (k2 10))))))))
  301. (test-breaks-ok)
  302. ;; ----------------------------------------
  303. ;; Overlapping continuations
  304. ;; Nested
  305. (let ([p1 (make-continuation-prompt-tag)]
  306. [p2 (make-continuation-prompt-tag)])
  307. (let ([k1 #f]
  308. [k2 #f])
  309. (test '(p1 p2 100)
  310. call-with-continuation-prompt
  311. (lambda ()
  312. (cons 'p1
  313. (call-with-continuation-prompt
  314. (lambda ()
  315. (cons 'p2
  316. ((call/cc
  317. (lambda (-k1)
  318. (set! k1 -k1)
  319. (call/cc (lambda (-k2)
  320. (set! k2 -k2)
  321. (lambda () '(100)))
  322. p2))
  323. p1))))
  324. p2)))
  325. p1)
  326. (err/rt-test (k1) exn:fail:contract:continuation?)
  327. (err/rt-test (k2) exn:fail:contract:continuation?)
  328. (err/rt-test (call-with-continuation-prompt
  329. (lambda () (k1))
  330. p2)
  331. exn:fail:contract:continuation?)
  332. (err/rt-test (call-with-continuation-prompt
  333. (lambda () (k2))
  334. p1)
  335. exn:fail:contract:continuation?)
  336. (test '(p1 p2 101) call-with-continuation-prompt
  337. (lambda ()
  338. (k1 (lambda () '(101))))
  339. p1)
  340. (test '(p2 102) call-with-continuation-prompt
  341. (lambda ()
  342. (k2 (lambda () '(102))))
  343. p2)
  344. (test '(p1 p2 102-1) call-with-continuation-prompt
  345. (lambda ()
  346. (k1 (lambda () (k2 (lambda () '(102-1))))))
  347. p1)))
  348. ;; Use default tag to catch a meta-continuation of p1.
  349. ;; Due to different implementations of the default tag,
  350. ;; this test is interesting in the main thread and
  351. ;; a sub thread:
  352. (let ()
  353. (define (go)
  354. (let ([p1 (make-continuation-prompt-tag)])
  355. (let ([k (call-with-continuation-prompt
  356. (lambda ()
  357. ((call/cc (lambda (k) (lambda () k))
  358. p1)))
  359. p1)])
  360. (let ([k2 (list
  361. (call-with-continuation-prompt
  362. (lambda ()
  363. (k (lambda ()
  364. (let/cc k k))))
  365. p1))])
  366. (if (procedure? (car k2))
  367. ((car k2) 10)
  368. (test '(10) values k2))))))
  369. (go)
  370. (let ([finished #f])
  371. (thread-wait
  372. (thread (lambda ()
  373. (go)
  374. (set! finished 'finished))))
  375. (test 'finished values finished)))
  376. ;; Use default tag to catch a meta-continuation of p1,
  377. ;; then catch continuation again (i.e., loop).
  378. (let ([finished #f])
  379. (define (go)
  380. (let ([p1 (make-continuation-prompt-tag)]
  381. [counter 10])
  382. (let ([k (call-with-continuation-prompt
  383. (lambda ()
  384. ((call/cc (lambda (k) (lambda () k))
  385. p1)))
  386. p1)])
  387. (let ([k2 (list
  388. (call-with-continuation-prompt
  389. (lambda ()
  390. (k (lambda ()
  391. ((let/cc k (lambda () k))))))
  392. p1))])
  393. (if (procedure? (car k2))
  394. ((car k2) (lambda ()
  395. (if (zero? counter)
  396. 10
  397. (begin
  398. (set! counter (sub1 counter))
  399. ((let/cc k (lambda () k)))))))
  400. (test '(10) values k2))
  401. (set! finished 'finished)))))
  402. (go)
  403. (let ([finished #f])
  404. (thread-wait
  405. (thread (lambda ()
  406. (go)
  407. (set! finished 'finished))))
  408. (test 'finished values finished)))
  409. ;; ----------------------------------------
  410. ;; Composable continuations
  411. (err/rt-test (call-with-continuation-barrier
  412. ;; When the test is not run in a REPL but is run in the
  413. ;; main thread, then it should fail without the barrier,
  414. ;; too. But we don't have enough control over the test
  415. ;; environment to assume that.
  416. (lambda ()
  417. (call-with-composable-continuation
  418. (lambda (x) x))))
  419. exn:fail:contract:continuation?)
  420. (err/rt-test (call-with-composable-continuation
  421. (lambda (x) x)
  422. (make-continuation-prompt-tag 'px))
  423. exn:fail:contract?)
  424. (let ([k (call-with-continuation-prompt
  425. (lambda ()
  426. (call-with-composable-continuation
  427. (lambda (k) k))))])
  428. (test 12 k 12)
  429. (test 13 k (k (k (k 13))))
  430. (test-values '(12 13) (lambda () (k 12 13))))
  431. (let ([k (call-with-continuation-prompt
  432. (lambda ()
  433. ((call-with-composable-continuation
  434. (lambda (k) (lambda () k))))))])
  435. (test 12 k (lambda () 12))
  436. (test-values '(12 13) (lambda () (k (lambda () (values 12 13)))))
  437. ;; Composition shouldn't introduce a prompt:
  438. (test 10 call-with-continuation-prompt
  439. (lambda ()
  440. (let ([k2 (k (lambda ()
  441. (let/cc k2 k2)))])
  442. (if (procedure? k2)
  443. (k2 10)
  444. k2))))
  445. ;; Escape from composed continuation:
  446. (let ([p (make-continuation-prompt-tag)])
  447. (test 8 call-with-continuation-prompt
  448. (lambda ()
  449. (+ 99 (k (lambda () (abort-current-continuation p 8)))))
  450. p
  451. values))
  452. (test 8 call-with-continuation-prompt
  453. (lambda ()
  454. (+ 99 (k (lambda () (abort-current-continuation
  455. (default-continuation-prompt-tag)
  456. 8)))))
  457. (default-continuation-prompt-tag)
  458. values))
  459. ;; Etc.
  460. (let ([k1 (call-with-continuation-prompt
  461. (lambda ()
  462. ((call-with-composable-continuation
  463. (lambda (k)
  464. (lambda () k))))))]
  465. [k2 (call-with-continuation-prompt
  466. (lambda ()
  467. ((call-with-composable-continuation
  468. (lambda (k)
  469. (lambda () k))))))])
  470. (test 1000
  471. call-with-continuation-prompt
  472. (lambda ()
  473. (k1 (lambda () (k2 (lambda () 1000))))))
  474. (test -1000 k1 (lambda () (k2 (lambda () -1000))))
  475. (let ([k3 (call-with-continuation-prompt
  476. (lambda ()
  477. (k1 (lambda ()
  478. ((call-with-composable-continuation
  479. (lambda (k)
  480. (lambda () k))))))))])
  481. (test 1001
  482. call-with-continuation-prompt
  483. (lambda ()
  484. (k3 (lambda () 1001))))
  485. (test -1001 k3 (lambda () -1001))
  486. (test 1002
  487. call-with-continuation-prompt
  488. (lambda ()
  489. (k1 (lambda () (k3 (lambda () 1002))))))
  490. (test -1002 k1 (lambda () (k3 (lambda () -1002)))))
  491. (let ([k4 (call-with-continuation-prompt
  492. (lambda ()
  493. (k1
  494. (lambda ()
  495. ((call-with-composable-continuation
  496. (lambda (k)
  497. (lambda () k))))))))])
  498. (test -1003 k4 (lambda () -1003)))
  499. (let ([k5 (call-with-continuation-prompt
  500. (lambda ()
  501. ((k1
  502. (lambda ()
  503. (call-with-composable-continuation
  504. (lambda (k)
  505. (lambda () k))))))))])
  506. (test -1004 k5 (lambda () -1004))
  507. (let ([k6 (call-with-continuation-prompt
  508. (lambda ()
  509. ((k5
  510. (lambda ()
  511. (call-with-composable-continuation
  512. (lambda (k)
  513. (lambda () k))))))))])
  514. (test -1005 k6 (lambda () -1005))))
  515. (let ([k7 (call-with-continuation-prompt
  516. (lambda ()
  517. ((k1
  518. (lambda ()
  519. ((k1
  520. (lambda ()
  521. (call-with-composable-continuation
  522. (lambda (k)
  523. (lambda () (lambda () k))))))))))))])
  524. (test -1006 k7 (lambda () (lambda () -1006)))
  525. (test '(-1007) call-with-continuation-prompt
  526. (lambda ()
  527. (list (k7 (lambda () (lambda () -1007)))))))
  528. )
  529. ;; Check that escape drops the meta-continuation:
  530. (test 0
  531. 'esc
  532. (let ([p1 (make-continuation-prompt-tag)])
  533. (let/cc esc
  534. (let ([k
  535. (call-with-continuation-prompt
  536. (lambda ()
  537. ((call-with-composable-continuation
  538. (lambda (k)
  539. (lambda () k))
  540. p1)))
  541. p1)])
  542. (/ (k (lambda () (esc 0))))))))
  543. ;; ----------------------------------------
  544. ;; Dynamic wind
  545. (test 89
  546. 'dw
  547. (let ([k (dynamic-wind
  548. void
  549. (lambda () (let ([k+e (let/cc k (cons k void))])
  550. ((cdr k+e) 89)
  551. (car k+e)))
  552. void)])
  553. (let/cc esc
  554. (k (cons void esc)))))
  555. (let ([l null])
  556. (let ([k2
  557. (dynamic-wind
  558. (lambda () (set! l (cons 'pre0 l)))
  559. (lambda ()
  560. (let ([k (call-with-continuation-prompt
  561. (lambda ()
  562. (dynamic-wind
  563. (lambda () (set! l (cons 'pre l)))
  564. (lambda () (let ([k (let/cc k k)])
  565. k))
  566. (lambda () (set! l (cons 'post l))))))])
  567. (test '(post pre pre0) values l)
  568. ;; Jump from one to the other:
  569. (let ([k2
  570. (call-with-continuation-prompt
  571. (lambda ()
  572. (dynamic-wind
  573. (lambda () (set! l (cons 'pre2 l)))
  574. (lambda ()
  575. (dynamic-wind
  576. (lambda () (set! l (cons 'pre3 l)))
  577. (lambda ()
  578. (let/cc k2 (k k2)))
  579. (lambda () (set! l (cons 'post3 l)))))
  580. (lambda () (set! l (cons 'post2 l))))))])
  581. (test '(post pre post2 post3 pre3 pre2 post pre pre0) values l)
  582. k2)))
  583. (lambda () (set! l (cons 'post0 l))))])
  584. (test '(post0 post pre post2 post3 pre3 pre2 post pre pre0) values l)
  585. ;; Restore in context with fewer DWs:
  586. (test 8 call-with-continuation-prompt (lambda () (k2 8)))
  587. (test '(post2 post3 pre3 pre2 post0 post pre post2 post3 pre3 pre2 post pre pre0) values l)
  588. ;; Restore in context with more DWs:
  589. (set! l null)
  590. (dynamic-wind
  591. (lambda () (set! l (cons 'pre4 l)))
  592. (lambda ()
  593. (dynamic-wind
  594. (lambda () (set! l (cons 'pre5 l)))
  595. (lambda ()
  596. (call-with-continuation-prompt k2))
  597. (lambda () (set! l (cons 'post5 l)))))
  598. (lambda () (set! l (cons 'post4 l))))
  599. (test '(post4 post5 post2 post3 pre3 pre2 pre5 pre4) values l)))
  600. ;; Like the meta-continuation test above, but add a dynamic wind
  601. ;; to be restored in the p1 continuation:
  602. (let ([p1 (make-continuation-prompt-tag)]
  603. [did #f])
  604. (let ([k (call-with-continuation-prompt
  605. (lambda ()
  606. (dynamic-wind
  607. (lambda ()
  608. (set! did 'in))
  609. (lambda ()
  610. ((call/cc (lambda (k) (lambda () k))
  611. p1)))
  612. (lambda ()
  613. (set! did 'out))))
  614. p1)])
  615. (set! did #f)
  616. (let ([k2 (list
  617. (call-with-continuation-prompt
  618. (lambda ()
  619. (k (lambda ()
  620. (test 'in values did)
  621. ((let/cc k (lambda () k))))))
  622. p1))])
  623. (test 'out values did)
  624. (if (procedure? (car k2))
  625. ((car k2) (lambda ()
  626. (test 'in values did)
  627. 10))
  628. (test '(10) values k2)))))
  629. ;; Composable continuations
  630. (let ([l null])
  631. (let ([k2
  632. (dynamic-wind
  633. (lambda () (set! l (cons 'pre0 l)))
  634. (lambda ()
  635. (let ([k (call-with-continuation-prompt
  636. (lambda ()
  637. (dynamic-wind
  638. (lambda () (set! l (cons 'pre l)))
  639. (lambda ()
  640. ((call-with-composable-continuation
  641. (lambda (k)
  642. (lambda () k)))))
  643. (lambda () (set! l (cons 'post l))))))])
  644. (test '(post pre pre0) values l)
  645. (test 12 k (lambda () 12))
  646. (test '(post pre post pre pre0) values l)
  647. k))
  648. (lambda () (set! l (cons 'post0 l))))])
  649. (test '(post0 post pre post pre pre0) values l)
  650. (test 73 k2 (lambda () 73))
  651. (test '(post pre post0 post pre post pre pre0) values l)
  652. (set! l null)
  653. ;; Add d-w inside k2:
  654. (let ([k3 (call-with-continuation-prompt
  655. (lambda ()
  656. (k2 (lambda ()
  657. (dynamic-wind
  658. (lambda () (set! l (cons 'pre2 l)))
  659. (lambda ()
  660. ((call-with-composable-continuation
  661. (lambda (k)
  662. (lambda () k)))))
  663. (lambda () (set! l (cons 'post2 l))))))))])
  664. (test '(post post2 pre2 pre) values l)
  665. (test 99 k3 (lambda () 99))
  666. (test '(post post2 pre2 pre post post2 pre2 pre) values l))
  667. (set! l null)
  668. ;; Add d-w outside k2:
  669. (let ([k4 (call-with-continuation-prompt
  670. (lambda ()
  671. (dynamic-wind
  672. (lambda () (set! l (cons 'pre2 l)))
  673. (lambda ()
  674. (k2 (lambda ()
  675. ((call-with-composable-continuation
  676. (lambda (k)
  677. (lambda () k)))))))
  678. (lambda () (set! l (cons 'post2 l))))))])
  679. (test '(post2 post pre pre2) values l)
  680. (test 99 k4 (lambda () 99))
  681. (test '(post2 post pre pre2 post2 post pre pre2) values l))))
  682. ;; Jump back into post:
  683. (let ([l null]
  684. [p1 (make-continuation-prompt-tag)]
  685. [p2 (make-continuation-prompt-tag)]
  686. [k2 #f])
  687. (define (out v) (set! l (cons v l)))
  688. (call-with-continuation-prompt
  689. (lambda ()
  690. (dynamic-wind
  691. (lambda () (out 'pre))
  692. (lambda ()
  693. (call-with-continuation-prompt
  694. (lambda ()
  695. (dynamic-wind
  696. (lambda () (out 'pre2))
  697. (lambda () (void))
  698. (lambda ()
  699. (call/cc (lambda (k)
  700. (set! k2 k))
  701. p2)
  702. (out 'post2))))
  703. p2))
  704. (lambda () (out 'post1))))
  705. p1)
  706. (call-with-continuation-prompt
  707. (lambda ()
  708. (k2 10))
  709. p2)
  710. (test '(post2 post1 post2 pre2 pre) values l))
  711. ;; Jump into post, then back out
  712. (let ([l null]
  713. [p1 (make-continuation-prompt-tag)]
  714. [p2 (make-continuation-prompt-tag)]
  715. [k2 #f]
  716. [count 0])
  717. (define (out v) (set! l (cons v l)))
  718. (let/cc esc
  719. (call-with-continuation-prompt
  720. (lambda ()
  721. (dynamic-wind
  722. (lambda () (out 'pre1))
  723. (lambda ()
  724. (call-with-continuation-prompt
  725. (lambda ()
  726. (dynamic-wind
  727. (lambda () (out 'pre2))
  728. (lambda () (void))
  729. (lambda ()
  730. (call/cc (lambda (k)
  731. (set! k2 k))
  732. p2)
  733. (out 'post2)
  734. (esc))))
  735. p2))
  736. (lambda () (out 'post1))))
  737. p1))
  738. (printf "here ~a\n" count)
  739. (set! count (add1 count))
  740. (unless (= count 3)
  741. (call-with-continuation-prompt
  742. (lambda ()
  743. (k2 10))
  744. p2))
  745. (test '(post2 post2 post1 post2 pre2 pre1) values l))
  746. (printf "into post from escape\n")
  747. ;; Jump into post from an escape, rather than
  748. ;; from a result continuation
  749. (let ([l null]
  750. [p1 (make-continuation-prompt-tag)]
  751. [p2 (make-continuation-prompt-tag)]
  752. [k2 #f]
  753. [count 0])
  754. (define (out v) (set! l (cons v l)))
  755. (let/cc esc
  756. (call-with-continuation-prompt
  757. (lambda ()
  758. (dynamic-wind
  759. (lambda () (out 'pre1))
  760. (lambda ()
  761. (call-with-continuation-prompt
  762. (lambda ()
  763. (dynamic-wind
  764. (lambda () (out 'pre2))
  765. (lambda () (esc))
  766. (lambda ()
  767. (call/cc (lambda (k)
  768. (set! k2 k))
  769. p2)
  770. (out 'post2))))
  771. p2))
  772. (lambda () (out 'post1))))
  773. p1))
  774. (set! count (add1 count))
  775. (unless (= count 3)
  776. (call-with-continuation-prompt
  777. (lambda ()
  778. (k2 10))
  779. p2))
  780. (test '(post2 post2 post1 post2 pre2 pre1) values l))
  781. ;; ----------------------------------------
  782. ;; Continuation marks
  783. (let ([go
  784. (lambda (access-tag catch-tag blocked?)
  785. (let ([k (call-with-continuation-prompt
  786. (lambda ()
  787. (with-continuation-mark
  788. 'x
  789. 17
  790. ((call/cc (lambda (k) (lambda () k))
  791. catch-tag))))
  792. catch-tag)])
  793. (with-continuation-mark
  794. 'x
  795. 18
  796. (with-continuation-mark
  797. 'y
  798. 8
  799. (begin
  800. (printf "here\n")
  801. (test 18 continuation-mark-set-first #f 'x #f catch-tag)
  802. (test '(18) continuation-mark-set->list (current-continuation-marks catch-tag) 'x catch-tag)
  803. (test 17
  804. call-with-continuation-prompt
  805. (lambda ()
  806. (k (lambda () (continuation-mark-set-first #f 'x #f catch-tag))))
  807. catch-tag)
  808. (test #f
  809. call-with-continuation-prompt
  810. (lambda ()
  811. (k (lambda () (continuation-mark-set-first #f 'y #f catch-tag))))
  812. catch-tag)
  813. (test (if (eq? catch-tag (default-continuation-prompt-tag)) #f 8)
  814. call-with-continuation-prompt
  815. (lambda ()
  816. (k (lambda () (continuation-mark-set-first #f 'y #f catch-tag))))
  817. (default-continuation-prompt-tag))
  818. (test (if blocked?
  819. '(17)
  820. '(17 18))
  821. call-with-continuation-prompt
  822. (lambda ()
  823. (k (lambda () (continuation-mark-set->list (current-continuation-marks access-tag)
  824. 'x access-tag))))
  825. catch-tag)
  826. (test '(17)
  827. continuation-mark-set->list (continuation-marks k catch-tag) 'x catch-tag)
  828. (test (if blocked?
  829. '()
  830. '(8))
  831. call-with-continuation-prompt
  832. (lambda ()
  833. (k (lambda () (continuation-mark-set->list (current-continuation-marks access-tag)
  834. 'y access-tag))))
  835. catch-tag)
  836. 'done)))))])
  837. (go (default-continuation-prompt-tag) (default-continuation-prompt-tag) #t)
  838. (let ([p2 (make-continuation-prompt-tag 'p2)])
  839. (call-with-continuation-prompt
  840. (lambda ()
  841. (go p2 p2 #t)
  842. (go p2 (default-continuation-prompt-tag) #f)
  843. (go (default-continuation-prompt-tag) p2 #f))
  844. p2)))
  845. (define (non-tail v) (values v))
  846. (let ()
  847. (define (go access-tag blocked?)
  848. (let ([k (call-with-continuation-prompt
  849. (lambda ()
  850. (with-continuation-mark
  851. 'x
  852. 71
  853. ((call-with-composable-continuation
  854. (lambda (k)
  855. (lambda () k)))))))])
  856. (test #f continuation-mark-set-first #f 'x)
  857. (test 71 k (lambda () (continuation-mark-set-first #f 'x)))
  858. (test '(71) continuation-mark-set->list (continuation-marks k) 'x)
  859. (test 71 'wcm (with-continuation-mark
  860. 'x 81
  861. (k (lambda () (continuation-mark-set-first #f 'x)))))
  862. (test '(71 81) 'wcm (with-continuation-mark
  863. 'x 81
  864. (non-tail
  865. (k (lambda ()
  866. (continuation-mark-set->list (current-continuation-marks) 'x))))))
  867. (test '(71) 'wcm (with-continuation-mark
  868. 'x 81
  869. (k (lambda ()
  870. (continuation-mark-set->list (current-continuation-marks) 'x)))))
  871. (test '(91 71 81) 'wcm (with-continuation-mark
  872. 'x 81
  873. (non-tail
  874. (k (lambda ()
  875. (non-tail
  876. (with-continuation-mark
  877. 'x 91
  878. (continuation-mark-set->list (current-continuation-marks) 'x))))))))
  879. (test '(91 81) 'wcm (with-continuation-mark
  880. 'x 81
  881. (non-tail
  882. (k (lambda ()
  883. (with-continuation-mark
  884. 'x 91
  885. (continuation-mark-set->list (current-continuation-marks) 'x)))))))
  886. (test '(91) 'wcm (with-continuation-mark
  887. 'x 81
  888. (k (lambda ()
  889. (with-continuation-mark
  890. 'x 91
  891. (continuation-mark-set->list (current-continuation-marks) 'x))))))
  892. (let ([k2 (with-continuation-mark
  893. 'x 101
  894. (call-with-continuation-prompt
  895. (lambda ()
  896. (with-continuation-mark
  897. 'x 111
  898. (non-tail
  899. (k (lambda ()
  900. ((call-with-composable-continuation
  901. (lambda (k2)
  902. (test (if blocked?
  903. '(71 111)
  904. '(71 111 101))
  905. continuation-mark-set->list (current-continuation-marks access-tag)
  906. 'x access-tag)
  907. (lambda () k2)))))))))))])
  908. (test '(71 111) continuation-mark-set->list (continuation-marks k2) 'x)
  909. (test '(71 111) k2 (lambda ()
  910. (continuation-mark-set->list (current-continuation-marks) 'x)))
  911. (test 71 k2 (lambda ()
  912. (continuation-mark-set-first #f 'x)))
  913. (test '(71 111 121) 'wcm (with-continuation-mark
  914. 'x 121
  915. (non-tail
  916. (k2 (lambda ()
  917. (continuation-mark-set->list (current-continuation-marks) 'x))))))
  918. )
  919. (let ([k2 (with-continuation-mark
  920. 'x 101
  921. (call-with-continuation-prompt
  922. (lambda ()
  923. (with-continuation-mark
  924. 'x 111
  925. (k (lambda ()
  926. ((call-with-composable-continuation
  927. (lambda (k2)
  928. (test (if blocked?
  929. '(71)
  930. '(71 101))
  931. continuation-mark-set->list (current-continuation-marks access-tag)
  932. 'x access-tag)
  933. (lambda () k2))))))))))])
  934. (test '(71) continuation-mark-set->list (continuation-marks k2) 'x)
  935. (test '(71) k2 (lambda ()
  936. (continuation-mark-set->list (current-continuation-marks) 'x)))
  937. (test 71 k2 (lambda ()
  938. (continuation-mark-set-first #f 'x)))
  939. (test '(71 121) 'wcm (with-continuation-mark
  940. 'x 121
  941. (non-tail
  942. (k2 (lambda ()
  943. (continuation-mark-set->list (current-continuation-marks) 'x)))))))))
  944. (go (default-continuation-prompt-tag) #t)
  945. (let ([p2 (make-continuation-prompt-tag 'p2)])
  946. (call-with-continuation-prompt
  947. (lambda ()
  948. (go p2 #f))
  949. p2)))
  950. ;; Check interaction of dynamic winds, continuation composition, and continuation marks
  951. (let ([pre-saw-xs null]
  952. [post-saw-xs null]
  953. [pre-saw-ys null]
  954. [post-saw-ys null])
  955. (let ([k (call-with-continuation-prompt
  956. (lambda ()
  957. (with-continuation-mark
  958. 'x
  959. 77
  960. (dynamic-wind
  961. (lambda ()
  962. (set! pre-saw-xs (continuation-mark-set->list (current-continuation-marks) 'x))
  963. (set! pre-saw-ys (continuation-mark-set->list (current-continuation-marks) 'y)))
  964. (lambda ()
  965. ((call-with-composable-continuation
  966. (lambda (k)
  967. (lambda () k)))))
  968. (lambda ()
  969. (set! post-saw-xs (continuation-mark-set->list (current-continuation-marks) 'x))
  970. (set! post-saw-ys (continuation-mark-set->list (current-continuation-marks) 'y)))))))])
  971. (test '(77) values pre-saw-xs)
  972. (test '() values pre-saw-ys)
  973. (test '(77) values post-saw-xs)
  974. (test '() values post-saw-ys)
  975. (let ([jump-in
  976. (lambda (wrap r-val y-val)
  977. (test r-val 'wcm
  978. (wrap
  979. (lambda (esc)
  980. (with-continuation-mark
  981. 'y y-val
  982. (k (lambda () (esc)))))))
  983. (test '(77) values pre-saw-xs)
  984. (test (list y-val) values pre-saw-ys)
  985. (test '(77) values post-saw-xs)
  986. (test (list y-val) values post-saw-ys)
  987. (let ([k3 (call-with-continuation-prompt
  988. (lambda ()
  989. ((call-with-composable-continuation
  990. (lambda (k)
  991. (lambda () k))))))])
  992. (test r-val 'wcm
  993. (wrap
  994. (lambda (esc)
  995. (k3
  996. (lambda ()
  997. (with-continuation-mark
  998. 'y y-val
  999. (k (lambda () (k3 (lambda () (esc)))))))))))))])
  1000. (jump-in (lambda (f) (f (lambda () 10))) 10 88)
  1001. (jump-in (lambda (f) (let/cc esc (f (lambda () (esc 20))))) 20 99)
  1002. (printf "here\n")
  1003. (jump-in (lambda (f)
  1004. (let ([p1 (make-continuation-prompt-tag)])
  1005. (call-with-continuation-prompt
  1006. (lambda ()
  1007. (f (lambda () (abort-current-continuation p1 (lambda () 30)))))
  1008. p1)))
  1009. 30 111)
  1010. (void))))
  1011. ;; Tail meta-calls should overwrite continuation marks
  1012. (let ([k (call-with-continuation-prompt
  1013. (lambda ()
  1014. ((call-with-composable-continuation
  1015. (lambda (k)
  1016. (lambda () k))))))])
  1017. (with-continuation-mark
  1018. 'n #f
  1019. (let loop ([n 10])
  1020. (unless (zero? n)
  1021. (with-continuation-mark
  1022. 'n n
  1023. (k (lambda ()
  1024. (test (list n) continuation-mark-set->list (current-continuation-marks) 'n)
  1025. (loop (sub1 n)))))))))
  1026. ;; Tail meta-calls should propagate cont marks
  1027. (let ([k (call-with-continuation-prompt
  1028. (lambda ()
  1029. ((call-with-composable-continuation
  1030. (lambda (k)
  1031. (lambda () k))))))])
  1032. (with-continuation-mark
  1033. 'n 10
  1034. (let loop ([n 10])
  1035. (test n continuation-mark-set-first #f 'n)
  1036. (test (list n) continuation-mark-set->list (current-continuation-marks) 'n)
  1037. (unless (zero? n)
  1038. (k (lambda ()
  1039. (with-continuation-mark
  1040. 'n (sub1 n)
  1041. (loop (sub1 n)))))))))
  1042. ;; Captured mark should replace installed mark
  1043. (let ([k (call-with-continuation-prompt
  1044. (lambda ()
  1045. (with-continuation-mark
  1046. 'n #t
  1047. ((call-with-composable-continuation
  1048. (lambda (k)
  1049. (lambda () k)))))))])
  1050. (with-continuation-mark
  1051. 'n #f
  1052. (let loop ([n 10])
  1053. (unless (zero? n)
  1054. (with-continuation-mark
  1055. 'n n
  1056. (k (lambda ()
  1057. (test (list #t) continuation-mark-set->list (current-continuation-marks) 'n)
  1058. (test #t continuation-mark-set-first #f 'n)
  1059. (loop (sub1 n)))))))))
  1060. ;; ----------------------------------------
  1061. ;; Olivier Danvy's traversal
  1062. ;; Shift & reset via composable and abort
  1063. (let ()
  1064. (define traverse
  1065. (lambda (xs)
  1066. (letrec ((visit
  1067. (lambda (xs)
  1068. (if (null? xs)
  1069. '()
  1070. (visit (call-with-composable-continuation
  1071. (lambda (k)
  1072. (abort-current-continuation
  1073. (default-continuation-prompt-tag)
  1074. (let ([v (cons (car xs)
  1075. (call-with-continuation-prompt
  1076. (lambda ()
  1077. (k (cdr xs)))))])
  1078. (lambda () v))))))))))
  1079. (call-with-continuation-prompt
  1080. (lambda ()
  1081. (visit xs))))))
  1082. (test '(1 2 3 4 5) traverse '(1 2 3 4 5)))
  1083. ;; Shift & reset using composable and call/cc
  1084. (let ()
  1085. (define call-in-application-context
  1086. (call-with-continuation-prompt
  1087. (lambda ()
  1088. ((call-with-current-continuation
  1089. (lambda (k) (lambda () k)))))))
  1090. (define traverse
  1091. (lambda (xs)
  1092. (letrec ((visit
  1093. (lambda (xs)
  1094. (if (null? xs)
  1095. '()
  1096. (visit (call-with-composable-continuation
  1097. (lambda (k)
  1098. (call-in-application-context
  1099. (lambda ()
  1100. (cons (car xs)
  1101. (call-with-continuation-prompt
  1102. (lambda ()
  1103. (k (cdr xs))))))))))))))
  1104. (call-with-continuation-prompt
  1105. (lambda ()
  1106. (visit xs))))))
  1107. (test '(1 2 3 4 5) traverse '(1 2 3 4 5)))
  1108. ;; control and prompt using composable and abort
  1109. (let ()
  1110. (define traverse
  1111. (lambda (xs)
  1112. (letrec ((visit
  1113. (lambda (xs)
  1114. (if (null? xs)
  1115. (list-tail '() 0)
  1116. (visit (call-with-composable-continuation
  1117. (lambda (k)
  1118. (abort-current-continuation
  1119. (default-continuation-prompt-tag)
  1120. (lambda ()
  1121. (cons (car xs)
  1122. (k (cdr xs))))))))))))
  1123. (call-with-continuation-prompt
  1124. (lambda ()
  1125. (visit xs))))))
  1126. (test '(5 4 3 2 1) traverse '(1 2 3 4 5)))
  1127. ;; control and prompt using composable and call/cc
  1128. (let ()
  1129. (define call-in-application-context
  1130. (call-with-continuation-prompt
  1131. (lambda ()
  1132. ((call-with-current-continuation
  1133. (lambda (k) (lambda () k)))))))
  1134. (define traverse
  1135. (lambda (xs)
  1136. (letrec ((visit
  1137. (lambda (xs)
  1138. (if (null? xs)
  1139. (list-tail '() 0)
  1140. (visit (call-with-composable-continuation
  1141. (lambda (k)
  1142. (call-in-application-context
  1143. (lambda ()
  1144. (cons (car xs)
  1145. (k (cdr xs))))))))))))
  1146. (call-with-continuation-prompt
  1147. (lambda ()
  1148. (visit xs))))))
  1149. (test '(5 4 3 2 1) traverse '(1 2 3 4 5)))
  1150. ;; ----------------------------------------
  1151. ;; Check unwinding of runstack overflows on prompt escape
  1152. (let ([try
  1153. (lambda (thread m-top n-top do-mid-stream do-abort)
  1154. (let ([result #f])
  1155. (thread-wait
  1156. (thread
  1157. (lambda ()
  1158. (set! result
  1159. (let pre-loop ([m m-top])
  1160. (if (zero? m)
  1161. (list
  1162. (do-mid-stream
  1163. (lambda ()
  1164. (call-with-continuation-prompt
  1165. (lambda ()
  1166. (let loop ([n n-top])
  1167. (if (zero? n)
  1168. (do-abort
  1169. (lambda ()
  1170. (abort-current-continuation
  1171. (default-continuation-prompt-tag)
  1172. (lambda () 5000))))
  1173. (+ (loop (sub1 n))))))))))
  1174. (list (car (pre-loop (sub1 m))))))))))
  1175. (test '(5000) values result)))])
  1176. (try thread 5000 10000 (lambda (mid) (mid)) (lambda (abort) (abort)))
  1177. (try thread 5000 10000 (lambda (mid) (mid))
  1178. (lambda (abort) ((call-with-continuation-prompt
  1179. (lambda ()
  1180. ((call-with-composable-continuation
  1181. (lambda (k) (lambda () k))))))
  1182. (lambda () 5000))))
  1183. (try thread 5000 10000 (lambda (mid) (mid))
  1184. (lambda (abort) ((call-with-continuation-prompt
  1185. (lambda ()
  1186. ((call/cc
  1187. (lambda (k) (lambda () k))))))
  1188. (lambda () 5000))))
  1189. (try thread 5000 10000 (lambda (mid) (mid))
  1190. (lambda (abort) (((call/cc
  1191. (lambda (k) (lambda () k))))
  1192. (lambda () (lambda (x) 5000)))))
  1193. (try thread 5000 10000
  1194. (lambda (mid) (call-with-continuation-barrier mid))
  1195. (lambda (abort) (((call/cc
  1196. (lambda (k) (lambda () k))))
  1197. (lambda () (lambda (x) 5000)))))
  1198. (let ([p (make-continuation-prompt-tag 'p)])
  1199. (try (lambda (f)
  1200. (thread
  1201. (lambda ()
  1202. (call-with-continuation-prompt f p))))
  1203. 5000 10000
  1204. (lambda (mid) (mid))
  1205. (lambda (abort)
  1206. ((call/cc
  1207. (lambda (k)
  1208. (thread-wait (thread
  1209. (lambda ()
  1210. (call-with-continuation-prompt
  1211. (lambda ()
  1212. (k abort))
  1213. p))))
  1214. (lambda () (abort-current-continuation p void)))
  1215. p)))))
  1216. )
  1217. (test-breaks-ok)
  1218. ;; ----------------------------------------
  1219. ;; Some repeats, but ensure a continuation prompt
  1220. ;; and check d-w interaction.
  1221. (let ([output null])
  1222. (call-with-continuation-prompt
  1223. (lambda ()
  1224. (dynamic-wind
  1225. (lambda () (set! output (cons 'in output)))
  1226. (lambda ()
  1227. (let ([finished #f])
  1228. (define (go)
  1229. (let ([p1 (make-continuation-prompt-tag)]
  1230. [counter 10])
  1231. (let ([k (call-with-continuation-prompt
  1232. (lambda ()
  1233. ((call/cc (lambda (k) (lambda () k))
  1234. p1)))
  1235. p1)])
  1236. (let ([k2 (list
  1237. (call-with-continuation-prompt
  1238. (lambda ()
  1239. (k (lambda ()
  1240. ((let/cc k (lambda () k))))))
  1241. p1))])
  1242. (current-milliseconds)
  1243. (if (procedure? (car k2))
  1244. ((car k2) (lambda ()
  1245. (if (zero? counter)
  1246. 10
  1247. (begin
  1248. (set! counter (sub1 counter))
  1249. ((let/cc k (lambda () k)))))))
  1250. (values '(10) values k2))
  1251. (set! finished 'finished)))))
  1252. (go)))
  1253. (lambda () (set! output (cons 'out output)))))
  1254. (default-continuation-prompt-tag)
  1255. void)
  1256. (test '(out in) values output))
  1257. (let ([output null])
  1258. (call-with-continuation-prompt
  1259. (lambda ()
  1260. (dynamic-wind
  1261. (lambda () (set! output (cons 'in output)))
  1262. (lambda ()
  1263. (let ([p1 (make-continuation-prompt-tag)])
  1264. (let/cc esc
  1265. (let ([k
  1266. (call-with-continuation-prompt
  1267. (lambda ()
  1268. ((call-with-composable-continuation
  1269. (lambda (k)
  1270. (lambda () k))
  1271. p1)))
  1272. p1)])
  1273. (/ (k (lambda () (esc 0))))))))
  1274. (lambda () (set! output (cons 'out output)))))
  1275. (default-continuation-prompt-tag)
  1276. void)
  1277. (test '(out in) values output))
  1278. ;;----------------------------------------
  1279. ;; tests invoking delimited captures in dynamic-wind pre- and post-thunks
  1280. ;; Arrange for a post-thunk to remove a target
  1281. ;; for an escape:
  1282. (err/rt-test
  1283. (let ([p1 (make-continuation-prompt-tag 'p1)]
  1284. [exit-k #f])
  1285. (let ([x (let/ec esc
  1286. (call-with-continuation-prompt
  1287. (lambda ()
  1288. (dynamic-wind
  1289. (lambda () (void))
  1290. (lambda () (esc 'done))
  1291. (lambda ()
  1292. ((call/cc
  1293. (lambda (k)
  1294. (set! exit-k k)
  1295. (lambda () 10))
  1296. p1))