1+ (module $generator
2+ (type $ft (func ))
3+ ;; Types of continuations used by the generator:
4+ ;; No need for param or result types: No data passed back to the
5+ ;; generator when resuming it, and $generator function has no return
6+ ;; values.
7+ (type $ct (cont $ft ))
8+ (func $print (import " spectest" " print_i32" ) (param i32 ))
9+
10+ ;; Tag used to coordinate between generator and consumer: The i32 param
11+ ;; corresponds to the generated values passed; no values passed back from
12+ ;; generator to consumer.
13+ (tag $gen (param i32 ))
14+
15+ ;; Simple generator yielding values from 100 down to 1
16+ (func $generator
17+ (local $i i32 )
18+ (local.set $i (i32.const 100 ))
19+ (loop $l
20+ ;; Suspend execution, pass current value of $i to consumer
21+ (suspend $gen (local.get $i ))
22+ ;; Decrement $i and exit loop once $i reaches 0
23+ (local.tee $i (i32.sub (local.get $i ) (i32.const 1 )))
24+ (br_if $l )
25+ )
26+ )
27+ (elem declare func $generator )
28+
29+ (func $consumer
30+ (local $c (ref $ct ))
31+ ;; Create continuation executing function $generator.
32+ ;; Execution only starts when resumed for the first time.
33+ (local.set $c (cont.new $ct (ref.func $generator )))
34+
35+ (loop $loop
36+ (block $on_gen (result i32 (ref $ct ))
37+ ;; Resume continuation $c
38+ (resume $ct (on $gen $on_gen ) (local.get $c ))
39+ ;; $generator returned: no more data
40+ (return )
41+ )
42+ ;; Generator suspended, stack now contains [i32 (ref $ct)]
43+ ;; Save continuation to resume it in the next iteration
44+ (local.set $c )
45+ ;; Stack now contains the i32 value produced by $generator
46+ (call $print )
47+
48+ (br $loop )
49+ )
50+ )
51+ (start $consumer )
52+ )
0 commit comments