-
Notifications
You must be signed in to change notification settings - Fork 4
/
yield.ss
111 lines (98 loc) · 2.92 KB
/
yield.ss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#lang scheme/base
(require (for-syntax scheme/base)
"base.ss")
; Variables --------------------------------------
; continuation-prompt-tag
(define yield-prompt
(make-continuation-prompt-tag 'yield))
; New implementation -----------------------------
; (yield-procedure -> target-procedure) -> target-procedure
(define (make-yieldable/composable-continuations yield->body)
; (U continuation #f)
; where continuation : (any -> any)
(define caller #f)
; (U continuation #f)
(define resume #f)
; d e f -> a b c
(define (yield . args)
(apply values
(call/cc
(lambda (k)
(set! resume k)
(apply caller args))
yield-prompt)))
; d e f -> a b c
(define (return . args)
(apply values
(call/cc
(lambda (k)
(set! resume #f)
(apply caller args))
yield-prompt)))
; a b c -> d e f
(define body
(yield->body yield))
; a b c -> d e f
(lambda args
(call-with-continuation-prompt
(lambda ()
(call/cc
(lambda (k)
(set! caller k)
(if resume
(resume args)
(call-with-values (cut apply body args)
return)))
yield-prompt))
yield-prompt)))
; Old implementation -----------------------------
; (yield-procedure -> target-procedure) -> target-procedure
(define (make-yieldable/full-continuations yield->body)
; (U continuation #f)
; where continuation : (any -> any)
(define caller #f)
; (U continuation #f)
(define resume #f)
; d e f -> a b c
(define (yield . args)
(apply values
(let/cc k
(set! resume k)
(apply caller args))))
; d e f -> a b c
(define (return . args)
(apply values
(let/cc k
(set! resume #f)
(apply caller args))))
; a b c -> d e f
(define body
(yield->body yield))
; a b c -> d e f
(lambda args
(let/cc k
(set! caller k)
(if resume
(resume args)
(call-with-values (cut apply body args)
return)))))
; Main interface ---------------------------------
; (yield-procedure -> target-procedure) -> target-procedure
;
; where target-procedure and yield-procedure have symmetric contracts:
;
; target-procedure : a b c -> d e f
; yield-procedure : d e f -> a b c
(define make-yieldable
make-yieldable/composable-continuations)
; syntax (yieldable (id) stmt ...)
(define-syntax (yieldable stx)
(syntax-case stx ()
[(_ yield statement ...)
#'(make-yieldable (lambda (yield) statement ...))]))
; Provide statements -----------------------------
(provide yieldable)
(provide/contract
[make-yieldable (-> procedure? procedure?)]
[make-yieldable/composable-continuations (-> procedure? procedure?)]
[make-yieldable/full-continuations (-> procedure? procedure?)])