Skip to content

Commit

Permalink
Fixed block type parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
BrendoCosta committed Oct 7, 2024
1 parent c7ac3aa commit 9cf2424
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 16 deletions.
28 changes: 19 additions & 9 deletions src/gwr/parser/instruction_parser.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -304,18 +304,28 @@ pub fn parse_instructions_until(from reader: byte_reader.ByteReader, with predic

pub fn parse_block_type(from reader: byte_reader.ByteReader) -> Result(#(byte_reader.ByteReader, instruction.BlockType), String)
{
//use #(reader, flag) <- result.try(byte_reader.read(from: reader, take: 1))
use data <- result.try(byte_reader.get_remaining(from: reader))
case data
// A structured instruction can consume input and produce output on the operand stack
// according to its annotated block type. It is given either as a type index that refers
// to a suitable function type, or as an optional value type inline, which is a shorthand
// for the function type [] -> [valtype?]
use #(_, first_byte) <- result.try(byte_reader.read(from: reader, take: 1))
case types_parser.is_value_type(first_byte)
{
<<0x40>> -> Ok(#(byte_reader.advance(from: reader, up_to: 1), instruction.EmptyBlock))
_ -> case types_parser.parse_value_type(from: reader)
True ->
{
use #(reader, value_type) <- result.try(types_parser.parse_value_type(from: reader))
Ok(#(reader, instruction.ValueTypeBlock(type_: option.Some(value_type))))
}
False ->
{
Ok(#(reader, value_type)) -> Ok(#(reader, instruction.ValueTypeBlock(type_: value_type)))
_ ->
case first_byte
{
use #(reader, index) <- result.try(value_parser.parse_signed_leb128_integer(from: reader))
Ok(#(reader, instruction.TypeIndexBlock(index: index)))
<<0x40>> -> Ok(#(byte_reader.advance(from: reader, up_to: 1), instruction.ValueTypeBlock(type_: option.None)))
_ ->
{
use #(reader, index) <- result.try(value_parser.parse_signed_leb128_integer(from: reader))
Ok(#(reader, instruction.TypeIndexBlock(index: index)))
}
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/gwr/parser/types_parser.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ pub fn parse_value_type(from reader: byte_reader.ByteReader) -> Result(#(byte_re
Ok(#(reader, value_type))
}

pub fn is_value_type(data: BitArray) -> Bool
{
case data
{
<<0x7f>> | <<0x7e>> | <<0x7d>> | <<0x7c>> | <<0x7b>> | <<0x70>> | <<0x6f>> -> True
_ -> False
}
}

pub fn parse_limits(from reader: byte_reader.ByteReader) -> Result(#(byte_reader.ByteReader, types.Limits), String)
{
// From the spec: "limits are encoded with a preceding flag indicating whether a maximum is present."
Expand Down
3 changes: 1 addition & 2 deletions src/gwr/syntax/instruction.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import ieee_float
/// https://webassembly.github.io/spec/core/syntax/instructions.html#control-instructions
pub type BlockType
{
EmptyBlock
TypeIndexBlock(index: index.TypeIndex)
ValueTypeBlock(type_: types.ValueType)
ValueTypeBlock(type_: Option(types.ValueType))
}

pub type Instruction
Expand Down
10 changes: 5 additions & 5 deletions test/gwr/parser/instruction_parser_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn parse_block_type___empty_block___test()
|> should.equal(
#(
byte_reader.ByteReader(..reader, current_position: 1),
instruction.EmptyBlock
instruction.ValueTypeBlock(type_: option.None)
)
)
}
Expand All @@ -33,7 +33,7 @@ pub fn parse_block_type___value_type_block___test()
|> should.equal(
#(
byte_reader.ByteReader(..reader, current_position: 1),
instruction.ValueTypeBlock(type_: types.Number(types.Integer32))
instruction.ValueTypeBlock(type_: option.Some(types.Number(types.Integer32)))
)
)
}
Expand Down Expand Up @@ -80,7 +80,7 @@ pub fn parse_instruction___loop___test()
#(
byte_reader.ByteReader(..reader, current_position: 9),
instruction.Loop(
block_type: instruction.ValueTypeBlock(type_: types.Number(types.Integer32)),
block_type: instruction.ValueTypeBlock(type_: option.Some(types.Number(types.Integer32))),
instructions: [
instruction.I32Const(value: 8),
instruction.I32Const(value: 65536),
Expand All @@ -100,7 +100,7 @@ pub fn parse_instruction___if___test()
#(
byte_reader.ByteReader(..reader, current_position: 7),
instruction.If(
block_type: instruction.ValueTypeBlock(type_: types.Number(types.Integer32)),
block_type: instruction.ValueTypeBlock(type_: option.Some(types.Number(types.Integer32))),
instructions: [
instruction.I32Const(value: 65536),
instruction.End
Expand All @@ -120,7 +120,7 @@ pub fn parse_instruction___if_else___test()
#(
byte_reader.ByteReader(..reader, current_position: 10),
instruction.If(
block_type: instruction.ValueTypeBlock(type_: types.Number(types.Integer32)),
block_type: instruction.ValueTypeBlock(type_: option.Some(types.Number(types.Integer32))),
instructions: [
instruction.I32Const(value: 65536),
],
Expand Down

0 comments on commit 9cf2424

Please sign in to comment.