diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 27deed05..35f1cc0c 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -98,11 +98,12 @@ Parametric Instructions .. _binary-select: .. math:: - \begin{array}{llclll} + \begin{array}{llclll@{\qquad}l} \production{instruction} & \Binstr &::=& \dots \\ &&|& \hex{1A} &\Rightarrow& \DROP \\ &&|& \hex{1B} &\Rightarrow& \SELECT \\ &&|& - \hex{1C}~~t^\ast{:}\Bvec(\Bvaltype) &\Rightarrow& \SELECT~t^\ast \\ + \hex{1C}~~\X{rt}{:}\Bblocktype + &\Rightarrow& \SELECT~[t] & (\iff \X{rt} = [t]) \\ \end{array} diff --git a/document/core/text/instructions.rst b/document/core/text/instructions.rst index d5901a87..6c04076a 100644 --- a/document/core/text/instructions.rst +++ b/document/core/text/instructions.rst @@ -163,7 +163,8 @@ Parametric Instructions \begin{array}{llclll} \production{instruction} & \Tplaininstr_I &::=& \dots \\ &&|& \text{drop} &\Rightarrow& \DROP \\ &&|& - \text{select}~((t{:}\Tresult)^\ast)^? &\Rightarrow& \SELECT~(t^\ast)^? \\ + \text{select} &\Rightarrow& \SELECT \\ &&|& + \text{select}~t{:}\Tresult &\Rightarrow& \SELECT~[t] \\ \end{array} diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 691778de..3dc748ef 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -259,7 +259,11 @@ let rec instr s = | 0x1a -> drop | 0x1b -> select None - | 0x1c -> select (Some (vec value_type s)) + | 0x1c -> + let ts = stack_type s in + (match List.length ts with + | 1 -> select (Some ts) + | _ -> error s pos "invalid number of select results") | 0x1d | 0x1e | 0x1f as b -> illegal s pos b diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 3d7d13a5..2cce07d9 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -168,7 +168,7 @@ let encode m = | Drop -> op 0x1a | Select None -> op 0x1b - | Select (Some ts) -> op 0x1c; vec value_type ts + | Select (Some ts) -> op 0x1c; stack_type ts | LocalGet x -> op 0x20; var x | LocalSet x -> op 0x21; var x diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 06e75c39..11c7870d 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -71,7 +71,7 @@ and instr' = | Unreachable (* trap unconditionally *) | Nop (* do nothing *) | Drop (* forget a value *) - | Select of value_type list option (* branchless conditional *) + | Select of stack_type option (* branchless conditional *) | Block of stack_type * instr list (* execute in sequence *) | Loop of stack_type * instr list (* loop header *) | If of stack_type * instr list * instr list (* conditional *) diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index 6bad0891..65683e5d 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -348,26 +348,26 @@ plain_instr : select_instr : | SELECT select_instr_results - { let at = at () in fun c -> let b, ts = $2 in - select (if b then (Some ts) else None) @@ at } + { let at = at () in fun c -> + select $2 @@ at } select_instr_results : - | LPAR RESULT value_type_list RPAR select_instr_results - { let _, ts = $5 in true, $3 @ ts } + | block_type + { Some $1 } | /* empty */ - { false, [] } + { None } select_instr_instr : | SELECT select_instr_results_instr { let at1 = ati 1 in - fun c -> let b, ts, es = $2 c in - select (if b then (Some ts) else None) @@ at1, es } + fun c -> let bt, es = $2 c in + select bt @@ at1, es } select_instr_results_instr : - | LPAR RESULT value_type_list RPAR select_instr_results_instr - { fun c -> let _, ts, es = $5 c in true, $3 @ ts, es } + | block_type instr + { fun c -> Some $1, $2 c } | instr - { fun c -> false, [], $1 c } + { fun c -> None, $1 c } call_instr : @@ -458,7 +458,7 @@ expr : /* Sugar */ expr1 : /* Sugar */ | plain_instr expr_list { fun c -> $2 c, $1 c } | SELECT select_expr_results - { fun c -> let b, ts, es = $2 c in es, select (if b then (Some ts) else None) } + { fun c -> let bt, es = $2 c in es, select bt } | CALL_INDIRECT var call_expr_type { fun c -> let x, es = $3 c in es, call_indirect ($2 c table) x } | CALL_INDIRECT call_expr_type /* Sugar */ @@ -473,10 +473,10 @@ expr1 : /* Sugar */ let ts, (es, es1, es2) = $3 c c' in es, if_ ts es1 es2 } select_expr_results : - | LPAR RESULT value_type_list RPAR select_expr_results - { fun c -> let _, ts, es = $5 c in true, $3 @ ts, es } + | block_type expr_list + { fun c -> Some $1, $2 c } | expr_list - { fun c -> false, [], $1 c } + { fun c -> None, $1 c } call_expr_type : | type_use call_expr_params diff --git a/test/core/select.wast b/test/core/select.wast index 33b7f624..638a112f 100644 --- a/test/core/select.wast +++ b/test/core/select.wast @@ -365,19 +365,20 @@ (module (func $arity-0-implicit (select (nop) (nop) (i32.const 1)))) "type mismatch" ) -(assert_invalid - (module (func $arity-0 (select (result) (nop) (nop) (i32.const 1)))) - "invalid result arity" +(assert_malformed + (module quote "(func $arity-0 (select (result) (nop) (nop) (i32.const 1)))") + "unexpected token" ) -(assert_invalid - (module (func $arity-2 (result i32 i32) - (select (result i32 i32) - (i32.const 0) (i32.const 0) - (i32.const 0) (i32.const 0) - (i32.const 1) - ) - )) - "invalid result arity" +(assert_malformed + (module quote + "(func $arity-2 (result i32 i32)" + "(select (result i32 i32)" + "(i32.const 0) (i32.const 0)" + "(i32.const 0) (i32.const 0)" + "(i32.const 1)" + "))" + ) + "unexpected token" )