-
Notifications
You must be signed in to change notification settings - Fork 17
/
t30_cc.nim
185 lines (144 loc) Β· 3.96 KB
/
t30_cc.nim
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
include preamble
suite "calling convention":
block:
## some different callback types
type
C = ref object of Continuation
H {.used.} = proc(x: int): float {.cps: C.}
I {.used.} = proc(): float {.cps: C.}
P {.used.} = proc(x: int) {.cps: C.}
S {.used.} = proc() {.cps: C.}
block:
## produce callbacks from a symbol
type
C = ref object of Continuation
proc toH(x: int): float {.cps: C.} = discard
proc toI(): float {.cps: C.} = discard
proc toP(x: int) {.cps: C.} = discard
proc toS() {.cps: C.} = discard
let h {.used.} = whelp toH
let i {.used.} = whelp toI
let p {.used.} = whelp toP
let s {.used.} = whelp toS
block:
## produce callbacks that match whelp types
type
C = ref object of Continuation
H {.used.} = proc(x: int): float {.cps: C.}
I {.used.} = proc(): float {.cps: C.}
P {.used.} = proc(x: int) {.cps: C.}
S {.used.} = proc() {.cps: C.}
proc toH(x: int): float {.cps: C.} = discard
proc toI(): float {.cps: C.} = discard
proc toP(x: int) {.cps: C.} = discard
proc toS() {.cps: C.} = discard
let h {.used.}: H = whelp toH
let i {.used.}: I = whelp toI
let p {.used.}: P = whelp toP
let s {.used.}: S = whelp toS
block:
## execute a callback with arguments
type
C = ref object of Continuation
proc foo(x: int): float {.cps: C.} =
result = x.float
const cb = whelp foo
var c = cb.call(3)
var d = cb.call(5)
check cb.recover(c) == 3.0
check cb.recover(d) == 5.0
block:
## callbacks run from inside cps run pass, tail, etc.
var k = newKiller 7
type
ContCall = proc(a: int): int {.cps: Cont.}
proc tail(c: Continuation; d: Cont): Cont =
d.mom = c
step 3
d
proc pass(c: Cont; d: Cont): Cont =
step 4
d
proc head(c: Cont): Cont =
step 1
c
proc bar(a: int): int {.cps: Cont.} =
noop()
step 5
return a * 2
proc foo(c: ContCall) {.cps: Cont.} =
step 2
var x = c(4)
step 6
check x == 8
step 7
foo: whelp bar
check k
block:
## whelp helps disambiguate cps callbacks at instantiation
var k = newKiller 2
type
ContCall {.used.} = proc(a: int): int {.cps: Cont.}
MoreCall {.used.} = proc(a: float): float {.cps: Cont.}
proc bar(a: float): float {.cps: Cont.} =
noop()
return a * 2.0
proc bar(a: int): int {.cps: Cont.} =
step 2
noop()
return a * 2
proc foo(c: ContCall) {.cps: Cont.} =
step 1
var x = c(4)
check x == 8
foo: whelp(ContCall, bar)
check k
block:
## run a callback in cps with natural syntax
when not cpsCallOperatorSupported or defined(cpsNoCallOperator):
skip "unsupported on nim " & NimVersion
else:
type
ContCall = proc(a: int): int {.cps: Cont.}
var k = newKiller 3
proc bar(a: int): int {.cps: Cont.} =
noop()
step 2
return a * 2
proc foo(c: ContCall) {.cps: Cont.} =
step 1
let x = c(4)
check x == 8
step 3
foo: whelp bar
check k
block:
## run a callback with no return value in cps
when not cpsCallOperatorSupported or defined(cpsNoCallOperator):
skip "unsupported on nim " & NimVersion
else:
type
ContCall = proc(a: int) {.cps: Cont.}
var k = newKiller 3
proc bar(a: int) {.cps: Cont.} =
noop()
step 2
proc foo(c: ContCall) {.cps: Cont.} =
step 1
c(4)
step 3
foo: whelp bar
check k
block:
## callback illustration
type
C = ref object of Continuation
Callback = proc(x: int): float {.cps: C.}
proc bar(a: int): float {.cps: C.} =
return 2.0 * a.float
const
cb: Callback = whelp bar
var x: C = cb.call(2)
var y: C = cb.call(4)
check cb.recover(x) == 4.0
check cb.recover(y) == 8.0