Skip to content

Bug in parsing instructions after resume #52

Closed
@ahuoguo

Description

@ahuoguo

Hi,

The following gen.wast taken from stack-switching explainer can't be parsed in the reference interpreter when unfolded

(module
  (type (;0;) (func))
  (type (;1;) (cont 0))
  (type (;2;) (func (param i32)))
  (type (;3;) (func (result i32 (ref 1))))
  (import "spectest" "print_i32" (func (;0;) (type 2)))
  (tag (;0;) (type 2) (param i32))
  (start 2)
  (elem (;0;) declare func 1)
  (func (;1;) (type 0)
    (local i32)
    i32.const 100
    local.set 0
    loop ;; label = @1
      local.get 0
      suspend 0
      local.get 0
      i32.const 1
      i32.sub
      local.tee 0
      br_if 0 (;@1;)
    end
  )
  (func (;2;) (type 0)
    (local (ref 1))
    ref.func 1
    cont.new 1
    local.set 0
    loop ;; label = @1
      block (type 3) (result i32 (ref 1)) ;; label = @2
        local.get 0
        resume 1 (on 0 0 (;@2;))
        i32.const 42
        call 0
        return
      end
      local.set 0
      call 0
      br 0 (;@1;)
    end
  )
)

It gives me the following syntax error:

gen-stripped.wast:34.9-34.13: syntax error: unexpected token

Here's the working folded version

(module $generator
  (type $ft (func))
  ;; Types of continuations used by the generator:
  ;; No need for param or result types: No data passed back to the
  ;; generator when resuming it, and $generator function has no return
  ;; values.
  (type $ct (cont $ft))
  (func $print (import "spectest" "print_i32") (param i32))
  
  ;; Tag used to coordinate between generator and consumer: The i32 param
  ;; corresponds to the generated values passed; no values passed back from
  ;; generator to consumer.
  (tag $gen (param i32))

  ;; Simple generator yielding values from 100 down to 1
  (func $generator
    (local $i i32)
    (local.set $i (i32.const 100))
    (loop $l
      ;; Suspend execution, pass current value of $i to consumer
      (suspend $gen (local.get $i))
      ;; Decrement $i and exit loop once $i reaches 0
      (local.tee $i (i32.sub (local.get $i) (i32.const 1)))
      (br_if $l)
    )
  )
  (elem declare func $generator)

  (func $consumer
    (local $c (ref $ct))
    ;; Create continuation executing function $generator.
    ;; Execution only starts when resumed for the first time.
    (local.set $c (cont.new $ct (ref.func $generator)))
    ;; (call $print (i32.const 42))
    (loop $loop
      (block $on_gen (result i32 (ref $ct))
        ;; Resume continuation $c
        (resume $ct (on $gen $on_gen) (local.get $c))
        (call $print (i32.const 42))
        ;; $generator returned: no more data
        (return)
      )
      ;; Generator suspended, stack now contains [i32 (ref $ct)]
      ;; Save continuation to resume it in the next iteration
      (local.set $c)
      ;; Stack now contains the i32 value produced by $generator
      (call $print)

      (br $loop)
    )
  )
  (start $consumer)
)

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions