/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

  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))
  1297. (printf "post\n"))))
  1298. p1))])
  1299. (call-with-continuation-barrier
  1300. (lambda ()
  1301. (call-with-continuation-prompt
  1302. (lambda ()
  1303. (exit-k (lambda () 'hi)))
  1304. p1)))))
  1305. exn:fail:contract:continuation?)
  1306. ;; Same thing, but escape via prompt:
  1307. (err/rt-test
  1308. (let ([p1 (make-continuation-prompt-tag 'p1)]
  1309. [p2 (make-continuation-prompt-tag 'p2)]
  1310. [output null]
  1311. [exit-k #f])
  1312. (let ([x (call-with-continuation-prompt
  1313. (lambda ()
  1314. (call-with-continuation-prompt
  1315. (lambda ()
  1316. (dynamic-wind
  1317. (lambda () (void))
  1318. (lambda () (abort-current-continuation p2 1 2 3))
  1319. (lambda ()
  1320. ((call/cc
  1321. (lambda (k)
  1322. (set! exit-k k)
  1323. (lambda () 10))
  1324. p1))
  1325. (set! output (cons 'post output)))))
  1326. p1))
  1327. p2
  1328. void)])
  1329. (call-with-continuation-barrier
  1330. (lambda ()
  1331. (call-with-continuation-prompt
  1332. (lambda ()
  1333. (exit-k (lambda () 'hi)))
  1334. p1)))))
  1335. exn:fail:contract?)
  1336. ;; Arrange for a barrier to interfere with a continuation
  1337. ;; jump after dynamic-winds are already being processed:
  1338. (let ([p1 (make-continuation-prompt-tag 'p1)]
  1339. [output null]
  1340. [exit-k #f])
  1341. (let ([go
  1342. (lambda (launch)
  1343. (let ([k (let/cc esc
  1344. (call-with-continuation-prompt
  1345. (lambda ()
  1346. (dynamic-wind
  1347. (lambda () (void))
  1348. (lambda ()
  1349. (with-handlers ([void (lambda (exn)
  1350. (test #f "should not be used!" #t))])
  1351. (launch esc)))
  1352. (lambda ()
  1353. ((call/cc
  1354. (lambda (k)
  1355. (set! exit-k k)
  1356. (lambda () 10))
  1357. p1))
  1358. (set! output (cons 'post output)))))
  1359. p1))])
  1360. (call-with-continuation-barrier
  1361. (lambda ()
  1362. (call-with-continuation-prompt
  1363. (lambda ()
  1364. (exit-k (lambda () 'hi)))
  1365. p1)))))])
  1366. (err/rt-test
  1367. (go (lambda (esc) (esc 'middle)))
  1368. exn:fail:contract:continuation?)
  1369. (test '(post post) values output)
  1370. (let ([meta (call-with-continuation-prompt
  1371. (lambda ()
  1372. ((call-with-composable-continuation
  1373. (lambda (k) (lambda () k))))))])
  1374. (err/rt-test
  1375. (go (lambda (esc)
  1376. (meta
  1377. (lambda () (esc 'ok)))))
  1378. exn:fail:contract:continuation?))
  1379. (test '(post post post post) values output)))
  1380. ;; Similar, but more checking of dropped d-ws:
  1381. (let ([p1 (make-continuation-prompt-tag 'p1)]
  1382. [output null]
  1383. [exit-k #f]
  1384. [done? #f])
  1385. ;; Capture a continuation w.r.t. the default prompt tag:
  1386. (call/cc
  1387. (lambda (esc)
  1388. (dynamic-wind
  1389. (lambda () (void))
  1390. (lambda ()
  1391. ;; Set a prompt for tag p1:
  1392. (call-with-continuation-prompt
  1393. (lambda ()
  1394. (dynamic-wind
  1395. (lambda () (void))
  1396. ;; inside d-w, jump out:
  1397. (lambda () (esc 'done))
  1398. (lambda ()
  1399. ;; As we jump out, capture a continuation
  1400. ;; w.r.t. p1:
  1401. ((call/cc
  1402. (lambda (k)
  1403. (set! exit-k k)
  1404. (lambda () 10))
  1405. p1))
  1406. (set! output (cons 'inner output)))))
  1407. p1))
  1408. (lambda ()
  1409. ;; This post thunk is not in the
  1410. ;; delimited continuation captured
  1411. ;; via tag p1:
  1412. (set! output (cons 'outer output))))))
  1413. (unless done?
  1414. (set! done? #t)
  1415. ;; Now invoke the delimited continuation, which must
  1416. ;; somehow continue the jump to `esc':
  1417. (call-with-continuation-prompt
  1418. (lambda ()
  1419. (exit-k (lambda () 10)))
  1420. p1))
  1421. (test '(inner outer inner) values output))
  1422. ;; Again, more checking of output
  1423. (let ([p1 (make-continuation-prompt-tag 'p1)]
  1424. [p2 (make-continuation-prompt-tag 'p2)]
  1425. [output null]
  1426. [exit-k #f])
  1427. ;; Set up a prompt tp jump to:
  1428. (call-with-continuation-prompt
  1429. (lambda ()
  1430. (dynamic-wind
  1431. (lambda () (void))
  1432. (lambda ()
  1433. ;; Set a prompt for tag p1:
  1434. (call-with-continuation-prompt
  1435. (lambda ()
  1436. (dynamic-wind
  1437. (lambda () (void))
  1438. ;; inside d-w, jump out:
  1439. (lambda () (abort-current-continuation
  1440. p2
  1441. "done"))
  1442. (lambda ()
  1443. ;; As we jump out, capture a continuation
  1444. ;; w.r.t. p1:
  1445. ((call/cc
  1446. (lambda (k)
  1447. (set! exit-k k)
  1448. (lambda () 10))
  1449. p1))
  1450. (set! output (cons 'inner output)))))
  1451. p1))
  1452. (lambda ()
  1453. ;; This post thunk is not in the
  1454. ;; delimited continuation captured
  1455. ;; via tag p1:
  1456. (set! output (cons 'outer output)))))
  1457. p2
  1458. (lambda (v)
  1459. (set! output (cons 'orig output))))
  1460. ;; Now call, redirecting the escape to here:
  1461. (call-with-continuation-prompt
  1462. (lambda ()
  1463. (call-with-continuation-prompt
  1464. (lambda ()
  1465. (exit-k (lambda () 10)))
  1466. p1))
  1467. p2
  1468. (lambda (v)
  1469. (set! output (cons 'new output))))
  1470. (test '(new inner orig outer inner) values output))
  1471. ;; abort past a tag
  1472. (test 10
  1473. values
  1474. (let ([p1 (make-continuation-prompt-tag)]
  1475. [p2 (make-continuation-prompt-tag)])
  1476. (call-with-continuation-prompt
  1477. (lambda ()
  1478. (call/cc
  1479. (lambda (k)
  1480. (call-with-continuation-prompt
  1481. (lambda ()
  1482. (k 10))
  1483. p2))
  1484. p1))
  1485. p1)))
  1486. ;; Check that a prompt is not somehow tied to its original
  1487. ;; barrier, so that jumps are not allowed when they should
  1488. ;; be:
  1489. (test 0
  1490. values
  1491. (let ([p1 (make-continuation-prompt-tag 'p1)]
  1492. [p2 (make-continuation-prompt-tag 'p2)])
  1493. (let ([k (call-with-continuation-prompt
  1494. (lambda ()
  1495. (call-with-continuation-prompt
  1496. (lambda ()
  1497. ((call-with-current-continuation
  1498. (lambda (k) (lambda () k))
  1499. p2)))
  1500. p1))
  1501. p2)])
  1502. (call-with-continuation-barrier
  1503. (lambda ()
  1504. (call-with-continuation-barrier
  1505. (lambda ()
  1506. (let ([k1
  1507. (call-with-continuation-prompt
  1508. (lambda ()
  1509. (k
  1510. (lambda ()
  1511. ;; prompt for p1 has been restored
  1512. (call/cc (lambda (k1) k1) p1))))
  1513. p2)])
  1514. (call-with-continuation-prompt
  1515. (lambda ()
  1516. (k1 0))
  1517. p1)))))))))
  1518. (test 12
  1519. values
  1520. (let ([p1 (make-continuation-prompt-tag 'p1)])
  1521. (let ([k (call-with-continuation-barrier
  1522. (lambda ()
  1523. (call-with-continuation-prompt
  1524. (lambda ()
  1525. ((call-with-current-continuation
  1526. (lambda (k) (lambda () k))
  1527. p1)))
  1528. p1)))])
  1529. (call-with-continuation-barrier
  1530. (lambda ()
  1531. (call-with-continuation-barrier
  1532. (lambda ()
  1533. (call-with-continuation-barrier
  1534. (lambda ()
  1535. (call-with-continuation-prompt
  1536. (lambda ()
  1537. (let/cc w
  1538. (call-with-continuation-prompt
  1539. (lambda ()
  1540. (k (lambda () (w 12))))
  1541. p1)))))))))))))
  1542. ;; Test capturing and invoking a composable continuation in a post thunk
  1543. (let ()
  1544. (define call/pt call-with-continuation-prompt)
  1545. (define call/comp-cc call-with-composable-continuation)
  1546. (define (go p0 direct?)
  1547. (define accum null)
  1548. (define (print v) (set! accum (append accum (list v))))
  1549. (define a #f)
  1550. (define do-a? #t)
  1551. (call/pt
  1552. (lambda ()
  1553. (dynamic-wind
  1554. (lambda () (print 1))
  1555. (lambda ()
  1556. (begin
  1557. (dynamic-wind
  1558. (lambda () (print 2))
  1559. (lambda ()
  1560. ((call/cc (lambda (k)
  1561. (begin
  1562. (set! a k)
  1563. (lambda () 12)))
  1564. p0)))
  1565. (lambda () (print 3)))
  1566. (dynamic-wind
  1567. (lambda () (print 4))
  1568. (lambda ()
  1569. (if do-a?
  1570. (begin
  1571. (set! do-a? #f)
  1572. (a (lambda () 11)))
  1573. 12))
  1574. (lambda ()
  1575. (begin
  1576. (print 5)
  1577. (call/comp-cc
  1578. (lambda (k)
  1579. (if direct?
  1580. (k 10)
  1581. (call/pt
  1582. (lambda ()
  1583. (k 10))
  1584. p0
  1585. (lambda (x) x))))
  1586. p0))))))
  1587. (lambda () (print 6))))
  1588. p0
  1589. (lambda (x) x))
  1590. accum)
  1591. (test '(1 2 3 4 5 1 6 2 3 4 5 1 6 6) go (default-continuation-prompt-tag) #t)
  1592. (test '(1 2 3 4 5 1 6 2 3 4 5 1 6 6) go (make-continuation-prompt-tag) #t)
  1593. (test '(1 2 3 4 5 1 2 3 4 5 1 6 6 2 3 4 5 1 6 6) go (default-continuation-prompt-tag) #f)
  1594. (test '(1 2 3 4 5 1 2 3 4 5 1 6 6 2 3 4 5 1 6 6) go (make-continuation-prompt-tag) #f))
  1595. ;; ----------------------------------------
  1596. ;; Run two levels of continuations where an explicit
  1597. ;; prompt in a capturing thread is represented by an
  1598. ;; implicit prompt in the calling thread.
  1599. (let ()
  1600. (define (go wrap)
  1601. (let ()
  1602. (define (foo thunk)
  1603. (call-with-continuation-prompt
  1604. (lambda ()
  1605. (wrap
  1606. (lambda ()
  1607. (let/cc ret
  1608. (let ([run? #f])
  1609. (let/cc run
  1610. (thread (lambda ()
  1611. (sync (system-idle-evt))
  1612. (set! run? #t)
  1613. (run))))
  1614. (when run? (ret (thunk))))))))))
  1615. (define s (make-semaphore))
  1616. (foo (lambda () (semaphore-post s)))
  1617. (test s sync s)))
  1618. (go (lambda (f) (f)))
  1619. (go (lambda (f) (dynamic-wind void f void))))
  1620. ;; ----------------------------------------
  1621. ;; Second continuation spans two meta-continuations,
  1622. ;; and cuts the deeper meta-continuation in half:
  1623. (test
  1624. '("x1")
  1625. 'nested-half
  1626. (let* ([says null]
  1627. [say (lambda (s)
  1628. (set! says (cons s says)))]
  1629. [a (make-continuation-prompt-tag 'a)]
  1630. [b (make-continuation-prompt-tag 'b)])
  1631. (let ([ak
  1632. (with-continuation-mark 'x "x0"
  1633. (call-with-continuation-prompt
  1634. (lambda ()
  1635. (with-continuation-mark 'y "y0"
  1636. (let ([bk (call-with-continuation-prompt
  1637. (lambda ()
  1638. (let ([f (call-with-composable-continuation
  1639. (lambda (k)
  1640. (lambda () k))
  1641. b)])
  1642. (say "bcall")
  1643. (begin0
  1644. (f)
  1645. (say "breturn"))))
  1646. b)])
  1647. (call-with-continuation-prompt
  1648. (lambda ()
  1649. ((bk (lambda ()
  1650. (let ([f (call/cc (lambda (k) (lambda () (lambda () k))) a)])
  1651. (begin0
  1652. (f)
  1653. (say "areturn")))))))
  1654. b))))
  1655. a))])
  1656. (with-continuation-mark 'x "x1"
  1657. (call-with-continuation-prompt
  1658. (lambda ()
  1659. (ak (lambda ()
  1660. (lambda ()
  1661. (continuation-mark-set->list (current-continuation-marks) 'x)))))
  1662. a)))))
  1663. ;; ----------------------------------------
  1664. ;; Tests related to cotinuations that capture pre-thunk frames
  1665. ;; Simple case:
  1666. (let ([t
  1667. (lambda (wrapper)
  1668. (test
  1669. '(pre1 mid1 post1 pre2 mid1 post1 post2)
  1670. 'cc1
  1671. (let ([k #f]
  1672. [recs null])
  1673. (define (queue v) (set! recs (cons v recs)))
  1674. (call-with-continuation-prompt
  1675. (lambda ()
  1676. (dynamic-wind
  1677. (lambda ()
  1678. (queue 'pre1)
  1679. (call-with-composable-continuation
  1680. (lambda (k0)
  1681. (set! k k0))))
  1682. (lambda () (queue 'mid1))
  1683. (lambda () (queue 'post1)))))
  1684. (wrapper
  1685. (lambda ()
  1686. (dynamic-wind
  1687. (lambda () (queue 'pre2))
  1688. (lambda () (k))
  1689. (lambda () (queue 'post2)))))
  1690. (reverse recs))))])
  1691. (t (lambda (f) (f)))
  1692. (t call-with-continuation-prompt))
  1693. ;; Mix in some extra dynamic winds:
  1694. (test
  1695. '(pre1 mid1 post1 pre2 mid1 post1 post2 pre2 mid1 post1 post2)
  1696. 'cc2
  1697. (let ([k #f]
  1698. [k2 #f]
  1699. [recs null])
  1700. (define (queue v) (set! recs (cons v recs)))
  1701. (call-with-continuation-prompt
  1702. (lambda ()
  1703. (call-with-continuation-prompt
  1704. (lambda ()
  1705. (dynamic-wind
  1706. (lambda ()
  1707. (queue 'pre1)
  1708. ((call-with-composable-continuation
  1709. (lambda (k0)
  1710. (set! k k0)
  1711. void))))
  1712. (lambda () (queue 'mid1))
  1713. (lambda () (queue 'post1)))))
  1714. (let/ec esc
  1715. (dynamic-wind
  1716. (lambda () (queue 'pre2))
  1717. (lambda ()
  1718. (k (lambda ()
  1719. (let/cc k0
  1720. (set! k2 k0))))
  1721. (esc))
  1722. (lambda () (queue 'post2))))))
  1723. (call-with-continuation-prompt
  1724. (lambda () (k2)))
  1725. (reverse recs)))
  1726. ;; Even more dynamic-winds:
  1727. (test
  1728. '(pre0 pre1 mid1 post1 post0
  1729. pre1.5 pre2 pre0 mid1 post1 post0 post2 post1.5
  1730. pre3 pre1.5 pre2 pre0 mid1 post1 post0 post2 post1.5 post3)
  1731. 'cc3
  1732. (let ([k #f]
  1733. [k2 #f]
  1734. [recs null])
  1735. (define (queue v) (set! recs (cons v recs)))
  1736. (call-with-continuation-prompt
  1737. (lambda ()
  1738. (dynamic-wind
  1739. (lambda ()
  1740. (queue 'pre0))
  1741. (lambda ()
  1742. (dynamic-wind
  1743. (lambda ()
  1744. (queue 'pre1)
  1745. ((call-with-composable-continuation
  1746. (lambda (k0)
  1747. (set! k k0)
  1748. void))))
  1749. (lambda () (queue 'mid1))
  1750. (lambda () (queue 'post1))))
  1751. (lambda ()
  1752. (queue 'post0)))))
  1753. (call-with-continuation-prompt
  1754. (lambda ()
  1755. (dynamic-wind
  1756. (lambda () (queue 'pre1.5))
  1757. (lambda ()
  1758. (dynamic-wind
  1759. (lambda () (queue 'pre2))
  1760. (lambda () (k (lambda ()
  1761. (call-with-composable-continuation
  1762. (lambda (k0)
  1763. (set! k2 k0))))))
  1764. (lambda () (queue 'post2))))
  1765. (lambda () (queue 'post1.5)))))
  1766. (call-with-continuation-prompt
  1767. (lambda ()
  1768. (dynamic-wind
  1769. (lambda () (queue 'pre3))
  1770. (lambda () (k2))
  1771. (lambda () (queue 'post3)))))
  1772. (reverse recs)))
  1773. ;; Arrange for the captured pre-thunk to trigger extra cloning
  1774. ;; of dynmaic wind records in continuation application:
  1775. (test
  1776. '(pre1 pre2 post2 post1 pre1 pre2 post2 post1 last pre2 post2 post1)
  1777. 'cc4
  1778. (let ([k #f]
  1779. [k2 #f]
  1780. [recs null]
  1781. [tag (make-continuation-prompt-tag)])
  1782. (define (queue v) (set! recs (cons v recs)))
  1783. (call-with-continuation-prompt
  1784. (lambda ()
  1785. (dynamic-wind
  1786. (lambda ()
  1787. (queue 'pre1)
  1788. ((call-with-composable-continuation
  1789. (lambda (k0)
  1790. (set! k k0)
  1791. void))))
  1792. (lambda ()
  1793. (dynamic-wind
  1794. (lambda () (queue 'pre2))
  1795. (lambda ()
  1796. ((call-with-composable-continuation
  1797. (lambda (k0)
  1798. (set! k2 k0)
  1799. void))))
  1800. (lambda () (queue 'post2))))
  1801. (lambda () (queue 'post1)))))
  1802. (let ([k3
  1803. (call-with-continuation-prompt
  1804. (lambda ()
  1805. (call-with-continuation-prompt
  1806. (lambda ()
  1807. (k2 (lambda ()
  1808. (call-with-composable-continuation
  1809. (lambda (k0)
  1810. (abort-current-continuation tag (lambda () k0)))))))))
  1811. tag)])
  1812. (queue 'last)
  1813. (call-with-continuation-prompt
  1814. (lambda ()
  1815. (k void))
  1816. tag))
  1817. (reverse recs)))
  1818. ;; ----------------------------------------
  1819. ;; Try long chain of composable continuations
  1820. (let ([long-loop
  1821. (lambda (on-overflow)
  1822. (let ([v (make-vector 6)])
  1823. (vector-set-performance-stats! v)
  1824. (let ([overflows (vector-ref v 5)])
  1825. ;; Although this is a constant-space loop, the implementation
  1826. ;; pushes each captured continuation further and further down
  1827. ;; the C stack. Eventually, the relevant segment wraps around,
  1828. ;; with an overflow. Push a little deeper and then capture
  1829. ;; that.
  1830. (let loop ([n 0][fuel #f])
  1831. (vector-set-performance-stats! v)
  1832. (cond
  1833. [(and (not fuel)
  1834. ((vector-ref v 5) . > . overflows))
  1835. (begin
  1836. (printf "Overflow at ~a\n" n)
  1837. (loop n 5))]
  1838. [(and fuel (zero? fuel))
  1839. (on-overflow)]
  1840. [else
  1841. ((call-with-continuation-prompt
  1842. (lambda ()
  1843. ((call-with-composable-continuation
  1844. (lambda (k)
  1845. (lambda (n f) k)))
  1846. (add1 n)
  1847. (and fuel (sub1 fuel)))))
  1848. loop)])))))]
  1849. [once-k #f])
  1850. (printf "Breaking long chain...\n")
  1851. (let ([t (thread (lambda () (long-loop void)))])
  1852. (sleep 0.05)
  1853. (break-thread t)
  1854. (sync (system-idle-evt))
  1855. (test #f thread-running? t))
  1856. (printf "Trying long chain...\n")
  1857. (let ([k (long-loop (lambda ()
  1858. ((let/cc k (lambda () k)))))])
  1859. (when (procedure? k)
  1860. (set! once-k k)
  1861. (k (lambda () 17)))
  1862. (test #t procedure? once-k)
  1863. (test k values 17)
  1864. (err/rt-test (call-with-continuation-barrier
  1865. (lambda ()
  1866. (once-k 18)))
  1867. exn:fail:contract:continuation?))
  1868. (printf "Trying long chain again...\n")
  1869. (let ([k (call-with-continuation-prompt
  1870. (lambda ()
  1871. (long-loop (lambda ()
  1872. ((call-with-composable-continuation
  1873. (lambda (k)
  1874. (lambda () k))))))))])
  1875. (test 18 k (lambda () 18))
  1876. (err/rt-test (k (lambda () (/ 0))) exn:fail:contract:divide-by-zero?)
  1877. (test 45 call-with-continuation-prompt
  1878. (lambda ()
  1879. (k (lambda () (abort-current-continuation
  1880. (default-continuation-prompt-tag)
  1881. (lambda () 45))))))))
  1882. ;; ----------------------------------------
  1883. ;; Check continuations captured in continuations applied in
  1884. ;; a thread:
  1885. (test (void)
  1886. 'simple-thread-transfer
  1887. (let ([k (call-with-continuation-prompt
  1888. (lambda ()
  1889. (call/cc values)))])
  1890. (sync (thread (lambda () (k 6))))
  1891. (void)))
  1892. (test (void)
  1893. 'capture-in-transferred-thread
  1894. (let ([k (call-with-continuation-prompt
  1895. (lambda ()
  1896. (let/ec esc
  1897. (call/cc esc)
  1898. (call/cc values))))])
  1899. (sync (thread (lambda () (k 6))))
  1900. (void)))
  1901. (let ()
  1902. (define sema (make-semaphore 1))
  1903. (define l null)
  1904. (define (push v) (semaphore-wait sema) (set! l (cons v l)) (semaphore-post sema))
  1905. (define (count n)
  1906. (let loop ([l l])
  1907. (cond
  1908. [(null? l) 0]
  1909. [(equal? (car l) n) (add1 (loop (cdr l)))]
  1910. [else (loop (cdr l))])))
  1911. (define (f)
  1912. (push 1)
  1913. (call/cc thread)
  1914. (push 2)
  1915. (call/cc thread)
  1916. (push 3))
  1917. (call-with-continuation-prompt f)
  1918. (sync (system-idle-evt))
  1919. (test 1 count 1)
  1920. (test 2 count 2)
  1921. (test 4 count 3))
  1922. ;; ----------------------------------------
  1923. ;; Test genearted by a random tester that turns out
  1924. ;; to check meta-continuation continuation-mark lookup
  1925. ;; in a dynamic-wind thunk:
  1926. (test
  1927. 'exn
  1928. 'random-dc-test
  1929. (with-handlers ([exn:fail? (lambda (exn) 'exn)])
  1930. (let ()
  1931. (define tag
  1932. (let ([tags (make-hash)])
  1933. (λ (v)
  1934. (hash-ref tags v
  1935. (λ ()
  1936. (let ([t (make-continuation-prompt-tag)])
  1937. (hash-set! tags v t)
  1938. t))))))
  1939. (define-syntax-rule (% tag-val expr handler)
  1940. (call-with-continuation-prompt
  1941. (λ () expr)
  1942. (let ([v tag-val])
  1943. (if (let comparable? ([v v])
  1944. (cond [(procedure? v) #f]
  1945. [(list? v) (andmap comparable? v)]
  1946. [else #t]))
  1947. (tag v)
  1948. (raise-type-error '% "non-procedure" v)))
  1949. (let ([h handler])
  1950. (λ (x) (h x)))))
  1951. (define (abort tag-val result)
  1952. (abort-current-continuation (tag tag-val) result))
  1953. (define (call/comp proc tag-val)
  1954. (call-with-composable-continuation (compose proc force-unary) (tag tag-val)))
  1955. (define (call/cm key val thunk)
  1956. (with-continuation-mark key val (thunk)))
  1957. (define (current-marks key tag-val)
  1958. (continuation-mark-set->list
  1959. (current-continuation-marks (tag tag-val))
  1960. key))
  1961. (define ((force-unary f) x) (f x))
  1962. (define (_call/cc proc tag-val)
  1963. (call/cc (compose proc force-unary) (tag tag-val)))
  1964. (letrec ((CEJ-comp-cont_13 #f)
  1965. (CEJ-skip-pre?_12 #f)
  1966. (CEJ-allocated?_11 #f)
  1967. (s-comp-cont_9 #f)
  1968. (s-skip-pre?_8 #f)
  1969. (s-allocated?_7 #f)
  1970. (N-comp-cont_4 #f)
  1971. (N-skip-pre?_3 #f)
  1972. (N-allocated?_2 #f)
  1973. (handlers-disabled?_0 #f))
  1974. (%
  1975. #t
  1976. ((begin
  1977. (set! handlers-disabled?_0 #t)
  1978. ((λ (v_1)
  1979. (%
  1980. v_1
  1981. ((λ (t_5)
  1982. (if N-allocated?_2
  1983. (begin (if handlers-disabled?_0 #f (set! N-skip-pre?_3 #t)) (N-comp-cont_4 t_5))
  1984. (%
  1985. 1
  1986. (dynamic-wind
  1987. (λ ()
  1988. (if handlers-disabled?_0
  1989. #f
  1990. (if N-allocated?_2
  1991. (if N-skip-pre?_3
  1992. (set! N-skip-pre?_3 #f)
  1993. (begin
  1994. (set! handlers-disabled?_0 #t)
  1995. ((λ (v_6)
  1996. (% v_6 (_call/cc (λ (k) (abort v_6 k)) v_6) (λ (x) (begin (set! handlers-disabled?_0 #f) x))))
  1997. print)))
  1998. #f)))
  1999. (λ () ((call/comp (λ (k) (begin (set! N-comp-cont_4 k) (abort 1 k))) 1)))
  2000. (λ () (if handlers-disabled?_0 (set! N-allocated?_2 #t) (if N-allocated?_2 #f (set! N-allocated?_2 #t)))))
  2001. (λ (k) (begin (if handlers-disabled?_0 #f (set! N-skip-pre?_3 #t)) (k t_5))))))
  2002. (λ ()
  2003. ((λ (t_10)
  2004. (if s-allocated?_7
  2005. (begin (if handlers-disabled?_0 #f (set! s-skip-pre?_8 #t)) (s-comp-cont_9 t_10))
  2006. (%
  2007. 1
  2008. (dynamic-wind
  2009. (λ () (if handlers-disabled?_0 #f (if s-allocated?_7 (if s-skip-pre?_8 (set! s-skip-pre?_8 #f) #f) #f)))
  2010. (λ () ((call/comp (λ (k) (begin (set! s-comp-cont_9 k) (abort 1 k))) 1)))
  2011. (λ ()
  2012. (if handlers-disabled?_0 (set! s-allocated?_7 #t) (if s-allocated?_7 #f (set! s-allocated?_7 #t)))))
  2013. (λ (k) (begin (if handlers-disabled?_0 #f (set! s-skip-pre?_8 #t)) (k t_10))))))
  2014. (λ ()
  2015. ((λ (t_14)
  2016. (if CEJ-allocated?_11
  2017. (begin (if handlers-disabled?_0 #f (set! CEJ-skip-pre?_12 #t)) (CEJ-comp-cont_13 t_14))
  2018. (%
  2019. 1
  2020. (dynamic-wind
  2021. (λ ()
  2022. (if handlers-disabled?_0
  2023. #f
  2024. (if CEJ-allocated?_11 (if CEJ-skip-pre?_12 (set! CEJ-skip-pre?_12 #f) first) #f)))
  2025. (λ () ((call/comp (λ (k) (begin (set! CEJ-comp-cont_13 k) (abort 1 k))) 1)))
  2026. (λ ()
  2027. (if handlers-disabled?_0
  2028. (set! CEJ-allocated?_11 #t)
  2029. (if CEJ-allocated?_11 call/cm (set! CEJ-allocated?_11 #t)))))
  2030. (λ (k) (begin (if handlers-disabled?_0 #f (set! CEJ-skip-pre?_12 #t)) (k t_14))))))
  2031. (λ () (_call/cc (λ (k) (abort v_1 k)) v_1)))))))
  2032. (λ (x) (begin (set! handlers-disabled?_0 #f) x))))
  2033. #t))
  2034. 1234)
  2035. (λ (x) x))))))
  2036. ;; ----------------------------------------
  2037. ;; Test genearted by a random tester that turns out
  2038. ;; to check meta-continuation offsets for dynamic-wind
  2039. ;; frames:
  2040. (test
  2041. 'expected-result
  2042. 'nested-meta-continuaion-test
  2043. (let ()
  2044. (define pt1 (make-continuation-prompt-tag))
  2045. (define pt3 (make-continuation-prompt-tag))
  2046. (define call/comp call-with-composable-continuation)
  2047. (define abort abort-current-continuation)
  2048. (define-syntax-rule (% pt body handler)
  2049. (call-with-continuation-prompt
  2050. (lambda () body)
  2051. pt
  2052. handler))
  2053. ;; (lambda (f) (f))
  2054. ;; as a composable continuation:
  2055. (define comp-app
  2056. (%
  2057. pt1
  2058. ((call/comp
  2059. (λ (k) (abort pt1 k))
  2060. pt1))
  2061. (lambda (k) k)))
  2062. ;; (lambda (f) (dynamic-wind void f void))
  2063. ;; as a composable continuation:
  2064. (define dw-comp-app
  2065. (%
  2066. pt1
  2067. (dynamic-wind
  2068. void
  2069. (λ ()
  2070. ((call/comp
  2071. (λ (k) (abort pt1 k))
  2072. pt1)))
  2073. void)
  2074. (lambda (k) k)))
  2075. (%
  2076. pt3
  2077. (dw-comp-app
  2078. (λ ()
  2079. (%
  2080. pt1
  2081. (dynamic-wind
  2082. void
  2083. (λ ()
  2084. ((call/comp
  2085. (λ (k) (abort pt1 k))
  2086. pt1)))
  2087. void)
  2088. (λ (k)
  2089. (k ; composable app under two dyn-winds
  2090. ;; where the outer dw is in a deeper meta-cont
  2091. (λ ()
  2092. (comp-app
  2093. (λ () ; at this point, both dws are in a meta-cont
  2094. (make-will-executor)
  2095. ((%
  2096. pt3
  2097. (comp-app
  2098. (λ () ;; both dws are in a meta-meta-cont
  2099. ;; as the continuation is captured
  2100. (call/cc (λ (k) k) pt3)))
  2101. void) ; = id continuation that aborts to pt3;
  2102. ;; as the continuation is applied, dws are back to
  2103. ;; being in a mere meta-cont, but the continuation
  2104. ;; itself will restore a meta-continuation layer
  2105. 'expected-result)))))))))
  2106. (λ (x) x))))
  2107. ;; ----------------------------------------
  2108. ;; There's a "is the target prompt still in place?"
  2109. ;; check that should not happen when a composable
  2110. ;; continuation is applied. (Random testing discovered
  2111. ;; an incorrect check.)
  2112. (test
  2113. 12345
  2114. 'no-prompt-check-on-compose
  2115. (let ()
  2116. (define pt1 (make-continuation-prompt-tag))
  2117. (define-syntax-rule (% pt body handler)
  2118. (call-with-continuation-prompt
  2119. (lambda () body)
  2120. pt
  2121. handler))
  2122. ;; (lambda (v) v)
  2123. ;; as a composable continuation:
  2124. (define comp-id
  2125. (%
  2126. pt1
  2127. (call-with-composable-continuation
  2128. (λ (k) (abort-current-continuation pt1 k))
  2129. pt1)
  2130. (lambda (k) k)))
  2131. ((% pt1
  2132. (dynamic-wind
  2133. (λ () (comp-id 2))
  2134. (λ ()
  2135. ;; As we jump back to this continuation,
  2136. ;; it's ok that no `pt1' prompt is
  2137. ;; in place anymore
  2138. (call-with-composable-continuation
  2139. (λ (k) (abort-current-continuation
  2140. pt1
  2141. k))
  2142. pt1))
  2143. (λ () #f))
  2144. (λ (x) x))
  2145. 12345)))
  2146. (test
  2147. 12345
  2148. 'no-prompt-post-check-on-compose
  2149. (let ()
  2150. (define pt1 (make-continuation-prompt-tag))
  2151. (define-syntax-rule (% pt body handler)
  2152. (call-with-continuation-prompt
  2153. (lambda () body)
  2154. pt
  2155. handler))
  2156. ((λ (y-comp-cont_7)
  2157. ((λ (x-comp-cont_3)
  2158. ((%
  2159. pt1
  2160. (x-comp-cont_3
  2161. (λ ()
  2162. (y-comp-cont_7
  2163. (λ () (call-with-composable-continuation
  2164. (λ (k) (abort-current-continuation pt1 k))
  2165. pt1)))))
  2166. (λ (x) x))
  2167. 12345))
  2168. (%
  2169. pt1
  2170. (dynamic-wind
  2171. (λ () (y-comp-cont_7 (λ () #f)))
  2172. (λ () ((call-with-composable-continuation
  2173. (λ (k) (abort-current-continuation pt1 k))
  2174. pt1)))
  2175. (λ () #f))
  2176. (λ (x) x))))
  2177. (%
  2178. pt1
  2179. (dynamic-wind
  2180. (λ () #f)
  2181. (λ () ((call-with-composable-continuation
  2182. (λ (k) (abort-current-continuation pt1 k))
  2183. pt1)))
  2184. (λ () #f))
  2185. (λ (x) x)))))