diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index f1d0a1c5..465498a3 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -590,7 +590,7 @@ instr_list : | instr1 instr_list { fun c -> $1 c @ $2 c } | select_instr_instr_list { $1 } | call_instr_instr_list { $1 } - | resume_instr_instr { fun c -> let e, es = $1 c in e :: es } + | resume_instr_instr_list { $1 } instr1 : | plain_instr { fun c -> [$1 c @@ $sloc] } @@ -768,25 +768,25 @@ call_instr_results_instr_list : | instr_list { fun c -> [], $1 c } -resume_instr_instr : +resume_instr_instr_list : | RESUME var resume_instr_handler_instr { let loc1 = $loc($1) in fun c -> let x = $2 c type_ in - let hs, es = $3 c in resume x hs @@ loc1, es } + let hs, es = $3 c in (resume x hs @@ loc1) :: es } | RESUME_THROW var var resume_instr_handler_instr { let loc1 = $loc($1) in fun c -> let x = $2 c type_ in let tag = $3 c tag in - let hs, es = $4 c in resume_throw x tag hs @@ loc1, es } + let hs, es = $4 c in (resume_throw x tag hs @@ loc1) :: es } resume_instr_handler_instr : | LPAR ON var var RPAR resume_instr_handler_instr { fun c -> let hs, es = $6 c in ($3 c tag, OnLabel ($4 c label)) :: hs, es } | LPAR ON var SWITCH RPAR resume_instr_handler_instr { fun c -> let hs, es = $6 c in ($3 c tag, OnSwitch) :: hs, es } - | instr1 + | instr_list { fun c -> [], $1 c } block_instr : diff --git a/test/core/stack-switching/cont.wast b/test/core/stack-switching/cont.wast index f83dfa86..91c4ba0c 100644 --- a/test/core/stack-switching/cont.wast +++ b/test/core/stack-switching/cont.wast @@ -927,6 +927,112 @@ ) (assert_return (invoke "main") (i32.const 10)) +;; Syntax: check unfolded forms +(module + (type $ft (func)) + (type $ct (cont $ft)) + (rec + (type $ft2 (func (param (ref null $ct2)))) + (type $ct2 (cont $ft2))) + + (tag $yield (param i32)) + (tag $swap) + + ;; Check cont.new + (func (result (ref $ct)) + ref.null $ft + block (param (ref null $ft)) (result (ref $ct)) + cont.new $ct + end + ) + ;; Check cont.bind + (func (param (ref $ct)) (result (ref $ct)) + local.get 0 + block (param (ref $ct)) (result (ref $ct)) + cont.bind $ct $ct + end + ) + ;; Check suspend + (func + block + suspend $swap + end + ) + ;; Check resume + (func (param $k (ref $ct)) (result i32) + (local.get $k) + block $on_yield (param (ref $ct)) (result i32 (ref $ct)) + resume $ct (on $yield $on_yield) + i32.const 42 + return + end + local.set $k + ) + ;; Check resume_throw + (func (param $k (ref $ct)) (result i32) + block $on_yield (result i32 (ref $ct)) + i32.const 42 + local.get $k + resume_throw $ct $yield + i32.const 42 + return + end + local.set $k + ) + ;; Check switch + (func (param $k (ref $ct2)) + local.get $k + block (param (ref $ct2)) (result (ref null $ct2)) + switch $ct2 $swap + end + drop + ) +) + +;; Syntax: check instructions in tail position in unfolded form +(module + (type $ft (func)) + (type $ct (cont $ft)) + (rec + (type $ft2 (func (param (ref null $ct2)))) + (type $ct2 (cont $ft2))) + + (tag $yield (param i32)) + (tag $swap) + + ;; Check cont.new + (func (result (ref $ct)) + ref.null $ft + cont.new $ct + ) + ;; Check cont.bind + (func (param (ref $ct)) (result (ref $ct)) + local.get 0 + cont.bind $ct $ct + ) + + ;; Check resume + (func (;2;) (param $k (ref $ct)) + local.get $k + resume $ct + ) + ;; Check resume_throw + (func (param $k (ref $ct)) + i32.const 42 + local.get $k + resume_throw $ct $yield + ) + ;; Check switch + (func (param $k (ref $ct2)) (result (ref null $ct2)) + local.get $k + switch $ct2 $swap + ) + ;; Check suspend + (func + suspend $swap + ) +) + (module (type $ft0 (func)) (type $ct0 (cont $ft0)) @@ -960,4 +1066,4 @@ (func (param $k (ref $ct)) (switch $ct $t))) - "type mismatch in switch tag") \ No newline at end of file + "type mismatch in switch tag")