From 31735c93aae6de9bba4e3adf26ccbba4db192c93 Mon Sep 17 00:00:00 2001 From: Ilya Rezvov Date: Fri, 23 Feb 2018 14:52:03 -0800 Subject: [PATCH] handle raw instructions properly --- src/Language/Wasm/Parser.y | 97 ++++++++++++++++++++++++++++++++------ tests/samples/if.wast | 4 +- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/src/Language/Wasm/Parser.y b/src/Language/Wasm/Parser.y index 125e543..a7e578f 100644 --- a/src/Language/Wasm/Parser.y +++ b/src/Language/Wasm/Parser.y @@ -270,7 +270,7 @@ import Debug.Trace as Debug 'loop' { Lexeme _ (TKeyword "loop") } 'if' { Lexeme _ (TKeyword "if") } 'else' { Lexeme _ (TKeyword "else") } --- unused now 'end' { Lexeme _ (TKeyword "end") } +'end' { Lexeme _ (TKeyword "end") } 'then' { Lexeme _ (TKeyword "then") } 'table' { Lexeme _ (TKeyword "table") } 'memory' { Lexeme _ (TKeyword "memory") } @@ -574,11 +574,70 @@ memarg4 :: { MemArg } memarg8 :: { MemArg } : opt(offset) opt(align) { MemArg (fromMaybe 0 $1) (fromMaybe 8 $2) } +instruction :: { [Instruction] } + : raw_instr { $1 } + | foldedinstr { $1 } + +-- TODO: handle call_direct call properly, now it tries to consume ')' +raw_instr :: { [Instruction] } + : plaininstr { [PlainInstr $1] } + | 'call_indirect' folded_call_indirect { $2 } + | 'block' opt(ident) raw_block { [$3 $2] } + | 'loop' opt(ident) raw_loop { [$3 $2] } + | 'if' opt(ident) raw_if_result { $3 $2 } + +raw_block :: { Maybe Ident -> Instruction } + : 'end' opt(ident) { \ident -> BlockInstr ident [] [] } + | raw_instr list(instruction) 'end' opt(ident) { \ident -> BlockInstr ident [] ($1 ++ concat $2) } + | '(' raw_block1 { $2 } + +raw_block1 :: { Maybe Ident -> Instruction } + : 'result' valtype ')' list(instruction) 'end' opt(ident) { + \ident -> BlockInstr ident [$2] (concat $4) + } + | foldedinstr1 list(instruction) 'end' opt(ident) { + \ident -> BlockInstr ident [] ($1 ++ concat $2) + } + +raw_loop :: { Maybe Ident -> Instruction } + : 'end' opt(ident) { \ident -> LoopInstr ident [] [] } + | raw_instr list(instruction) 'end' opt(ident) { + \ident -> LoopInstr ident [] ($1 ++ concat $2) + } + | '(' raw_loop1 { $2 } + +raw_loop1 :: { Maybe Ident -> Instruction } + : 'result' valtype ')' list(instruction) 'end' opt(ident) { + \ident -> LoopInstr ident [$2] (concat $4) + } + | foldedinstr1 list(instruction) 'end' opt(ident) { + \ident -> LoopInstr ident [] ($1 ++ concat $2) + } + +raw_if_result :: { Maybe Ident -> [Instruction] } + : raw_else { \ident -> [IfInstr ident [] [] $1] } + | raw_instr list(instruction) raw_else { + \ident -> [IfInstr ident [] ($1 ++ concat $2) $3] + } + | '(' raw_if_result1 { $2 } + +raw_if_result1 :: { Maybe Ident -> [Instruction] } + : 'result' valtype ')' list(instruction) raw_else { + \ident -> [IfInstr ident [$2] (concat $4) $5] + } + | foldedinstr1 list(instruction) raw_else { + \ident -> [IfInstr ident [] ($1 ++ concat $2) $3] + } + +raw_else :: { [Instruction] } + : 'end' opt(ident) { [] } + | 'else' opt(ident) list(instruction) 'end' opt(ident) { concat $3 } + foldedinstr :: { [Instruction] } : '(' foldedinstr1 { $2 } foldedinstr1 :: { [Instruction] } - : plaininstr list(foldedinstr) ')' { concat $2 ++ [PlainInstr $1] } + : plaininstr list(instruction) ')' { concat $2 ++ [PlainInstr $1] } | 'call_indirect' folded_call_indirect { $2 } | 'block' opt(ident) folded_block { [$3 $2] } | 'loop' opt(ident) folded_loop { [$3 $2] } @@ -589,20 +648,24 @@ folded_block :: { Maybe Ident -> Instruction } | '(' folded_block1 { $2 } folded_block1 :: { Maybe Ident -> Instruction } - : 'result' valtype ')' list(foldedinstr) ')' { \ident -> BlockInstr ident [$2] (concat $4) } - | foldedinstr1 list(foldedinstr) ')' { \ident -> BlockInstr ident [] ($1 ++ concat $2) } + : 'result' valtype ')' list(instruction) ')' { \ident -> BlockInstr ident [$2] (concat $4) } + | foldedinstr1 list(instruction) ')' { \ident -> BlockInstr ident [] ($1 ++ concat $2) } folded_loop :: { Maybe Ident -> Instruction } : ')' { \ident -> LoopInstr ident [] [] } | '(' folded_loop1 { $2 } folded_loop1 :: { Maybe Ident -> Instruction } - : 'result' valtype ')' list(foldedinstr) ')' { \ident -> LoopInstr ident [$2] (concat $4) } - | foldedinstr1 list(foldedinstr) ')' { \ident -> LoopInstr ident [] ($1 ++ concat $2) } + : 'result' valtype ')' list(instruction) ')' { \ident -> LoopInstr ident [$2] (concat $4) } + | foldedinstr1 list(instruction) ')' { \ident -> LoopInstr ident [] ($1 ++ concat $2) } folded_if_result :: { Maybe Ident -> [Instruction] } - : 'result' valtype ')' '(' folded_then_else { \ident -> [IfInstr ident [$2] (fst $5) (snd $5)] } - | 'result' valtype ')' '(' foldedinstr1 '(' folded_then_else { \ident -> $5 ++ [IfInstr ident [$2] (fst $7) (snd $7)] } + : 'result' valtype ')' '(' folded_then_else { + \ident -> [IfInstr ident [$2] (fst $5) (snd $5)] + } + | 'result' valtype ')' '(' foldedinstr1 '(' folded_then_else { + \ident -> $5 ++ [IfInstr ident [$2] (fst $7) (snd $7)] + } | folded_if { $1 } folded_if :: { Maybe Ident -> [Instruction] } @@ -610,11 +673,11 @@ folded_if :: { Maybe Ident -> [Instruction] } | foldedinstr1 '(' folded_then_else { \ident -> $1 ++ [IfInstr ident [] (fst $3) (snd $3)] } folded_then_else :: { ([Instruction], [Instruction]) } - : 'then' list(foldedinstr) ')' folded_else { (concat $2, $4)} + : 'then' list(instruction) ')' folded_else { (concat $2, $4)} folded_else :: { [Instruction] } : ')' { [] } - | '(' 'else' list(foldedinstr) ')' ')' { concat $3 } + | '(' 'else' list(instruction) ')' ')' { concat $3 } folded_call_indirect :: { [Instruction] } : ')' { [PlainInstr $ CallIndirect $ AnonimousTypeUse $ FuncType [] []] } @@ -636,7 +699,7 @@ folded_call_indirect_functype1 :: { (Maybe FuncType, [Instruction]) } : paramsresulttypeuse folded_call_indirect_functype { (Just $ mergeFuncType $1 $ fromMaybe emptyFuncType $ fst $2, snd $2) } - | foldedinstr1 list(foldedinstr) ')' { (Nothing, $1 ++ concat $2) } + | foldedinstr1 list(instruction) ')' { (Nothing, $1 ++ concat $2) } importdesc :: { ImportDesc } : 'func' opt(ident) typeuse ')' { ImportFunc $2 $3 } @@ -652,7 +715,10 @@ function :: { [ModuleField] } : 'func' opt(ident) export_import_typeuse_locals_body { $3 $2 } export_import_typeuse_locals_body :: { Maybe Ident -> [ModuleField] } - : ')' { \ident -> [MFFunc $ Function ident (AnonimousTypeUse $ FuncType [] []) [] []] } + : ')' { \i -> [MFFunc $ emptyFunction { ident = i }] } + | raw_instr list(instruction) ')' { + \i -> [MFFunc $ emptyFunction { ident = i, body = $1 ++ concat $2 }] + } | '(' export_import_typeuse_locals_body1 { $2 } export_import_typeuse_locals_body1 :: { Maybe Ident -> [ModuleField] } @@ -696,12 +762,13 @@ signature_locals_body1 :: { Function } locals_body :: { ([LocalType], [Instruction]) } : ')' { ([], []) } + | raw_instr list(instruction) ')' { ([], $1 ++ concat $2)} | '(' locals_body1 { $2 } locals_body1 :: { ([LocalType], [Instruction]) } : 'local' list(valtype) ')' locals_body { (map (LocalType Nothing) $2 ++ fst $4, snd $4) } | 'local' ident valtype ')' locals_body { (LocalType (Just $2) $3 : fst $5, snd $5) } - | foldedinstr1 list(foldedinstr) ')' { ([], $1 ++ concat $2) } + | foldedinstr1 list(instruction) ')' { ([], $1 ++ concat $2) } -- FUNCTION END -- @@ -715,11 +782,11 @@ globaltype :: { GlobalType } | '(' 'mut' valtype ')' { Mut $3 } global_type_export_import :: { Maybe Ident -> [ModuleField] } - : valtype list(foldedinstr) ')' { \ident -> [MFGlobal $ Global ident (Const $1) $ concat $2] } + : valtype list(instruction) ')' { \ident -> [MFGlobal $ Global ident (Const $1) $ concat $2] } | '(' global_mut_export_import { $2 } global_mut_export_import :: { Maybe Ident -> [ModuleField] } - : 'mut' valtype ')' list(foldedinstr) ')' { \ident -> [MFGlobal $ Global ident (Mut $2) $ concat $4] } + : 'mut' valtype ')' list(instruction) ')' { \ident -> [MFGlobal $ Global ident (Mut $2) $ concat $4] } | 'export' name ')' global_type_export_import { \ident -> (MFExport $ Export $2 $ ExportGlobal $ Named `fmap` ident) : ($4 ident) } diff --git a/tests/samples/if.wast b/tests/samples/if.wast index b827c5e..a609345 100644 --- a/tests/samples/if.wast +++ b/tests/samples/if.wast @@ -3,7 +3,6 @@ (module ;; Auxiliary definition (func $dummy) - (func (export "empty") (param i32) (if (get_local 0) (then)) (if (get_local 0) (then) (else)) @@ -25,7 +24,7 @@ (else (call $dummy) (call $dummy) (i32.const 9)) ) ) - +(; (func (export "nested") (param i32 i32) (result i32) (if (result i32) (get_local 0) (then @@ -129,4 +128,5 @@ ) (get_local 1) ) + ;) ) \ No newline at end of file