Skip to content

Commit b7e4ed5

Browse files
Add a simple and more involved generator example (WebAssembly#31)
* Add a simple and more involved generator example * More examples
1 parent d24a9bd commit b7e4ed5

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
;; Generators
2+
3+
;; generator interface
4+
(module $generator
5+
(tag $yield (export "yield") (param i32))
6+
)
7+
(register "generator")
8+
9+
(module $examples
10+
(type $func (func))
11+
(type $cont (cont $func))
12+
13+
(tag $yield (import "generator" "yield") (param i32))
14+
15+
(func $log (import "spectest" "print_i32") (param i32))
16+
17+
;; yields successive natural numbers
18+
(func $naturals (export "naturals")
19+
(local $n i32)
20+
(loop $l
21+
(suspend $yield (local.get $n))
22+
(local.set $n (i32.add (local.get $n) (i32.const 1)))
23+
(br $l)
24+
)
25+
)
26+
27+
;; yields 1-2-3
28+
(func $one-two-three (export "one-two-three")
29+
(suspend $yield (i32.const 1))
30+
(suspend $yield (i32.const 2))
31+
(suspend $yield (i32.const 3))
32+
)
33+
34+
;; yields successive Fibonacci numbers
35+
(func $fibonacci (export "fibonacci")
36+
(local $a i32)
37+
(local $b i32)
38+
(local $t i32)
39+
(local.set $b (i32.const 1))
40+
(loop $l
41+
(suspend $yield (local.get $a))
42+
(local.set $t (local.get $a))
43+
(local.set $a (local.get $b))
44+
(local.set $b (i32.add (local.get $t) (local.get $a)))
45+
(br $l)
46+
)
47+
)
48+
49+
(func $print-first (export "print-first") (param $n i32) (param $k (ref $cont))
50+
(loop $l
51+
(block $on_yield (result i32 (ref $cont))
52+
(if (local.get $n)
53+
(then (resume $cont (tag $yield $on_yield) (local.get $k)))
54+
)
55+
(return)
56+
) ;; $on_yield (result i32 (ref $cont))
57+
(local.set $k)
58+
(call $log)
59+
(local.set $n (i32.add (local.get $n) (i32.const -1)))
60+
(br $l)
61+
)
62+
(unreachable)
63+
)
64+
65+
(func $sum-first (export "sum-first") (param $n i32) (param $k (ref $cont)) (result i32)
66+
(local $sum i32)
67+
(loop $l
68+
(block $on_yield (result i32 (ref $cont))
69+
(if (local.get $n)
70+
(then (resume $cont (tag $yield $on_yield) (local.get $k)))
71+
)
72+
(return (local.get $sum))
73+
) ;; $on_yield (result i32 (ref $cont))
74+
(local.set $k)
75+
(local.set $sum (i32.add (local.get $sum)))
76+
(local.set $n (i32.add (local.get $n) (i32.const -1)))
77+
(br $l)
78+
)
79+
(unreachable)
80+
)
81+
)
82+
(register "examples")
83+
84+
;; storing generators in a global table and then accessing them through i32 handles
85+
;; without knowledge of handlers
86+
(module $manager
87+
(type $func (func))
88+
(type $cont (cont $func))
89+
90+
(tag $yield (import "generator" "yield") (param i32))
91+
92+
(table $active 0 (ref null $cont))
93+
94+
(func $init (export "init") (param $k (ref $cont)) (result i32)
95+
(table.grow $active (local.get $k) (i32.const 1))
96+
)
97+
98+
(func $next (export "next") (param $g i32) (result i32)
99+
(local $next_k (ref $cont))
100+
(local $next_v i32)
101+
(block $on_yield (result i32 (ref $cont))
102+
(resume $cont (tag $yield $on_yield)
103+
(table.get $active (local.get $g))
104+
)
105+
(return (i32.const -1))
106+
) ;; $on_yield (result i32 (ref $cont))
107+
(local.set $next_k)
108+
(local.set $next_v)
109+
(table.set (local.get $g) (local.get $next_k))
110+
(return (local.get $next_v))
111+
)
112+
)
113+
(register "manager")
114+
115+
(module
116+
(type $func (func))
117+
(type $cont (cont $func))
118+
119+
(elem declare func $naturals $fibonacci $one-two-three)
120+
121+
(func $log (import "spectest" "print_i32") (param i32))
122+
(func $naturals (import "examples" "naturals"))
123+
(func $fibonacci (import "examples" "fibonacci"))
124+
(func $one-two-three (import "examples" "one-two-three"))
125+
(func $print-first (import "examples" "print-first") (param $n i32) (param $k (ref $cont)))
126+
(func $sum-first (import "examples" "sum-first") (param $n i32) (param $k (ref $cont)) (result i32))
127+
(func $init (import "manager" "init") (param $k (ref $cont)) (result i32))
128+
(func $next (import "manager" "next") (param i32) (result i32))
129+
130+
(func $print-with-next (param $n i32) (param $gen i32)
131+
(loop $l
132+
(if (i32.eqz (local.get $n)) (then (return)))
133+
(call $next (local.get $gen))
134+
(call $log)
135+
(local.set $n (i32.add (local.get $n) (i32.const -1)))
136+
(br $l)
137+
)
138+
)
139+
140+
(func $interleave-naturals-and-fib
141+
(local $gen1 i32)
142+
(local $gen2 i32)
143+
(local.set $gen1 (call $init (cont.new $cont (ref.func $naturals))))
144+
(local.set $gen2 (call $init (cont.new $cont (ref.func $fibonacci))))
145+
(call $print-with-next (i32.const 5) (local.get $gen1))
146+
(call $print-with-next (i32.const 5) (local.get $gen2))
147+
(call $print-with-next (i32.const 5) (local.get $gen1))
148+
(call $print-with-next (i32.const 5) (local.get $gen2))
149+
(call $print-with-next (i32.const 5) (local.get $gen1))
150+
(call $print-with-next (i32.const 5) (local.get $gen2))
151+
(call $print-with-next (i32.const 5) (local.get $gen1))
152+
(call $print-with-next (i32.const 5) (local.get $gen2))
153+
)
154+
155+
(func $main (export "main")
156+
(call $interleave-naturals-and-fib)
157+
(call $print-first (i32.const 42) (cont.new $cont (ref.func $naturals)))
158+
(call $print-first (i32.const 42) (cont.new $cont (ref.func $fibonacci)))
159+
(call $sum-first (i32.const 101) (cont.new $cont (ref.func $naturals)))
160+
(call $log)
161+
(call $sum-first (i32.const 10) (cont.new $cont (ref.func $one-two-three)))
162+
(call $log)
163+
)
164+
)
165+
166+
(invoke "main")

0 commit comments

Comments
 (0)