diff --git a/.vscode/settings.json b/.vscode/settings.json index a477200..c8a9e85 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,21 +1,21 @@ { - "[javascript]": { - "editor.defaultFormatter": "biomejs.biome" - }, - "[typescript]": { - "editor.defaultFormatter": "biomejs.biome" - }, - "[javascriptreact]": { - "editor.defaultFormatter": "biomejs.biome" - }, - "[typescriptreact]": { - "editor.defaultFormatter": "biomejs.biome" - }, - "[gleam]": { - "editor.defaultFormatter": "gleam.gleam" - }, - "typescript.tsdk": "./node_modules/typescript/lib", - "editor.tabSize": 2, - "editor.defaultFormatter": "biomejs.biome", - "editor.formatOnSave": true + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[gleam]": { + "editor.defaultFormatter": "gleam.gleam" + }, + "typescript.tsdk": "./node_modules/typescript/lib", + "editor.tabSize": 2, + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": false } diff --git a/README.md b/README.md index 74d70e3..c7d056b 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ let assert Ok(add_module) = rec_type.func_type([val_type.i32, val_type.i32], [val_type.i32]), ) // 4. Tell the wasm module that "function 0" has the type of "type 0" - |> module.add_function_type(type_idx_0) + |> module.append_function_type_index(type_idx_0) // 5. Add the body of the function to the module at function index 0 |> module.add_code( // 5.a Function parameters and locals must be defined here: [..parameters, ..locals] @@ -71,4 +71,11 @@ Some of these goals are personal, 2. Be compatible with JavaScript and Gleam Targets 3. Validate and Host WASM modules in a Spec Compliant way (not necessarily with performance in mind) 4. (Personal) - Conquer the WebAssembly GC specification, validation, execution, and building -5. Make a developer friendly interface for generating abstract WASM modules, manipulating code, and compile them to WASM binaries \ No newline at end of file +5. Make a developer friendly interface for generating abstract WASM modules, manipulating code, and compile them to WASM binaries + +## Maintainers + +Special Thanks to + +Rishit Chaudhary + diff --git a/gleam.toml b/gleam.toml index 6e3b1a7..2ea6a76 100644 --- a/gleam.toml +++ b/gleam.toml @@ -1,4 +1,4 @@ -name = "shinecoder" +name = "shine_coder" version = "0.0.1" # Fill out these fields if you intend to generate HTML documentation or publish @@ -17,6 +17,8 @@ gleam_stdlib = ">= 0.34.0 and < 2.0.0" ieee_float = ">= 1.0.0 and < 2.0.0" pprint = ">= 1.0.3 and < 2.0.0" simplifile = ">= 2.1.0 and < 3.0.0" +shine_tree = ">= 0.0.3 and < 1.0.0" +gleamy_structures = ">= 1.0.0 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index c378ccb..2557177 100644 --- a/manifest.toml +++ b/manifest.toml @@ -4,17 +4,21 @@ packages = [ { name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" }, { name = "glam", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "66EC3BCD632E51EED029678F8DF419659C1E57B1A93D874C5131FE220DFAD2B2" }, - { name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" }, - { name = "gleam_stdlib", version = "0.39.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "2D7DE885A6EA7F1D5015D1698920C9BAF7241102836CE0C3837A4F160128A9C4" }, + { name = "gleam_erlang", version = "0.26.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "3DF72F95F4716883FA51396FB0C550ED3D55195B541568CAF09745984FD37AD1" }, + { name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" }, + { name = "gleamy_structures", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleamy_structures", source = "hex", outer_checksum = "FF1B7600123B2B7C15E91BEBE6F417B4003928BF4282EF01A74A792B4ED6985A" }, { name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" }, - { name = "ieee_float", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "ieee_float", source = "hex", outer_checksum = "A9C8728DE26A8AA563FF2F49F8802C8875A41BAE86024B34A458C6EB821F1F00" }, + { name = "ieee_float", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "ieee_float", source = "hex", outer_checksum = "F0585C3CF3F93634F40C8EAFBA7AEC98584E8B7B94D1F88C4C8EB4B51732F912" }, { name = "pprint", version = "1.0.3", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "76BBB92E23D12D954BD452686543F29EDE8EBEBB7FC0ACCBCA66EEF276EC3A06" }, + { name = "shine_tree", version = "0.0.6", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "shine_tree", source = "hex", outer_checksum = "AA365F6E10934F15B086CE9EB2ACF63B9992FA1F29ECBADA7A4B1E95241891E7" }, { name = "simplifile", version = "2.1.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "BDD04F5D31D6D34E2EDFAEF0B68A6297AEC939888C3BFCE61133DE13857F6DA2" }, ] [requirements] gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } +gleamy_structures = { version = ">= 1.0.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } ieee_float = { version = ">= 1.0.0 and < 2.0.0" } pprint = { version = ">= 1.0.3 and < 2.0.0" } +shine_tree = { version = ">= 0.0.3 and < 1.0.0" } simplifile = { version = ">= 2.1.0 and < 3.0.0" } diff --git a/src/builder/expression.gleam b/src/builder/expression.gleam index 130d4cb..e23d482 100644 --- a/src/builder/expression.gleam +++ b/src/builder/expression.gleam @@ -1,51 +1,43 @@ +import gleam/list import gleam/option.{type Option, None, Some} -import internal/finger_tree.{type FingerTree} import internal/structure/types.{ type BlockType, type Expr, type Instruction, Block, Expr, If, Loop, } type BlockDefinition { EmptyTop - OuterMostBlock(instructions: FingerTree(Instruction)) - IfBlock(bt: BlockType, instructions: FingerTree(Instruction)) + OuterMostBlock(instructions: List(Instruction)) + IfBlock(bt: BlockType, instructions: List(Instruction)) ElseBlock( bt: BlockType, - if_instructions: FingerTree(Instruction), - else_instructions: FingerTree(Instruction), + if_instructions: List(Instruction), + else_instructions: List(Instruction), ) - LoopBlock(bt: BlockType, instructions: FingerTree(Instruction)) - InlineBlock(bt: BlockType, instructions: FingerTree(Instruction)) + LoopBlock(bt: BlockType, instructions: List(Instruction)) + InlineBlock(bt: BlockType, instructions: List(Instruction)) } pub opaque type ExpressionBuilder { ExpressionBuilder( result: Option(Expr), top: BlockDefinition, - block_stack: FingerTree(BlockDefinition), + block_stack: List(BlockDefinition), ) } pub fn new() -> ExpressionBuilder { - ExpressionBuilder(None, OuterMostBlock(finger_tree.empty), finger_tree.empty) + ExpressionBuilder(None, OuterMostBlock([]), []) } pub fn begin_if(builder: ExpressionBuilder, bt: BlockType) -> ExpressionBuilder { let ExpressionBuilder(result, top, block_stack) = builder - ExpressionBuilder( - result, - IfBlock(bt, finger_tree.empty), - block_stack - |> finger_tree.push(top), - ) + ExpressionBuilder(result, IfBlock(bt, []), [top, ..block_stack]) } pub fn begin_else(builder: ExpressionBuilder) { case builder.top { IfBlock(bt, instructions) -> - ExpressionBuilder( - ..builder, - top: ElseBlock(bt, instructions, finger_tree.empty), - ) + ExpressionBuilder(..builder, top: ElseBlock(bt, instructions, [])) EmptyTop -> panic as "Stack state underflow" _ -> panic as "Invalid stack state, cannot start else block" } @@ -55,103 +47,98 @@ pub fn begin_loop( builder: ExpressionBuilder, bt: BlockType, ) -> ExpressionBuilder { - ExpressionBuilder( - builder.result, - LoopBlock(bt, finger_tree.empty), - builder.block_stack - |> finger_tree.push(builder.top), - ) + ExpressionBuilder(builder.result, LoopBlock(bt, []), [ + builder.top, + ..builder.block_stack + ]) } pub fn begin_block( builder: ExpressionBuilder, bt: BlockType, ) -> ExpressionBuilder { - ExpressionBuilder( - builder.result, - InlineBlock(bt, finger_tree.empty), - builder.block_stack - |> finger_tree.push(builder.top), - ) + ExpressionBuilder(builder.result, InlineBlock(bt, []), [ + builder.top, + ..builder.block_stack + ]) } pub fn end(builder: ExpressionBuilder) { case builder { ExpressionBuilder(None, OuterMostBlock(instructions), block_stack) - if block_stack == finger_tree.empty - -> Ok(ExpressionBuilder(Some(Expr(instructions)), EmptyTop, block_stack)) + if block_stack == [] + -> + Ok(ExpressionBuilder( + Some(Expr(instructions |> list.reverse)), + EmptyTop, + block_stack, + )) ExpressionBuilder(None, IfBlock(bt, if_instructions), block_stack) -> - do_append(block_stack, If(bt, if_instructions, None)) + do_append(block_stack, If(bt, if_instructions |> list.reverse, None)) ExpressionBuilder( None, ElseBlock(bt, if_instructions, else_instructions), block_stack, ) -> - do_append(block_stack, If(bt, if_instructions, Some(else_instructions))) + do_append( + block_stack, + If( + bt, + if_instructions |> list.reverse, + Some(else_instructions |> list.reverse), + ), + ) ExpressionBuilder(None, LoopBlock(bt, loop_instructions), block_stack) -> - do_append(block_stack, Loop(bt, Expr(loop_instructions))) + do_append(block_stack, Loop(bt, Expr(loop_instructions |> list.reverse))) ExpressionBuilder(None, InlineBlock(bt, block_instructions), block_stack) -> - do_append(block_stack, Block(bt, Expr(block_instructions))) + do_append( + block_stack, + Block(bt, Expr(block_instructions |> list.reverse)), + ) ExpressionBuilder(_, EmptyTop, _) -> Error("Stack state underflow") _ -> Error("Invalid stack state") } } -fn do_append( - next_stack: FingerTree(BlockDefinition), - next_instruction: Instruction, -) { - case next_stack |> finger_tree.pop() { - Ok(#(OuterMostBlock(outer_instructions), next_stack)) -> +fn do_append(next_stack: List(BlockDefinition), next_instruction: Instruction) { + case next_stack { + [OuterMostBlock(outer_instructions), ..next_stack] -> Ok(ExpressionBuilder( None, - OuterMostBlock( - outer_instructions - |> finger_tree.push(next_instruction), - ), + OuterMostBlock([next_instruction, ..outer_instructions]), next_stack, )) - Ok(#(IfBlock(outer_bt, outer_if_instructions), next_stack)) -> + [IfBlock(outer_bt, outer_if_instructions), ..next_stack] -> Ok(ExpressionBuilder( None, - IfBlock( - outer_bt, - outer_if_instructions |> finger_tree.push(next_instruction), - ), + IfBlock(outer_bt, [next_instruction, ..outer_if_instructions]), next_stack, )) - Ok(#( + [ ElseBlock(outer_bt, outer_if_instructions, outer_else_instructions), - next_stack, - )) -> + ..next_stack + ] -> Ok(ExpressionBuilder( None, - ElseBlock( - outer_bt, - outer_if_instructions, - outer_else_instructions |> finger_tree.push(next_instruction), - ), + ElseBlock(outer_bt, outer_if_instructions, [ + next_instruction, + ..outer_else_instructions + ]), next_stack, )) - Ok(#(LoopBlock(outer_bt, outer_instructions), next_stack)) -> + [LoopBlock(outer_bt, outer_instructions), ..next_stack] -> Ok(ExpressionBuilder( None, - LoopBlock( - outer_bt, - outer_instructions |> finger_tree.push(next_instruction), - ), + LoopBlock(outer_bt, [next_instruction, ..outer_instructions]), next_stack, )) - Ok(#(InlineBlock(outer_bt, outer_instructions), next_stack)) -> + [InlineBlock(outer_bt, outer_instructions), ..next_stack] -> Ok(ExpressionBuilder( None, - InlineBlock( - outer_bt, - outer_instructions |> finger_tree.push(next_instruction), - ), + InlineBlock(outer_bt, [next_instruction, ..outer_instructions]), next_stack, )) _ -> Error("Stack state underflow") @@ -163,35 +150,31 @@ pub fn push(builder: ExpressionBuilder, inst: Instruction) { OuterMostBlock(instructions) -> ExpressionBuilder( None, - OuterMostBlock(instructions |> finger_tree.push(inst)), + OuterMostBlock([inst, ..instructions]), builder.block_stack, ) IfBlock(bt, instructions) -> ExpressionBuilder( None, - IfBlock(bt, instructions |> finger_tree.push(inst)), + IfBlock(bt, [inst, ..instructions]), builder.block_stack, ) ElseBlock(bt, if_instructions, else_instructions) -> ExpressionBuilder( None, - ElseBlock( - bt, - if_instructions, - else_instructions |> finger_tree.push(inst), - ), + ElseBlock(bt, if_instructions, else_instructions |> list.append([inst])), builder.block_stack, ) LoopBlock(bt, instructions) -> ExpressionBuilder( None, - LoopBlock(bt, instructions |> finger_tree.push(inst)), + LoopBlock(bt, [inst, ..instructions]), builder.block_stack, ) InlineBlock(bt, instructions) -> ExpressionBuilder( None, - InlineBlock(bt, instructions |> finger_tree.push(inst)), + InlineBlock(bt, [inst, ..instructions]), builder.block_stack, ) _ -> panic as "Expression completed, cannot push instruction" @@ -200,9 +183,8 @@ pub fn push(builder: ExpressionBuilder, inst: Instruction) { pub fn end_unwrap(builder) { case builder { - ExpressionBuilder(None, OuterMostBlock(instructions), stack) - if stack == finger_tree.empty - -> Expr(instructions) + ExpressionBuilder(None, OuterMostBlock(instructions), stack) if stack == [] -> + Expr(instructions |> list.reverse) _ -> panic as "Unable to unwrap, invalid expression state" } } diff --git a/src/builder/instructions/README.md b/src/builder/instructions/README.md new file mode 100644 index 0000000..ff55401 --- /dev/null +++ b/src/builder/instructions/README.md @@ -0,0 +1,17 @@ +# WASM Instructions + +Regarding the WebAssembly specification, it might be difficult to understand the purpose of each opcode. The following sections can help you find the information you are looking for. + +## Instructions Structure + +- [Numeric Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#numeric-instructions) +- [Vector (v128) Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#vector-instructions) +- [Reference Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html) +- [Aggregate Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#aggregate-instructions) +- [Parametric Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#parametric-instructions) +- [Variable Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#variable-instructions) +- [Table Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#table-instructions) +- [Memory Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#memory-instructions) +- [Control Instructions](https://webassembly.github.io/gc/core/syntax/instructions.html#control-instructions) + +These instructions are constructed while using the `ExpressionBuilder` api, which only help build the binary representation. diff --git a/src/builder/instructions/any.gleam b/src/builder/instructions/any.gleam index 5b3c6bf..ac61988 100644 --- a/src/builder/instructions/any.gleam +++ b/src/builder/instructions/any.gleam @@ -1,6 +1,7 @@ import builder/expression.{type ExpressionBuilder} import internal/structure/types.{AnyConvertExtern} +/// Convert an external value to an anyref pub fn convert_extern(builder: ExpressionBuilder) { builder |> expression.push(AnyConvertExtern) diff --git a/src/builder/instructions/array.gleam b/src/builder/instructions/array.gleam index dfa11c1..f0a8771 100644 --- a/src/builder/instructions/array.gleam +++ b/src/builder/instructions/array.gleam @@ -16,9 +16,13 @@ pub fn array_new_default(builder: ExpressionBuilder, idx: TypeIDX) { |> expression.push(ArrayNewDefault(idx)) } -pub fn array_new_data(builder: ExpressionBuilder, idx: TypeIDX, data: DataIDX) { +pub fn array_new_data( + builder: ExpressionBuilder, + idx: TypeIDX, + data_idx: DataIDX, +) { builder - |> expression.push(ArrayNewData(idx, data)) + |> expression.push(ArrayNewData(idx, data_idx)) } pub fn array_new_elem(builder: ExpressionBuilder, idx: TypeIDX, elem: ElemIDX) { diff --git a/src/builder/instructions/control.gleam b/src/builder/instructions/control.gleam index 8fc240e..56a3fe0 100644 --- a/src/builder/instructions/control.gleam +++ b/src/builder/instructions/control.gleam @@ -1,5 +1,4 @@ import builder/expression.{type ExpressionBuilder} -import internal/finger_tree.{type FingerTree} import internal/structure/types.{ type BlockType, type FuncIDX, type LabelIDX, type RefType, type TableIDX, type TypeIDX, type ValType, Br, BrIf, BrOnCast, BrOnCastFail, BrOnNonNull, @@ -36,7 +35,7 @@ pub fn select(builder: ExpressionBuilder) { |> expression.push(Select) } -pub fn select_t(builder: ExpressionBuilder, val_type: FingerTree(ValType)) { +pub fn select_t(builder: ExpressionBuilder, val_type: List(ValType)) { builder |> expression.push(SelectT(val_type)) } @@ -135,7 +134,7 @@ pub fn br_on_null(builder: ExpressionBuilder, label_idx: LabelIDX) { pub fn br_table( builder: ExpressionBuilder, - labels: FingerTree(LabelIDX), + labels: List(LabelIDX), default: LabelIDX, ) { builder diff --git a/src/builder/mem_builder.gleam b/src/builder/mem_builder.gleam new file mode 100644 index 0000000..b92b315 --- /dev/null +++ b/src/builder/mem_builder.gleam @@ -0,0 +1,278 @@ +import gleam/bit_array +import gleam/int +import gleam/result +import gleamy/red_black_tree_map.{type Map} +import internal/structure/numbers.{ + type F32, type F64, type I32, type I64, type V128Value, decode_f32, decode_f64, + i32, i64, v128, +} +import internal/structure/types.{type Limits} + +pub opaque type MemBuilder { + MemBuilder( + page_count: Int, + // just a constant value. page_size (64KiB) * page_count = byte count + limits: Limits, + // min pages and max pages + // chunks of 64 bytes + data: Map(Int, BitArray), + ) +} + +pub fn write_bytes( + mem_builder: MemBuilder, + ptr: Int, + bytes: BitArray, +) -> Result(MemBuilder, String) { + let byte_size = bit_array.byte_size(bytes) + case ptr + byte_size, mem_builder.page_count * 65_536 - 1 { + ptr, max_address if ptr > max_address -> Error("Address out of bounds.") + _, _ -> Ok(do_write_bytes(mem_builder, ptr, <<>>, byte_size)) + } +} + +fn do_write_bytes( + mem_builder: MemBuilder, + ptr: Int, + bytes: BitArray, + rest_byte_count: Int, +) { + let segment_index = ptr / 64 + let segment_offset = ptr |> int.bitwise_and(63) + let next_segment_ptr = { segment_index + 1 } * 64 + case rest_byte_count { + 0 -> mem_builder + // if overflow + rest_byte_count -> { + let to_write_byte_count = + 64 + |> int.subtract(segment_offset) + |> int.min(rest_byte_count) + let to_write_bit_count = to_write_byte_count * 8 + + let assert <> = bytes + + let assert << + start:bits-size(segment_offset), + _:bits-size(to_write_bit_count), + end:bits, + >> = case red_black_tree_map.find(mem_builder.data, segment_index) { + Ok(segment) -> segment + _ -> <<0:512>> + } + + case rest { + <<>> -> mem_builder + _ -> + do_write_bytes( + MemBuilder( + ..mem_builder, + data: red_black_tree_map.insert(mem_builder.data, segment_index, << + start:bits, + to_write:bits, + end:bits, + >>), + ), + next_segment_ptr, + rest, + rest_byte_count - to_write_byte_count, + ) + } + } + } +} + +pub fn read_bytes( + mem_builder: MemBuilder, + ptr: Int, + size: Int, +) -> Result(BitArray, String) { + case ptr + size, mem_builder.page_count * 65_536 - 1 { + ptr, max_address if ptr > max_address -> Error("Address out of bounds.") + _, _ -> Ok(do_read_bytes(mem_builder, ptr, <<>>, size)) + } +} + +fn do_read_bytes( + mem_builder: MemBuilder, + ptr: Int, + acc: BitArray, + rest_byte_count: Int, +) -> BitArray { + let segment_index = ptr / 64 + let segment_offset = ptr |> int.bitwise_and(63) + let segment_bits_offset = segment_offset * 8 + let next_segment_ptr = { segment_index + 1 } * 64 + let to_read_bytes = next_segment_ptr - ptr + let to_read_bits = to_read_bytes * 8 + let assert << + _:bits-size(segment_bits_offset), + data:bits-size(to_read_bits), + _:bits, + >> = case red_black_tree_map.find(mem_builder.data, segment_index) { + Ok(segment) -> segment + _ -> <<0:512>> + } + case rest_byte_count - to_read_bytes { + 0 -> <> + rest_byte_count -> + do_read_bytes( + mem_builder, + ptr + to_read_bytes, + <>, + rest_byte_count, + ) + } +} + +pub fn write_int( + mem_builder: MemBuilder, + ptr: Int, + num: Int, + size: Int, +) -> Result(MemBuilder, String) { + let bit_count = size * 8 + write_bytes(mem_builder, ptr, <>) +} + +pub fn read_uint( + mem_builder: MemBuilder, + ptr: Int, + size: Int, +) -> Result(Int, String) { + let bit_size = size * 8 + case read_bytes(mem_builder, ptr, size) { + Ok(<>) -> Ok(value) + Error(e) -> Error(e) + _ -> panic as "Invalid BitArray size" + } +} + +pub fn read_int( + mem_builder: MemBuilder, + ptr: Int, + size: Int, +) -> Result(Int, String) { + let bit_size = size * 8 + case read_bytes(mem_builder, ptr, size) { + Ok(<>) -> Ok(value) + Error(e) -> Error(e) + _ -> panic as "Invalid BitArray size" + } +} + +pub fn i64_load(mem_builder: MemBuilder, ptr: Int) -> Result(I64, String) { + result.try(read_int(mem_builder, ptr, 8), i64) +} + +pub fn i32_load(mem_builder: MemBuilder, ptr: Int) -> Result(I32, String) { + result.try(read_int(mem_builder, ptr, 4), i32) +} + +// F32Load +pub fn f32_load(mem_builder: MemBuilder, ptr: Int) -> Result(F32, String) { + use bytes <- result.try(read_bytes(mem_builder, ptr, 4)) + case decode_f32(bytes) { + Ok(#(value, <<>>)) -> Ok(value) + _ -> Error("Invalid byte sequence.") + } +} + +pub fn f64_load(mem_builder: MemBuilder, ptr: Int) -> Result(F64, String) { + use bytes <- result.try(read_bytes(mem_builder, ptr, 8)) + case decode_f64(bytes) { + Ok(#(value, <<>>)) -> Ok(value) + _ -> Error("Invalid byte sequence.") + } +} + +// V128Load +pub fn v128_load(mem_builder: MemBuilder, ptr: Int) -> Result(V128Value, String) { + result.try(read_bytes(mem_builder, ptr, 16), v128) +} +// I64Load16S +// I64Load16U +// I64Load8S +// I64Load8U +// I32Load16S +// I32Load16U +// I32Load8S +// I32Load8U +// I64Load32S +// I64Load32U +// V128Load8x8S +// V128Load8x8U +// V128Load16x4S +// V128Load16x4U +// V128Load32x2S +// V128Load32x2U +// V128Load32Zero +// V128Load64Zero +// V128Load64Splat +// V128Load32Splat +// V128Load16Splat +// V128Load8Splat +// V128Load8Lane +// V128Load16Lane +// V128Load32Lane +// V128Load64Lane +// I32Load +// I32Load16S +// I32Load16U +// I32Load8S +// I32Load8U +// I64Load +// I64Load16S +// I64Load16U +// I64Load8S +// I64Load8U +// I64Load32S +// I64Load32U +// F64Load +// F32Load +// V128Load +// V128Load8x8S +// V128Load8x8U +// V128Load16x4S +// V128Load16x4U +// V128Load32x2S +// V128Load32x2U +// V128Load32Zero +// V128Load64Zero +// V128Load64Splat +// V128Load32Splat +// V128Load16Splat +// V128Load8Splat +// V128Load8Lane +// V128Load16Lane +// V128Load32Lane +// V128Load64Lane + +// I64Store +// I64Store8 +// I64Store16 +// I64Store32 +// I32Store +// I32Store8 +// I32Store16 +// F64Store +// F32Store +// V128Store +// V128Store8Lane +// V128Store16Lane +// V128Store32Lane +// V128Store64Lane +// I64Store +// I64Store16 +// I64Store8 +// I64Store32 +// I32Store +// I32Store16 +// I32Store8 +// F64Store +// F32Store +// V128Store +// V128Store8Lane +// V128Store16Lane +// V128Store32Lane +// V128Store64Lane diff --git a/src/builder/module.gleam b/src/builder/module.gleam index aec40ff..75fdc0f 100644 --- a/src/builder/module.gleam +++ b/src/builder/module.gleam @@ -1,7 +1,7 @@ +import gleam/list import gleam/option.{type Option, None, Some} import gleam/set.{type Set} import internal/binary/modules -import internal/finger_tree.{type FingerTree} import internal/structure/modules.{ type BinaryModule, type CustomSection, type ExportSection, type FunctionSection, type GlobalSection, type MemorySection, @@ -12,18 +12,29 @@ import internal/structure/modules.{ } as structure_modules import internal/structure/numbers.{type U32, u32} import internal/structure/types.{ - type Export, type Expr, type FuncIDX, type Global, type GlobalIDX, type Limits, - type Locals, type MemIDX, type MemType, type RecType, type RefType, type Table, - type TableIDX, type TableType, type TypeIDX, type ValType, ActiveData, - ActiveElemMode, Code, Const, DataIDX, DeclarativeElemMode, ElemExpressions, - ElemFuncs, ElemIDX, FuncExport, FuncHeapType, FuncIDX, FuncImport, - GlobalExport, GlobalIDX, GlobalImport, GlobalType, HeapTypeRefType, LabelIDX, - Limits, LocalIDX, Locals, MemExport, MemIDX, MemImport, MemType, PassiveData, - PassiveElemMode, TableExport, TableIDX, TableImport, TableType, TypeIDX, Var, + type Export, type Expr, type FieldType, type FuncIDX, type Global, + type GlobalIDX, type Limits, type Locals, type MemIDX, type MemType, + type RecType, type RefType, type Table, type TableIDX, type TableType, + type TypeIDX, type ValType, ActiveData, ActiveElemMode, ArrayCompositeType, + ArrayType, Code, Const, DataIDX, DeclarativeElemMode, ElemExpressions, +<<<<<<< HEAD + ElemFuncs, ElemIDX, FieldIDX, FieldType, FuncCompositeType, FuncExport, + FuncHeapType, FuncIDX, FuncImport, FuncType, Global, GlobalExport, GlobalIDX, + GlobalImport, GlobalType, HeapTypeRefType, LabelIDX, Limits, LocalIDX, Locals, + MemExport, MemIDX, MemImport, MemType, PassiveData, PassiveElemMode, RecType, +======= + ElemFuncs, ElemIDX, FieldType, FuncCompositeType, FuncExport, FuncHeapType, + FuncIDX, FuncImport, FuncType, Global, GlobalExport, GlobalIDX, GlobalImport, + GlobalType, HeapTypeRefType, LabelIDX, Limits, LocalIDX, Locals, MemExport, + MemIDX, MemImport, MemType, PassiveData, PassiveElemMode, RecType, +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) + StructCompositeType, StructType, SubType, Table, TableExport, TableIDX, + TableImport, TableType, TypeIDX, Var, } pub const new = structure_modules.binary_module_new +/// Add a custom section to the module after the last modified section. pub fn custom_section(module: BinaryModule, name: String, data: BitArray) { case module { BinaryModule( @@ -444,29 +455,103 @@ pub fn custom_section(module: BinaryModule, name: String, data: BitArray) { } } -fn add_to_optional_list(items: Option(FingerTree(u)), item: u) { +fn add_to_optional_list(items: Option(List(u)), item: u) { case items { - Some(items) -> Some(finger_tree.push(items, item)) - None -> Some(finger_tree.single(item)) + Some(items) -> Some(items |> list.append([item])) + None -> Some([item]) } } +/// Add a new concrete Recursive Type to the TypeSection. pub fn add_type(module: BinaryModule, type_: RecType) { let BinaryModule(types: types, ..) = module case types { - None -> - BinaryModule( - ..module, - types: Some(TypeSection(finger_tree.single(type_))), - ) + None -> BinaryModule(..module, types: Some(TypeSection([type_]))) Some(TypeSection(types)) -> BinaryModule( ..module, - types: Some(TypeSection(finger_tree.push(types, type_))), + types: Some(TypeSection(list.append(types, [type_]))), ) } } +/// Add a new concrete FuncType to the TypeSection. +pub fn add_func_type( + module: BinaryModule, + parameters: List(ValType), + results: List(ValType), +) { + let func_type = +<<<<<<< HEAD + SubType(False, [], FuncCompositeType(FuncType(parameters, results))) + + add_type(module, RecType([func_type])) +======= + SubType( + False, + finger_tree.empty, + FuncCompositeType(FuncType( + finger_tree.from_list(parameters), + finger_tree.from_list(results), + )), + ) + + add_type(module, RecType(finger_tree.single(func_type))) +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) +} + +/// Add a new concrete ArrayType to the TypeSection +pub fn add_array_type(module: BinaryModule, element_type: FieldType) { + let array_type = +<<<<<<< HEAD + SubType(False, [], ArrayCompositeType(ArrayType(element_type))) + add_type(module, RecType([array_type])) +======= + SubType( + False, + finger_tree.empty, + ArrayCompositeType(ArrayType(element_type)), + ) + add_type(module, RecType(finger_tree.single(array_type))) +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) +} + +// Add a new StructType to the TypeSection +pub fn add_struct_type(module: BinaryModule, fields: List(FieldType)) { +<<<<<<< HEAD + let struct_type = SubType(False, [], StructCompositeType(StructType(fields))) + + add_type(module, RecType([struct_type])) +======= + let struct_type = + SubType( + False, + finger_tree.empty, + StructCompositeType(StructType(finger_tree.from_list(fields))), + ) + + add_type(module, RecType(finger_tree.single(struct_type))) +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) +} + +// Add a new StructType to the TypeSection that is marked as "final" +pub fn add_final_struct_type(module: BinaryModule, fields: List(FieldType)) { +<<<<<<< HEAD + let struct_type = SubType(True, [], StructCompositeType(StructType(fields))) + + add_type(module, RecType([struct_type])) +======= + let struct_type = + SubType( + True, + finger_tree.empty, + StructCompositeType(StructType(finger_tree.from_list(fields))), + ) + + add_type(module, RecType(finger_tree.single(struct_type))) +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) +} + /// Import a function from the host. The module_name and name are used to identify the /// import as the host specifies it. The type of the function is defined by a TypeIDX that /// points into the TypeSection. Type indexes at this point *must* be absolute, or this @@ -482,21 +567,16 @@ pub fn import_func( None, TypeIDX(_) -> BinaryModule( ..module, - imports: Some( - ImportSection( - finger_tree.single(FuncImport(module_name, name, type_)), - ), - ), + imports: Some(ImportSection([FuncImport(module_name, name, type_)])), ) Some(ImportSection(imports)), TypeIDX(_) -> BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( - imports, - FuncImport(module_name, name, type_), - )), + ImportSection( + list.append(imports, [FuncImport(module_name, name, type_)]), + ), ), ) @@ -524,24 +604,16 @@ pub fn import_global( BinaryModule( ..module, imports: Some( - ImportSection( - finger_tree.single(GlobalImport( - module_name, - name, - GlobalType(vt, mut), - )), - ), + ImportSection([GlobalImport(module_name, name, GlobalType(vt, mut))]), ), ) Some(ImportSection(imports)) -> BinaryModule( ..module, - imports: Some( - ImportSection(finger_tree.push( - imports, - GlobalImport(module_name, name, GlobalType(vt, mut)), - )), - ), + imports: Some(ImportSection( + imports + |> list.append([GlobalImport(module_name, name, GlobalType(vt, mut))]), + )), ) } } @@ -562,23 +634,20 @@ pub fn import_table( BinaryModule( ..module, imports: Some( - ImportSection( - finger_tree.single(TableImport( - module_name, - name, - TableType(ref_type, limits), - )), - ), + ImportSection([ + TableImport(module_name, name, TableType(ref_type, limits)), + ]), ), ) Some(ImportSection(imports)) -> BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( - imports, - TableImport(module_name, name, TableType(ref_type, limits)), - )), + ImportSection( + list.append(imports, [ + TableImport(module_name, name, TableType(ref_type, limits)), + ]), + ), ), ) } @@ -586,7 +655,7 @@ pub fn import_table( /// Import a memory from the host. The module_name and name are used to identify the /// import as the host specifies it. The type of the memory is defined by a MemType. -/// +/// /// Note: There can only be one memory per module. pub fn import_memory( module: BinaryModule, @@ -601,86 +670,100 @@ pub fn import_memory( BinaryModule( ..module, imports: Some( - ImportSection( - finger_tree.single(MemImport( - module_name, - name, - MemType(Limits(min, max)), - )), - ), + ImportSection([ + MemImport(module_name, name, MemType(Limits(min, max))), + ]), ), ) Some(ImportSection(imports)) -> BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( - imports, - MemImport(module_name, name, MemType(Limits(min, max))), - )), + ImportSection( + list.append(imports, [ + MemImport(module_name, name, MemType(Limits(min, max))), + ]), + ), ), ) } } -pub fn add_function_type(module: BinaryModule, type_: TypeIDX) { +/// Appends a function type, defined by it's index, into the function signature +/// section. This is not the same as adding a concrete function type to the module's type section. +/// It merely describes the signature of a given function in the import and code section. +/// +/// Note: The function type index must be absolute, and the function type must already be defined +/// in the type section in order for the module to be valid. +/// +/// Every function signature must be defined in the function section. +/// +/// Panics if the index is a RecTypeIDX or a DefType +pub fn append_function_type_index(module: BinaryModule, type_: TypeIDX) { case module, type_ { BinaryModule(functions: None, ..), TypeIDX(_) -> - BinaryModule( - ..module, - functions: Some(FunctionSection(finger_tree.single(type_))), - ) + BinaryModule(..module, functions: Some(FunctionSection([type_]))) BinaryModule(functions: Some(FunctionSection(functions)), ..), TypeIDX(_) -> BinaryModule( ..module, - functions: Some(FunctionSection(finger_tree.push(functions, type_))), + functions: Some(FunctionSection(list.append(functions, [type_]))), ) _, _ -> panic as "Invalid type index" } } -pub fn add_table(module: BinaryModule, table: Table) { +/// Add a WebAssembly table to the module defined by it's reference type, it's minimum and optional +/// maximum size, and an optional constant initializer expression. +pub fn add_table( + module: BinaryModule, + ref_type: RefType, + min: U32, + max: Option(U32), + init: Option(Expr), +) { let BinaryModule(tables: tables, ..) = module + let table = Table(TableType(ref_type, Limits(min, max)), init) case tables { - None -> - BinaryModule( - ..module, - tables: Some(TableSection(finger_tree.single(table))), - ) + None -> BinaryModule(..module, tables: Some(TableSection([table]))) Some(TableSection(tables)) -> BinaryModule( ..module, - tables: Some(TableSection(finger_tree.push(tables, table))), + tables: Some(TableSection(list.append(tables, [table]))), ) } } +/// Add a WebAssembly memory to the module defined by it's memory type. +/// +/// Note: Currently, only one memory is allowed per module, as described in the WebAssembly spec. pub fn add_memory(module: BinaryModule, memory: MemType) { let BinaryModule(memories: memories, ..) = module case memories { - None -> - BinaryModule( - ..module, - memories: Some(MemorySection(finger_tree.single(memory))), - ) + None -> BinaryModule(..module, memories: Some(MemorySection([memory]))) _ -> panic as "Only one memory is allowed per module." } } -pub fn add_global(module: BinaryModule, global: Global) { +/// Add a WebAssembly global to the module defined by it's global type, mutability option +/// and initializer expression. +pub fn add_global(module: BinaryModule, vt: ValType, mut: Bool, init: Expr) { let BinaryModule(globals: globals, ..) = module + let global = + Global( + GlobalType(vt, case mut { + True -> Var + False -> Const + }), + init, + ) case globals { - None -> - BinaryModule( - ..module, - globals: Some(GlobalSection(finger_tree.single(global))), - ) + None -> BinaryModule(..module, globals: Some(GlobalSection([global]))) Some(GlobalSection(globals)) -> BinaryModule( ..module, - globals: Some(GlobalSection(finger_tree.push(globals, global))), + globals: Some(GlobalSection(list.append(globals, [global]))), ) } } @@ -693,116 +776,116 @@ fn unique_export_name(acc: Set(String), export: Export) { } } +/// Export a function to the module. The function is given by it's index into the function section, +/// and it's name. pub fn export_func(module: BinaryModule, name: String, func: FuncIDX) { let BinaryModule(exports: exports, ..) = module case exports { None -> BinaryModule( ..module, - exports: Some(ExportSection(finger_tree.single(FuncExport(name, func)))), + exports: Some(ExportSection([FuncExport(name, func)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, FuncExport(name, func))), + ExportSection(list.append(exports, [FuncExport(name, func)])), ), ) } } } +/// Export a table to the module. The table is given by it's index into the table section, +/// and it's name. pub fn export_table(module: BinaryModule, name: String, table: TableIDX) { let BinaryModule(exports: exports, ..) = module case exports { None -> BinaryModule( ..module, - exports: Some( - ExportSection(finger_tree.single(TableExport(name, table))), - ), + exports: Some(ExportSection([TableExport(name, table)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, TableExport(name, table))), + ExportSection(list.append(exports, [TableExport(name, table)])), ), ) } } } +/// Export a memory to the module. The memory is given by it's index into the memory section, +/// and it's name. +<<<<<<< HEAD +/// +======= +/// +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) +/// Note: Currently, only one memory is allowed per module, as described in the WebAssembly spec. +/// https://webassembly.github.io/gc/core/syntax/modules.html#memories pub fn export_memory(module: BinaryModule, name: String, memory: MemIDX) { let BinaryModule(exports: exports, ..) = module case exports { None -> BinaryModule( ..module, - exports: Some( - ExportSection(finger_tree.single(MemExport(name, memory))), - ), + exports: Some(ExportSection([MemExport(name, memory)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, MemExport(name, memory))), + ExportSection(list.append(exports, [MemExport(name, memory)])), ), ) } } } +/// Export a global to the module. The global is given by it's index into the global section, +/// and it's name. pub fn export_global(module: BinaryModule, name: String, global: GlobalIDX) { let BinaryModule(exports: exports, ..) = module case exports { None -> BinaryModule( ..module, - exports: Some( - ExportSection(finger_tree.single(GlobalExport(name, global))), - ), + exports: Some(ExportSection([GlobalExport(name, global)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, GlobalExport(name, global))), + ExportSection(list.append(exports, [GlobalExport(name, global)])), ), ) } } } +/// Set the start function for the module. pub fn set_start(module: BinaryModule, func: FuncIDX) { BinaryModule(..module, start: Some(StartSection(func))) } +/// Add an active element segment with the given list of function indexes to the module. +/// It will initialize the given table at the given offset when the module is instantiated. pub fn active_funcs_element_segment( module: BinaryModule, offset: Expr, @@ -815,32 +898,34 @@ pub fn active_funcs_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - finger_tree.single(ElemFuncs( + ElementSection([ + ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + funcs, ActiveElemMode(table_index, offset), - )), - ), + ), + ]), ), ) Some(ElementSection(elements)) -> BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( - elements, - ElemFuncs( - HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), - ActiveElemMode(table_index, offset), - ), - )), + ElementSection( + list.append(elements, [ + ElemFuncs( + HeapTypeRefType(FuncHeapType, False), + funcs, + ActiveElemMode(table_index, offset), + ), + ]), + ), ), ) } } +/// Add a passive element segment with the given list of function indexes to the module. pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) { let BinaryModule(elements: elements, ..) = module case elements { @@ -848,32 +933,34 @@ pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) BinaryModule( ..module, elements: Some( - ElementSection( - finger_tree.single(ElemFuncs( + ElementSection([ + ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + funcs, PassiveElemMode, - )), - ), + ), + ]), ), ) Some(ElementSection(elements)) -> BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( - elements, - ElemFuncs( - HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), - PassiveElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemFuncs( + HeapTypeRefType(FuncHeapType, False), + funcs, + PassiveElemMode, + ), + ]), + ), ), ) } } +/// Add a declarative element segment with the given list of function indexes to the module. pub fn declarative_funcs_element_segment( module: BinaryModule, funcs: List(FuncIDX), @@ -884,32 +971,36 @@ pub fn declarative_funcs_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - finger_tree.single(ElemFuncs( + ElementSection([ + ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + funcs, DeclarativeElemMode, - )), - ), + ), + ]), ), ) Some(ElementSection(elements)) -> BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( - elements, - ElemFuncs( - HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), - DeclarativeElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemFuncs( + HeapTypeRefType(FuncHeapType, False), + funcs, + DeclarativeElemMode, + ), + ]), + ), ), ) } } +/// Add an active element segment with the given list of expressions to the module. +/// It will initialize the given table at the given offset when the module is instantiated. +/// The expressions must all match the given reference type. pub fn active_element_segment( module: BinaryModule, ref_type: RefType, @@ -923,13 +1014,13 @@ pub fn active_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - finger_tree.single(ElemExpressions( + ElementSection([ + ElemExpressions( ref_type, - finger_tree.from_list(exprs), + exprs, ActiveElemMode(table_index, offset), - )), - ), + ), + ]), ), ) } @@ -937,19 +1028,22 @@ pub fn active_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( - elements, - ElemExpressions( - ref_type, - finger_tree.from_list(exprs), - ActiveElemMode(table_index, offset), - ), - )), + ElementSection( + list.append(elements, [ + ElemExpressions( + ref_type, + exprs, + ActiveElemMode(table_index, offset), + ), + ]), + ), ), ) } } +/// Add a passive element segment with the given list of expressions to the module. +/// The expressions must all match the given reference type. pub fn passive_element_segment( module: BinaryModule, ref_type: RefType, @@ -961,13 +1055,7 @@ pub fn passive_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - finger_tree.single(ElemExpressions( - ref_type, - finger_tree.from_list(exprs), - PassiveElemMode, - )), - ), + ElementSection([ElemExpressions(ref_type, exprs, PassiveElemMode)]), ), ) } @@ -975,19 +1063,18 @@ pub fn passive_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( - elements, - ElemExpressions( - ref_type, - finger_tree.from_list(exprs), - PassiveElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemExpressions(ref_type, exprs, PassiveElemMode), + ]), + ), ), ) } } +/// Add a declarative element segment with the given list of expressions to the module. +/// The expressions must all match the given reference type. pub fn declarative_element_segment( module: BinaryModule, ref_type: RefType, @@ -999,13 +1086,7 @@ pub fn declarative_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - finger_tree.single(ElemExpressions( - ref_type, - finger_tree.from_list(exprs), - DeclarativeElemMode, - )), - ), + ElementSection([ElemExpressions(ref_type, exprs, DeclarativeElemMode)]), ), ) } @@ -1013,14 +1094,11 @@ pub fn declarative_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( - elements, - ElemExpressions( - ref_type, - finger_tree.from_list(exprs), - DeclarativeElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemExpressions(ref_type, exprs, DeclarativeElemMode), + ]), + ), ), ) } @@ -1028,14 +1106,17 @@ pub fn declarative_element_segment( fn concatenate_locals(locals: List(ValType)) { case locals { - [] -> finger_tree.new() - [a, ..rest] -> do_concatenate_locals(rest, finger_tree.new(), #(1, a)) + [] -> [] + [a, ..rest] -> do_concatenate_locals(rest, [], #(1, a)) } } +/// fn i32 i32 i32 f32 -> void +/// "Locals" +/// fn (3 i32) (1 f32) fn do_concatenate_locals( locals: List(ValType), - acc: FingerTree(Locals), + acc: List(Locals), current: #(Int, ValType), ) { case locals, current { @@ -1045,18 +1126,20 @@ fn do_concatenate_locals( let assert Ok(count) = u32(count) let locals = Locals(count, current_type) - do_concatenate_locals(rest, finger_tree.push(acc, locals), #(1, val_type)) + do_concatenate_locals(rest, [locals, ..acc], #(1, val_type)) } [], #(count, current_type) -> { let assert Ok(count) = u32(count) let locals = Locals(count, current_type) - finger_tree.push(acc, locals) + [locals, ..acc] |> list.reverse } } } -/// Add a code function to the code section. +/// Add the function's definition to the code section. The given locals must be in order +/// and match the function section's parameters, followed by any local variables needed +/// by the function. pub fn add_code(module: BinaryModule, locals: List(ValType), body: Expr) { let BinaryModule(code: code, ..) = module @@ -1064,18 +1147,17 @@ pub fn add_code(module: BinaryModule, locals: List(ValType), body: Expr) { case code { None -> - BinaryModule( - ..module, - code: Some(CodeSection(finger_tree.single(Code(locals, body)))), - ) + BinaryModule(..module, code: Some(CodeSection([Code(locals, body)]))) Some(CodeSection(code)) -> BinaryModule( ..module, - code: Some(CodeSection(finger_tree.push(code, Code(locals, body)))), + code: Some(CodeSection(list.append(code, [Code(locals, body)]))), ) } } +/// Add an active data segment to the module. The data will initialize the given +/// memory index at the given offset when the module is instantiated. pub fn add_active_data( module: BinaryModule, mem_idx: MemIDX, @@ -1087,45 +1169,41 @@ pub fn add_active_data( None -> BinaryModule( ..module, - data: Some( - DataSection(finger_tree.single(ActiveData(mem_idx, offset, data))), - ), + data: Some(DataSection([ActiveData(mem_idx, offset, data)])), ) Some(DataSection(data_section)) -> BinaryModule( ..module, data: Some( - DataSection(finger_tree.push( - data_section, - ActiveData(mem_idx, offset, data), - )), + DataSection( + list.append(data_section, [ActiveData(mem_idx, offset, data)]), + ), ), ) } } +/// Add a passive data segment to the module. A passive element segment's elements +/// can be copied to a table using the WebAssembly `table.init` instruction. pub fn add_passive_data(module: BinaryModule, data: BitArray) { let BinaryModule(data: data_section, ..) = module case data_section { - None -> - BinaryModule( - ..module, - data: Some(DataSection(finger_tree.single(PassiveData(data)))), - ) + None -> BinaryModule(..module, data: Some(DataSection([PassiveData(data)]))) Some(DataSection(data_section)) -> BinaryModule( ..module, - data: Some( - DataSection(finger_tree.push(data_section, PassiveData(data))), - ), + data: Some(DataSection(list.append(data_section, [PassiveData(data)]))), ) } } +/// Set the number of data segments in the module. This section is not necessary, but is +/// useful for validation. pub fn set_data_count(module: BinaryModule, count: U32) { BinaryModule(..module, data_count: Some(DataCountSection(count))) } +/// Create a type index, as long as the index is a valid U32 value. pub fn type_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(TypeIDX(idx)) @@ -1133,6 +1211,7 @@ pub fn type_idx(idx: Int) { } } +/// Create a function index, as long as the index is a valid U32 value. pub fn local_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(LocalIDX(idx)) @@ -1140,6 +1219,7 @@ pub fn local_idx(idx: Int) { } } +/// Create a global index, as long as the index is a valid U32 value. pub fn global_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(GlobalIDX(idx)) @@ -1147,6 +1227,7 @@ pub fn global_idx(idx: Int) { } } +/// Create a table index, as long as the index is a valid U32 value. pub fn table_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(TableIDX(idx)) @@ -1154,6 +1235,7 @@ pub fn table_idx(idx: Int) { } } +/// Create a memory index, as long as the index is a valid U32 value. pub fn mem_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(MemIDX(idx)) @@ -1161,6 +1243,7 @@ pub fn mem_idx(idx: Int) { } } +/// Create an element index, as long as the index is a valid U32 value. pub fn elem_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(ElemIDX(idx)) @@ -1168,6 +1251,7 @@ pub fn elem_idx(idx: Int) { } } +/// Create a data index, as long as the index is a valid U32 value. pub fn data_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(DataIDX(idx)) @@ -1175,6 +1259,7 @@ pub fn data_idx(idx: Int) { } } +/// Create a label index, as long as the index is a valid U32 value. pub fn label_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(LabelIDX(idx)) @@ -1182,6 +1267,7 @@ pub fn label_idx(idx: Int) { } } +/// Create a function index, as long as the index is a valid U32 value. pub fn func_idx(idx: Int) { case u32(idx) { Ok(idx) -> Ok(FuncIDX(idx)) @@ -1189,6 +1275,36 @@ pub fn func_idx(idx: Int) { } } +<<<<<<< HEAD +/// Create a field index, as long as the index is a valid U32 value. The index must +/// must be less than the number of fields in the struct. +pub fn field_idx(idx: Int) { + case u32(idx) { + Ok(idx) -> Ok(FieldIDX(idx)) + Error(msg) -> Error(msg) + } +} + +======= +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) +/// Encode the module into a BitArray, as long as the module is syntatically correctly. +/// Modules encoded with this function will not be validated. Please use the `validate` +/// function to validate the module before encoding to ensure that the module is usable. +/// +/// Note: The validate function has not been implemented yet, and is not provided as part +/// of the MVP of shine_coder pub fn encode(module: BinaryModule) { modules.encode_module(module) } + +/// Decode the module from a BitArray. +/// +/// This method will fail if the module is invalid. +/// +/// It returns: +/// +/// - Ok(#(the_module, unparsed_bits)) +/// - Error(message) +pub fn decode(module: BitArray) { + modules.decode_module(module) +} diff --git a/src/builder/types/block_type.gleam b/src/builder/types/block_type.gleam new file mode 100644 index 0000000..06ec340 --- /dev/null +++ b/src/builder/types/block_type.gleam @@ -0,0 +1,13 @@ +import internal/structure/types.{ + type TypeIDX, type ValType, FuncTypeBlockType, ValTypeBlockType, VoidBlockType, +} + +pub const void = VoidBlockType + +pub fn val_type(vt: ValType) { + ValTypeBlockType(vt) +} + +pub fn func_type(idx: TypeIDX) { + FuncTypeBlockType(idx) +} diff --git a/src/builder/types/composite_type.gleam b/src/builder/types/composite_type.gleam new file mode 100644 index 0000000..f619cf4 --- /dev/null +++ b/src/builder/types/composite_type.gleam @@ -0,0 +1,25 @@ +import internal/structure/types.{ + type FieldType, type FuncType, type StructType, type ValType, + ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, + StructCompositeType, StructType, +} + +pub fn from_func_type(func_type: FuncType) { + FuncCompositeType(func_type) +} + +pub fn func_type(parameters: List(ValType), results: List(ValType)) { + FuncCompositeType(FuncType(parameters, results)) +} + +pub fn struct_type(fields: List(FieldType)) { + StructCompositeType(StructType(fields)) +} + +pub fn from_struct_type(struct_type: StructType) { + StructCompositeType(struct_type) +} + +pub fn array_type(element_type: FieldType) { + ArrayCompositeType(ArrayType(element_type)) +} diff --git a/src/builder/types/func_type.gleam b/src/builder/types/func_type.gleam index a5085f6..5c56d53 100644 --- a/src/builder/types/func_type.gleam +++ b/src/builder/types/func_type.gleam @@ -1,11 +1,7 @@ -import internal/finger_tree import internal/structure/types.{type ValType, FuncType} /// Create a FuncType from the given list of parameter types and result types /// https://webassembly.github.io/gc/core/syntax/types.html#function-types pub fn new(param_types: List(ValType), result_types: List(ValType)) { - FuncType( - finger_tree.from_list(param_types), - finger_tree.from_list(result_types), - ) + FuncType(param_types, result_types) } diff --git a/src/builder/types/rec_type.gleam b/src/builder/types/rec_type.gleam index 43e8c2a..31eb704 100644 --- a/src/builder/types/rec_type.gleam +++ b/src/builder/types/rec_type.gleam @@ -1,45 +1,25 @@ -import internal/finger_tree import internal/structure/types.{ - type FieldType, type StructType, type SubType, type ValType, + type FieldType, type FuncType, type StructType, type SubType, type ValType, ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, RecType, StructCompositeType, StructType, SubType, } pub fn from_sub_types(sub_types: List(SubType)) { - RecType(sub_types |> finger_tree.from_list) + RecType(sub_types) +} + +pub fn from_func_type(func_type: FuncType) { + RecType([SubType(True, [], FuncCompositeType(func_type))]) } pub fn func_type(parameters: List(ValType), results: List(ValType)) { - RecType( - finger_tree.from_list([ - SubType( - True, - finger_tree.new(), - FuncCompositeType(FuncType( - finger_tree.from_list(parameters), - finger_tree.from_list(results), - )), - ), - ]), - ) + RecType([SubType(True, [], FuncCompositeType(FuncType(parameters, results)))]) } pub fn from_struct_type(struct_type: StructType) { - RecType( - finger_tree.from_list([ - SubType(True, finger_tree.new(), StructCompositeType(struct_type)), - ]), - ) + RecType([SubType(True, [], StructCompositeType(struct_type))]) } pub fn array_type(element_type: FieldType) { - RecType( - finger_tree.from_list([ - SubType( - True, - finger_tree.new(), - ArrayCompositeType(ArrayType(element_type)), - ), - ]), - ) + RecType([SubType(True, [], ArrayCompositeType(ArrayType(element_type)))]) } diff --git a/src/builder/types/storage_type.gleam b/src/builder/types/storage_type.gleam new file mode 100644 index 0000000..e63998a --- /dev/null +++ b/src/builder/types/storage_type.gleam @@ -0,0 +1,22 @@ +import internal/structure/types.{ + type RefType, F32ValType, F64ValType, I16StorageType, I32ValType, I64ValType, + I8StorageType, RefTypeValType, V128ValType, ValTypeStorageType, +} + +pub const i8 = I8StorageType + +pub const i16 = I16StorageType + +pub const i32 = ValTypeStorageType(I32ValType) + +pub const i64 = ValTypeStorageType(I64ValType) + +pub const f32 = ValTypeStorageType(F32ValType) + +pub const f64 = ValTypeStorageType(F64ValType) + +pub const v128 = ValTypeStorageType(V128ValType) + +pub fn ref_type(ref_type: RefType) { + ValTypeStorageType(RefTypeValType(ref_type)) +} diff --git a/src/builder/types/struct_type.gleam b/src/builder/types/struct_type.gleam index d8c234c..0c113db 100644 --- a/src/builder/types/struct_type.gleam +++ b/src/builder/types/struct_type.gleam @@ -1,4 +1,4 @@ -import internal/finger_tree +import gleam/list import internal/structure/types.{ type RefType, type StructType, type TypeIDX, ConcreteHeapType, Const, F32ValType, F64ValType, FieldType, HeapTypeRefType, I16StorageType, I32ValType, @@ -9,22 +9,19 @@ import internal/structure/types.{ /// Create an empty Struct type /// https://webassembly.github.io/gc/core/syntax/types.html#aggregate-types pub fn new() { - StructType(finger_tree.empty) + StructType([]) } /// Add an immutable `i8` field to the struct pub fn i8_field(struct_type: StructType) { - StructType( - struct_type.ft - |> finger_tree.push(FieldType(I8StorageType, Const)), - ) + StructType(list.append(struct_type.ft, [FieldType(I8StorageType, Const)])) } /// Add a mutable `i8` field to the struct pub fn i8_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(I8StorageType, Var)), + |> list.append([FieldType(I8StorageType, Var)]), ) } @@ -32,7 +29,7 @@ pub fn i8_mut_field(struct_type: StructType) { pub fn i16_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(I16StorageType, Const)), + |> list.append([FieldType(I16StorageType, Const)]), ) } @@ -40,7 +37,7 @@ pub fn i16_field(struct_type: StructType) { pub fn i16_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(I16StorageType, Var)), + |> list.append([FieldType(I16StorageType, Var)]), ) } @@ -48,7 +45,7 @@ pub fn i16_mut_field(struct_type: StructType) { pub fn i32_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(I32ValType), Const)), + |> list.append([FieldType(ValTypeStorageType(I32ValType), Const)]), ) } @@ -56,7 +53,7 @@ pub fn i32_field(struct_type: StructType) { pub fn i32_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(I32ValType), Var)), + |> list.append([FieldType(ValTypeStorageType(I32ValType), Var)]), ) } @@ -64,7 +61,7 @@ pub fn i32_mut_field(struct_type: StructType) { pub fn i64_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(I64ValType), Const)), + |> list.append([FieldType(ValTypeStorageType(I64ValType), Const)]), ) } @@ -72,7 +69,7 @@ pub fn i64_field(struct_type: StructType) { pub fn i64_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(I64ValType), Var)), + |> list.append([FieldType(ValTypeStorageType(I64ValType), Var)]), ) } @@ -80,7 +77,7 @@ pub fn i64_mut_field(struct_type: StructType) { pub fn f32_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(F32ValType), Const)), + |> list.append([FieldType(ValTypeStorageType(F32ValType), Const)]), ) } @@ -88,7 +85,7 @@ pub fn f32_field(struct_type: StructType) { pub fn f32_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(F32ValType), Var)), + |> list.append([FieldType(ValTypeStorageType(F32ValType), Var)]), ) } @@ -96,7 +93,7 @@ pub fn f32_mut_field(struct_type: StructType) { pub fn f64_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(F64ValType), Const)), + |> list.append([FieldType(ValTypeStorageType(F64ValType), Const)]), ) } @@ -104,7 +101,7 @@ pub fn f64_field(struct_type: StructType) { pub fn f64_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(F64ValType), Var)), + |> list.append([FieldType(ValTypeStorageType(F64ValType), Var)]), ) } @@ -112,7 +109,7 @@ pub fn f64_mut_field(struct_type: StructType) { pub fn v128_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(V128ValType), Const)), + |> list.append([FieldType(ValTypeStorageType(V128ValType), Const)]), ) } @@ -120,7 +117,7 @@ pub fn v128_field(struct_type: StructType) { pub fn v128_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(ValTypeStorageType(V128ValType), Var)), + |> list.append([FieldType(ValTypeStorageType(V128ValType), Var)]), ) } @@ -128,10 +125,9 @@ pub fn v128_mut_field(struct_type: StructType) { pub fn from_ref_type_field(struct_type: StructType, ref_type: RefType) { StructType( struct_type.ft - |> finger_tree.push(FieldType( - ValTypeStorageType(RefTypeValType(ref_type)), - Const, - )), + |> list.append([ + FieldType(ValTypeStorageType(RefTypeValType(ref_type)), Const), + ]), ) } @@ -139,10 +135,9 @@ pub fn from_ref_type_field(struct_type: StructType, ref_type: RefType) { pub fn from_ref_type_mut_field(struct_type: StructType, ref_type: RefType) { StructType( struct_type.ft - |> finger_tree.push(FieldType( - ValTypeStorageType(RefTypeValType(ref_type)), - Var, - )), + |> list.append([ + FieldType(ValTypeStorageType(RefTypeValType(ref_type)), Var), + ]), ) } @@ -152,12 +147,14 @@ pub fn from_ref_type_mut_field(struct_type: StructType, ref_type: RefType) { pub fn from_type_index_field(struct_type: StructType, type_idx: TypeIDX) { StructType( struct_type.ft - |> finger_tree.push(FieldType( - ValTypeStorageType( - RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), False)), + |> list.append([ + FieldType( + ValTypeStorageType( + RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), False)), + ), + Const, ), - Const, - )), + ]), ) } @@ -167,12 +164,14 @@ pub fn from_type_index_field(struct_type: StructType, type_idx: TypeIDX) { pub fn from_type_index_mut_field(struct_type: StructType, type_idx: TypeIDX) { StructType( struct_type.ft - |> finger_tree.push(FieldType( - ValTypeStorageType( - RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), False)), + |> list.append([ + FieldType( + ValTypeStorageType( + RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), False)), + ), + Var, ), - Var, - )), + ]), ) } @@ -185,12 +184,14 @@ pub fn from_type_index_nullable_field( ) { StructType( struct_type.ft - |> finger_tree.push(FieldType( - ValTypeStorageType( - RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), True)), + |> list.append([ + FieldType( + ValTypeStorageType( + RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), True)), + ), + Const, ), - Const, - )), + ]), ) } @@ -203,11 +204,13 @@ pub fn from_type_index_nullable_mut_field( ) { StructType( struct_type.ft - |> finger_tree.push(FieldType( - ValTypeStorageType( - RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), True)), + |> list.append([ + FieldType( + ValTypeStorageType( + RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), True)), + ), + Var, ), - Var, - )), + ]), ) } diff --git a/src/internal/binary/common.gleam b/src/internal/binary/common.gleam index 72294e9..505caf2 100644 --- a/src/internal/binary/common.gleam +++ b/src/internal/binary/common.gleam @@ -1,25 +1,25 @@ import gleam/bit_array import gleam/bytes_builder.{type BytesBuilder} import gleam/int +import gleam/list import gleam/option.{type Option, None, Some} import gleam/result import gleam/string import internal/binary/values.{decode_u32, encode_u32} -import internal/finger_tree.{type FingerTree} import internal/structure/numbers.{u32, unwrap_u32} /// Encode a vector of items using the given encoding function pub fn encode_vec( builder: BytesBuilder, - items: FingerTree(u), + items: List(u), encode_fn: fn(BytesBuilder, u) -> Result(BytesBuilder, String), ) { // Vectors are encoded as the number of items (in uleb128) and then each item - use size <- result.try(finger_tree.size(items) |> u32) + use size <- result.try(list.length(items) |> u32) builder |> encode_u32(size) // this function is a loop over the items in the vector - |> finger_tree.try_reducel(items, _, encode_fn) + |> list.try_fold(items, _, encode_fn) } /// Decode a vector of items using the given decoding function @@ -29,21 +29,21 @@ pub fn decode_vec( ) { // Vectors are encoded as the number of items (in uleb128) and then n items use #(size, rest) <- result.try(decode_u32(bits)) - do_decode_vec(rest, size |> unwrap_u32, finger_tree.new(), decode_fn) + do_decode_vec(rest, size |> unwrap_u32, [], decode_fn) } /// Loop over each item in a vector, and decode them using the given decoding function fn do_decode_vec( bits: BitArray, size: Int, - acc: FingerTree(u), + acc: List(u), decode_fn: fn(BitArray) -> Result(#(u, BitArray), String), ) { case size { 0 -> Ok(#(acc, bits)) _ -> { use #(val, rest) <- result.try(decode_fn(bits)) - do_decode_vec(rest, size - 1, acc |> finger_tree.push(val), decode_fn) + do_decode_vec(rest, size - 1, acc |> list.append([val]), decode_fn) } } } @@ -157,7 +157,7 @@ pub fn encode_byte_vec(builder: BytesBuilder, bytes: BitArray) { /// is generated by creating a new BytesBuilder, and then calculating the byte length /// of that section. Each section has the following format, and is written to the final /// BytesBuilder buffer with the following pattern: -/// +/// /// [section_id: byte] [byte_length: u32] [section_bytes: bytes(byte_length)] pub fn encode_section_from_builder( builder: BytesBuilder, diff --git a/src/internal/binary/modules.gleam b/src/internal/binary/modules.gleam index 77e06e5..3dcab2a 100644 --- a/src/internal/binary/modules.gleam +++ b/src/internal/binary/modules.gleam @@ -1,4 +1,5 @@ import gleam/bytes_builder.{type BytesBuilder} +import gleam/list import gleam/option.{type Option, None, Some} import gleam/result import internal/binary/common.{encode_section_from_builder} @@ -11,7 +12,6 @@ import internal/binary/types.{ encode_ref_type, encode_table_idx, encode_table_type, encode_type_idx, } import internal/binary/values.{encode_u32} -import internal/finger_tree.{type FingerTree} import internal/structure/modules.{ type BinaryModule, type CodeSection, type CustomSection, type DataCountSection, type DataSection, type ElementSection, type ExportSection, @@ -62,7 +62,7 @@ pub fn encode_module(module: BinaryModule) { // The next section is always the function section if it exists with id 0x03. // Despite the name, this section is used to define the types of each function - // in the code section which has the actual function bodies. + // in the code section which has the actual function bodies. use builder <- result.try( builder |> common.encode_option(module.functions, encode_function_section), ) @@ -279,13 +279,13 @@ pub fn decode_data_section(bits: BitArray) { /// Locals are encoded with a count and a val_type, describing a vector /// of local variables. For example: -/// +/// /// With three "locals" definitions: /// [(1 i32) (4 i64) (2 f32)] -/// +/// /// This results in the following local variables defined in a given function body: /// [(i32) (i64) (i64) (i64) (i64) (f32) (f32)] -/// +/// /// This function decodes a single set of "locals" definitions. fn decode_locals(bits: BitArray) { use #(count, rest) <- result.try(values.decode_u32(bits)) @@ -294,7 +294,7 @@ fn decode_locals(bits: BitArray) { } /// Decode a single code segment from the given bit array. -/// +/// /// A code segment is defined by a single u32 value, which denotes the /// byte size of the locals and function body combined, followed by the /// locals definitions, and the function body itself. @@ -469,7 +469,7 @@ pub fn decode_start_section(bits: BitArray) { fn decode_export(bits: BitArray) { use #(name, rest) <- result.try(common.decode_string(bits)) case rest { - // type 0 is a function export + // type 0 is a function export <<0, rest:bits>> -> { use #(func_idx, rest) <- result.map(decode_func_idx(rest)) #(FuncExport(name, func_idx), rest) @@ -625,7 +625,7 @@ pub fn decode_type_section(bits: BitArray) { /// Decode a set of consecutive custom sections. pub fn decode_custom_sections(bits: BitArray) { - do_decode_custom_sections(bits, finger_tree.new()) + do_decode_custom_sections(bits, []) } fn do_decode_custom_section(rest: BitArray) { @@ -642,11 +642,11 @@ pub fn decode_custom_section(bits: BitArray) { /// This method is a helper function for emulating a while loop that continues /// until the next wasm binary section isn't a custom one -fn do_decode_custom_sections(bits: BitArray, acc: FingerTree(CustomSection)) { +fn do_decode_custom_sections(bits: BitArray, acc: List(CustomSection)) { case decode_custom_section(bits) { Ok(#(Some(section), rest)) -> - do_decode_custom_sections(rest, acc |> finger_tree.push(section)) - _ -> Ok(#(Some(acc), bits)) + do_decode_custom_sections(rest, [section, ..acc]) + _ -> Ok(#(Some(acc |> list.reverse), bits)) } } @@ -655,18 +655,17 @@ fn do_decode_custom_sections(bits: BitArray, acc: FingerTree(CustomSection)) { /// exhausted. pub fn encode_custom_sections( builder: BytesBuilder, - sections: Option(FingerTree(CustomSection)), + sections: Option(List(CustomSection)), ) { case sections { - Some(sections) -> - finger_tree.try_reducel(sections, builder, encode_custom_section) + Some(sections) -> list.try_fold(sections, builder, encode_custom_section) None -> Ok(builder) } } /// Encode a single custom section. This method writes the following byte patterns /// to the builder: -/// +/// /// 1. A single 0x00 byte denoting a custom section /// 2. The byte length of the entire section: [byte_length: u32] /// 3. The name of the custom section: [byte_length: u32] [string_bytes: utf8] @@ -686,7 +685,7 @@ pub fn encode_custom_section(builder: BytesBuilder, section: CustomSection) { } /// Encode a type section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x01 byte denoting a type section /// 2. A vector of RecTypes which can be either a single type, or a group of /// mutually recursive subtypes. @@ -701,7 +700,7 @@ pub fn encode_type_section(builder: BytesBuilder, section: TypeSection) { } /// Encode a single import. This method writes the following byte patterns: -/// +/// /// 1. A single 0x00 byte followed by a function import or /// 2. A single 0x01 byte followed by a table import or /// 3. A single 0x02 byte followed by a memory import or @@ -752,7 +751,7 @@ pub fn encode_import(builder: BytesBuilder, import_: Import) { /// [0x03] [module_name_length: u32] [module_name: string] .. /// [global_name_length: u32] [global_name: string] [global_type: GlobalType] /// Encode an import section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x02 byte denoting an import section /// 2. The byte length of the following section payload /// 3. A vector of imports: [import_length: u32] [imports: Import*] @@ -765,7 +764,7 @@ pub fn encode_import_section(builder: BytesBuilder, section: ImportSection) { } /// Encode a function section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x03 byte denoting a function section /// 2. The byte length of the following section payload /// 3. A vector of type indices: [function_length: u32] [type_indices: TypeIDX*] @@ -784,7 +783,7 @@ pub fn encode_function_section( } /// Encode a single table. This method writes the following byte patterns: -/// +/// /// 1. A single table type: [table_type: TableType] or... /// 2. Two bytes denoting a table with an initializer expression: [0x40, 0x00] [expr: Expression] pub fn encode_table(builder: BytesBuilder, table: Table) { @@ -802,7 +801,7 @@ pub fn encode_table(builder: BytesBuilder, table: Table) { } /// Encode a table section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x04 byte denoting a table section /// 2. The byte length of the following section payload /// 3. A vector of tables: [table_length: u32] [tables: Table*] @@ -817,7 +816,7 @@ pub fn encode_table_section(builder: BytesBuilder, table_section: TableSection) /// Encode a memory section. This is usually a vector of memory types with /// a single element. It encodes the following byte patterns: -/// +/// /// 1. A single 0x05 byte denoting a memory section /// 2. The byte length of the following section payload /// 3. A vector of memory types: [memory_length: u32] [memory_types: MemType*] @@ -835,9 +834,9 @@ pub fn encode_memory_section( } /// Encode a single global. This method writes the following byte patterns: -/// +/// /// [global_type: GlobalType] [init: Expression] -/// +/// /// Note: The expression result type must match the global type specified. pub fn encode_global(builder: BytesBuilder, global: Global) { use builder <- result.try(builder |> encode_global_type(global.type_)) @@ -845,7 +844,7 @@ pub fn encode_global(builder: BytesBuilder, global: Global) { } /// Encode a global section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x06 byte denoting a global section /// 2. The byte length of the following section payload /// 3. A vector of globals: [global_length: u32] [globals: Global*] @@ -863,9 +862,9 @@ pub fn encode_global_section( /// Encode a single export. Exports define the module contents that can be used externally /// by the web assembly host. -/// +/// /// Exports can be encoded in the following ways: -/// +/// /// 1. [name_length: u32] [name: utf8] [0x00] [func_idx: FuncIDX] indicating a function export /// 2. [name_length: u32] [name: utf8] [0x01] [table_idx: TableIDX] indicating a table export. /// 3. [name_length: u32] [name: utf8] [0x02] [mem_idx: MemIDX] indicating a memory export. @@ -873,7 +872,7 @@ pub fn encode_global_section( pub fn encode_export(builder: BytesBuilder, export_: Export) { use builder <- result.try(builder |> common.encode_string(export_.name)) case export_ { - // + // FuncExport(_, func_idx) -> builder |> bytes_builder.append(<<0x00>>) @@ -894,7 +893,7 @@ pub fn encode_export(builder: BytesBuilder, export_: Export) { } /// Encode an export section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x07 byte denoting an export section /// 2. The byte length of the following section payload /// 3. A vector of exports: [exports_length: u32] [exports: Export*] @@ -911,7 +910,7 @@ pub fn encode_export_section( } /// Encode a start section. This method writes the following byte patterns: -/// +/// /// 1. A single 0x08 byte denoting a start section /// 2. The byte length of the following section payload which is a single u32 /// 3. The start function index as a u32 @@ -925,7 +924,7 @@ pub fn encode_start_section(builder: BytesBuilder, start_section: StartSection) /// Encode a single element segment. This method writes a byte pattern based /// on the type of elements and how they are treated to the web assembly module. -/// +/// /// For more information on how they are encoded, see the specification here: /// https://webassembly.github.io/gc/core/binary/modules.html#element-section pub fn encode_element_segment(builder: BytesBuilder, element: Elem) { @@ -1050,11 +1049,11 @@ pub fn encode_element_segment(builder: BytesBuilder, element: Elem) { } /// Encodes an element section. This method writes the following byte patterns: -/// +/// /// 1. A 0x09 byte, indicating the start of an element section /// 2. The byte length of the section as a u32 /// 3. A vector of encoded element segments -/// +/// /// For more information, please see: /// https://webassembly.github.io/gc/core/binary/modules.html#element-section pub fn encode_element_section( @@ -1071,7 +1070,7 @@ pub fn encode_element_section( /// Encode a code segment, also known as a function body. This method writes the following /// byte patterns: -/// +/// /// 1. The byte length of the segment as a u32 /// 2. A vector of encoded locals /// 3. An expression containing the function body, terminated by a single 0x0B (end) byte. @@ -1088,7 +1087,7 @@ pub fn encode_code_segment(builder: BytesBuilder, code: Code) { } /// Encodes a code section. This method writes the following byte patterns: -/// +/// /// 1. A 0x0A (10) byte, indicating the start of a code section /// 2. The byte length of the section as a u32 /// 3. A vector of encoded code segments @@ -1158,11 +1157,11 @@ fn encode_data_segment(builder: BytesBuilder, data: Data) { } /// Encode a data section. This method writes the following byte patterns: -/// +/// /// 1. A 0x0B (11) byte, indicating the start of a data section /// 2. The byte length of the section as a u32 /// 3. A vector of encoded data segments: [data_section_count: u32] [data_segments: Data*] -/// +/// pub fn encode_data_section(builder: BytesBuilder, data_section: DataSection) { use section_builder <- result.try( bytes_builder.new() @@ -1174,7 +1173,7 @@ pub fn encode_data_section(builder: BytesBuilder, data_section: DataSection) { } /// Encodes a data count section. This method writes the following byte patterns: -/// +/// /// 1. A 0x0C (12) byte, indicating the start of a data count section /// 2. The byte length of the section as a u32 /// 3. The number of data segments in the module as a u32 diff --git a/src/internal/binary/types.gleam b/src/internal/binary/types.gleam index 1ae5816..f4c0591 100644 --- a/src/internal/binary/types.gleam +++ b/src/internal/binary/types.gleam @@ -1,5 +1,6 @@ import gleam/bytes_builder.{type BytesBuilder} import gleam/int +import gleam/list import gleam/option.{None, Some} import gleam/result import internal/binary/common @@ -7,7 +8,6 @@ import internal/binary/values.{ decode_i32, decode_i64, decode_s33, decode_u32, encode_i32, encode_i64, encode_s33, encode_u32, } -import internal/finger_tree.{type FingerTree} import internal/structure/numbers.{ decode_f32, decode_f64, encode_f32, encode_f64, s33, u32, unwrap_s33, unwrap_u32, @@ -341,7 +341,7 @@ pub fn encode_ref_type(builder: BytesBuilder, ref_type: RefType) { } /// Decodes a ValType from the given bits. -/// +/// /// A valtype may be: /// 1. an I32 /// 2. an I64 @@ -377,10 +377,7 @@ pub fn encode_val_type(builder: BytesBuilder, val_type: ValType) { } /// Encoding a result type is the same as encoding a vector of ValTypes -pub fn encode_result_type( - builder: BytesBuilder, - result_type: FingerTree(ValType), -) { +pub fn encode_result_type(builder: BytesBuilder, result_type: List(ValType)) { builder |> common.encode_vec(result_type, encode_val_type) } @@ -420,7 +417,7 @@ pub fn encode_array_type(builder: BytesBuilder, array_type: ArrayType) { } /// Decoding a field type follows the following byte pattern: -/// +/// /// 1. Decode a storage type /// 2. Decode a mutability flag pub fn decode_field_type(bits: BitArray) { @@ -439,7 +436,7 @@ pub fn encode_field_type(builder: BytesBuilder, field_type: FieldType) { } /// Decoding a storage type follows the one of following byte pattern: -/// +/// /// 1. [0x78] - This represents a packed type I8 /// 2. [0x77] - This represents a packed type I16 /// 3. Any other value - This represents a ValType @@ -455,7 +452,7 @@ pub fn decode_storage_type(bits: BitArray) { } /// Encoding a storage type follows the one of following byte pattern: -/// +/// /// 1. [0x78] - This represents a packed type I8 /// 2. [0x77] - This represents a packed type I16 /// 3. Any other value - This represents a ValType @@ -468,7 +465,7 @@ pub fn encode_storage_type(builder: BytesBuilder, storage_type: StorageType) { } /// Decoding a mutability flag follows the following byte pattern: -/// +/// /// 1. [0x00] - This represents a const /// 2. [0x01] - This represents a var pub fn decode_mut(bits: BitArray) { @@ -480,7 +477,7 @@ pub fn decode_mut(bits: BitArray) { } /// Encoding a mutability flag follows the following byte pattern: -/// +/// /// 1. [0x00] - This represents a const /// 2. [0x01] - This represents a var pub fn encode_mut(builder: BytesBuilder, mut: Mut) { @@ -504,7 +501,7 @@ pub fn encode_struct_type(builder: BytesBuilder, struct_type: StructType) { } /// Decoding a composite type uses one of the following byte patterns: -/// +/// /// 1. [0x5E] - This represents an array type followed by a single field type /// 2. [0x5F] - This represents a struct type followed by a vector of field types /// 3. [0x60] - This represents a function type followed by a function type @@ -527,7 +524,7 @@ pub fn decode_comp_type(bits: BitArray) { } /// Encoding a composite type uses one of the following byte patterns: -/// +/// /// 1. [0x5E] - This represents an array type followed by a single field type /// 2. [0x5F] - This represents a struct type followed by a vector of field types /// 3. [0x60] - This represents a function type followed by a function type @@ -549,7 +546,7 @@ pub fn encode_composite_type(builder: BytesBuilder, comp_type: CompositeType) { } /// Decoding a recursive type uses one of the following byte patterns: -/// +/// /// 1. [0x4E] - This represents a vector of sub types that are iso-recursive /// 2. A single subtype wrapped inside of a rectype group pub fn decode_rec_type(bits: BitArray) { @@ -560,32 +557,28 @@ pub fn decode_rec_type(bits: BitArray) { } _ -> { use #(st, rest) <- result.map(decode_sub_type(bits)) - #(RecType(finger_tree.from_list([st])), rest) + #(RecType([st]), rest) } } } /// Encoding a recursive type uses one of the following byte patterns: -/// +/// /// 1. [0x4E] - This represents a vector of sub types that are iso-recursive /// 2. A single subtype wrapped inside of a rectype group pub fn encode_rec_type(builder: BytesBuilder, rec_type: RecType) { - case rec_type.sub_types |> finger_tree.size { - 1 -> - case rec_type.sub_types |> finger_tree.shift { - Ok(#(sub_type, _)) -> encode_sub_type(builder, sub_type) - Error(_) -> Error("Invalid recursive type") - } - t if t > 1 -> + case rec_type.sub_types { + [sub_type] -> encode_sub_type(builder, sub_type) + [] -> Error("Invalid recursive type") + sub_types -> builder |> bytes_builder.append(<<0x4E>>) - |> common.encode_vec(rec_type.sub_types, encode_sub_type) - _ -> Error("Invalid recursive type") + |> common.encode_vec(sub_types, encode_sub_type) } } /// Decoding a subtype uses one of the following byte patterns: -/// +/// /// 1. [0x50] - This represents a subtype, followed by a vector of type indexes, /// and a single composite type. /// 2. [0x4F] - This represents a *FINAL* subtype, followed by a vector of type indexes, @@ -605,34 +598,34 @@ pub fn decode_sub_type(bits: BitArray) { } _ -> { use #(ct, rest) <- result.map(decode_comp_type(bits)) - #(SubType(True, finger_tree.new(), ct), rest) + #(SubType(True, [], ct), rest) } } } /// Encoding a subtype uses one of the following byte patterns: -/// +/// /// 1. [0x50] - This represents a subtype, followed by a vector of type indexes, /// and a single composite type. /// 2. [0x4F] - This represents a *FINAL* subtype, followed by a vector of type indexes, /// and a single composite type. /// 3. A single composite type that is *FINAL* pub fn encode_sub_type(builder: BytesBuilder, sub_type: SubType) { - case sub_type.final, sub_type.t |> finger_tree.size { - True, 0 -> builder |> encode_composite_type(sub_type.ct) - True, _ -> { + case sub_type.final, sub_type.t { + True, [] -> builder |> encode_composite_type(sub_type.ct) + True, match_idxs -> { use builder <- result.try( builder |> bytes_builder.append(<<0x4F>>) - |> common.encode_vec(sub_type.t, encode_type_idx), + |> common.encode_vec(match_idxs, encode_type_idx), ) builder |> encode_composite_type(sub_type.ct) } - False, _ -> { + False, match_idxs -> { use builder <- result.try( builder |> bytes_builder.append(<<0x50>>) - |> common.encode_vec(sub_type.t, encode_type_idx), + |> common.encode_vec(match_idxs, encode_type_idx), ) builder |> encode_composite_type(sub_type.ct) } @@ -673,7 +666,7 @@ pub fn encode_field_idx(builder: BytesBuilder, field_idx: FieldIDX) { } /// Decoding a TypeIDX is the same as decoding a u32. -/// +/// /// Note: Despite the fact that type indices are replacable by RecTypeIDXs and DefTypes, /// these forms are impossible when used in a binary format. pub fn decode_type_idx(bits: BitArray) { @@ -682,7 +675,7 @@ pub fn decode_type_idx(bits: BitArray) { } /// Encoding a TypeIDX is the same as encoding a u32. -/// +/// /// Note: Despite the fact that type indices are replacable by RecTypeIDXs and DefTypes, /// these forms are impossible when used in a binary format. pub fn encode_type_idx(builder: BytesBuilder, type_idx: TypeIDX) { @@ -759,7 +752,7 @@ pub fn encode_label_idx(builder: BytesBuilder, type_idx: LabelIDX) { } /// Decoding a limits definition follows two possible formats: -/// +/// /// 1. [0x00] [min: u32] - This represents a memory without a maximum size /// 2. [0x01] [min: u32] [max: u32] - This represents a memory with a maximum size pub fn decode_limits(bits: BitArray) { @@ -778,7 +771,7 @@ pub fn decode_limits(bits: BitArray) { } /// Encoding a limits definition follows two possible formats: -/// +/// /// 1. [0x00] [min: u32] - This represents a memory without a maximum size /// 2. [0x01] [min: u32] [max: u32] - This represents a memory with a maximum size pub fn encode_limits(builder: BytesBuilder, limits: Limits) { @@ -811,7 +804,7 @@ pub fn encode_mem_type(builder: BytesBuilder, mem_type: MemType) { } /// Table types are encoded using the following format: -/// +/// /// TableType -> [ref_type: RefType] [limits: Limits] pub fn decode_table_type(rest: BitArray) { use #(rt, rest) <- result.try(decode_ref_type(rest)) @@ -820,7 +813,7 @@ pub fn decode_table_type(rest: BitArray) { } /// Table types are encoded using the following format: -/// +/// /// TableType -> [ref_type: RefType] [limits: Limits] pub fn encode_table_type(builder: BytesBuilder, table_type: TableType) { use builder <- result.try(builder |> encode_ref_type(table_type.t)) @@ -828,7 +821,7 @@ pub fn encode_table_type(builder: BytesBuilder, table_type: TableType) { } /// Global types are encoded using the following format: -/// +/// /// GlobalType -> [val_type: ValType] [mutability: Mutability] pub fn decode_global_type(rest: BitArray) { use #(vt, rest) <- result.try(decode_val_type(rest)) @@ -837,7 +830,7 @@ pub fn decode_global_type(rest: BitArray) { } /// Global types are encoded using the following format: -/// +/// /// GlobalType -> [val_type: ValType] [mutability: Mutability] pub fn encode_global_type(builder: BytesBuilder, global_type: GlobalType) { use builder <- result.try(builder |> encode_val_type(global_type.vt)) @@ -845,7 +838,7 @@ pub fn encode_global_type(builder: BytesBuilder, global_type: GlobalType) { } /// Block types are encoded into three possible formats: -/// +/// /// 1. [0x40] - This represents a void block without any operands or results /// 2. A single ValType - This represents a block type that consumes a single ValType /// operand. @@ -870,7 +863,7 @@ pub fn decode_block_type(bits: BitArray) { } /// Block types are encoded into three possible formats: -/// +/// /// 1. [0x40] - This represents a void block without any operands or results /// 2. A single ValType - This represents a block type that consumes a single ValType /// operand. @@ -891,7 +884,7 @@ pub fn encode_block_type(builder: BytesBuilder, block_type: BlockType) { /// Cast flags define the behavior of the `cast` instruction, defining which /// heap type operands are nullable. -/// +/// /// Please see the control instructions for more information: /// https://webassembly.github.io/gc/core/binary/instructions.html#control-instructions pub fn decode_cast_flags(bits: BitArray) { @@ -920,7 +913,7 @@ pub fn encode_cast_flags(builder: BytesBuilder, cast_flags: #(Bool, Bool)) { /// MemArgs define the way load and store operations work in linear memory. They use the /// following format: -/// +/// /// MemArg -> [offset: u32] [align: u32] pub fn decode_mem_arg(bits: BitArray) { use #(offset, rest) <- result.try(decode_u32(bits)) @@ -930,7 +923,7 @@ pub fn decode_mem_arg(bits: BitArray) { /// MemArgs define the way load and store operations work in linear memory. They use the /// following format: -/// +/// /// MemArg -> [offset: u32] [align: u32] pub fn encode_mem_arg(builder: BytesBuilder, mem_arg: MemArg) { Ok( @@ -960,27 +953,27 @@ pub fn encode_expression( /// until the list is empty. pub fn do_encode_instructions( builder: BytesBuilder, - insts: FingerTree(Instruction), + insts: List(Instruction), ) -> Result(BytesBuilder, String) { insts - |> finger_tree.try_reducel(builder, encode_instruction) + |> list.try_fold(builder, encode_instruction) } /// This function decodes an expression from a given BitArray, stopping when it /// encounters an "end" instruction. pub fn decode_expression(bits: BitArray) -> Result(#(Expr, BitArray), String) { - do_decode_expression(bits, finger_tree.empty) + do_decode_expression(bits, []) } fn do_decode_expression( bits: BitArray, - acc: FingerTree(Instruction), + acc: List(Instruction), ) -> Result(#(Expr, BitArray), String) { case bits { - <<0x0B, rest:bits>> -> Ok(#(Expr(acc), rest)) + <<0x0B, rest:bits>> -> Ok(#(Expr(acc |> list.reverse), rest)) _ -> { use #(inst, rest) <- result.try(decode_instruction(bits)) - do_decode_expression(rest, acc |> finger_tree.push(inst)) + do_decode_expression(rest, [inst, ..acc]) } } } @@ -988,22 +981,20 @@ fn do_decode_expression( /// This function decodes an if instruction, which is a special type of block /// that can contain an "else" instruction that denotes an alternative case /// if the condition is false. -/// +/// /// If an "end" is encountered before an "else" is encountered, the "else" branch /// is set to None, and the "If" instruction is returned. fn do_decode_if_instruction( bits: BitArray, bt: BlockType, - acc: FingerTree(Instruction), + acc: List(Instruction), ) -> Result(#(Instruction, BitArray), String) { case bits { - <<0x0B, rest:bits>> -> Ok(#(If(bt, acc, None), rest)) - <<0x05, rest:bits>> -> { - do_decode_else_instruction(rest, bt, acc, finger_tree.empty) - } + <<0x0B, rest:bits>> -> Ok(#(If(bt, acc |> list.reverse, None), rest)) + <<0x05, rest:bits>> -> do_decode_else_instruction(rest, bt, acc, []) _ -> { use #(inst, rest) <- result.try(decode_instruction(bits)) - do_decode_if_instruction(rest, bt, acc |> finger_tree.push(inst)) + do_decode_if_instruction(rest, bt, [inst, ..acc]) } } } @@ -1014,25 +1005,21 @@ fn do_decode_if_instruction( fn do_decode_else_instruction( bits: BitArray, bt: BlockType, - if_acc: FingerTree(Instruction), - else_acc: FingerTree(Instruction), + if_acc: List(Instruction), + else_acc: List(Instruction), ) -> Result(#(Instruction, BitArray), String) { case bits { - <<0x0B, rest:bits>> -> Ok(#(If(bt, if_acc, Some(else_acc)), rest)) + <<0x0B, rest:bits>> -> + Ok(#(If(bt, if_acc |> list.reverse, Some(else_acc |> list.reverse)), rest)) _ -> { use #(inst, rest) <- result.try(decode_instruction(bits)) - do_decode_else_instruction( - rest, - bt, - if_acc, - else_acc |> finger_tree.push(inst), - ) + do_decode_else_instruction(rest, bt, if_acc, [inst, ..else_acc]) } } } /// For information on how each instruction is encoded, please see the specification: -/// +/// /// https://webassembly.github.io/gc/core/binary/instructions.html#instructions pub fn encode_instruction( builder: BytesBuilder, @@ -2271,7 +2258,7 @@ pub fn encode_instruction( } /// For information on how each instruction is decoded, please see the specification: -/// +/// /// https://webassembly.github.io/gc/core/binary/instructions.html#instructions pub fn decode_instruction( bits: BitArray, @@ -2293,7 +2280,7 @@ pub fn decode_instruction( } <<0x04, rest:bits>> -> { use #(bt, rest) <- result.try(decode_block_type(rest)) - do_decode_if_instruction(rest, bt, finger_tree.empty) + do_decode_if_instruction(rest, bt, []) } <<0x0C, rest:bits>> -> { use #(label_idx, rest) <- result.map(decode_u32(rest)) diff --git a/src/internal/finger_tree.gleam b/src/internal/finger_tree.gleam deleted file mode 100644 index e5d27ae..0000000 --- a/src/internal/finger_tree.gleam +++ /dev/null @@ -1,622 +0,0 @@ -import gleam/option.{type Option, None, Some} -import gleam/result - -pub opaque type FingerTree(u) { - Empty - Single(u) - Deep(size: Int, Finger(u), FingerTree(Node(u)), Finger(u)) -} - -type Finger(u) { - One(u) - Two(u, u) - Three(u, u, u) - Four(u, u, u, u) -} - -type Node(u) { - Node1(u) - Node2(u, u) - Node3(u, u, u) -} - -pub fn single(u: u) -> FingerTree(u) { - Single(u) -} - -pub fn unshift(tree: FingerTree(u), a: u) -> FingerTree(u) { - case tree { - Empty -> Single(a) - Single(b) -> Deep(2, One(a), Empty, One(b)) - Deep(s, One(b), m, sf) -> Deep(s + 1, Two(a, b), m, sf) - Deep(s, Two(b, c), m, sf) -> Deep(s + 1, Three(a, b, c), m, sf) - Deep(s, Three(b, c, d), m, sf) -> Deep(s + 1, Four(a, b, c, d), m, sf) - Deep(s, Four(b, c, d, e), Empty, sf) -> - Deep(s + 1, Two(a, b), Single(Node3(c, d, e)), sf) - Deep(s, Four(b, c, d, e), Single(v), sf) -> - Deep(s + 1, Two(a, b), Deep(3, One(Node3(c, d, e)), Empty, One(v)), sf) - Deep(s, Four(b, c, d, e), v, sf) -> - Deep(s + 1, Two(a, b), unshift_node(v, Node3(c, d, e)), sf) - } -} - -fn unshift_node(tree: FingerTree(a), node: a) -> FingerTree(a) { - tree |> unshift(node) -} - -pub fn push(tree: FingerTree(u), a: u) -> FingerTree(u) { - case tree { - Empty -> Single(a) - Single(b) -> Deep(2, One(b), Empty, One(a)) - Deep(s, pr, m, One(b)) -> Deep(s + 1, pr, m, Two(b, a)) - Deep(s, pr, m, Two(c, b)) -> Deep(s + 1, pr, m, Three(c, b, a)) - Deep(s, pr, m, Three(d, c, b)) -> Deep(s + 1, pr, m, Four(d, c, b, a)) - Deep(s, pr, m, Four(e, d, c, b)) -> - Deep(s + 1, pr, do_push(m, Node3(e, d, c)), Two(b, a)) - } -} - -fn do_push(tree: FingerTree(Node(a)), node: Node(a)) -> FingerTree(Node(a)) { - tree |> push(node) -} - -pub fn reducer(tree: FingerTree(u), acc: v, r_fn: fn(v, u) -> v) -> v { - case tree { - Empty -> acc - Single(u) -> r_fn(acc, u) - Deep(_, pr, m, sf) -> { - let acc = reducer_finger(sf, acc, r_fn) - let acc = reducer_node(m, acc, r_fn) - reducer_finger(pr, acc, r_fn) - } - } -} - -fn reducer_finger(finger: Finger(u), acc: v, r_fn: fn(v, u) -> v) -> v { - case finger { - One(u) -> r_fn(acc, u) - Two(v, u) -> acc |> r_fn(u) |> r_fn(v) - Three(w, v, u) -> acc |> r_fn(u) |> r_fn(v) |> r_fn(w) - Four(x, w, v, u) -> acc |> r_fn(u) |> r_fn(v) |> r_fn(w) |> r_fn(x) - } -} - -fn reducer_node(node: FingerTree(Node(u)), acc: v, r_fn: fn(v, u) -> v) -> v { - use acc, node <- reducer(node, acc) - case node { - Node1(u) -> r_fn(acc, u) - Node2(v, u) -> acc |> r_fn(u) |> r_fn(v) - Node3(w, v, u) -> acc |> r_fn(u) |> r_fn(v) |> r_fn(w) - } -} - -pub fn reducel(tree: FingerTree(u), acc: v, r_fn: fn(v, u) -> v) -> v { - case tree { - Empty -> acc - Single(u) -> r_fn(acc, u) - Deep(_, pr, m, sf) -> { - let acc = reducel_finger(pr, acc, r_fn) - let acc = reducel_node(m, acc, r_fn) - reducel_finger(sf, acc, r_fn) - } - } -} - -fn reducel_finger(finger: Finger(u), acc: v, r_fn: fn(v, u) -> v) -> v { - case finger { - One(u) -> r_fn(acc, u) - Two(u, v) -> acc |> r_fn(u) |> r_fn(v) - Three(u, v, w) -> acc |> r_fn(u) |> r_fn(v) |> r_fn(w) - Four(u, v, w, x) -> acc |> r_fn(u) |> r_fn(v) |> r_fn(w) |> r_fn(x) - } -} - -fn reducel_node(node: FingerTree(Node(u)), acc: v, r_fn: fn(v, u) -> v) -> v { - use acc, node <- reducer(node, acc) - case node { - Node1(u) -> r_fn(acc, u) - Node2(u, v) -> acc |> r_fn(u) |> r_fn(v) - Node3(u, v, w) -> acc |> r_fn(u) |> r_fn(v) |> r_fn(w) - } -} - -pub fn from_list(l: List(e)) { - do_from_list(l, Empty) -} - -fn do_from_list(l: List(e), tree: FingerTree(e)) { - case tree, l { - _, [] -> tree - Empty, [a, b, c, d, e, f, g, h, i, j, k, ..rest] -> - do_from_list( - rest, - Deep(11, Four(a, b, c, d), Single(Node3(e, f, g)), Four(h, i, j, k)), - ) - Empty, [a, b, c, d, e, f, g, h, i, j] -> - Deep(10, Four(a, b, c, d), Single(Node2(e, f)), Four(g, h, i, j)) - Empty, [a, b, c, d, e, f, g, h, i] -> - Deep(9, Four(a, b, c, d), Single(Node1(e)), Four(f, g, h, i)) - Empty, [a, b, c, d, e, f, g, h] -> - Deep(8, Four(a, b, c, d), Empty, Four(e, f, g, h)) - Empty, [a, b, c, d, e, f, g] -> - Deep(7, Four(a, b, c, d), Empty, Three(e, f, g)) - Empty, [a, b, c, d, e, f] -> Deep(6, Four(a, b, c, d), Empty, Two(e, f)) - Empty, [a, b, c, d, e] -> Deep(5, Three(a, b, c), Empty, Two(d, e)) - Empty, [a, b, c, d] -> Deep(4, Two(a, b), Empty, Two(c, d)) - Empty, [a, b, c] -> Deep(3, Two(a, b), Empty, One(c)) - Empty, [a, b] -> Deep(2, One(a), Empty, One(b)) - Empty, [a] -> Single(a) - - Single(a), [b, c, d, e, f, g, h, ..rest] -> - do_from_list(rest, Deep(8, Four(a, b, c, d), Empty, Four(e, f, g, h))) - Single(a), [b, c, d, e, f, g] -> - Deep(7, Four(a, b, c, d), Empty, Three(e, f, g)) - Single(a), [b, c, d, e, f] -> Deep(6, Four(a, b, c, d), Empty, Two(e, f)) - Single(a), [b, c, d, e] -> Deep(5, Three(a, b, c), Empty, Two(d, e)) - Single(a), [b, c, d] -> Deep(4, Two(a, b), Empty, Two(c, d)) - Single(a), [b, c] -> Deep(3, Two(a, b), Empty, One(c)) - Single(a), [b] -> Deep(2, One(a), Empty, One(b)) - - Deep(s, pr, m, Four(a, b, c, d)), [e, f, g, ..rest] -> - do_from_list( - rest, - Deep(s + 3, pr, m |> push(Node3(a, b, c)), Four(d, e, f, g)), - ) - Deep(s, pr, m, Four(a, b, c, d)), [e, f] -> - Deep(s + 2, pr, m |> push(Node2(a, b)), Four(c, d, e, f)) - Deep(s, pr, m, Four(a, b, c, d)), [e] -> - Deep(s + 1, pr, m |> push(Node1(a)), Four(b, c, d, e)) - Deep(s, pr, m, sf), [e, f, g, h, ..rest] -> - do_from_list( - rest, - Deep(s + 4, pr, m |> push(sf |> to_node), Four(e, f, g, h)), - ) - Deep(s, pr, m, sf), [e, f, g] -> - Deep(s + 3, pr, m |> push(sf |> to_node), Three(e, f, g)) - Deep(s, pr, m, sf), [e, f] -> - Deep(s + 2, pr, m |> push(sf |> to_node), Two(e, f)) - Deep(s, pr, m, sf), [e] -> Deep(s + 1, pr, m |> push(sf |> to_node), One(e)) - } -} - -fn to_node(digits: Finger(u)) { - case digits { - One(u) -> Node1(u) - Two(u, v) -> Node2(u, v) - Three(u, v, w) -> Node3(u, v, w) - _ -> panic as "Somehow this broke?" - } -} - -pub fn to_list(tree: FingerTree(e)) { - reducer(tree, [], fn(h, xs) { [xs, ..h] }) -} - -pub fn shift(tree: FingerTree(e)) -> Result(#(e, FingerTree(e)), Nil) { - case tree { - Empty -> Error(Nil) - Single(e) -> Ok(#(e, Empty)) - Deep(s, pr, m, sf) -> { - // a is the first element in the tree - case shift_finger(pr) { - #(popped_a, Some(new_pr)) -> Ok(#(popped_a, Deep(s - 1, new_pr, m, sf))) - #(popped_a, None) -> { - // the first element is now in the middle of the tree - // the next element is the first element in the tree - - // pop the first node out of the tree - case shift_node_tree(m) { - Ok(#(Node3(a, b, c), rest_nodes)) -> - Ok(#(popped_a, Deep(s - 1, Three(a, b, c), rest_nodes, sf))) - Ok(#(Node2(a, b), rest_nodes)) -> - Ok(#(popped_a, Deep(s - 1, Two(a, b), rest_nodes, sf))) - Ok(#(Node1(a), rest_nodes)) -> - Ok(#(popped_a, Deep(s - 1, One(a), rest_nodes, sf))) - Error(Nil) -> { - // the tree in the middle is empty - case shift_finger(sf) { - #(new_a, Some(new_sf)) -> - Ok(#(popped_a, Deep(s - 1, One(new_a), Empty, new_sf))) - #(new_a, None) -> Ok(#(popped_a, Single(new_a))) - } - } - } - } - } - } - } -} - -fn shift_node_tree(nodes: FingerTree(Node(u))) { - shift(nodes) -} - -fn shift_finger(finger: Finger(u)) { - case finger { - One(u) -> #(u, None) - Two(u, v) -> #(u, Some(One(v))) - Three(u, v, w) -> #(u, Some(Two(v, w))) - Four(u, v, w, x) -> #(u, Some(Three(v, w, x))) - } -} - -pub fn pop(tree: FingerTree(e)) -> Result(#(e, FingerTree(e)), Nil) { - case tree { - Empty -> Error(Nil) - Single(e) -> Ok(#(e, Empty)) - Deep(s, pr, m, sf) -> { - // a is the first element in the tree - case pop_finger(sf) { - #(popped_a, Some(new_sf)) -> Ok(#(popped_a, Deep(s - 1, pr, m, new_sf))) - #(popped_a, None) -> { - // the last element is now in the middle of the tree - // the next element is the last element in the tree - - // pop the first node out of the tree - case pop_node_tree(m) { - Ok(#(Node3(a, b, c), rest_nodes)) -> - Ok(#(popped_a, Deep(s - 1, pr, rest_nodes, Three(a, b, c)))) - Ok(#(Node2(a, b), rest_nodes)) -> - Ok(#(popped_a, Deep(s - 1, pr, rest_nodes, Two(a, b)))) - Ok(#(Node1(a), rest_nodes)) -> - Ok(#(popped_a, Deep(s - 1, pr, rest_nodes, One(a)))) - Error(Nil) -> { - // the tree itself is now empty, and the next element must be in the suffix - case pop_finger(pr) { - #(new_a, Some(new_pr)) -> - Ok(#(popped_a, Deep(s - 1, new_pr, Empty, One(new_a)))) - #(new_a, None) -> Ok(#(popped_a, Single(new_a))) - } - } - } - } - } - } - } -} - -fn pop_node_tree(nodes: FingerTree(Node(u))) { - pop(nodes) -} - -fn pop_finger(finger: Finger(u)) { - case finger { - One(u) -> #(u, None) - Two(u, v) -> #(v, Some(One(u))) - Three(u, v, w) -> #(w, Some(Two(u, v))) - Four(u, v, w, x) -> #(x, Some(Three(u, v, w))) - } -} - -pub fn filter(tree: FingerTree(e), f: fn(e) -> Bool) -> FingerTree(e) { - reducel(tree, Empty, fn(acc, e) { - case f(e) { - True -> acc |> push(e) - False -> acc - } - }) -} - -pub fn new() { - Empty -} - -pub fn reverse(tree: FingerTree(e)) -> FingerTree(e) { - reducel(tree, Empty, unshift) -} - -pub fn map(tree: FingerTree(e), f: fn(e) -> v) -> FingerTree(v) { - use acc, e <- reducel(tree, Empty) - acc |> push(f(e)) -} - -pub fn drop(tree: FingerTree(e), n: Int) -> #(FingerTree(e), FingerTree(e)) { - do_drop(tree, n, Empty) -} - -fn do_drop(tree: FingerTree(e), n: Int, acc: FingerTree(e)) { - case shift(tree), n { - Ok(#(a, rest)), 0 -> #(acc |> push(a), rest) - Ok(#(a, rest)), _ -> do_drop(rest, n - 1, acc |> push(a)) - Error(Nil), _ -> #(acc, tree) - } -} - -pub fn get(tree: FingerTree(u), get_idx: Int) { - case - reducel(tree, #(None, 0), fn(i, n) -> #(Option(u), Int) { - case i, n { - #(None, idx), n if idx == get_idx -> #(Some(n), idx + 1) - #(a, n), _ -> #(a, n + 1) - } - }) - { - #(Some(u), _) -> Ok(u) - _ -> Error("Index out of bounds") - } -} - -pub const empty = Empty - -pub fn size(tree: FingerTree(e)) { - case tree { - Empty -> 0 - Single(_) -> 1 - Deep(s, _, _, _) -> s - } -} - -pub fn try_reducel( - tree: FingerTree(u), - acc: v, - l_fn: fn(v, u) -> Result(v, w), -) -> Result(v, w) { - case tree { - Empty -> Ok(acc) - Single(u) -> l_fn(acc, u) - Deep(_, pr, m, sf) -> { - use acc <- result.try(try_reducel_finger(pr, acc, l_fn)) - use acc <- result.try(try_reducel_node(m, acc, l_fn)) - try_reducel_finger(sf, acc, l_fn) - } - } -} - -fn try_reducel_finger( - finger: Finger(u), - acc: v, - l_fn: fn(v, u) -> Result(v, w), -) -> Result(v, w) { - case finger { - One(u) -> l_fn(acc, u) - Two(u, v) -> { - use acc <- result.try(l_fn(acc, u)) - l_fn(acc, v) - } - Three(u, v, w) -> { - use acc <- result.try(l_fn(acc, u)) - use acc <- result.try(l_fn(acc, v)) - l_fn(acc, w) - } - Four(u, v, w, x) -> { - use acc <- result.try(l_fn(acc, u)) - use acc <- result.try(l_fn(acc, v)) - use acc <- result.try(l_fn(acc, w)) - l_fn(acc, x) - } - } -} - -fn try_reducel_node( - node: FingerTree(Node(u)), - acc: v, - l_fn: fn(v, u) -> Result(v, w), -) -> Result(v, w) { - use acc, node <- try_reducel(node, acc) - case node { - Node1(u) -> l_fn(acc, u) - Node2(u, v) -> { - use acc <- result.try(l_fn(acc, u)) - l_fn(acc, v) - } - Node3(u, v, w) -> { - use acc <- result.try(l_fn(acc, u)) - use acc <- result.try(l_fn(acc, v)) - l_fn(acc, w) - } - } -} - -pub fn try_map( - tree: FingerTree(u), - map_fn: fn(u) -> Result(v, w), -) -> Result(FingerTree(v), w) { - case tree { - Empty -> Ok(Empty) - Single(u) -> { - use u <- result.map(map_fn(u)) - Single(u) - } - Deep(s, pr, m, sf) -> { - use pr <- result.try(try_map_finger(pr, map_fn)) - use m <- result.try(try_map_node(m, map_fn)) - use sf <- result.map(try_map_finger(sf, map_fn)) - Deep(s, pr, m, sf) - } - } -} - -fn try_map_finger( - finger: Finger(u), - map_fn: fn(u) -> Result(v, w), -) -> Result(Finger(v), w) { - case finger { - One(u) -> { - use u <- result.map(map_fn(u)) - One(u) - } - Two(u, v) -> { - use u <- result.try(map_fn(u)) - use v <- result.map(map_fn(v)) - Two(u, v) - } - Three(u, v, w) -> { - use u <- result.try(map_fn(u)) - use v <- result.try(map_fn(v)) - use w <- result.map(map_fn(w)) - Three(u, v, w) - } - Four(u, v, w, x) -> { - use u <- result.try(map_fn(u)) - use v <- result.try(map_fn(v)) - use w <- result.try(map_fn(w)) - use x <- result.map(map_fn(x)) - Four(u, v, w, x) - } - } -} - -fn try_map_node( - node_tree: FingerTree(Node(u)), - map_fn: fn(u) -> Result(v, w), -) -> Result(FingerTree(Node(v)), w) { - use node <- try_map(node_tree) - case node { - Node1(u) -> { - use u <- result.map(map_fn(u)) - Node1(u) - } - Node2(u, v) -> { - use u <- result.try(map_fn(u)) - use v <- result.map(map_fn(v)) - Node2(u, v) - } - Node3(u, v, w) -> { - use u <- result.try(map_fn(u)) - use v <- result.try(map_fn(v)) - use w <- result.map(map_fn(w)) - Node3(u, v, w) - } - } -} - -pub fn append(tree1: FingerTree(u), tree2: FingerTree(u)) -> FingerTree(u) { - case tree1, tree2 { - Empty, tree2 -> tree2 - Single(u), tree2 -> tree2 |> unshift(u) - tree1, Empty -> tree1 - tree1, Single(u) -> tree1 |> push(u) - tree1, tree2 -> reducel(tree2, tree1, push) - } -} - -pub fn prepend(tree1: FingerTree(u), tree2: FingerTree(u)) -> FingerTree(u) { - append(tree2, tree1) -} - -pub fn reducel_index(tree: FingerTree(u), acc: v, f: fn(v, u, Int) -> v) { - let #(acc, _) = do_reducel_index(tree, acc, 0, f) - acc -} - -fn do_reducel_index( - tree: FingerTree(u), - acc: v, - index: Int, - f: fn(v, u, Int) -> v, -) { - case tree { - Empty -> #(acc, index) - Single(u) -> #(f(acc, u, index), index + 1) - Deep(_, pr, m, sf) -> { - let #(acc, index) = do_reducel_index_finger(pr, acc, index, f) - let #(acc, index) = do_reducel_index_node_tree(m, acc, index, f) - let #(acc, index) = do_reducel_index_finger(sf, acc, index, f) - #(acc, index) - } - } -} - -fn do_reducel_index_finger( - finger: Finger(u), - acc: v, - index: Int, - f: fn(v, u, Int) -> v, -) { - case finger { - One(u) -> #(f(acc, u, index), index + 1) - Two(u, v) -> { - let acc = f(acc, u, index) - #(f(acc, v, index), index + 1) - } - Three(u, v, w) -> { - let acc = f(acc, u, index) - let acc = f(acc, v, index + 1) - #(f(acc, w, index + 2), index + 3) - } - Four(u, v, w, x) -> { - let acc = f(acc, u, index) - let acc = f(acc, v, index + 1) - let acc = f(acc, w, index + 2) - #(f(acc, x, index + 3), index + 4) - } - } -} - -fn do_reducel_index_node_tree( - node_tree: FingerTree(Node(u)), - acc: v, - index: Int, - f: fn(v, u, Int) -> v, -) -> #(v, Int) { - use #(acc, index), node <- reducel(node_tree, #(acc, index)) - case node { - Node1(u) -> #(f(acc, u, index), index + 1) - Node2(u, v) -> { - let acc = f(acc, u, index) - #(f(acc, v, index + 1), index + 2) - } - Node3(u, v, w) -> { - let acc = f(acc, u, index) - let acc = f(acc, v, index + 1) - #(f(acc, w, index + 2), index + 3) - } - } -} - -pub fn map_index(tree: FingerTree(u), f: fn(u, Int) -> v) -> FingerTree(v) { - use tree, item, index <- reducel_index(tree, Empty) - tree |> push(f(item, index)) -} - -pub fn set(tree: FingerTree(u), target_index: Int, target_item: u) { - case tree |> size { - n if n > target_index -> Error(Nil) - _ -> - Ok({ - use u, index <- map_index(tree) - case target_index == index { - True -> target_item - False -> u - } - }) - } -} - -pub fn take(tree: FingerTree(u), count: Int) { - do_take(tree, Empty, count) -} - -fn do_take(tree: FingerTree(u), acc: FingerTree(u), count: Int) { - case tree, count { - _, 0 -> Ok(#(acc, tree)) - Empty, _ -> Error(Nil) - tree, count -> - case shift(tree) { - Ok(#(u, tree)) -> do_take(tree, acc |> push(u), count - 1) - Error(_) -> Error(Nil) - } - } -} - -pub fn peekl(tree: FingerTree(u)) -> Result(u, Nil) { - case tree { - Empty -> Error(Nil) - Single(u) -> Ok(u) - Deep(_, One(u), _, _) -> Ok(u) - Deep(_, Two(u, _), _, _) -> Ok(u) - Deep(_, Three(u, _, _), _, _) -> Ok(u) - Deep(_, Four(u, _, _, _), _, _) -> Ok(u) - } -} - -pub fn peekr(tree: FingerTree(u)) -> Result(u, Nil) { - case tree { - Empty -> Error(Nil) - Single(u) -> Ok(u) - Deep(_, _, _, One(u)) -> Ok(u) - Deep(_, _, _, Two(_, u)) -> Ok(u) - Deep(_, _, _, Three(_, _, u)) -> Ok(u) - Deep(_, _, _, Four(_, _, _, u)) -> Ok(u) - } -} diff --git a/src/internal/structure/equality.gleam b/src/internal/structure/equality.gleam new file mode 100644 index 0000000..47d7c11 --- /dev/null +++ b/src/internal/structure/equality.gleam @@ -0,0 +1,73 @@ +// import gleam/bool +// import gleam/option.{type Option, None, Some} +// import gleam/result.{map} +// import gleam/set.{type Set} +// import internal/structure/modules.{type BinaryModule} +// import internal/structure/numbers +// import internal/structure/types.{ +// type HeapType, type TypeIDX, ConcreteHeapType, RecTypeIDX, TypeIDX, +// } +// import visitor + +// pub type RecTypeContext = +// Option(#(BinaryModule, Int)) + +// pub type EqualityElement { +// EqualityHeapType(heap_type1: HeapType, heap_type2: HeapType) +// EqualityTypeIDX(type_idx1: TypeIDX, type_idx2: TypeIDX) +// } + +// pub fn heap_types_equal( +// heap_type1: HeapType, +// heap_type2: HeapType, +// cache: Set(EqualityElement), +// rec_type_context: RecTypeContext, +// ) { +// use <- bool.guard(heap_type1 == heap_type2, Ok(Nil)) +// use <- bool.guard( +// cache |> set.contains(EqualityHeapType(heap_type1, heap_type2)), +// Ok(Nil), +// ) +// case heap_type1, heap_type2 { +// ConcreteHeapType(type_idx1), ConcreteHeapType(type_idx2) -> +// type_indexes_equal( +// type_idx1, +// type_idx2, +// cache |> set.insert(EqualityHeapType(heap_type1, heap_type2)), +// rec_type_context, +// ) +// _, _ -> Error("Heap types are not equal") +// } +// } + +// pub fn unroll_type_idx(start: Int, index: TypeIDX) { +// case index { +// RecTypeIDX(rec_type_idx) -> { +// let rec_type_idx = numbers.unwrap_u32(rec_type_idx) +// use type_idx <- map(numbers.u32(rec_type_idx + start)) +// TypeIDX(type_idx) +// } +// _ -> Ok(index) +// } +// } + +// pub fn type_indexes_equal( +// type_idx1: TypeIDX, +// type_idx2: TypeIDX, +// cache: Set(EqualityElement), +// rec_type_context: RecTypeContext, +// ) { +// use <- bool.guard(type_idx1 == type_idx2, Ok(Nil)) +// use <- bool.guard( +// cache |> set.contains(EqualityTypeIDX(type_idx1, type_idx2)), +// Ok(Nil), +// ) +// case type_idx1, type_idx2, rec_type_context { +// _, _, None -> Error("Type indexes are not equal") +// a, b, Some(#(_, index)) -> { +// visitor.empty_visitor +// |> visitor.on_enter_type_idx(unroll_type_idx) +// |> visitor.visit_type_idx() +// } +// } +// } diff --git a/src/internal/structure/modules.gleam b/src/internal/structure/modules.gleam index 1031b38..33df07d 100644 --- a/src/internal/structure/modules.gleam +++ b/src/internal/structure/modules.gleam @@ -1,5 +1,4 @@ import gleam/option.{type Option, None} -import internal/finger_tree.{type FingerTree} import internal/structure/numbers.{type U32} import internal/structure/types.{ type Code, type Data, type Elem, type Export, type FuncIDX, type Global, @@ -11,63 +10,66 @@ import internal/structure/types.{ /// for web assembly targets. pub type BinaryModule { BinaryModule( - custom_0: Option(FingerTree(CustomSection)), + custom_0: Option(List(CustomSection)), types: Option(TypeSection), - custom_1: Option(FingerTree(CustomSection)), + custom_1: Option(List(CustomSection)), imports: Option(ImportSection), - custom_2: Option(FingerTree(CustomSection)), + custom_2: Option(List(CustomSection)), functions: Option(FunctionSection), - custom_3: Option(FingerTree(CustomSection)), + custom_3: Option(List(CustomSection)), tables: Option(TableSection), - custom_4: Option(FingerTree(CustomSection)), + custom_4: Option(List(CustomSection)), memories: Option(MemorySection), - custom_5: Option(FingerTree(CustomSection)), + custom_5: Option(List(CustomSection)), globals: Option(GlobalSection), - custom_6: Option(FingerTree(CustomSection)), + custom_6: Option(List(CustomSection)), exports: Option(ExportSection), - custom_7: Option(FingerTree(CustomSection)), + custom_7: Option(List(CustomSection)), start: Option(StartSection), - custom_8: Option(FingerTree(CustomSection)), + custom_8: Option(List(CustomSection)), elements: Option(ElementSection), - custom_9: Option(FingerTree(CustomSection)), + custom_9: Option(List(CustomSection)), code: Option(CodeSection), - custom_10: Option(FingerTree(CustomSection)), + custom_10: Option(List(CustomSection)), data: Option(DataSection), - custom_11: Option(FingerTree(CustomSection)), + custom_11: Option(List(CustomSection)), data_count: Option(DataCountSection), - custom_12: Option(FingerTree(CustomSection)), + custom_12: Option(List(CustomSection)), ) } +/// An empty, valid, binary wasm module +pub const empty = BinaryModule( + custom_0: None, + types: None, + custom_1: None, + imports: None, + custom_2: None, + functions: None, + custom_3: None, + tables: None, + custom_4: None, + memories: None, + custom_5: None, + globals: None, + custom_6: None, + exports: None, + custom_7: None, + start: None, + custom_8: None, + elements: None, + custom_9: None, + code: None, + custom_10: None, + data: None, + custom_11: None, + data_count: None, + custom_12: None, +) + /// This method returns a new BinaryModule pub fn binary_module_new() { - BinaryModule( - custom_0: None, - types: None, - custom_1: None, - imports: None, - custom_2: None, - functions: None, - custom_3: None, - tables: None, - custom_4: None, - memories: None, - custom_5: None, - globals: None, - custom_6: None, - exports: None, - custom_7: None, - start: None, - custom_8: None, - elements: None, - custom_9: None, - code: None, - custom_10: None, - data: None, - custom_11: None, - data_count: None, - custom_12: None, - ) + empty } /// WebAssembly allows for unlimited custom sections that can be added between other sections @@ -80,14 +82,14 @@ pub type CustomSection { /// recursive type group. This allows for a compact storage of this type information, and when /// "unrolled", these types become the type index for validation and execution. pub type TypeSection { - TypeSection(types: FingerTree(RecType)) + TypeSection(types: List(RecType)) } /// WebAssembly modules can import functions, tables, memories, and globals. This section /// contains a list of those imports to describe what the module expects to use from /// the host. pub type ImportSection { - ImportSection(imports: FingerTree(Import)) + ImportSection(imports: List(Import)) } /// The WebAssembly function section is not a list of function declarations. Rather, it @@ -95,7 +97,7 @@ pub type ImportSection { /// In order for a WebAssembly module to be valid, each type index must refer to a type /// that expands to a function composite type. pub type FunctionSection { - FunctionSection(funcs: FingerTree(TypeIDX)) + FunctionSection(funcs: List(TypeIDX)) } /// WebAssembly modules can declare tables which are pre-allocated arrays of values that @@ -103,27 +105,27 @@ pub type FunctionSection { /// (which is a classification of object) that can be nullable and a limit that describes /// how many can exist within. pub type TableSection { - TableSection(tables: FingerTree(Table)) + TableSection(tables: List(Table)) } /// WebAssembly modules can declare linear memories which represent conceptual linear memory /// segments that can be used by the module for memory allocation and other operations. pub type MemorySection { - MemorySection(mts: FingerTree(MemType)) + MemorySection(mts: List(MemType)) } /// WebAssembly modules can declare global values which can be mutable and accessible from /// both the host and the WebAssembly module. Each global is defined by the ValueType it /// can hold, it's mutabliity, and an initial value. pub type GlobalSection { - GlobalSection(globals: FingerTree(Global)) + GlobalSection(globals: List(Global)) } /// WebAssembly modules can export functions, tables, memories, and globals. This section /// simply describes the set of exports in the module defined by a name, an export type, and /// a corresponding index to the other section containing that export. pub type ExportSection { - ExportSection(exports: FingerTree(Export)) + ExportSection(exports: List(Export)) } /// The WebAssembly start section specifies the index of the function to be called when the @@ -135,11 +137,11 @@ pub type StartSection { /// In web assembly, tables can be initialized with element segments. Each one of these segments /// contains a list of RefType values that can either be initialized when the module is instantiated (active), /// preallocated for later use (passive), or declared up front for wasm engine optimization (declarative). -/// +/// /// Typically, modules only have active or passive element segments, and are most commonly used for /// function refrences for indirect function calls. pub type ElementSection { - ElementSection(elems: FingerTree(Elem)) + ElementSection(elems: List(Elem)) } /// WebAssembly modules can declare callable functions called "Code"s which define the shape @@ -148,14 +150,14 @@ pub type ElementSection { /// of operations that represent the body of the function. Every body is terminated by an /// 0x0B "end" byte instruction to signify the end of the expression. pub type CodeSection { - CodeSection(codes: FingerTree(Code)) + CodeSection(codes: List(Code)) } /// WebAssembly modules can declare linear data segments which are pre-allocated byte arrays /// of data that can either be instantiated and written into the Module's linear memory, or /// declared as static segment for later use. pub type DataSection { - DataSection(data: FingerTree(Data)) + DataSection(data: List(Data)) } /// The WebAssembly data count section simply contains the number of data segments in the diff --git a/src/internal/structure/types.gleam b/src/internal/structure/types.gleam index c57f338..d016538 100644 --- a/src/internal/structure/types.gleam +++ b/src/internal/structure/types.gleam @@ -1,11 +1,12 @@ +import gleam/list import gleam/option.{type Option} import gleam/result -import internal/finger_tree.{type FingerTree} import internal/structure/common.{between} import internal/structure/numbers.{ type F32, type F64, type I32, type I64, type U32, type V128Value, } +/// Get the lane_16 indx nvalue as an integer pub fn unwrap_lane_16(val: LaneIDX16) { val.val } @@ -23,6 +24,7 @@ pub opaque type LaneIDX16 { LaneIDX16(val: Int) } +/// Get the lane_2 index value as an integer pub fn unwrap_lane_2(val: LaneIDX2) { val.val } @@ -40,6 +42,7 @@ pub opaque type LaneIDX2 { LaneIDX2(val: Int) } +/// Get the lane_4 index value as an integer pub fn unwrap_lane_4(val: LaneIDX4) { val.val } @@ -57,6 +60,7 @@ pub opaque type LaneIDX4 { LaneIDX4(val: Int) } +/// Get the lane_8 index value as an integer pub fn unwrap_lane_8(val: LaneIDX8) { val.val } @@ -74,28 +78,10 @@ pub opaque type LaneIDX8 { LaneIDX8(val: Int) } -/// This type is used to describe a number type, namely the primary wasm number types -/// Please see: https://webassembly.github.io/gc/core/syntax/types.html#number-types -pub type NumType { - I32NumType - I64NumType - F32NumType - F64NumType -} - -/// A bool is always an I32 -pub const bool = I32NumType - -/// This type is used to describe a SIMD vector type -/// pleasae see: https://webassembly.github.io/gc/core/syntax/types.html#vector-types -pub type VecType { - VecType -} - /// Please see: https://webassembly.github.io/gc/core/syntax/types.html#heap-types /// For validation and execution, please see: https://webassembly.github.io/gc/core/valid/conventions.html#types -/// Please note that Abstract Heap Types are a seperate type, and are combined with heap types -/// in this convention for the sake of clarity, and ease of encoding and decoding +/// Please note that Abstract Heap Types are a seperate type, and are combined here with +/// heap types in this convention for the sake of clarity and performance. pub type HeapType { FuncHeapType NoFuncHeapType @@ -111,26 +97,10 @@ pub type HeapType { BotHeapType } -/// This is a collection of all the abstract classifications of RefTypes -/// Please see: https://webassembly.github.io/gc/core/syntax/types.html#heap-types -pub type AbstractHeapType { - FuncAbstractHeapType - NoAbstractFuncHeapType - ExternAbstractHeapType - NoExternAbstractHeapType - AnyAbstractHeapType - EqAbstractHeapType - I31AbstractHeapType - StructAbstractHeapType - ArrayAbstractHeapType - NoneAbstractHeapType -} - -/// A refrence type describes a refrence to an object that may or may not be nullable +/// A refrence type classifies a refrence by it's underlying type /// Please see: https://webassembly.github.io/gc/core/syntax/types.html#reference-types pub type RefType { HeapTypeRefType(ht: HeapType, null: Bool) - /// Shorthand for (ref null Any) AnyRefType /// Shorthand for (ref null Eq) @@ -153,9 +123,12 @@ pub type RefType { NoExternRefType } +/// This function is used to check if a refrence type is nullable pub fn ref_type_is_nullable(rt: RefType) { case rt { + // If the ref type is a heap type, check the mutability HeapTypeRefType(_, mut) -> mut + // Otherwise, all the shorthands are default nullable _ -> True } } @@ -200,19 +173,19 @@ pub type BlockType { /// An instruction type is two result types, one for the parameters, and one for the results. pub type InstructionType { - InstructionType(parameters: FingerTree(ValType), results: FingerTree(ValType)) + InstructionType(parameters: List(ValType), results: List(ValType)) } /// A function type describes the shape of the parameters and results of a given function. /// Please see: https://webassembly.github.io/gc/core/syntax/types.html#function-types pub type FuncType { - FuncType(parameters: FingerTree(ValType), results: FingerTree(ValType)) + FuncType(parameters: List(ValType), results: List(ValType)) } /// A struct type describes the shape of the fields of a given struct. /// Please see: https://webassembly.github.io/gc/core/syntax/types.html#aggregate-types pub type StructType { - StructType(ft: FingerTree(FieldType)) + StructType(ft: List(FieldType)) } /// An array type describes an array with the given field type. @@ -221,7 +194,7 @@ pub type ArrayType { ArrayType(ft: FieldType) } -/// A field type is classified by a "StorageType" and a "Mutability" state. +/// A field type is classified by a "StorageType" and a "Mutability" state. /// Please See: https://webassembly.github.io/gc/core/syntax/types.html#aggregate-types pub type FieldType { FieldType(st: StorageType, mut: Mut) @@ -266,7 +239,7 @@ pub type CompositeType { /// It is used to describe the shape of mutually recursive SubTypes. /// Please see: https://webassembly.github.io/gc/core/syntax/types.html#recursive-types pub type RecType { - RecType(sub_types: FingerTree(SubType)) + RecType(sub_types: List(SubType)) } /// An index into an array of types, either a recursive type, a module subtype, or a @@ -320,7 +293,7 @@ pub type MemIDX { /// also an array of matching subtype indexes that the type matches. /// Please see: https://webassembly.github.io/gc/core/syntax/types.html#recursive-types pub type SubType { - SubType(final: Bool, t: FingerTree(TypeIDX), ct: CompositeType) + SubType(final: Bool, t: List(TypeIDX), ct: CompositeType) } /// A definition of a limit range, which has a minimum, and an optional maximum which defaults @@ -364,72 +337,15 @@ pub type ExternType { GlobalExternType(gt: GlobalType) } -/// This function returns all the ExternTypes that are FuncTypes -/// https://webassembly.github.io/gc/core/syntax/types.html#id5 -pub fn get_extern_func_types( - et: FingerTree(ExternType), -) -> FingerTree(ExternType) { - et - |> finger_tree.filter(fn(et) { - case et { - FuncExternType(_) -> True - _ -> False - } - }) -} - -/// This function returns all the ExternTypes that are TableTypes -/// https://webassembly.github.io/gc/core/syntax/types.html#id5 -pub fn get_extern_table_types( - et: FingerTree(ExternType), -) -> FingerTree(ExternType) { - et - |> finger_tree.filter(fn(et) { - case et { - TableExternType(_) -> True - _ -> False - } - }) -} - -/// This function returns all the ExternTypes that are MemTypes -/// https://webassembly.github.io/gc/core/syntax/types.html#id5 -pub fn get_extern_memory_types( - et: FingerTree(ExternType), -) -> FingerTree(ExternType) { - et - |> finger_tree.filter(fn(et) { - case et { - MemExternType(_) -> True - _ -> False - } - }) -} - -/// This function returns all the ExternTypes that are GlobalTypes -/// https://webassembly.github.io/gc/core/syntax/types.html#id5 -pub fn get_extern_global_types( - et: FingerTree(ExternType), -) -> FingerTree(ExternType) { - et - |> finger_tree.filter(fn(et) { - case et { - GlobalExternType(_) -> True - _ -> False - } - }) -} - -/// A deftype is a "wrapper", referred to as an "unrolled" type that identifies a SubType. -/// That SubType is represented by a refrence to a specific recursive type, and then indexing -/// into that refrence's subtype. +/// A deftype is a "wrapper", referred to as an "unrolled" recursive type that indexes into the +/// given RecType's SubTypes. It is used for WebAssembly validation and execution. /// Please see: https://webassembly.github.io/gc/core/valid/conventions.html#defined-types pub type DefType { DefType(rt: RecType, idx: Int) } /// A local type is represented as a value type and wether or not it has been initialized. -/// Please see: https://webassembly.github.io/gc/core/valid/conventions.html#local-types +/// Please see: https://webassembly.github.io/gc/core/valid/conventions.html#local-types pub type LocalType { LocalType(initialized: Bool, t: ValType) } @@ -865,7 +781,7 @@ pub type Instruction { ExternConvertAny Drop Select - SelectT(vt: FingerTree(ValType)) + SelectT(vt: List(ValType)) LocalGet(idx: LocalIDX) LocalSet(idx: LocalIDX) LocalTee(idx: LocalIDX) @@ -936,12 +852,12 @@ pub type Instruction { Loop(bt: BlockType, instructions: Expr) If( bt: BlockType, - instructions: FingerTree(Instruction), - else_instructions: Option(FingerTree(Instruction)), + instructions: List(Instruction), + else_instructions: Option(List(Instruction)), ) Br(label: LabelIDX) BrIf(label: LabelIDX) - BrTable(labels: FingerTree(LabelIDX), default: LabelIDX) + BrTable(labels: List(LabelIDX), default: LabelIDX) BrOnNull(label: LabelIDX) BrOnNonNull(label: LabelIDX) BrOnCast(label: LabelIDX, rt1: RefType, rt2: RefType) @@ -950,7 +866,6 @@ pub type Instruction { Call(func_idx: FuncIDX) CallRef(type_idx: TypeIDX) CallIndirect(table_idx: TableIDX, type_idx: TypeIDX) - // expand(TypeSection[type_idx].subtype[sub_type_index]) -> CompositeType ReturnCall(func_idx: FuncIDX) ReturnCallRef(type_idx: TypeIDX) ReturnCallIndirect(table_idx: TableIDX, type_idx: TypeIDX) @@ -961,7 +876,7 @@ pub type Instruction { /// This function helps obtain the result type of an instruction in the form of an `InstructionType`. /// Instruction types are two sets of "Result Types" that describe the operands and results of a /// given instruction, based on the "Context" of the function executing it. -/// +/// /// TODO: Add more instruction types, and add the Validation Context as a parameter. pub fn get_instruction_type( instruction: Instruction, @@ -969,19 +884,13 @@ pub fn get_instruction_type( case instruction { End | Else -> Error(Nil) - I64Const(_) -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([I64ValType]))) + I64Const(_) -> Ok(InstructionType([], [I64ValType])) I32Const(_) | ArrayLen | I31GetS | I31GetU -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([I32ValType]))) - F64Const(_) -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([F64ValType]))) - F32Const(_) -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([F32ValType]))) + Ok(InstructionType([], [I32ValType])) + F64Const(_) -> Ok(InstructionType([], [F64ValType])) + F32Const(_) -> Ok(InstructionType([], [F32ValType])) I64Popcnt | I64Ctz | I64Clz | I64Extend32S | I64Extend16S | I64Extend8S -> - Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([I64ValType]), - )) + Ok(InstructionType([I64ValType], [I64ValType])) I32Popcnt | I32Ctz | I32Clz @@ -993,21 +902,11 @@ pub fn get_instruction_type( | I32Load16U(_) | I32Load8S(_) | I32Load8U(_) - | MemoryGrow -> - Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([I32ValType]), - )) + | MemoryGrow -> Ok(InstructionType([I32ValType], [I32ValType])) F64Nearest | F64Trunc | F64Floor | F64Ceil | F64Sqrt | F64Neg | F64Abs -> - Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([F64ValType]), - )) + Ok(InstructionType([F64ValType], [F64ValType])) F32Nearest | F32Trunc | F32Floor | F32Ceil | F32Sqrt | F32Neg | F32Abs -> - Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([F32ValType]), - )) + Ok(InstructionType([F32ValType], [F32ValType])) I64Rotr | I64Rotl | I64ShrS @@ -1022,11 +921,7 @@ pub fn get_instruction_type( | I64DivU | I64Mul | I64Sub - | I64Add -> - Ok(InstructionType( - finger_tree.from_list([I64ValType, I64ValType]), - finger_tree.from_list([I64ValType]), - )) + | I64Add -> Ok(InstructionType([I64ValType, I64ValType], [I64ValType])) I32Rotr | I32Rotl | I32ShrS @@ -1051,26 +946,12 @@ pub fn get_instruction_type( | I32LtS | I32LtU | I32Ne - | I32Eq -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, I32ValType]), - finger_tree.from_list([I32ValType]), - )) + | I32Eq -> Ok(InstructionType([I32ValType, I32ValType], [I32ValType])) F64Copysign | F64Max | F64Min | F64Div | F64Mul | F64Sub | F64Add -> - Ok(InstructionType( - finger_tree.from_list([F64ValType, F64ValType]), - finger_tree.from_list([F64ValType]), - )) + Ok(InstructionType([F64ValType, F64ValType], [F64ValType])) F32Copysign | F32Max | F32Min | F32Div | F32Mul | F32Sub | F32Add -> - Ok(InstructionType( - finger_tree.from_list([F32ValType, F32ValType]), - finger_tree.from_list([F32ValType]), - )) - I64Eqz | I32WrapI64 -> - Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F32ValType, F32ValType], [F32ValType])) + I64Eqz | I32WrapI64 -> Ok(InstructionType([I64ValType], [I32ValType])) I64GeS | I64GeU | I64LeS @@ -1080,22 +961,12 @@ pub fn get_instruction_type( | I64LtS | I64LtU | I64Ne - | I64Eq -> - Ok(InstructionType( - finger_tree.from_list([I64ValType, I64ValType]), - finger_tree.from_list([I32ValType]), - )) + | I64Eq -> Ok(InstructionType([I64ValType, I64ValType], [I32ValType])) F64Ge | F64Le | F64Gt | F64Lt | F64Ne | F64Eq -> - Ok(InstructionType( - finger_tree.from_list([F64ValType, F64ValType]), - finger_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F64ValType, F64ValType], [I32ValType])) F32Ge | F32Le | F32Gt | F32Lt | F32Ne | F32Eq -> - Ok(InstructionType( - finger_tree.from_list([F32ValType, F32ValType]), - finger_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F32ValType, F32ValType], [I32ValType])) I64ExtendI32S | I64ExtendI32U | I64Load(_) @@ -1104,74 +975,32 @@ pub fn get_instruction_type( | I64Load8S(_) | I64Load8U(_) | I64Load32S(_) - | I64Load32U(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([I64ValType]), - )) + | I64Load32U(_) -> Ok(InstructionType([I32ValType], [I64ValType])) I64TruncF64S | I64TruncF64U | I64TruncSatF64S | I64TruncSatF64U - | I64ReinterpretF64 -> - Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([I64ValType]), - )) + | I64ReinterpretF64 -> Ok(InstructionType([F64ValType], [I64ValType])) I64TruncF32S | I64TruncF32U | I64TruncSatF32S | I64TruncSatF32U -> - Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([I64ValType]), - )) + Ok(InstructionType([F32ValType], [I64ValType])) I32TruncF64S | I32TruncF64U | I32TruncSatF64S | I32TruncSatF64U -> - Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F64ValType], [I32ValType])) I32TruncF32S | I32TruncF32U | I32TruncSatF32S | I32TruncSatF32U - | I32ReinterpretF32 -> - Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([I32ValType]), - )) - F32DemoteF64 -> - Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([F64ValType]), - )) - F64PromoteF32 -> - Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([F32ValType]), - )) + | I32ReinterpretF32 -> Ok(InstructionType([F32ValType], [I32ValType])) + F32DemoteF64 -> Ok(InstructionType([F32ValType], [F64ValType])) + F64PromoteF32 -> Ok(InstructionType([F64ValType], [F32ValType])) F64ConvertI64S | F64ConvertI64U | F64ReinterpretI64 -> - Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([F64ValType]), - )) + Ok(InstructionType([I64ValType], [F64ValType])) F64ConvertI32S | F64ConvertI32U | F64Load(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([F64ValType]), - )) + Ok(InstructionType([I32ValType], [F64ValType])) F32ConvertI64S | F32ConvertI64U -> - Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([F32ValType]), - )) + Ok(InstructionType([I64ValType], [F32ValType])) F32ConvertI32S | F32ConvertI32U | F32ReinterpretI32 | F32Load(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([F32ValType]), - )) - V128Const(_) -> - Ok(InstructionType( - finger_tree.new(), - finger_tree.from_list([V128ValType]), - )) + Ok(InstructionType([I32ValType], [F32ValType])) + V128Const(_) -> Ok(InstructionType([], [V128ValType])) V128Not | I64x2Neg | I64x2Abs @@ -1209,11 +1038,7 @@ pub fn get_instruction_type( | F32x4DemoteF64x2Zero | F64x2ConvertLowI32x4S | F64x2ConvertLowI32x4U - | F64x2PromoteLowF32x4 -> - Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([V128ValType]), - )) + | F64x2PromoteLowF32x4 -> Ok(InstructionType([V128ValType], [V128ValType])) V128Xor | V128AndNot | V128Or @@ -1346,16 +1171,11 @@ pub fn get_instruction_type( | F32x4Mul | F32x4Sub | F32x4Add - | I64x2Mul -> - Ok(InstructionType( - finger_tree.from_list([V128ValType, V128ValType]), - finger_tree.from_list([V128ValType]), - )) + | I64x2Mul -> Ok(InstructionType([V128ValType, V128ValType], [V128ValType])) V128Bitselect -> - Ok(InstructionType( - finger_tree.from_list([V128ValType, V128ValType, V128ValType]), - finger_tree.from_list([V128ValType]), - )) + Ok( + InstructionType([V128ValType, V128ValType, V128ValType], [V128ValType]), + ) V128AnyTrue | I8x16ExtractLaneS(_) | I16x8ExtractLaneS(_) @@ -1368,11 +1188,7 @@ pub fn get_instruction_type( | I64x2Bitmask | I32x4Bitmask | I16x8Bitmask - | I8x16Bitmask -> - Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([I32ValType]), - )) + | I8x16Bitmask -> Ok(InstructionType([V128ValType], [I32ValType])) I32x4Splat | I16x8Splat | I8x16Splat @@ -1388,46 +1204,14 @@ pub fn get_instruction_type( | V128Load64Splat(_) | V128Load32Splat(_) | V128Load16Splat(_) - | V128Load8Splat(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([V128ValType]), - )) - I64x2Splat -> - Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([V128ValType]), - )) - F32x4Splat -> - Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([V128ValType]), - )) - F64x2Splat -> - Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([V128ValType]), - )) - I64x2ExtractLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([I64ValType]), - )) - I32x4ExtractLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([I32ValType]), - )) - F32x4ExtractLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([F32ValType]), - )) - F64x2ExtractLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([F64ValType]), - )) + | V128Load8Splat(_) -> Ok(InstructionType([I32ValType], [V128ValType])) + I64x2Splat -> Ok(InstructionType([I64ValType], [V128ValType])) + F32x4Splat -> Ok(InstructionType([F32ValType], [V128ValType])) + F64x2Splat -> Ok(InstructionType([F64ValType], [V128ValType])) + I64x2ExtractLane(_) -> Ok(InstructionType([V128ValType], [I64ValType])) + I32x4ExtractLane(_) -> Ok(InstructionType([V128ValType], [I32ValType])) + F32x4ExtractLane(_) -> Ok(InstructionType([V128ValType], [F32ValType])) + F64x2ExtractLane(_) -> Ok(InstructionType([V128ValType], [F64ValType])) I8x16ReplaceLane(_) | I16x8ReplaceLane(_) | I32x4ReplaceLane(_) @@ -1442,27 +1226,14 @@ pub fn get_instruction_type( | I16x8Shl | I8x16ShrS | I8x16ShrU - | I8x16Shl -> - Ok(InstructionType( - finger_tree.from_list([V128ValType, I32ValType]), - finger_tree.from_list([V128ValType]), - )) + | I8x16Shl -> Ok(InstructionType([V128ValType, I32ValType], [V128ValType])) I64x2ReplaceLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType, I64ValType]), - finger_tree.from_list([V128ValType]), - )) + Ok(InstructionType([V128ValType, I64ValType], [V128ValType])) F32x4ReplaceLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType, F32ValType]), - finger_tree.from_list([V128ValType]), - )) + Ok(InstructionType([V128ValType, F32ValType], [V128ValType])) F64x2ReplaceLane(_) -> - Ok(InstructionType( - finger_tree.from_list([V128ValType, F64ValType]), - finger_tree.from_list([V128ValType]), - )) - Nop -> Ok(InstructionType(finger_tree.new(), finger_tree.new())) + Ok(InstructionType([V128ValType, F64ValType], [V128ValType])) + Nop -> Ok(InstructionType([], [])) // TODO: Each of these instructions need to be implemented and checked RefFunc(_) @@ -1528,84 +1299,59 @@ pub fn get_instruction_type( | StructNew(_) | StructNewDefault(_) -> todo - RefI31 -> - Ok(InstructionType( - finger_tree.new(), - finger_tree.from_list([RefTypeValType(I31RefType)]), - )) + RefI31 -> Ok(InstructionType([], [RefTypeValType(I31RefType)])) AnyConvertExtern -> - Ok(InstructionType( - finger_tree.from_list([RefTypeValType(ExternRefType)]), - finger_tree.from_list([RefTypeValType(AnyRefType)]), - )) + Ok( + InstructionType([RefTypeValType(ExternRefType)], [ + RefTypeValType(AnyRefType), + ]), + ) ExternConvertAny -> - Ok(InstructionType( - finger_tree.from_list([RefTypeValType(AnyRefType)]), - finger_tree.from_list([RefTypeValType(ExternRefType)]), - )) + Ok( + InstructionType([RefTypeValType(AnyRefType)], [ + RefTypeValType(ExternRefType), + ]), + ) I64Store(_) | I64Store16(_) | I64Store8(_) | I64Store32(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, I64ValType]), - finger_tree.new(), - )) + Ok(InstructionType([I32ValType, I64ValType], [])) I32Store(_) | I32Store16(_) | I32Store8(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, I32ValType]), - finger_tree.new(), - )) - F64Store(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, F64ValType]), - finger_tree.new(), - )) - F32Store(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, F32ValType]), - finger_tree.new(), - )) + Ok(InstructionType([I32ValType, I32ValType], [])) + F64Store(_) -> Ok(InstructionType([I32ValType, F64ValType], [])) + F32Store(_) -> Ok(InstructionType([I32ValType, F32ValType], [])) V128Store(_) | V128Store8Lane(_, _) | V128Store16Lane(_, _) | V128Store32Lane(_, _) | V128Store64Lane(_, _) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, V128ValType]), - finger_tree.new(), - )) + Ok(InstructionType([I32ValType, V128ValType], [])) V128Load8Lane(_, _) | V128Load16Lane(_, _) | V128Load32Lane(_, _) | V128Load64Lane(_, _) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, V128ValType]), - finger_tree.from_list([V128ValType]), - )) - MemorySize -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([I32ValType]))) + Ok(InstructionType([I32ValType, V128ValType], [V128ValType])) + MemorySize -> Ok(InstructionType([], [I32ValType])) MemoryFill | MemoryCopy | MemoryInit(_) -> - Ok(InstructionType( - finger_tree.from_list([I32ValType, I32ValType, I32ValType]), - finger_tree.new(), - )) - DataDrop(_) -> Ok(InstructionType(finger_tree.new(), finger_tree.new())) + Ok(InstructionType([I32ValType, I32ValType, I32ValType], [])) + DataDrop(_) -> Ok(InstructionType([], [])) } } -/// An expression is a "End" [0x0B] terminated sequence of instructions +/// An expression is a "End" [0x0B] terminated sequence of instructions that describe a +/// calculated value. pub type Expr { - Expr(insts: FingerTree(Instruction)) + Expr(insts: List(Instruction)) } -/// Expanding a deftype extracts the "CompositeType" of the refrenced subtype to -/// identify what kind of DefinedType it is. +/// Expanding a deftype extracts the "CompositeType" of the referenced subtype it points to. pub fn def_type_expand(dt: DefType) { let DefType(RecType(st), idx) = dt - use st <- result.map(st |> finger_tree.get(idx)) + use st <- result.map(st |> list.drop(idx) |> list.first) st.ct } -/// An import describes a function, table, memory, or global expected to be provided -/// by the WebAssembly host. +/// An import describes a function, table, memory, or global that is given to the +/// WebAssembly module when it is instantiated. Each import is defined by a module +/// namespace, a name, and a given type. pub type Import { FuncImport(mod: String, name: String, type_idx: TypeIDX) TableImport(mod: String, name: String, table_type: TableType) @@ -1613,49 +1359,56 @@ pub type Import { GlobalImport(mod: String, name: String, global_type: GlobalType) } -/// A set of defined locals, (3:u32 i32:valtype), which describe how many of each type +/// A set of defined locals, (3:u32 i32:valtype), which describe how many of each type /// of local is defined in a given code section. -/// -/// E.X. Locals* -> (3 i32) (2 i64) (1 f32) -/// -/// This sequence of "Locals" expands to ValType* -> (i32) (i32) (i32) (i64) (i64) (f32) +/// +/// E.x. Locals* -> (3 i32) (2 i64) (1 f32) +/// +/// This sequence of "Locals" expands to `ValType* -> (i32) (i32) (i32) (i64) (i64) (f32)` /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#functions pub type Locals { Locals(count: U32, type_: ValType) } -/// A WebAssembly table that is defined by a TableType, and is optionally initialized by -/// an Expression +/// A WebAssembly table is defined by a TableType, and is optionally initialized by +/// an Expression. /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#tables pub type Table { Table(type_: TableType, init: Option(Expr)) } -/// A WebAssembly Memory defined by it's memory type +/// A WebAssembly memory defined by it's memory type, which is just a set of limits. /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#memories pub type Mem { Mem(type_: MemType) } -/// A WebAssembly Global defined by it's global type and constant initializer +/// A WebAssembly Global defined by a global type and constant initializer expression. /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#globals pub type Global { Global(type_: GlobalType, init: Expr) } -/// A WebAssembly element segment that describes a sequence of Expressions to help initialize tables +/// A WebAssembly element segment that describes a sequence of Expressions or Function Indexes +/// used to initialize tables. /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#element-segments pub type Elem { - ElemFuncs(type_: RefType, init: FingerTree(FuncIDX), mode: ElemMode) - ElemExpressions(type_: RefType, init: FingerTree(Expr), mode: ElemMode) -} - -/// An element segment defines a sequence of expressions, but how those elements are used is -/// determined by the ElemMode provided as a "SegmentType" -/// -/// - `Passive`: This segment is used to define tables that are not initialized from function calls -/// - `Active`: This segment is used to define tables that are initialized when the module is instantiated, on a given table, at a specific index -/// - `Declarative`: This segment is used to define refrences that are created later from code + ElemFuncs(type_: RefType, init: List(FuncIDX), mode: ElemMode) + ElemExpressions(type_: RefType, init: List(Expr), mode: ElemMode) +} + +/// An element segment defines a sequence of expressions used to describe items that can be used in a +/// WebAssembly table. There are three different types of element segments, and they describe how the +/// module and the WebAssembly host utilizes them. +/// +/// The types are: +/// - `Passive`: This segment type defines a static vector of expressions that can be used later with +/// other instructions. +/// - `Active`: This segment is used to initialize tables when the module is instantiated. Each `Active` +/// segment contains a table index and a constant expression defining an offset into that table. +/// - `Declarative`: This segment describes a static vector of expressions that can be used to forward-declare +/// references formed in the code with instructions like `ref.func`. +/// /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#element-segments pub type ElemMode { PassiveElemMode @@ -1663,8 +1416,8 @@ pub type ElemMode { DeclarativeElemMode } -/// An export describes an item that is provided back to the WebAssembly host -/// for later use. +/// An export describes an item that is available to the host environment when the module is +/// instantiated. /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#exports pub type Export { FuncExport(name: String, func_idx: FuncIDX) @@ -1673,69 +1426,18 @@ pub type Export { GlobalExport(name: String, global_idx: GlobalIDX) } -/// A convention to identify if and export is a function -/// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#exports -pub fn export_is_func(export: Export) -> Bool { - case export { - FuncExport(_, _) -> True - _ -> False - } -} - -/// A convention to identify if and export is a table -/// Conventions: https://webassembly.github.io/gc/core/syntax/modules.html#exports -pub fn export_is_table(export: Export) -> Bool { - case export { - TableExport(_, _) -> True - _ -> False - } -} - -/// A convention to identify if and export is a memory -/// Conventions: https://webassembly.github.io/gc/core/syntax/modules.html#exports -pub fn export_is_mem(export: Export) -> Bool { - case export { - MemExport(_, _) -> True - _ -> False - } -} - -/// A convention to identify if and export is a global -/// Conventions: https://webassembly.github.io/gc/core/syntax/modules.html#exports -pub fn export_is_global(export: Export) -> Bool { - case export { - GlobalExport(_, _) -> True - _ -> False - } -} - -/// A convenience method to filter out exports that are not functions -pub fn funcs(exports: FingerTree(Export)) -> FingerTree(Export) { - exports |> finger_tree.filter(export_is_func) -} - -/// A convenience method to filter out exports that are not tables -pub fn tables(exports: FingerTree(Export)) -> FingerTree(Export) { - exports |> finger_tree.filter(export_is_table) -} - -/// A convenience method to filter out exports that are not memories -pub fn mems(exports: FingerTree(Export)) -> FingerTree(Export) { - exports |> finger_tree.filter(export_is_mem) -} - -/// A convenience method to filter out exports that are not globals -pub fn globals(exports: FingerTree(Export)) -> FingerTree(Export) { - exports |> finger_tree.filter(export_is_global) -} - -/// A WebAssembly function defined by it's locals and function body +/// A WebAssembly function body defined by it's locals and an expression. pub type Code { - Code(locals: FingerTree(Locals), body: Expr) + Code(locals: List(Locals), body: Expr) } -/// A WebAssembly data segment that describes the "type" of the data segment, the memory it -/// writes into, the offset into that memory, and the data itself. +/// Data segments can be used to initialize a range of memory from a static vector of bytes. +/// +/// The types are: +/// - `ActiveData`: This segment type defines a static vector of bytes that fill the given memory +/// by it's index and at the given offset when the module is instantiated. +/// - `PassiveData`: This segment type defines a static vector of bytes that can be used later with +/// other instructions like table.init_data and memory.init. pub type Data { ActiveData(mem: MemIDX, offset: Expr, init: BitArray) PassiveData(init: BitArray) @@ -1746,7 +1448,9 @@ pub fn unwrap_local_idx(idx: LocalIDX) { idx.id |> numbers.unwrap_u32 } -/// Return the integer value of a type index +/// Return the integer value of a type index if it's a concrete index. +/// +/// Panics if the index is a RecTypeIDX or a DefType pub fn unwrap_type_idx(idx: TypeIDX) { case idx { TypeIDX(idx) -> idx |> numbers.unwrap_u32 diff --git a/src/internal/validation/README.md b/src/internal/validation/README.md new file mode 100644 index 0000000..1ec31d1 --- /dev/null +++ b/src/internal/validation/README.md @@ -0,0 +1,14 @@ +## Validation + +- [Numeric Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#numeric-instructions) +- [Reference Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#reference-instructions) +- [Aggregate Reference Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#aggregate-reference-instructions) +- [Scalar Reference Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#scalar-reference-instructions) +- [External Reference Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#external-reference-instructions) +- [Vector (v128) Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#vector-instructions) +- [Parametric Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#parametric-instructions) +- [Variable Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#variable-instructions) +- [Table Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#table-instructions) +- [Memory Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#memory-instructions) +- [Control Instructions](https://webassembly.github.io/gc/core/valid/instructions.html#control-instructions) +- []() \ No newline at end of file diff --git a/src/internal/validation/common.gleam b/src/internal/validation/common.gleam new file mode 100644 index 0000000..272b75c --- /dev/null +++ b/src/internal/validation/common.gleam @@ -0,0 +1,39 @@ +import gleam/option.{type Option, None} +import internal/structure/types.{ + type Data, type DefType, type Elem, type FuncIDX, type GlobalType, type Locals, + type MemType, type RecType, type TableType, type ValType, +} + +pub type Context { + Context( + types: List(DefType), + funcs: List(DefType), + tables: List(TableType), + mems: List(MemType), + globals: List(GlobalType), + elems: List(Elem), + data: List(Data), + locals: List(Locals), + labels: List(List(ValType)), + return: Option(List(ValType)), + refs: List(FuncIDX), + ) +} + +pub const empty_context = Context( + types: [], + funcs: [], + tables: [], + mems: [], + globals: [], + elems: [], + data: [], + locals: [], + labels: [], + return: None, + refs: [], +) + +pub fn roll_rec_types(rec_type: RecType) -> List(DefType) { + todo +} diff --git a/src/internal/validation/module.gleam b/src/internal/validation/module.gleam new file mode 100644 index 0000000..56de6c0 --- /dev/null +++ b/src/internal/validation/module.gleam @@ -0,0 +1,26 @@ +import gleam/list +import gleam/option.{None, Some} +import gleam/result +import internal/structure/modules.{type BinaryModule, TypeSection} +import internal/structure/types.{type RecType} +import internal/validation/common.{ + type Context, Context, empty_context, roll_rec_types, +} +import internal/validation/types.{rec_type_is_valid} as _validation_types + +pub fn validate_type(ctx_prime: Context, rec_type: RecType) { + let def_types = rec_type |> roll_rec_types + let ctx = Context(..ctx_prime, types: list.append(ctx_prime.types, def_types)) + use _ <- result.map(rec_type_is_valid(ctx, rec_type)) + ctx +} + +pub fn validate_module(module: BinaryModule) { + use context <- result.try(case module.types { + Some(TypeSection(types)) -> + list.try_fold(types, empty_context, validate_type) + None -> Ok(empty_context) + }) + + Ok(context) +} diff --git a/src/internal/validation/types.gleam b/src/internal/validation/types.gleam new file mode 100644 index 0000000..9e98400 --- /dev/null +++ b/src/internal/validation/types.gleam @@ -0,0 +1,100 @@ +import gleam/list +import gleam/option.{type Option, None, Some} +import internal/structure/modules +import internal/structure/numbers +import internal/structure/types.{ + type DefType, type ExternType, type Global, type GlobalType, type Limits, + type MemType, type RecType, type RefType, type Table, type TableType, + type ValType, FuncCompositeType, FuncExternType, GlobalExternType, + HeapTypeRefType, Limits, MemExternType, RefTypeValType, TableExternType, +} +import internal/validation/common.{type Context} + +const limits_2_16 = 65_536 + +const limits_2_32_minus_1 = 4_294_967_295 + +pub fn expand(_: Context, def_type: DefType) { + let sub_types = def_type.rt.sub_types + let index = def_type.idx + case list.drop(sub_types, index) { + [] -> Error("Invalid DefType: RecType index out of bounds.") + [sub_type, ..] -> Ok(sub_type.ct) + } +} + +pub fn def_type_is_function_type(ctx: Context, def_type: DefType) { + case expand(ctx, def_type) { + Ok(FuncCompositeType(_)) -> True + _ -> False + } +} + +pub fn is_defaultable(val_type: ValType) { + case val_type { + RefTypeValType(HeapTypeRefType(_, False)) -> False + _ -> True + } +} + +pub fn extern_type_is_valid(ctx: Context, extern_type: ExternType) { + case extern_type { + FuncExternType(def_type) -> + def_type_is_valid(ctx, def_type) + && def_type_is_function_type(ctx, def_type) + TableExternType(table_type) -> table_type_is_valid(ctx, table_type) + MemExternType(mem_type) -> mem_type_is_valid(ctx, mem_type) + GlobalExternType(global_type) -> global_type_is_valid(ctx, global_type) + } +} + +pub fn global_is_valid(ctx: Context, global: Global) { + global_type_is_valid(ctx, global.type_) +} + +pub fn global_type_is_valid(ctx: Context, global_type: GlobalType) { + val_type_is_valid(ctx, global_type.vt) +} + +pub fn val_type_is_valid(ctx: Context, val_type: ValType) { + todo +} + +pub fn mem_type_is_valid(ctx: Context, mem_type: MemType) { + limits_is_valid(ctx, mem_type.limits, limits_2_16) +} + +pub fn limits_is_valid(_: Context, limits: Limits, range: Int) { + case limits { + Limits(n, None) -> { + let n = numbers.unwrap_u32(n) + n <= range + } + Limits(n, Some(m)) -> { + let n = numbers.unwrap_u32(n) + let m = numbers.unwrap_u32(m) + n <= range && m <= range && n <= m + } + } +} + +pub fn table_is_valid(ctx: Context, table: Table) { + table_type_is_valid(ctx, table.type_) +} + +pub fn table_type_is_valid(ctx: Context, table_type: TableType) { + ref_type_is_valid(ctx, table_type.t) + && limits_is_valid(ctx, table_type.limits, limits_2_32_minus_1) +} + +pub fn def_type_is_valid(ctx: Context, def_type: DefType) { + todo +} + +pub fn ref_type_is_valid(ctx: Context, ref_type: RefType) { + todo +} + +pub fn rec_type_is_valid(ctx: Context, rec_type: RecType) { + todo +} diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam new file mode 100644 index 0000000..48d68bc --- /dev/null +++ b/src/internal/visitor.gleam @@ -0,0 +1,3105 @@ +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/result.{map, try} +import internal/structure/modules.{ + type BinaryModule, type CodeSection, type CustomSection, type DataCountSection, + type DataSection, type ElementSection, type ExportSection, + type FunctionSection, type GlobalSection, type ImportSection, + type MemorySection, type StartSection, type TableSection, type TypeSection, + BinaryModule, CodeSection, DataSection, ElementSection, ExportSection, + FunctionSection, GlobalSection, ImportSection, MemorySection, StartSection, + TableSection, TypeSection, +} +import internal/structure/types.{ + type ArrayType, type BlockType, type Code, type CompositeType, type Data, + type DataIDX, type DefType, type Elem, type ElemIDX, type ElemMode, + type Export, type Expr, type FieldIDX, type FieldType, type FuncIDX, + type FuncType, type Global, type GlobalIDX, type GlobalType, type HeapType, + type Import, type Instruction, type LabelIDX, type Limits, type LocalIDX, + type Locals, type MemIDX, type MemType, type RecType, type RefType, + type StorageType, type StructType, type SubType, type Table, type TableIDX, + type TableType, type TypeIDX, type ValType, ActiveData, ActiveElemMode, + AnyHeapType, AnyRefType, ArrayCompositeType, ArrayCopy, ArrayFill, ArrayGet, + ArrayGetS, ArrayGetU, ArrayHeapType, ArrayInitData, ArrayInitElem, ArrayNew, + ArrayNewData, ArrayNewDefault, ArrayNewElem, ArrayNewFixed, ArrayRefType, + ArraySet, ArrayType, Block, Br, BrIf, BrOnCast, BrOnCastFail, BrOnNonNull, + BrOnNull, BrTable, Call, CallIndirect, CallRef, Code, ConcreteHeapType, + DataDrop, DeclarativeElemMode, DefType, DefTypeReference, ElemDrop, + ElemExpressions, ElemFuncs, EqHeapType, EqRefType, Expr, ExternHeapType, + ExternRefType, F32ValType, F64ValType, FieldType, FuncCompositeType, + FuncExport, FuncHeapType, FuncImport, FuncRefType, FuncType, FuncTypeBlockType, + Global, GlobalExport, GlobalGet, GlobalImport, GlobalSet, GlobalType, + HeapTypeRefType, I16StorageType, I31HeapType, I31RefType, I32ValType, + I64ValType, I8StorageType, If, LabelIDX, Limits, LocalGet, LocalSet, LocalTee, + Locals, Loop, MemExport, MemIDX, MemImport, MemType, MemoryInit, + NoExternHeapType, NoExternRefType, NoFuncHeapType, NoFuncRefType, NoneHeapType, + NoneRefType, PassiveData, PassiveElemMode, RecType, RecTypeIDX, RefCast, + RefCastNullable, RefFunc, RefNull, RefTest, RefTestNullable, RefTypeValType, + ReturnCall, ReturnCallIndirect, ReturnCallRef, SelectT, StructCompositeType, + StructGet, StructGetS, StructGetU, StructHeapType, StructRefType, StructSet, + StructType, SubType, Table, TableCopy, TableExport, TableFill, TableGet, + TableGrow, TableImport, TableInit, TableSet, TableSize, TableType, TypeIDX, + V128ValType, ValTypeBlockType, ValTypeStorageType, VoidBlockType, +} + +pub type VisitorCallback(ctx, element) = + fn(ctx, element) -> Result(#(ctx, element), String) + +pub const empty_visitor = BinaryModuleVisitor( + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, +) + +pub type BinaryModuleVisitor(ctx) { + BinaryModuleVisitor( + on_enter_module: Option(VisitorCallback(ctx, BinaryModule)), + on_exit_module: Option(VisitorCallback(ctx, BinaryModule)), + on_enter_custom_section: Option(VisitorCallback(ctx, Option(CustomSection))), + on_exit_custom_section: Option(VisitorCallback(ctx, Option(CustomSection))), + on_enter_type_section: Option(VisitorCallback(ctx, Option(TypeSection))), + on_exit_type_section: Option(VisitorCallback(ctx, Option(TypeSection))), + on_enter_import_section: Option(VisitorCallback(ctx, Option(ImportSection))), + on_exit_import_section: Option(VisitorCallback(ctx, Option(ImportSection))), + on_enter_table_section: Option(VisitorCallback(ctx, Option(TableSection))), + on_exit_table_section: Option(VisitorCallback(ctx, Option(TableSection))), + on_enter_memory_section: Option(VisitorCallback(ctx, Option(MemorySection))), + on_exit_memory_section: Option(VisitorCallback(ctx, Option(MemorySection))), + on_enter_start_section: Option(VisitorCallback(ctx, Option(StartSection))), + on_exit_start_section: Option(VisitorCallback(ctx, Option(StartSection))), + on_enter_element_segment: Option(VisitorCallback(ctx, Elem)), + on_exit_element_segment: Option(VisitorCallback(ctx, Elem)), + on_enter_element_section: Option( + VisitorCallback(ctx, Option(ElementSection)), + ), + on_exit_element_section: Option( + VisitorCallback(ctx, Option(ElementSection)), + ), + on_enter_import: Option(VisitorCallback(ctx, Import)), + on_exit_import: Option(VisitorCallback(ctx, Import)), + on_enter_func_import: Option(VisitorCallback(ctx, Import)), + on_exit_func_import: Option(VisitorCallback(ctx, Import)), + on_enter_table_import: Option(VisitorCallback(ctx, Import)), + on_exit_table_import: Option(VisitorCallback(ctx, Import)), + on_enter_mem_import: Option(VisitorCallback(ctx, Import)), + on_exit_mem_import: Option(VisitorCallback(ctx, Import)), + on_enter_global_import: Option(VisitorCallback(ctx, Import)), + on_exit_global_import: Option(VisitorCallback(ctx, Import)), + on_enter_table_type: Option(VisitorCallback(ctx, TableType)), + on_exit_table_type: Option(VisitorCallback(ctx, TableType)), + on_enter_table: Option(VisitorCallback(ctx, Table)), + on_exit_table: Option(VisitorCallback(ctx, Table)), + on_enter_global: Option(VisitorCallback(ctx, Global)), + on_exit_global: Option(VisitorCallback(ctx, Global)), + on_enter_global_type: Option(VisitorCallback(ctx, GlobalType)), + on_exit_global_type: Option(VisitorCallback(ctx, GlobalType)), + on_enter_mem_type: Option(VisitorCallback(ctx, MemType)), + on_exit_mem_type: Option(VisitorCallback(ctx, MemType)), + on_enter_def_type: Option(VisitorCallback(ctx, DefType)), + on_exit_def_type: Option(VisitorCallback(ctx, DefType)), + on_enter_rec_type: Option(VisitorCallback(ctx, RecType)), + on_exit_rec_type: Option(VisitorCallback(ctx, RecType)), + on_enter_sub_type: Option(VisitorCallback(ctx, SubType)), + on_exit_sub_type: Option(VisitorCallback(ctx, SubType)), + on_enter_type_idx: Option(VisitorCallback(ctx, TypeIDX)), + on_exit_type_idx: Option(VisitorCallback(ctx, TypeIDX)), + on_enter_rec_type_idx: Option(VisitorCallback(ctx, TypeIDX)), + on_exit_rec_type_idx: Option(VisitorCallback(ctx, TypeIDX)), + on_enter_def_type_reference: Option(VisitorCallback(ctx, TypeIDX)), + on_exit_def_type_reference: Option(VisitorCallback(ctx, TypeIDX)), + on_enter_comp_type: Option(VisitorCallback(ctx, CompositeType)), + on_exit_comp_type: Option(VisitorCallback(ctx, CompositeType)), + on_enter_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_exit_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_enter_func_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_exit_func_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_enter_struct_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_exit_struct_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_enter_array_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_exit_array_composite_type: Option(VisitorCallback(ctx, CompositeType)), + on_enter_func_type: Option(VisitorCallback(ctx, FuncType)), + on_enter_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_func_type: Option(VisitorCallback(ctx, FuncType)), + on_enter_v128_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_v128_val_type: Option(VisitorCallback(ctx, ValType)), + on_enter_i32_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_i32_val_type: Option(VisitorCallback(ctx, ValType)), + on_enter_i64_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_i64_val_type: Option(VisitorCallback(ctx, ValType)), + on_enter_f32_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_f32_val_type: Option(VisitorCallback(ctx, ValType)), + on_enter_f64_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_f64_val_type: Option(VisitorCallback(ctx, ValType)), + on_enter_ref_type_val_type: Option(VisitorCallback(ctx, ValType)), + on_exit_ref_type_val_type: Option(VisitorCallback(ctx, ValType)), + on_enter_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_heap_type_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_heap_type_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_any_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_any_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_eq_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_eq_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_i31_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_i31_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_struct_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_struct_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_array_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_array_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_func_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_func_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_extern_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_extern_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_none_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_none_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_no_func_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_no_func_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_no_extern_ref_type: Option(VisitorCallback(ctx, RefType)), + on_exit_no_extern_ref_type: Option(VisitorCallback(ctx, RefType)), + on_enter_struct_type: Option(VisitorCallback(ctx, StructType)), + on_exit_struct_type: Option(VisitorCallback(ctx, StructType)), + on_enter_field_type: Option(VisitorCallback(ctx, FieldType)), + on_exit_field_type: Option(VisitorCallback(ctx, FieldType)), + on_enter_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_enter_i8_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_enter_i16_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_enter_val_type_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_exit_i8_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_exit_i16_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_exit_val_type_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_exit_storage_type: Option(VisitorCallback(ctx, StorageType)), + on_enter_array_type: Option(VisitorCallback(ctx, ArrayType)), + on_exit_array_type: Option(VisitorCallback(ctx, ArrayType)), + on_enter_function_section: Option( + VisitorCallback(ctx, Option(FunctionSection)), + ), + on_exit_function_section: Option( + VisitorCallback(ctx, Option(FunctionSection)), + ), + on_enter_code_section: Option(VisitorCallback(ctx, Option(CodeSection))), + on_exit_code_section: Option(VisitorCallback(ctx, Option(CodeSection))), + on_enter_func_idx: Option(VisitorCallback(ctx, FuncIDX)), + on_exit_func_idx: Option(VisitorCallback(ctx, FuncIDX)), + on_enter_table_idx: Option(VisitorCallback(ctx, TableIDX)), + on_exit_table_idx: Option(VisitorCallback(ctx, TableIDX)), + on_enter_mem_idx: Option(VisitorCallback(ctx, MemIDX)), + on_exit_mem_idx: Option(VisitorCallback(ctx, MemIDX)), + on_enter_global_idx: Option(VisitorCallback(ctx, GlobalIDX)), + on_exit_global_idx: Option(VisitorCallback(ctx, GlobalIDX)), + on_enter_elem_expressions: Option(VisitorCallback(ctx, Elem)), + on_exit_elem_expressions: Option(VisitorCallback(ctx, Elem)), + on_enter_elem_funcs: Option(VisitorCallback(ctx, Elem)), + on_exit_elem_funcs: Option(VisitorCallback(ctx, Elem)), + on_enter_global_section: Option(VisitorCallback(ctx, Option(GlobalSection))), + on_exit_global_section: Option(VisitorCallback(ctx, Option(GlobalSection))), + on_enter_export_section: Option(VisitorCallback(ctx, Option(ExportSection))), + on_exit_export_section: Option(VisitorCallback(ctx, Option(ExportSection))), + on_enter_export: Option(VisitorCallback(ctx, Export)), + on_exit_export: Option(VisitorCallback(ctx, Export)), + on_enter_func_export: Option(VisitorCallback(ctx, Export)), + on_exit_func_export: Option(VisitorCallback(ctx, Export)), + on_enter_table_export: Option(VisitorCallback(ctx, Export)), + on_exit_table_export: Option(VisitorCallback(ctx, Export)), + on_enter_mem_export: Option(VisitorCallback(ctx, Export)), + on_exit_mem_export: Option(VisitorCallback(ctx, Export)), + on_enter_global_export: Option(VisitorCallback(ctx, Export)), + on_exit_global_export: Option(VisitorCallback(ctx, Export)), + on_enter_limits: Option(VisitorCallback(ctx, Limits)), + on_exit_limits: Option(VisitorCallback(ctx, Limits)), + on_enter_expr: Option(VisitorCallback(ctx, Expr)), + on_exit_expr: Option(VisitorCallback(ctx, Expr)), + on_enter_instruction: Option(VisitorCallback(ctx, Instruction)), + on_exit_instruction: Option(VisitorCallback(ctx, Instruction)), + on_enter_element_mode: Option(VisitorCallback(ctx, ElemMode)), + on_exit_element_mode: Option(VisitorCallback(ctx, ElemMode)), + on_enter_declarative_elem_mode: Option(VisitorCallback(ctx, ElemMode)), + on_exit_declarative_elem_mode: Option(VisitorCallback(ctx, ElemMode)), + on_enter_passive_elem_mode: Option(VisitorCallback(ctx, ElemMode)), + on_exit_passive_elem_mode: Option(VisitorCallback(ctx, ElemMode)), + on_enter_active_elem_mode: Option(VisitorCallback(ctx, ElemMode)), + on_exit_active_elem_mode: Option(VisitorCallback(ctx, ElemMode)), + on_enter_code: Option(VisitorCallback(ctx, Code)), + on_exit_code: Option(VisitorCallback(ctx, Code)), + on_enter_locals: Option(VisitorCallback(ctx, Locals)), + on_exit_locals: Option(VisitorCallback(ctx, Locals)), + on_enter_data_section: Option(VisitorCallback(ctx, Option(DataSection))), + on_exit_data_section: Option(VisitorCallback(ctx, Option(DataSection))), + on_enter_active_data: Option(VisitorCallback(ctx, Data)), + on_exit_active_data: Option(VisitorCallback(ctx, Data)), + on_enter_passive_data: Option(VisitorCallback(ctx, Data)), + on_exit_passive_data: Option(VisitorCallback(ctx, Data)), + on_enter_data: Option(VisitorCallback(ctx, Data)), + on_exit_data: Option(VisitorCallback(ctx, Data)), + on_enter_data_count_section: Option( + VisitorCallback(ctx, Option(DataCountSection)), + ), + on_exit_data_count_section: Option( + VisitorCallback(ctx, Option(DataCountSection)), + ), + on_enter_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_func_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_func_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_no_func_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_no_func_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_extern_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_extern_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_no_extern_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_no_extern_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_any_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_any_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_eq_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_eq_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_i31_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_i31_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_struct_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_struct_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_array_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_array_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_none_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_none_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_concrete_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_exit_concrete_heap_type: Option(VisitorCallback(ctx, HeapType)), + on_enter_ref_null: Option(VisitorCallback(ctx, Instruction)), + on_exit_ref_null: Option(VisitorCallback(ctx, Instruction)), + on_enter_ref_func: Option(VisitorCallback(ctx, Instruction)), + on_exit_ref_func: Option(VisitorCallback(ctx, Instruction)), + on_enter_ref_test: Option(VisitorCallback(ctx, Instruction)), + on_exit_ref_test: Option(VisitorCallback(ctx, Instruction)), + on_enter_ref_test_nullable: Option(VisitorCallback(ctx, Instruction)), + on_exit_ref_test_nullable: Option(VisitorCallback(ctx, Instruction)), + on_enter_ref_cast: Option(VisitorCallback(ctx, Instruction)), + on_exit_ref_cast: Option(VisitorCallback(ctx, Instruction)), + on_enter_ref_cast_nullable: Option(VisitorCallback(ctx, Instruction)), + on_exit_ref_cast_nullable: Option(VisitorCallback(ctx, Instruction)), + on_enter_struct_get: Option(VisitorCallback(ctx, Instruction)), + on_exit_struct_get: Option(VisitorCallback(ctx, Instruction)), + on_enter_struct_get_s: Option(VisitorCallback(ctx, Instruction)), + on_exit_struct_get_s: Option(VisitorCallback(ctx, Instruction)), + on_enter_struct_get_u: Option(VisitorCallback(ctx, Instruction)), + on_exit_struct_get_u: Option(VisitorCallback(ctx, Instruction)), + on_enter_struct_set: Option(VisitorCallback(ctx, Instruction)), + on_exit_struct_set: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_new: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_new: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_new_default: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_new_default: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_new_data: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_new_data: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_new_elem: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_new_elem: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_new_fixed: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_new_fixed: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_get: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_get: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_get_s: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_get_s: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_get_u: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_get_u: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_set: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_set: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_fill: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_fill: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_copy: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_copy: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_init_data: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_init_data: Option(VisitorCallback(ctx, Instruction)), + on_enter_array_init_elem: Option(VisitorCallback(ctx, Instruction)), + on_exit_array_init_elem: Option(VisitorCallback(ctx, Instruction)), + on_enter_select_t: Option(VisitorCallback(ctx, Instruction)), + on_exit_select_t: Option(VisitorCallback(ctx, Instruction)), + on_enter_local_get: Option(VisitorCallback(ctx, Instruction)), + on_exit_local_get: Option(VisitorCallback(ctx, Instruction)), + on_enter_local_set: Option(VisitorCallback(ctx, Instruction)), + on_exit_local_set: Option(VisitorCallback(ctx, Instruction)), + on_enter_local_tee: Option(VisitorCallback(ctx, Instruction)), + on_exit_local_tee: Option(VisitorCallback(ctx, Instruction)), + on_enter_global_get: Option(VisitorCallback(ctx, Instruction)), + on_exit_global_get: Option(VisitorCallback(ctx, Instruction)), + on_enter_global_set: Option(VisitorCallback(ctx, Instruction)), + on_exit_global_set: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_get: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_get: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_set: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_set: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_size: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_size: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_grow: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_grow: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_fill: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_fill: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_copy: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_copy: Option(VisitorCallback(ctx, Instruction)), + on_enter_table_init: Option(VisitorCallback(ctx, Instruction)), + on_exit_table_init: Option(VisitorCallback(ctx, Instruction)), + on_enter_elem_drop: Option(VisitorCallback(ctx, Instruction)), + on_exit_elem_drop: Option(VisitorCallback(ctx, Instruction)), + on_enter_memory_init: Option(VisitorCallback(ctx, Instruction)), + on_exit_memory_init: Option(VisitorCallback(ctx, Instruction)), + on_enter_data_drop: Option(VisitorCallback(ctx, Instruction)), + on_exit_data_drop: Option(VisitorCallback(ctx, Instruction)), + on_enter_block: Option(VisitorCallback(ctx, Instruction)), + on_exit_block: Option(VisitorCallback(ctx, Instruction)), + on_enter_loop: Option(VisitorCallback(ctx, Instruction)), + on_exit_loop: Option(VisitorCallback(ctx, Instruction)), + on_enter_if: Option(VisitorCallback(ctx, Instruction)), + on_exit_if: Option(VisitorCallback(ctx, Instruction)), + on_enter_br: Option(VisitorCallback(ctx, Instruction)), + on_exit_br: Option(VisitorCallback(ctx, Instruction)), + on_enter_br_if: Option(VisitorCallback(ctx, Instruction)), + on_exit_br_if: Option(VisitorCallback(ctx, Instruction)), + on_enter_br_table: Option(VisitorCallback(ctx, Instruction)), + on_exit_br_table: Option(VisitorCallback(ctx, Instruction)), + on_enter_br_on_null: Option(VisitorCallback(ctx, Instruction)), + on_exit_br_on_null: Option(VisitorCallback(ctx, Instruction)), + on_enter_br_on_non_null: Option(VisitorCallback(ctx, Instruction)), + on_exit_br_on_non_null: Option(VisitorCallback(ctx, Instruction)), + on_enter_br_on_cast: Option(VisitorCallback(ctx, Instruction)), + on_exit_br_on_cast: Option(VisitorCallback(ctx, Instruction)), + on_enter_br_on_cast_fail: Option(VisitorCallback(ctx, Instruction)), + on_exit_br_on_cast_fail: Option(VisitorCallback(ctx, Instruction)), + on_enter_call: Option(VisitorCallback(ctx, Instruction)), + on_exit_call: Option(VisitorCallback(ctx, Instruction)), + on_enter_call_ref: Option(VisitorCallback(ctx, Instruction)), + on_exit_call_ref: Option(VisitorCallback(ctx, Instruction)), + on_enter_call_indirect: Option(VisitorCallback(ctx, Instruction)), + on_exit_call_indirect: Option(VisitorCallback(ctx, Instruction)), + on_enter_return_call: Option(VisitorCallback(ctx, Instruction)), + on_exit_return_call: Option(VisitorCallback(ctx, Instruction)), + on_enter_return_call_ref: Option(VisitorCallback(ctx, Instruction)), + on_exit_return_call_ref: Option(VisitorCallback(ctx, Instruction)), + on_enter_return_call_indirect: Option(VisitorCallback(ctx, Instruction)), + on_exit_return_call_indirect: Option(VisitorCallback(ctx, Instruction)), + on_enter_label_idx: Option(VisitorCallback(ctx, LabelIDX)), + on_exit_label_idx: Option(VisitorCallback(ctx, LabelIDX)), + on_enter_block_type: Option(VisitorCallback(ctx, BlockType)), + on_exit_block_type: Option(VisitorCallback(ctx, BlockType)), + on_enter_void_block_type: Option(VisitorCallback(ctx, BlockType)), + on_exit_void_block_type: Option(VisitorCallback(ctx, BlockType)), + on_enter_val_type_block_type: Option(VisitorCallback(ctx, BlockType)), + on_exit_val_type_block_type: Option(VisitorCallback(ctx, BlockType)), + on_enter_func_type_block_type: Option(VisitorCallback(ctx, BlockType)), + on_exit_func_type_block_type: Option(VisitorCallback(ctx, BlockType)), + on_enter_field_idx: Option(VisitorCallback(ctx, FieldIDX)), + on_exit_field_idx: Option(VisitorCallback(ctx, FieldIDX)), + on_enter_data_idx: Option(VisitorCallback(ctx, DataIDX)), + on_exit_data_idx: Option(VisitorCallback(ctx, DataIDX)), + on_enter_elem_idx: Option(VisitorCallback(ctx, ElemIDX)), + on_exit_elem_idx: Option(VisitorCallback(ctx, ElemIDX)), + on_enter_local_idx: Option(VisitorCallback(ctx, LocalIDX)), + on_exit_local_idx: Option(VisitorCallback(ctx, LocalIDX)), + ) +} + +pub fn do_visit_module( + ctx: context, + module: BinaryModule, + visitor: BinaryModuleVisitor(context), +) { + let BinaryModuleVisitor( + on_enter_module: on_enter, + on_exit_module: on_exit, + .., + ) = visitor + + use #(ctx, module) <- try(case on_enter { + Some(f) -> f(ctx, module) + None -> Ok(#(ctx, module)) + }) + + use #(ctx, custom_0) <- result.try(do_visit_custom_sections( + ctx, + module.custom_0, + visitor, + )) + use #(ctx, types) <- result.try(do_visit_type_section( + ctx, + module.types, + visitor, + )) + use #(ctx, custom_1) <- result.try(do_visit_custom_sections( + ctx, + module.custom_1, + visitor, + )) + use #(ctx, imports) <- result.try(do_visit_import_section( + ctx, + module.imports, + visitor, + )) + use #(ctx, custom_2) <- result.try(do_visit_custom_sections( + ctx, + module.custom_2, + visitor, + )) + use #(ctx, functions) <- result.try(do_visit_function_section( + ctx, + module.functions, + visitor, + )) + use #(ctx, custom_3) <- result.try(do_visit_custom_sections( + ctx, + module.custom_3, + visitor, + )) + use #(ctx, tables) <- result.try(do_visit_table_section( + ctx, + module.tables, + visitor, + )) + use #(ctx, custom_4) <- result.try(do_visit_custom_sections( + ctx, + module.custom_4, + visitor, + )) + use #(ctx, memories) <- result.try(do_visit_memory_section( + ctx, + module.memories, + visitor, + )) + use #(ctx, custom_5) <- result.try(do_visit_custom_sections( + ctx, + module.custom_5, + visitor, + )) + use #(ctx, globals) <- result.try(do_visit_global_section( + ctx, + module.globals, + visitor, + )) + use #(ctx, custom_6) <- result.try(do_visit_custom_sections( + ctx, + module.custom_6, + visitor, + )) + use #(ctx, exports) <- result.try(do_visit_export_section( + ctx, + module.exports, + visitor, + )) + use #(ctx, custom_7) <- result.try(do_visit_custom_sections( + ctx, + module.custom_7, + visitor, + )) + use #(ctx, start) <- result.try(do_visit_start_section( + ctx, + module.start, + visitor, + )) + use #(ctx, custom_8) <- result.try(do_visit_custom_sections( + ctx, + module.custom_8, + visitor, + )) + use #(ctx, elements) <- result.try(do_visit_element_section( + ctx, + module.elements, + visitor, + )) + use #(ctx, custom_9) <- result.try(do_visit_custom_sections( + ctx, + module.custom_9, + visitor, + )) + use #(ctx, code) <- result.try(do_visit_code_section( + ctx, + module.code, + visitor, + )) + use #(ctx, custom_10) <- result.try(do_visit_custom_sections( + ctx, + module.custom_10, + visitor, + )) + use #(ctx, data) <- result.try(do_visit_data_section( + ctx, + module.data, + visitor, + )) + use #(ctx, custom_11) <- result.try(do_visit_custom_sections( + ctx, + module.custom_11, + visitor, + )) + use #(ctx, data_count) <- result.try(do_visit_data_count_section( + ctx, + module.data_count, + visitor, + )) + use #(ctx, custom_12) <- result.try(do_visit_custom_sections( + ctx, + module.custom_12, + visitor, + )) + + let module = + BinaryModule( + custom_0: custom_0, + types: types, + custom_1: custom_1, + imports: imports, + custom_2: custom_2, + functions: functions, + custom_3: custom_3, + tables: tables, + custom_4: custom_4, + memories: memories, + custom_5: custom_5, + globals: globals, + custom_6: custom_6, + exports: exports, + custom_7: custom_7, + start: start, + custom_8: custom_8, + elements: elements, + custom_9: custom_9, + code: code, + custom_10: custom_10, + data: data, + custom_11: custom_11, + data_count: data_count, + custom_12: custom_12, + ) + case on_exit { + Some(f) -> f(ctx, module) + None -> Ok(#(ctx, module)) + } +} + +fn do_visit(ctx, element, visitor: Option(VisitorCallback(ctx, element))) { + case visitor { + Some(f) -> f(ctx, element) + None -> Ok(#(ctx, element)) + } +} + +fn do_visit_element_list( + ctx, + elements: List(element), + visitor: BinaryModuleVisitor(ctx), + do_visit_callback: fn(ctx, element, BinaryModuleVisitor(ctx)) -> + Result(#(ctx, element), String), +) { + use #(ctx, elements, _) <- map( + list.try_fold(elements, #(ctx, [], visitor), fn(acc, element) { + let #(ctx, acc, visitor) = acc + use #(ctx, element) <- map(do_visit_callback(ctx, element, visitor)) + #(ctx, [element, ..acc], visitor) + }), + ) + #(ctx, elements |> list.reverse) +} + +pub fn do_visit_type_section( + ctx, + type_section: Option(TypeSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(TypeSection)), String) { + use #(ctx, type_section) <- enter( + ctx, + type_section, + visitor.on_enter_type_section, + visitor.on_exit_type_section, + ) + + case type_section { + Some(TypeSection(types)) -> { + use #(ctx, types) <- map(do_visit_element_list( + ctx, + types, + visitor, + do_visit_rec_type, + )) + #(ctx, Some(TypeSection(types))) + } + None -> Ok(#(ctx, None)) + } +} + +pub fn do_visit_rec_type( + ctx, + rec_type: RecType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, RecType), String) { + use #(ctx, rec_type) <- enter( + ctx, + rec_type, + visitor.on_enter_rec_type, + visitor.on_exit_rec_type, + ) + use #(ctx, sub_types) <- map(do_visit_element_list( + ctx, + rec_type.sub_types, + visitor, + do_visit_sub_type, + )) + #(ctx, RecType(sub_types)) +} + +pub fn do_visit_sub_type( + ctx, + sub_type, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, SubType), String) { + use #(ctx, SubType(final, t, ct)) <- enter( + ctx, + sub_type, + visitor.on_enter_sub_type, + visitor.on_exit_sub_type, + ) + use #(ctx, t) <- try(do_visit_element_list(ctx, t, visitor, do_visit_type_idx)) + use #(ctx, ct) <- map(do_visit_composite_type(ctx, ct, visitor)) + #(ctx, SubType(final, t, ct)) +} + +pub fn do_visit_type_idx( + ctx, + type_idx: TypeIDX, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, TypeIDX), String) { + use #(ctx, type_idx) <- enter( + ctx, + type_idx, + visitor.on_enter_type_idx, + visitor.on_exit_type_idx, + ) + + case type_idx { + TypeIDX(_) -> Ok(#(ctx, type_idx)) + RecTypeIDX(_) -> + enter( + ctx, + type_idx, + visitor.on_enter_rec_type_idx, + visitor.on_exit_rec_type_idx, + Ok, + ) + DefTypeReference(_) -> + enter( + ctx, + type_idx, + visitor.on_enter_def_type_reference, + visitor.on_exit_def_type_reference, + Ok, + ) + } +} + +pub fn do_visit_composite_type( + ctx, + composite_type: CompositeType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, CompositeType), String) { + use #(ctx, composite_type) <- enter( + ctx, + composite_type, + visitor.on_enter_composite_type, + visitor.on_exit_composite_type, + ) + + use #(ctx, composite_type) <- + case composite_type { + FuncCompositeType(_) -> enter( + ctx, + composite_type, + visitor.on_enter_func_composite_type, + visitor.on_exit_func_composite_type, + _, + ) + StructCompositeType(_) -> enter( + ctx, + composite_type, + visitor.on_enter_struct_composite_type, + visitor.on_exit_struct_composite_type, + _, + ) + ArrayCompositeType(_) -> enter( + ctx, + composite_type, + visitor.on_enter_array_composite_type, + visitor.on_exit_array_composite_type, + _, + ) + } + + case composite_type { + FuncCompositeType(func_type) -> { + use #(ctx, func_type) <- map(do_visit_func_type(ctx, func_type, visitor)) + #(ctx, FuncCompositeType(func_type)) + } + StructCompositeType(struct_type) -> { + use #(ctx, struct_type) <- map(do_visit_struct_type( + ctx, + struct_type, + visitor, + )) + #(ctx, StructCompositeType(struct_type)) + } + ArrayCompositeType(array_type) -> { + use #(ctx, array_type) <- map(do_visit_array_type( + ctx, + array_type, + visitor, + )) + #(ctx, ArrayCompositeType(array_type)) + } + } +} + +pub fn do_visit_def_type( + ctx, + def_type: DefType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, DefType), String) { + use #(ctx, DefType(rec_type, idx)) <- enter( + ctx, + def_type, + visitor.on_enter_def_type, + visitor.on_exit_def_type, + ) + + use #(ctx, rec_type) <- map(do_visit_rec_type(ctx, rec_type, visitor)) + + #(ctx, DefType(rec_type, idx)) +} + +pub fn do_visit_func_type( + ctx, + func_type: FuncType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, FuncType), String) { + use #(ctx, FuncType(parameters, results)) <- enter( + ctx, + func_type, + visitor.on_enter_func_type, + visitor.on_exit_func_type, + ) + + use #(ctx, parameters) <- try(do_visit_element_list( + ctx, + parameters, + visitor, + do_visit_val_type, + )) + + use #(ctx, results) <- map(do_visit_element_list( + ctx, + results, + visitor, + do_visit_val_type, + )) + + #(ctx, FuncType(parameters, results)) +} + +pub fn do_visit_val_type( + ctx, + val_type: ValType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, ValType), String) { + use #(ctx, val_type) <- enter( + ctx, + val_type, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + ) + + use #(ctx, val_type) <- + case val_type { + V128ValType -> enter( + ctx, + val_type, + visitor.on_enter_v128_val_type, + visitor.on_exit_v128_val_type, + _, + ) + I32ValType -> enter( + ctx, + val_type, + visitor.on_enter_i32_val_type, + visitor.on_exit_i32_val_type, + _, + ) + I64ValType -> enter( + ctx, + val_type, + visitor.on_enter_i64_val_type, + visitor.on_exit_i64_val_type, + _, + ) + F32ValType -> enter( + ctx, + val_type, + visitor.on_enter_f32_val_type, + visitor.on_exit_f32_val_type, + _, + ) + F64ValType -> enter( + ctx, + val_type, + visitor.on_enter_f64_val_type, + visitor.on_exit_f64_val_type, + _, + ) + RefTypeValType(_) -> enter( + ctx, + val_type, + visitor.on_enter_ref_type_val_type, + visitor.on_exit_ref_type_val_type, + _, + ) + _ -> try(Ok(#(ctx, val_type)), _) + } + + case val_type { + RefTypeValType(rt) -> { + use #(ctx, rt) <- map(do_visit_ref_type(ctx, rt, visitor)) + + #(ctx, RefTypeValType(rt)) + } + _ -> Ok(#(ctx, val_type)) + } +} + +pub fn do_visit_ref_type( + ctx, + ref_type: RefType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, RefType), String) { + use #(ctx, ref_type) <- enter( + ctx, + ref_type, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + ) + + use #(ctx, ref_type) <- + case ref_type { + HeapTypeRefType(_, _) -> enter( + ctx, + ref_type, + visitor.on_enter_heap_type_ref_type, + visitor.on_exit_heap_type_ref_type, + _, + ) + AnyRefType -> enter( + ctx, + ref_type, + visitor.on_enter_any_ref_type, + visitor.on_exit_any_ref_type, + _, + ) + EqRefType -> enter( + ctx, + ref_type, + visitor.on_enter_eq_ref_type, + visitor.on_exit_eq_ref_type, + _, + ) + I31RefType -> enter( + ctx, + ref_type, + visitor.on_enter_i31_ref_type, + visitor.on_exit_i31_ref_type, + _, + ) + StructRefType -> enter( + ctx, + ref_type, + visitor.on_enter_struct_ref_type, + visitor.on_exit_struct_ref_type, + _, + ) + ArrayRefType -> enter( + ctx, + ref_type, + visitor.on_enter_array_ref_type, + visitor.on_exit_array_ref_type, + _, + ) + FuncRefType -> enter( + ctx, + ref_type, + visitor.on_enter_func_ref_type, + visitor.on_exit_func_ref_type, + _, + ) + ExternRefType -> enter( + ctx, + ref_type, + visitor.on_enter_extern_ref_type, + visitor.on_exit_extern_ref_type, + _, + ) + NoneRefType -> enter( + ctx, + ref_type, + visitor.on_enter_none_ref_type, + visitor.on_exit_none_ref_type, + _, + ) + NoFuncRefType -> enter( + ctx, + ref_type, + visitor.on_enter_no_func_ref_type, + visitor.on_exit_no_func_ref_type, + _, + ) + NoExternRefType -> enter( + ctx, + ref_type, + visitor.on_enter_no_extern_ref_type, + visitor.on_exit_no_extern_ref_type, + _, + ) + } + case ref_type { + HeapTypeRefType(ht, mut) -> { + use #(ctx, ht) <- map(do_visit_heap_type(ctx, ht, visitor)) + #(ctx, HeapTypeRefType(ht, mut)) + } + _ -> Ok(#(ctx, ref_type)) + } +} + +pub fn do_visit_struct_type( + ctx, + struct_type: StructType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, StructType), String) { + use #(ctx, StructType(fields)) <- enter( + ctx, + struct_type, + visitor.on_enter_struct_type, + visitor.on_exit_struct_type, + ) + + use #(ctx, fields) <- map(do_visit_element_list( + ctx, + fields, + visitor, + do_visit_field_type, + )) + #(ctx, StructType(fields)) +} + +pub fn do_visit_array_type( + ctx, + array_type: ArrayType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, ArrayType), String) { + use #(ctx, ArrayType(field_type)) <- enter( + ctx, + array_type, + visitor.on_enter_array_type, + visitor.on_exit_array_type, + ) + + use #(ctx, field_type) <- map(do_visit_field_type(ctx, field_type, visitor)) + #(ctx, ArrayType(field_type)) +} + +pub fn do_visit_custom_sections( + ctx, + custom_sections: Option(List(CustomSection)), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(List(CustomSection))), String) { + case custom_sections { + Some(custom_sections) -> + do_visit_custom_sections_filter(ctx, custom_sections, [], visitor) + _ -> Ok(#(ctx, custom_sections)) + } +} + +fn do_visit_custom_sections_filter( + ctx, + custom_sections: List(CustomSection), + acc: List(CustomSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(List(CustomSection))), String) { + case custom_sections { + [] -> Ok(#(ctx, Some(acc))) + [custom_section, ..custom_sections] -> { + use #(ctx, optional_custom_section) <- try(do_visit_custom_section( + ctx, + custom_section, + visitor, + )) + + case optional_custom_section { + Some(custom_section) -> + do_visit_custom_sections_filter( + ctx, + custom_sections, + [custom_section, ..acc], + visitor, + ) + None -> + do_visit_custom_sections_filter(ctx, custom_sections, acc, visitor) + } + } + } +} + +pub fn do_visit_custom_section( + ctx, + custom_section: CustomSection, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(CustomSection)), String) { + enter( + ctx, + Some(custom_section), + visitor.on_enter_custom_section, + visitor.on_exit_custom_section, + Ok, + ) +} + +pub fn do_visit_import_section( + ctx, + import_section: Option(ImportSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(ImportSection)), String) { + use #(ctx, import_section) <- enter( + ctx, + import_section, + visitor.on_enter_import_section, + visitor.on_exit_import_section, + ) + + case import_section { + Some(ImportSection(imports)) -> { + use #(ctx, imports) <- map(do_visit_element_list( + ctx, + imports, + visitor, + do_visit_import, + )) + #(ctx, Some(ImportSection(imports))) + } + _ -> Ok(#(ctx, import_section)) + } +} + +pub fn do_visit_import(ctx, import_: Import, visitor: BinaryModuleVisitor(ctx)) { + use #(ctx, import_) <- enter( + ctx, + import_, + visitor.on_enter_import, + visitor.on_exit_import, + ) + + use #(ctx, import_) <- + case import_ { + FuncImport(_, _, _) -> enter( + ctx, + import_, + visitor.on_enter_func_import, + visitor.on_exit_func_import, + _, + ) + TableImport(_, _, _) -> enter( + ctx, + import_, + visitor.on_enter_table_import, + visitor.on_exit_table_import, + _, + ) + MemImport(_, _, _) -> enter( + ctx, + import_, + visitor.on_enter_mem_import, + visitor.on_exit_mem_import, + _, + ) + GlobalImport(_, _, _) -> enter( + ctx, + import_, + visitor.on_enter_global_import, + visitor.on_exit_global_import, + _, + ) + } + case import_ { + FuncImport(mod, name, type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, FuncImport(mod, name, type_idx)) + } + TableImport(mod, name, table_type) -> { + use #(ctx, table_type) <- map(do_visit_table_type( + ctx, + table_type, + visitor, + )) + #(ctx, TableImport(mod, name, table_type)) + } + MemImport(mod, name, mem_type) -> { + use #(ctx, mem_type) <- map(do_visit_mem_type(ctx, mem_type, visitor)) + #(ctx, MemImport(mod, name, mem_type)) + } + GlobalImport(mod, name, global_type) -> { + use #(ctx, global_type) <- map(do_visit_global_type( + ctx, + global_type, + visitor, + )) + #(ctx, GlobalImport(mod, name, global_type)) + } + } +} + +pub fn do_visit_function_section( + ctx, + section: Option(FunctionSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(FunctionSection)), String) { + use #(ctx, section) <- enter( + ctx, + section, + visitor.on_enter_function_section, + visitor.on_exit_function_section, + ) + case section { + Some(FunctionSection(indexes)) -> { + use #(ctx, indices) <- map(do_visit_element_list( + ctx, + indexes, + visitor, + do_visit_type_idx, + )) + #(ctx, Some(FunctionSection(indices))) + } + _ -> Ok(#(ctx, section)) + } +} + +pub fn do_visit_table_section( + ctx, + table_section: Option(TableSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(TableSection)), String) { + use #(ctx, table_section) <- enter( + ctx, + table_section, + visitor.on_enter_table_section, + visitor.on_exit_table_section, + ) + + case table_section { + Some(TableSection(tables)) -> { + use #(ctx, tables) <- map(do_visit_element_list( + ctx, + tables, + visitor, + do_visit_table, + )) + #(ctx, Some(TableSection(tables))) + } + _ -> Ok(#(ctx, table_section)) + } +} + +pub fn do_visit_memory_section( + ctx, + memories: Option(MemorySection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(MemorySection)), String) { + use #(ctx, memories) <- enter( + ctx, + memories, + visitor.on_enter_memory_section, + visitor.on_exit_memory_section, + ) + case memories { + Some(MemorySection(memories)) -> { + use #(ctx, memories) <- map(do_visit_element_list( + ctx, + memories, + visitor, + do_visit_mem_type, + )) + #(ctx, Some(MemorySection(memories))) + } + _ -> Ok(#(ctx, memories)) + } +} + +pub fn do_visit_global_section( + ctx, + globals: Option(GlobalSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(GlobalSection)), String) { + use #(ctx, globals) <- enter( + ctx, + globals, + visitor.on_enter_global_section, + visitor.on_exit_global_section, + ) + case globals { + Some(GlobalSection(globals)) -> { + use #(ctx, globals) <- map(do_visit_element_list( + ctx, + globals, + visitor, + do_visit_global, + )) + #(ctx, Some(GlobalSection(globals))) + } + _ -> Ok(#(ctx, globals)) + } +} + +pub fn do_visit_global(ctx, global: Global, visitor: BinaryModuleVisitor(ctx)) { + use #(ctx, Global(global_type, init)) <- enter( + ctx, + global, + visitor.on_enter_global, + visitor.on_exit_global, + ) + + use #(ctx, global_type) <- try(do_visit_global_type(ctx, global_type, visitor)) + use #(ctx, init) <- map(do_visit_expr(ctx, init, visitor)) + + #(ctx, Global(global_type, init)) +} + +pub fn do_visit_export_section( + ctx, + exports: Option(ExportSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(ExportSection)), String) { + use #(ctx, exports) <- enter( + ctx, + exports, + visitor.on_enter_export_section, + visitor.on_exit_export_section, + ) + + case exports { + Some(ExportSection(exports)) -> { + use #(ctx, exports) <- map(do_visit_element_list( + ctx, + exports, + visitor, + do_visit_export, + )) + #(ctx, Some(ExportSection(exports))) + } + _ -> Ok(#(ctx, exports)) + } +} + +pub fn do_visit_export(ctx, export: Export, visitor: BinaryModuleVisitor(ctx)) { + use #(ctx, export) <- enter( + ctx, + export, + visitor.on_enter_export, + visitor.on_exit_export, + ) + + use #(ctx, export) <- + case export { + FuncExport(_, _) -> enter( + ctx, + export, + visitor.on_enter_func_export, + visitor.on_exit_func_export, + _, + ) + TableExport(_, _) -> enter( + ctx, + export, + visitor.on_enter_table_export, + visitor.on_exit_table_export, + _, + ) + MemExport(_, _) -> enter( + ctx, + export, + visitor.on_enter_mem_export, + visitor.on_exit_mem_export, + _, + ) + GlobalExport(_, _) -> enter( + ctx, + export, + visitor.on_enter_global_export, + visitor.on_exit_global_export, + _, + ) + } + + case export { + FuncExport(name, func_idx) -> { + use #(ctx, func_idx) <- map(do_visit_func_idx(ctx, func_idx, visitor)) + #(ctx, FuncExport(name, func_idx)) + } + TableExport(name, table_idx) -> { + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableExport(name, table_idx)) + } + MemExport(name, mem_idx) -> { + use #(ctx, mem_idx) <- map(do_visit_mem_idx(ctx, mem_idx, visitor)) + #(ctx, MemExport(name, mem_idx)) + } + GlobalExport(name, global_idx) -> { + use #(ctx, global_idx) <- map(do_visit_global_idx( + ctx, + global_idx, + visitor, + )) + #(ctx, GlobalExport(name, global_idx)) + } + } +} + +pub fn do_visit_start_section( + ctx, + start_section: Option(StartSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(StartSection)), String) { + use #(ctx, start_section) <- enter( + ctx, + start_section, + visitor.on_enter_start_section, + visitor.on_exit_start_section, + ) + + case start_section { + Some(StartSection(func_idx)) -> { + use #(ctx, func_idx) <- map(do_visit_func_idx(ctx, func_idx, visitor)) + #(ctx, Some(StartSection(func_idx))) + } + _ -> Ok(#(ctx, start_section)) + } +} + +pub fn do_visit_element_section( + ctx, + elements: Option(ElementSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(ElementSection)), String) { + use #(ctx, elements) <- enter( + ctx, + elements, + visitor.on_enter_element_section, + visitor.on_exit_element_section, + ) + + case elements { + Some(ElementSection(elements)) -> { + use #(ctx, elements) <- map(do_visit_element_list( + ctx, + elements, + visitor, + do_visit_element_segment, + )) + #(ctx, Some(ElementSection(elements))) + } + _ -> Ok(#(ctx, elements)) + } +} + +pub fn do_visit_element_segment( + ctx, + element_segment: Elem, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Elem), String) { + use #(ctx, element_segment) <- enter( + ctx, + element_segment, + visitor.on_enter_element_segment, + visitor.on_exit_element_segment, + ) + + use #(ctx, element_segment) <- + case element_segment { + ElemFuncs(_, _, _) -> enter( + ctx, + element_segment, + visitor.on_enter_elem_funcs, + visitor.on_exit_elem_funcs, + _, + ) + ElemExpressions(_, _, _) -> enter( + ctx, + element_segment, + visitor.on_enter_elem_expressions, + visitor.on_exit_elem_expressions, + _, + ) + } + + case element_segment { + ElemExpressions(ref_type, exprs, mode) -> { + use #(ctx, ref_type) <- try(do_visit_ref_type(ctx, ref_type, visitor)) + use #(ctx, exprs) <- try(do_visit_element_list( + ctx, + exprs, + visitor, + do_visit_expr, + )) + use #(ctx, mode) <- map(do_visit_element_mode(ctx, mode, visitor)) + + #(ctx, ElemExpressions(ref_type, exprs, mode)) + } + ElemFuncs(ref_type, func_idxs, mode) -> { + use #(ctx, ref_type) <- try(do_visit_ref_type(ctx, ref_type, visitor)) + use #(ctx, func_idxs) <- try(do_visit_element_list( + ctx, + func_idxs, + visitor, + do_visit_func_idx, + )) + use #(ctx, mode) <- map(do_visit_element_mode(ctx, mode, visitor)) + + #(ctx, ElemFuncs(ref_type, func_idxs, mode)) + } + } +} + +pub fn do_visit_element_mode( + ctx, + mode: ElemMode, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, ElemMode), String) { + use #(ctx, mode) <- enter( + ctx, + mode, + visitor.on_enter_element_mode, + visitor.on_exit_element_mode, + ) + + case mode { + DeclarativeElemMode -> enter( + ctx, + mode, + visitor.on_enter_declarative_elem_mode, + visitor.on_exit_declarative_elem_mode, + _, + ) + PassiveElemMode -> enter( + ctx, + mode, + visitor.on_enter_passive_elem_mode, + visitor.on_exit_passive_elem_mode, + _, + ) + ActiveElemMode(_, _) -> enter( + ctx, + mode, + visitor.on_enter_active_elem_mode, + visitor.on_exit_active_elem_mode, + _, + ) + } + + case mode { + ActiveElemMode(table_idx, offset) -> { + use #(ctx, table_idx) <- try(do_visit_table_idx(ctx, table_idx, visitor)) + use #(ctx, offset) <- map(do_visit_expr(ctx, offset, visitor)) + #(ctx, ActiveElemMode(table_idx, offset)) + } + _ -> Ok(#(ctx, mode)) + } +} + +pub fn do_visit_code_section( + ctx, + code: Option(CodeSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(CodeSection)), String) { + use #(ctx, code) <- enter( + ctx, + code, + visitor.on_enter_code_section, + visitor.on_exit_code_section, + ) + + case code { + Some(CodeSection(code)) -> { + use #(ctx, codes) <- map(do_visit_element_list( + ctx, + code, + visitor, + do_visit_code, + )) + #(ctx, Some(CodeSection(codes))) + } + _ -> Ok(#(ctx, code)) + } +} + +pub fn do_visit_code( + ctx, + code: Code, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Code), String) { + use #(ctx, Code(locals, body)) <- enter( + ctx, + code, + visitor.on_enter_code, + visitor.on_exit_code, + ) + + use #(ctx, locals) <- try(do_visit_element_list( + ctx, + locals, + visitor, + do_visit_locals, + )) + + use #(ctx, body) <- map(do_visit_expr(ctx, body, visitor)) + + #(ctx, Code(locals, body)) +} + +pub fn do_visit_locals( + ctx, + locals: Locals, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Locals), String) { + use #(ctx, Locals(count, val_type)) <- enter( + ctx, + locals, + visitor.on_enter_locals, + visitor.on_exit_locals, + ) + + use #(ctx, val_type) <- map(do_visit_val_type(ctx, val_type, visitor)) + + #(ctx, Locals(count, val_type)) +} + +pub fn do_visit_data_section( + ctx, + data_section: Option(DataSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(DataSection)), String) { + use #(ctx, data_section) <- enter( + ctx, + data_section, + visitor.on_enter_data_section, + visitor.on_exit_data_section, + ) + + case data_section { + Some(DataSection(data_segments)) -> { + use #(ctx, data_segments) <- map(do_visit_element_list( + ctx, + data_segments, + visitor, + do_visit_data, + )) + #(ctx, Some(DataSection(data_segments))) + } + _ -> Ok(#(ctx, data_section)) + } +} + +pub fn do_visit_data( + ctx, + data: Data, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Data), String) { + use #(ctx, data) <- enter( + ctx, + data, + visitor.on_enter_data, + visitor.on_exit_data, + ) + + use #(ctx, data) <- + case data { + ActiveData(_, _, _) -> enter( + ctx, + data, + visitor.on_enter_active_data, + visitor.on_exit_active_data, + _, + ) + PassiveData(_) -> enter( + ctx, + data, + visitor.on_enter_passive_data, + visitor.on_exit_passive_data, + _, + ) + } + + case data { + ActiveData(mem_idx, offset, init) -> { + use #(ctx, mem_idx) <- try(do_visit_mem_idx(ctx, mem_idx, visitor)) + use #(ctx, offset) <- map(do_visit_expr(ctx, offset, visitor)) + #(ctx, ActiveData(mem_idx, offset, init)) + } + PassiveData(_) -> Ok(#(ctx, data)) + } +} + +pub fn do_visit_data_count_section( + ctx, + data_count_section: Option(DataCountSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(DataCountSection)), String) { + enter( + ctx, + data_count_section, + visitor.on_enter_data_count_section, + visitor.on_exit_data_count_section, + Ok, + ) +} + +pub fn do_visit_heap_type( + ctx, + heap_type: HeapType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, HeapType), String) { + use #(ctx, heap_type) <- enter( + ctx, + heap_type, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + ) + + use #(ctx, heap_type) <- + case heap_type { + FuncHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_func_heap_type, + visitor.on_exit_func_heap_type, + _, + ) + NoFuncHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_no_func_heap_type, + visitor.on_exit_no_func_heap_type, + _, + ) + ExternHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_extern_heap_type, + visitor.on_exit_extern_heap_type, + _, + ) + NoExternHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_no_extern_heap_type, + visitor.on_exit_no_extern_heap_type, + _, + ) + AnyHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_any_heap_type, + visitor.on_exit_any_heap_type, + _, + ) + EqHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_eq_heap_type, + visitor.on_exit_eq_heap_type, + _, + ) + I31HeapType -> enter( + ctx, + heap_type, + visitor.on_enter_i31_heap_type, + visitor.on_exit_i31_heap_type, + _, + ) + StructHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_struct_heap_type, + visitor.on_exit_struct_heap_type, + _, + ) + ArrayHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_array_heap_type, + visitor.on_exit_array_heap_type, + _, + ) + NoneHeapType -> enter( + ctx, + heap_type, + visitor.on_enter_none_heap_type, + visitor.on_exit_none_heap_type, + _, + ) + ConcreteHeapType(_) -> enter( + ctx, + heap_type, + visitor.on_enter_concrete_heap_type, + visitor.on_exit_concrete_heap_type, + _, + ) + _ -> fn(_) { Ok(#(ctx, heap_type)) } + } + + case heap_type { + ConcreteHeapType(idx) -> { + use #(ctx, idx) <- map(do_visit_type_idx(ctx, idx, visitor)) + #(ctx, ConcreteHeapType(idx)) + } + _ -> Ok(#(ctx, heap_type)) + } +} + +pub fn do_visit_field_type( + ctx, + field_type: FieldType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, FieldType), String) { + use #(ctx, FieldType(storage_type, mut)) <- enter( + ctx, + field_type, + visitor.on_enter_field_type, + visitor.on_exit_field_type, + ) + use #(ctx, st) <- map(do_visit_storage_type(ctx, storage_type, visitor)) + #(ctx, FieldType(st, mut)) +} + +pub fn do_visit_storage_type( + ctx, + storage_type: StorageType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, StorageType), String) { + use #(ctx, storage_type) <- enter( + ctx, + storage_type, + visitor.on_enter_storage_type, + visitor.on_exit_storage_type, + ) + + use #(ctx, storage_type) <- + case storage_type { + I8StorageType -> enter( + ctx, + storage_type, + visitor.on_enter_i8_storage_type, + visitor.on_exit_i8_storage_type, + _, + ) + I16StorageType -> enter( + ctx, + storage_type, + visitor.on_enter_i16_storage_type, + visitor.on_exit_i16_storage_type, + _, + ) + ValTypeStorageType(_) -> enter( + ctx, + storage_type, + visitor.on_enter_val_type_storage_type, + visitor.on_exit_val_type_storage_type, + _, + ) + } + + case storage_type { + ValTypeStorageType(vt) -> { + use #(ctx, vt) <- map(do_visit_val_type(ctx, vt, visitor)) + #(ctx, ValTypeStorageType(vt)) + } + a -> Ok(#(ctx, a)) + } +} + +pub fn do_visit_table_type( + ctx, + table_type: TableType, + visitor: BinaryModuleVisitor(ctx), +) { + use #(ctx, TableType(rt, limits)) <- enter( + ctx, + table_type, + visitor.on_enter_table_type, + visitor.on_exit_table_type, + ) + + use #(ctx, rt) <- try(do_visit_ref_type(ctx, rt, visitor)) + use #(ctx, limits) <- map(do_visit_limits(ctx, limits, visitor)) + + let table_type = TableType(rt, limits) + #(ctx, table_type) +} + +pub fn do_visit_limits( + ctx, + limits: Limits, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Limits), String) { + enter(ctx, limits, visitor.on_enter_limits, visitor.on_exit_limits, Ok) +} + +pub fn do_visit_mem_type( + ctx, + mem_type: MemType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, MemType), String) { + use #(ctx, MemType(limits)) <- enter( + ctx, + mem_type, + visitor.on_enter_mem_type, + visitor.on_exit_mem_type, + ) + use #(ctx, limits) <- map(do_visit_limits(ctx, limits, visitor)) + + #(ctx, MemType(limits)) +} + +pub fn do_visit_global_type( + ctx, + global_type: GlobalType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, GlobalType), String) { + use #(ctx, GlobalType(vt, mut)) <- enter( + ctx, + global_type, + visitor.on_enter_global_type, + visitor.on_exit_global_type, + ) + + use #(ctx, vt) <- map(do_visit_val_type(ctx, vt, visitor)) + #(ctx, GlobalType(vt, mut)) +} + +pub fn do_visit_table( + ctx, + table: Table, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Table), String) { + use #(ctx, Table(table_type, init_expr)) <- enter( + ctx, + table, + visitor.on_enter_table, + visitor.on_exit_table, + ) + + use #(ctx, table_type) <- try(do_visit_table_type(ctx, table_type, visitor)) + + use #(ctx, init_expr) <- map(case init_expr { + Some(init_expr) -> { + use #(ctx, init_expr) <- map(do_visit_expr(ctx, init_expr, visitor)) + #(ctx, Some(init_expr)) + } + None -> Ok(#(ctx, None)) + }) + + let table = Table(table_type, init_expr) + #(ctx, table) +} + +pub fn do_visit_expr( + ctx, + expr: Expr, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Expr), String) { + use #(ctx, Expr(body)) <- enter( + ctx, + expr, + visitor.on_enter_expr, + visitor.on_exit_expr, + ) + + use #(ctx, body) <- map(do_visit_element_list( + ctx, + body, + visitor, + do_visit_instruction, + )) + + #(ctx, Expr(body)) +} + +pub fn do_visit_instruction( + ctx, + instruction: Instruction, + visitor: BinaryModuleVisitor(ctx), +) { + use #(ctx, instruction) <- enter( + ctx, + instruction, + visitor.on_enter_instruction, + visitor.on_exit_instruction, + ) + + use #(ctx, instruction) <- + case instruction { + RefNull(_) -> enter( + ctx, + instruction, + visitor.on_enter_ref_null, + visitor.on_exit_ref_null, + _, + ) + RefFunc(_) -> enter( + ctx, + instruction, + visitor.on_enter_ref_func, + visitor.on_exit_ref_func, + _, + ) + RefTest(_) -> enter( + ctx, + instruction, + visitor.on_enter_ref_test, + visitor.on_exit_ref_test, + _, + ) + RefTestNullable(_) -> enter( + ctx, + instruction, + visitor.on_enter_ref_test_nullable, + visitor.on_exit_ref_test_nullable, + _, + ) + RefCast(_) -> enter( + ctx, + instruction, + visitor.on_enter_ref_cast, + visitor.on_exit_ref_cast, + _, + ) + RefCastNullable(_) -> enter( + ctx, + instruction, + visitor.on_enter_ref_cast_nullable, + visitor.on_exit_ref_cast_nullable, + _, + ) + StructGet(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_struct_get, + visitor.on_exit_struct_get, + _, + ) + StructGetS(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_struct_get_s, + visitor.on_exit_struct_get_s, + _, + ) + StructGetU(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_struct_get_u, + visitor.on_exit_struct_get_u, + _, + ) + StructSet(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_struct_set, + visitor.on_exit_struct_set, + _, + ) + ArrayNew(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_new, + visitor.on_exit_array_new, + _, + ) + ArrayNewDefault(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_new_default, + visitor.on_exit_array_new_default, + _, + ) + ArrayNewData(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_array_new_data, + visitor.on_exit_array_new_data, + _, + ) + ArrayNewElem(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_array_new_elem, + visitor.on_exit_array_new_elem, + _, + ) + ArrayNewFixed(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_array_new_fixed, + visitor.on_exit_array_new_fixed, + _, + ) + ArrayGet(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_get, + visitor.on_exit_array_get, + _, + ) + ArrayGetS(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_get_s, + visitor.on_exit_array_get_s, + _, + ) + ArrayGetU(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_get_u, + visitor.on_exit_array_get_u, + _, + ) + ArraySet(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_set, + visitor.on_exit_array_set, + _, + ) + ArrayFill(_) -> enter( + ctx, + instruction, + visitor.on_enter_array_fill, + visitor.on_exit_array_fill, + _, + ) + ArrayCopy(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_array_copy, + visitor.on_exit_array_copy, + _, + ) + ArrayInitData(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_array_init_data, + visitor.on_exit_array_init_data, + _, + ) + ArrayInitElem(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_array_init_elem, + visitor.on_exit_array_init_elem, + _, + ) + SelectT(_) -> enter( + ctx, + instruction, + visitor.on_enter_select_t, + visitor.on_exit_select_t, + _, + ) + LocalGet(_) -> enter( + ctx, + instruction, + visitor.on_enter_local_get, + visitor.on_exit_local_get, + _, + ) + LocalSet(_) -> enter( + ctx, + instruction, + visitor.on_enter_local_set, + visitor.on_exit_local_set, + _, + ) + LocalTee(_) -> enter( + ctx, + instruction, + visitor.on_enter_local_tee, + visitor.on_exit_local_tee, + _, + ) + GlobalGet(_) -> enter( + ctx, + instruction, + visitor.on_enter_global_get, + visitor.on_exit_global_get, + _, + ) + GlobalSet(_) -> enter( + ctx, + instruction, + visitor.on_enter_global_set, + visitor.on_exit_global_set, + _, + ) + TableGet(_) -> enter( + ctx, + instruction, + visitor.on_enter_table_get, + visitor.on_exit_table_get, + _, + ) + TableSet(_) -> enter( + ctx, + instruction, + visitor.on_enter_table_set, + visitor.on_exit_table_set, + _, + ) + TableSize(_) -> enter( + ctx, + instruction, + visitor.on_enter_table_size, + visitor.on_exit_table_size, + _, + ) + TableGrow(_) -> enter( + ctx, + instruction, + visitor.on_enter_table_grow, + visitor.on_exit_table_grow, + _, + ) + TableFill(_) -> enter( + ctx, + instruction, + visitor.on_enter_table_fill, + visitor.on_exit_table_fill, + _, + ) + TableCopy(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_table_copy, + visitor.on_exit_table_copy, + _, + ) + TableInit(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_table_init, + visitor.on_exit_table_init, + _, + ) + ElemDrop(_) -> enter( + ctx, + instruction, + visitor.on_enter_elem_drop, + visitor.on_exit_elem_drop, + _, + ) + MemoryInit(_) -> enter( + ctx, + instruction, + visitor.on_enter_memory_init, + visitor.on_exit_memory_init, + _, + ) + DataDrop(_) -> enter( + ctx, + instruction, + visitor.on_enter_data_drop, + visitor.on_exit_data_drop, + _, + ) + Block(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_block, + visitor.on_exit_block, + _, + ) + Loop(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_loop, + visitor.on_exit_loop, + _, + ) + If(_, _, _) -> enter( + ctx, + instruction, + visitor.on_enter_if, + visitor.on_exit_if, + _, + ) + Br(_) -> enter( + ctx, + instruction, + visitor.on_enter_br, + visitor.on_exit_br, + _, + ) + BrIf(_) -> enter( + ctx, + instruction, + visitor.on_enter_br_if, + visitor.on_exit_br_if, + _, + ) + BrTable(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_br_table, + visitor.on_exit_br_table, + _, + ) + BrOnNull(_) -> enter( + ctx, + instruction, + visitor.on_enter_br_on_null, + visitor.on_exit_br_on_null, + _, + ) + BrOnNonNull(_) -> enter( + ctx, + instruction, + visitor.on_enter_br_on_non_null, + visitor.on_exit_br_on_non_null, + _, + ) + BrOnCast(_, _, _) -> enter( + ctx, + instruction, + visitor.on_enter_br_on_cast, + visitor.on_exit_br_on_cast, + _, + ) + BrOnCastFail(_, _, _) -> enter( + ctx, + instruction, + visitor.on_enter_br_on_cast_fail, + visitor.on_exit_br_on_cast_fail, + _, + ) + Call(_) -> enter( + ctx, + instruction, + visitor.on_enter_call, + visitor.on_exit_call, + _, + ) + CallRef(_) -> enter( + ctx, + instruction, + visitor.on_enter_call_ref, + visitor.on_exit_call_ref, + _, + ) + CallIndirect(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_call_indirect, + visitor.on_exit_call_indirect, + _, + ) + ReturnCall(_) -> enter( + ctx, + instruction, + visitor.on_enter_return_call, + visitor.on_exit_return_call, + _, + ) + ReturnCallRef(_) -> enter( + ctx, + instruction, + visitor.on_enter_return_call_ref, + visitor.on_exit_return_call_ref, + _, + ) + ReturnCallIndirect(_, _) -> enter( + ctx, + instruction, + visitor.on_enter_return_call_indirect, + visitor.on_exit_return_call_indirect, + _, + ) + _ -> fn(_) { Ok(#(ctx, instruction)) } + } + + case instruction { + RefNull(heap_type) -> { + use #(ctx, heap_type) <- map(do_visit_heap_type(ctx, heap_type, visitor)) + #(ctx, RefNull(heap_type)) + } + RefFunc(func_idx) -> { + use #(ctx, func_idx) <- map(do_visit_func_idx(ctx, func_idx, visitor)) + #(ctx, RefFunc(func_idx)) + } + RefTest(heap_type) -> { + use #(ctx, heap_type) <- map(do_visit_heap_type(ctx, heap_type, visitor)) + #(ctx, RefTest(heap_type)) + } + RefTestNullable(heap_type) -> { + use #(ctx, heap_type) <- map(do_visit_heap_type(ctx, heap_type, visitor)) + #(ctx, RefTestNullable(heap_type)) + } + RefCast(heap_type) -> { + use #(ctx, heap_type) <- map(do_visit_heap_type(ctx, heap_type, visitor)) + #(ctx, RefCast(heap_type)) + } + RefCastNullable(heap_type) -> { + use #(ctx, heap_type) <- map(do_visit_heap_type(ctx, heap_type, visitor)) + #(ctx, RefCastNullable(heap_type)) + } + StructGet(type_idx, field_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, field_idx) <- map(do_visit_field_idx(ctx, field_idx, visitor)) + #(ctx, StructGet(type_idx, field_idx)) + } + StructGetS(type_idx, field_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, field_idx) <- map(do_visit_field_idx(ctx, field_idx, visitor)) + #(ctx, StructGetS(type_idx, field_idx)) + } + StructGetU(type_idx, field_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, field_idx) <- map(do_visit_field_idx(ctx, field_idx, visitor)) + #(ctx, StructGetU(type_idx, field_idx)) + } + StructSet(type_idx, field_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, field_idx) <- map(do_visit_field_idx(ctx, field_idx, visitor)) + #(ctx, StructSet(type_idx, field_idx)) + } + ArrayNew(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayNew(type_idx)) + } + ArrayNewDefault(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayNewDefault(type_idx)) + } + ArrayNewData(type_idx, data_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, data_idx) <- map(do_visit_data_idx(ctx, data_idx, visitor)) + #(ctx, ArrayNewData(type_idx, data_idx)) + } + ArrayNewElem(type_idx, elem_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, elem_idx) <- map(do_visit_elem_idx(ctx, elem_idx, visitor)) + #(ctx, ArrayNewElem(type_idx, elem_idx)) + } + ArrayNewFixed(type_idx, size) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayNewFixed(type_idx, size)) + } + ArrayGet(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayGet(type_idx)) + } + ArrayGetS(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayGetS(type_idx)) + } + ArrayGetU(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayGetU(type_idx)) + } + ArraySet(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArraySet(type_idx)) + } + ArrayFill(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ArrayFill(type_idx)) + } + ArrayCopy(type_idx1, type_idx2) -> { + use #(ctx, type_idx1) <- try(do_visit_type_idx(ctx, type_idx1, visitor)) + use #(ctx, type_idx2) <- map(do_visit_type_idx(ctx, type_idx2, visitor)) + #(ctx, ArrayCopy(type_idx1, type_idx2)) + } + ArrayInitData(type_idx, data_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, data_idx) <- map(do_visit_data_idx(ctx, data_idx, visitor)) + #(ctx, ArrayInitData(type_idx, data_idx)) + } + ArrayInitElem(type_idx, elem_idx) -> { + use #(ctx, type_idx) <- try(do_visit_type_idx(ctx, type_idx, visitor)) + use #(ctx, elem_idx) <- map(do_visit_elem_idx(ctx, elem_idx, visitor)) + #(ctx, ArrayInitElem(type_idx, elem_idx)) + } + SelectT(val_types) -> { + use #(ctx, val_types) <- map(do_visit_element_list( + ctx, + val_types, + visitor, + do_visit_val_type, + )) + #(ctx, SelectT(val_types)) + } + LocalGet(local_idx) -> { + use #(ctx, local_idx) <- map(do_visit_local_idx(ctx, local_idx, visitor)) + #(ctx, LocalGet(local_idx)) + } + LocalSet(local_idx) -> { + use #(ctx, local_idx) <- map(do_visit_local_idx(ctx, local_idx, visitor)) + #(ctx, LocalSet(local_idx)) + } + LocalTee(local_idx) -> { + use #(ctx, local_idx) <- map(do_visit_local_idx(ctx, local_idx, visitor)) + #(ctx, LocalTee(local_idx)) + } + GlobalGet(global_idx) -> { + use #(ctx, global_idx) <- map(do_visit_global_idx( + ctx, + global_idx, + visitor, + )) + #(ctx, GlobalGet(global_idx)) + } + GlobalSet(global_idx) -> { + use #(ctx, global_idx) <- map(do_visit_global_idx( + ctx, + global_idx, + visitor, + )) + #(ctx, GlobalSet(global_idx)) + } + TableGet(table_idx) -> { + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableGet(table_idx)) + } + TableSet(table_idx) -> { + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableSet(table_idx)) + } + TableSize(table_idx) -> { + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableSize(table_idx)) + } + TableGrow(table_idx) -> { + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableGrow(table_idx)) + } + TableFill(table_idx) -> { + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableFill(table_idx)) + } + TableCopy(dest_idx, src_idx) -> { + use #(ctx, dest_idx) <- try(do_visit_table_idx(ctx, dest_idx, visitor)) + use #(ctx, src_idx) <- map(do_visit_table_idx(ctx, src_idx, visitor)) + #(ctx, TableCopy(dest_idx, src_idx)) + } + TableInit(elem_idx, table_idx) -> { + use #(ctx, elem_idx) <- try(do_visit_elem_idx(ctx, elem_idx, visitor)) + use #(ctx, table_idx) <- map(do_visit_table_idx(ctx, table_idx, visitor)) + #(ctx, TableInit(elem_idx, table_idx)) + } + ElemDrop(elem_idx) -> { + use #(ctx, elem_idx) <- map(do_visit_elem_idx(ctx, elem_idx, visitor)) + #(ctx, ElemDrop(elem_idx)) + } + MemoryInit(data_idx) -> { + use #(ctx, data_idx) <- map(do_visit_data_idx(ctx, data_idx, visitor)) + #(ctx, MemoryInit(data_idx)) + } + DataDrop(data_idx) -> { + use #(ctx, data_idx) <- map(do_visit_data_idx(ctx, data_idx, visitor)) + #(ctx, DataDrop(data_idx)) + } + Block(block_type, body) -> { + use #(ctx, block_type) <- try(do_visit_block_type( + ctx, + block_type, + visitor, + )) + use #(ctx, body) <- map(do_visit_expr(ctx, body, visitor)) + #(ctx, Block(block_type, body)) + } + Loop(block_type, body) -> { + use #(ctx, block_type) <- try(do_visit_block_type( + ctx, + block_type, + visitor, + )) + use #(ctx, body) <- map(do_visit_expr(ctx, body, visitor)) + #(ctx, Loop(block_type, body)) + } + If(block_type, if_instructions, else_instructions) -> { + use #(ctx, block_type) <- try(do_visit_block_type( + ctx, + block_type, + visitor, + )) + use #(ctx, if_instructions) <- try(do_visit_element_list( + ctx, + if_instructions, + visitor, + do_visit_instruction, + )) + use #(ctx, else_instructions) <- map(case else_instructions { + Some(else_instructions) -> { + use #(ctx, else_instructions) <- map(do_visit_element_list( + ctx, + else_instructions, + visitor, + do_visit_instruction, + )) + #(ctx, Some(else_instructions)) + } + None -> Ok(#(ctx, None)) + }) + #(ctx, If(block_type, if_instructions, else_instructions)) + } + Br(label_idx) -> { + use #(ctx, label_idx) <- map(do_visit_label_idx(ctx, label_idx, visitor)) + #(ctx, Br(label_idx)) + } + BrIf(label_idx) -> { + use #(ctx, label_idx) <- map(do_visit_label_idx(ctx, label_idx, visitor)) + #(ctx, BrIf(label_idx)) + } + BrTable(label_idxs, default_label_idx) -> { + use #(ctx, label_idxs) <- try(do_visit_element_list( + ctx, + label_idxs, + visitor, + do_visit_label_idx, + )) + use #(ctx, default_label_idx) <- map(do_visit_label_idx( + ctx, + default_label_idx, + visitor, + )) + #(ctx, BrTable(label_idxs, default_label_idx)) + } + BrOnNull(label_idx) -> { + use #(ctx, label_idx) <- map(do_visit_label_idx(ctx, label_idx, visitor)) + #(ctx, BrOnNull(label_idx)) + } + BrOnNonNull(label_idx) -> { + use #(ctx, label_idx) <- map(do_visit_label_idx(ctx, label_idx, visitor)) + #(ctx, BrOnNonNull(label_idx)) + } + BrOnCast(label_idx, ref_type1, ref_type2) -> { + use #(ctx, label_idx) <- try(do_visit_label_idx(ctx, label_idx, visitor)) + use #(ctx, ref_type1) <- try(do_visit_ref_type(ctx, ref_type1, visitor)) + use #(ctx, ref_type2) <- map(do_visit_ref_type(ctx, ref_type2, visitor)) + #(ctx, BrOnCast(label_idx, ref_type1, ref_type2)) + } + BrOnCastFail(label_idx, ref_type1, ref_type2) -> { + use #(ctx, label_idx) <- try(do_visit_label_idx(ctx, label_idx, visitor)) + use #(ctx, ref_type1) <- try(do_visit_ref_type(ctx, ref_type1, visitor)) + use #(ctx, ref_type2) <- map(do_visit_ref_type(ctx, ref_type2, visitor)) + #(ctx, BrOnCastFail(label_idx, ref_type1, ref_type2)) + } + Call(func_idx) -> { + use #(ctx, func_idx) <- map(do_visit_func_idx(ctx, func_idx, visitor)) + #(ctx, Call(func_idx)) + } + CallRef(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, CallRef(type_idx)) + } + CallIndirect(table_idx, type_idx) -> { + use #(ctx, table_idx) <- try(do_visit_table_idx(ctx, table_idx, visitor)) + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, CallIndirect(table_idx, type_idx)) + } + ReturnCall(func_idx) -> { + use #(ctx, func_idx) <- map(do_visit_func_idx(ctx, func_idx, visitor)) + #(ctx, ReturnCall(func_idx)) + } + ReturnCallRef(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ReturnCallRef(type_idx)) + } + ReturnCallIndirect(table_idx, type_idx) -> { + use #(ctx, table_idx) <- try(do_visit_table_idx(ctx, table_idx, visitor)) + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, ReturnCallIndirect(table_idx, type_idx)) + } + _ -> Ok(#(ctx, instruction)) + } +} + +pub fn do_visit_func_idx( + ctx, + func_idx: FuncIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter(ctx, func_idx, visitor.on_enter_func_idx, visitor.on_exit_func_idx, Ok) +} + +pub fn do_visit_table_idx( + ctx, + table_idx: TableIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter( + ctx, + table_idx, + visitor.on_enter_table_idx, + visitor.on_exit_table_idx, + Ok, + ) +} + +pub fn do_visit_mem_idx(ctx, mem_idx: MemIDX, visitor: BinaryModuleVisitor(ctx)) { + enter(ctx, mem_idx, visitor.on_enter_mem_idx, visitor.on_exit_mem_idx, Ok) +} + +pub fn do_visit_global_idx( + ctx, + global_idx: GlobalIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter( + ctx, + global_idx, + visitor.on_enter_global_idx, + visitor.on_exit_global_idx, + Ok, + ) +} + +fn enter( + ctx, + element, + on_enter: Option(VisitorCallback(ctx, element)), + on_exit: Option(VisitorCallback(ctx, element)), + body: fn(#(ctx, element)) -> Result(#(ctx, element), String), +) { + use #(ctx, element) <- try(do_visit(ctx, element, on_enter)) + use #(ctx, element) <- try(body(#(ctx, element))) + do_visit(ctx, element, on_exit) +} + +pub fn do_visit_label_idx( + ctx, + label_idx: LabelIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter( + ctx, + label_idx, + visitor.on_enter_label_idx, + visitor.on_exit_label_idx, + Ok, + ) +} + +pub fn do_visit_field_idx( + ctx, + field_idx: FieldIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter( + ctx, + field_idx, + visitor.on_enter_field_idx, + visitor.on_exit_field_idx, + Ok, + ) +} + +pub fn do_visit_data_idx( + ctx, + data_idx: DataIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter(ctx, data_idx, visitor.on_enter_data_idx, visitor.on_exit_data_idx, Ok) +} + +pub fn do_visit_elem_idx( + ctx, + elem_idx: ElemIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter(ctx, elem_idx, visitor.on_enter_elem_idx, visitor.on_exit_elem_idx, Ok) +} + +pub fn do_visit_local_idx( + ctx, + local_idx: LocalIDX, + visitor: BinaryModuleVisitor(ctx), +) { + enter( + ctx, + local_idx, + visitor.on_enter_local_idx, + visitor.on_exit_local_idx, + Ok, + ) +} + +pub fn do_visit_block_type( + ctx, + block_type: BlockType, + visitor: BinaryModuleVisitor(ctx), +) { + use #(ctx, block_type) <- enter( + ctx, + block_type, + visitor.on_enter_block_type, + visitor.on_exit_block_type, + ) + + use #(ctx, block_type) <- + case block_type { + VoidBlockType -> enter( + ctx, + block_type, + visitor.on_enter_void_block_type, + visitor.on_exit_void_block_type, + _, + ) + ValTypeBlockType(_) -> enter( + ctx, + block_type, + visitor.on_enter_val_type_block_type, + visitor.on_exit_val_type_block_type, + _, + ) + FuncTypeBlockType(_) -> enter( + ctx, + block_type, + visitor.on_enter_func_type_block_type, + visitor.on_exit_func_type_block_type, + _, + ) + } + + case block_type { + ValTypeBlockType(val_type) -> { + use #(ctx, val_type) <- map(do_visit_val_type(ctx, val_type, visitor)) + #(ctx, ValTypeBlockType(val_type)) + } + FuncTypeBlockType(type_idx) -> { + use #(ctx, type_idx) <- map(do_visit_type_idx(ctx, type_idx, visitor)) + #(ctx, FuncTypeBlockType(type_idx)) + } + _ -> Ok(#(ctx, block_type)) + } +} diff --git a/src/shinecoder.gleam b/src/shine_coder.gleam similarity index 94% rename from src/shinecoder.gleam rename to src/shine_coder.gleam index 822fde4..0fb12a2 100644 --- a/src/shinecoder.gleam +++ b/src/shine_coder.gleam @@ -17,7 +17,7 @@ pub fn main() { |> module.add_type( rec_type.func_type([val_type.i32, val_type.i32], [val_type.i32]), ) - |> module.add_function_type(type_idx_0) + |> module.append_function_type_index(type_idx_0) |> module.add_code( [val_type.i32, val_type.i32], expression.new() diff --git a/src/values.gleam b/src/values.gleam new file mode 100644 index 0000000..097bcd0 --- /dev/null +++ b/src/values.gleam @@ -0,0 +1,60 @@ +import internal/structure/numbers.{ + f32, f64, i16, i32, i64, i8, u16, u32, u64, u8, unwrap_f32, unwrap_f64, + unwrap_i16, unwrap_i32, unwrap_i64, unwrap_i8, unwrap_u16, unwrap_u32, + unwrap_u64, unwrap_u8, unwrap_v128, v128, +} + +// Construct a single i8 constant value +pub const i8 = i8 + +pub const unwrap_i8 = unwrap_i8 + +// Construct a single u8 constant value +pub const u8 = u8 + +pub const unwrap_u8 = unwrap_u8 + +// Construct a single i16 constant value +pub const i16 = i16 + +pub const unwrap_i16 = unwrap_i16 + +// Construct a single u16 constant value +pub const u16 = u16 + +pub const unwrap_u16 = unwrap_u16 + +// Construct a single i32 constant value +pub const i32 = i32 + +pub const unwrap_i32 = unwrap_i32 + +// Construct a single u32 constant value +pub const u32 = u32 + +pub const unwrap_u32 = unwrap_u32 + +// Construct a single i64 constant value +pub const i64 = i64 + +pub const unwrap_i64 = unwrap_i64 + +// Construct a single u64 constant value +pub const u64 = u64 + +pub const unwrap_u64 = unwrap_u64 + +// Construct a single f32 constant value +pub const f32 = f32 + +pub const unwrap_f32 = unwrap_f32 + +// Construct a single f64 constant value +pub const f64 = f64 + +pub const unwrap_f64 = unwrap_f64 + +// Construct a single v128 constant value +pub const v128 = v128 + +pub const unwrap_v128 = unwrap_v128 diff --git a/src/visitor.gleam b/src/visitor.gleam new file mode 100644 index 0000000..33aee7c --- /dev/null +++ b/src/visitor.gleam @@ -0,0 +1,3234 @@ +import gleam/option.{type Option, Some} +import internal/structure/modules.{ + type BinaryModule, type CodeSection, type CustomSection, type DataCountSection, + type DataSection, type ElementSection, type ExportSection, + type FunctionSection, type GlobalSection, type ImportSection, + type MemorySection, type StartSection, type TableSection, type TypeSection, +} +import internal/structure/types.{ + type ArrayType, type BlockType, type Code, type CompositeType, type Data, + type DataIDX, type DefType, type Elem, type ElemIDX, type ElemMode, + type Export, type Expr, type FieldIDX, type FieldType, type FuncIDX, + type FuncType, type Global, type GlobalIDX, type GlobalType, type HeapType, + type Import, type Instruction, type LabelIDX, type Limits, type LocalIDX, + type Locals, type MemIDX, type MemType, type RecType, type RefType, + type StorageType, type StructType, type SubType, type Table, type TableIDX, + type TableType, type TypeIDX, type ValType, +} +import internal/visitor.{ + type VisitorCallback, BinaryModuleVisitor, do_visit_array_type, + do_visit_block_type, do_visit_code, do_visit_code_section, + do_visit_composite_type, do_visit_custom_section, do_visit_data, + do_visit_data_count_section, do_visit_data_idx, do_visit_data_section, + do_visit_def_type, do_visit_elem_idx, do_visit_element_mode, + do_visit_element_section, do_visit_element_segment, do_visit_export, + do_visit_export_section, do_visit_expr, do_visit_field_idx, + do_visit_field_type, do_visit_func_idx, do_visit_func_type, + do_visit_function_section, do_visit_global, do_visit_global_idx, + do_visit_global_section, do_visit_global_type, do_visit_heap_type, + do_visit_import, do_visit_import_section, do_visit_instruction, + do_visit_label_idx, do_visit_limits, do_visit_local_idx, do_visit_locals, + do_visit_mem_idx, do_visit_mem_type, do_visit_memory_section, do_visit_module, + do_visit_rec_type, do_visit_ref_type, do_visit_start_section, + do_visit_storage_type, do_visit_struct_type, do_visit_sub_type, do_visit_table, + do_visit_table_idx, do_visit_table_section, do_visit_table_type, + do_visit_type_idx, do_visit_type_section, do_visit_val_type, +} + +pub fn on_enter_module( + visitor: BinaryModuleVisitor(ctx), + on_enter_module: VisitorCallback(ctx, BinaryModule), +) { + BinaryModuleVisitor(..visitor, on_enter_module: Some(on_enter_module)) +} + +pub fn on_exit_module( + visitor: BinaryModuleVisitor(ctx), + on_exit_module: VisitorCallback(ctx, BinaryModule), +) { + BinaryModuleVisitor(..visitor, on_exit_module: Some(on_exit_module)) +} + +pub fn on_enter_custom_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_custom_section: VisitorCallback(ctx, Option(CustomSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_custom_section: Some(on_enter_custom_section), + ) +} + +pub fn on_exit_custom_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_custom_section: VisitorCallback(ctx, Option(CustomSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_custom_section: Some(on_exit_custom_section), + ) +} + +pub fn on_enter_type_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_type_section: VisitorCallback(ctx, Option(TypeSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_type_section: Some(on_enter_type_section), + ) +} + +pub fn on_exit_type_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_type_section: VisitorCallback(ctx, Option(TypeSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_type_section: Some(on_exit_type_section), + ) +} + +pub fn on_enter_import_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_import_section: VisitorCallback(ctx, Option(ImportSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_import_section: Some(on_enter_import_section), + ) +} + +pub fn on_exit_import_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_import_section: VisitorCallback(ctx, Option(ImportSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_import_section: Some(on_exit_import_section), + ) +} + +pub fn on_enter_table_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_section: VisitorCallback(ctx, Option(TableSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_table_section: Some(on_enter_table_section), + ) +} + +pub fn on_exit_table_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_section: VisitorCallback(ctx, Option(TableSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_table_section: Some(on_exit_table_section), + ) +} + +pub fn on_enter_memory_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_memory_section: VisitorCallback(ctx, Option(MemorySection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_memory_section: Some(on_enter_memory_section), + ) +} + +pub fn on_exit_memory_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_memory_section: VisitorCallback(ctx, Option(MemorySection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_memory_section: Some(on_exit_memory_section), + ) +} + +pub fn on_enter_start_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_start_section: VisitorCallback(ctx, Option(StartSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_start_section: Some(on_enter_start_section), + ) +} + +pub fn on_exit_start_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_start_section: VisitorCallback(ctx, Option(StartSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_start_section: Some(on_exit_start_section), + ) +} + +pub fn on_enter_element_segment( + visitor: BinaryModuleVisitor(ctx), + on_enter_element_segment: VisitorCallback(ctx, Elem), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_element_segment: Some(on_enter_element_segment), + ) +} + +pub fn on_exit_element_segment( + visitor: BinaryModuleVisitor(ctx), + on_exit_element_segment: VisitorCallback(ctx, Elem), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_element_segment: Some(on_exit_element_segment), + ) +} + +pub fn on_enter_element_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_element_section: VisitorCallback(ctx, Option(ElementSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_element_section: Some(on_enter_element_section), + ) +} + +pub fn on_exit_element_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_element_section: VisitorCallback(ctx, Option(ElementSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_element_section: Some(on_exit_element_section), + ) +} + +pub fn on_enter_import( + visitor: BinaryModuleVisitor(ctx), + on_enter_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor(..visitor, on_enter_import: Some(on_enter_import)) +} + +pub fn on_exit_import( + visitor: BinaryModuleVisitor(ctx), + on_exit_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor(..visitor, on_exit_import: Some(on_exit_import)) +} + +pub fn on_enter_func_import( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_func_import: Some(on_enter_func_import), + ) +} + +pub fn on_exit_func_import( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor(..visitor, on_exit_func_import: Some(on_exit_func_import)) +} + +pub fn on_enter_table_import( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_table_import: Some(on_enter_table_import), + ) +} + +pub fn on_exit_table_import( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_table_import: Some(on_exit_table_import), + ) +} + +pub fn on_enter_mem_import( + visitor: BinaryModuleVisitor(ctx), + on_enter_mem_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor(..visitor, on_enter_mem_import: Some(on_enter_mem_import)) +} + +pub fn on_exit_mem_import( + visitor: BinaryModuleVisitor(ctx), + on_exit_mem_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor(..visitor, on_exit_mem_import: Some(on_exit_mem_import)) +} + +pub fn on_enter_global_import( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_global_import: Some(on_enter_global_import), + ) +} + +pub fn on_exit_global_import( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_import: VisitorCallback(ctx, Import), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_global_import: Some(on_exit_global_import), + ) +} + +pub fn on_enter_table_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_type: VisitorCallback(ctx, TableType), +) { + BinaryModuleVisitor(..visitor, on_enter_table_type: Some(on_enter_table_type)) +} + +pub fn on_exit_table_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_type: VisitorCallback(ctx, TableType), +) { + BinaryModuleVisitor(..visitor, on_exit_table_type: Some(on_exit_table_type)) +} + +pub fn on_enter_table( + visitor: BinaryModuleVisitor(ctx), + on_enter_table: VisitorCallback(ctx, Table), +) { + BinaryModuleVisitor(..visitor, on_enter_table: Some(on_enter_table)) +} + +pub fn on_exit_table( + visitor: BinaryModuleVisitor(ctx), + on_exit_table: VisitorCallback(ctx, Table), +) { + BinaryModuleVisitor(..visitor, on_exit_table: Some(on_exit_table)) +} + +pub fn on_enter_global( + visitor: BinaryModuleVisitor(ctx), + on_enter_global: VisitorCallback(ctx, Global), +) { + BinaryModuleVisitor(..visitor, on_enter_global: Some(on_enter_global)) +} + +pub fn on_exit_global( + visitor: BinaryModuleVisitor(ctx), + on_exit_global: VisitorCallback(ctx, Global), +) { + BinaryModuleVisitor(..visitor, on_exit_global: Some(on_exit_global)) +} + +pub fn on_enter_global_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_type: VisitorCallback(ctx, GlobalType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_global_type: Some(on_enter_global_type), + ) +} + +pub fn on_exit_global_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_type: VisitorCallback(ctx, GlobalType), +) { + BinaryModuleVisitor(..visitor, on_exit_global_type: Some(on_exit_global_type)) +} + +pub fn on_enter_mem_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_mem_type: VisitorCallback(ctx, MemType), +) { + BinaryModuleVisitor(..visitor, on_enter_mem_type: Some(on_enter_mem_type)) +} + +pub fn on_exit_mem_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_mem_type: VisitorCallback(ctx, MemType), +) { + BinaryModuleVisitor(..visitor, on_exit_mem_type: Some(on_exit_mem_type)) +} + +pub fn on_enter_def_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_def_type: VisitorCallback(ctx, DefType), +) { + BinaryModuleVisitor(..visitor, on_enter_def_type: Some(on_enter_def_type)) +} + +pub fn on_exit_def_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_def_type: VisitorCallback(ctx, DefType), +) { + BinaryModuleVisitor(..visitor, on_exit_def_type: Some(on_exit_def_type)) +} + +pub fn on_enter_rec_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_rec_type: VisitorCallback(ctx, RecType), +) { + BinaryModuleVisitor(..visitor, on_enter_rec_type: Some(on_enter_rec_type)) +} + +pub fn on_exit_rec_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_rec_type: VisitorCallback(ctx, RecType), +) { + BinaryModuleVisitor(..visitor, on_exit_rec_type: Some(on_exit_rec_type)) +} + +pub fn on_enter_sub_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_sub_type: VisitorCallback(ctx, SubType), +) { + BinaryModuleVisitor(..visitor, on_enter_sub_type: Some(on_enter_sub_type)) +} + +pub fn on_exit_sub_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_sub_type: VisitorCallback(ctx, SubType), +) { + BinaryModuleVisitor(..visitor, on_exit_sub_type: Some(on_exit_sub_type)) +} + +pub fn on_enter_type_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_type_idx: VisitorCallback(ctx, TypeIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_type_idx: Some(on_enter_type_idx)) +} + +pub fn on_exit_type_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_type_idx: VisitorCallback(ctx, TypeIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_type_idx: Some(on_exit_type_idx)) +} + +pub fn on_enter_rec_type_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_rec_type_idx: VisitorCallback(ctx, TypeIDX), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_rec_type_idx: Some(on_enter_rec_type_idx), + ) +} + +pub fn on_exit_rec_type_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_rec_type_idx: VisitorCallback(ctx, TypeIDX), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_rec_type_idx: Some(on_exit_rec_type_idx), + ) +} + +pub fn on_enter_def_type_reference( + visitor: BinaryModuleVisitor(ctx), + on_enter_def_type_reference: VisitorCallback(ctx, TypeIDX), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_def_type_reference: Some(on_enter_def_type_reference), + ) +} + +pub fn on_exit_def_type_reference( + visitor: BinaryModuleVisitor(ctx), + on_exit_def_type_reference: VisitorCallback(ctx, TypeIDX), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_def_type_reference: Some(on_exit_def_type_reference), + ) +} + +pub fn on_enter_comp_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_comp_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor(..visitor, on_enter_comp_type: Some(on_enter_comp_type)) +} + +pub fn on_exit_comp_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_comp_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor(..visitor, on_exit_comp_type: Some(on_exit_comp_type)) +} + +pub fn on_enter_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_composite_type: Some(on_enter_composite_type), + ) +} + +pub fn on_exit_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_composite_type: Some(on_exit_composite_type), + ) +} + +pub fn on_enter_func_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_func_composite_type: Some(on_enter_func_composite_type), + ) +} + +pub fn on_exit_func_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_func_composite_type: Some(on_exit_func_composite_type), + ) +} + +pub fn on_enter_struct_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_struct_composite_type: Some(on_enter_struct_composite_type), + ) +} + +pub fn on_exit_struct_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_struct_composite_type: Some(on_exit_struct_composite_type), + ) +} + +pub fn on_enter_array_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_composite_type: Some(on_enter_array_composite_type), + ) +} + +pub fn on_exit_array_composite_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_composite_type: VisitorCallback(ctx, CompositeType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_composite_type: Some(on_exit_array_composite_type), + ) +} + +pub fn on_enter_func_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_type: VisitorCallback(ctx, FuncType), +) { + BinaryModuleVisitor(..visitor, on_enter_func_type: Some(on_enter_func_type)) +} + +pub fn on_enter_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor(..visitor, on_enter_val_type: Some(on_enter_val_type)) +} + +pub fn on_exit_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor(..visitor, on_exit_val_type: Some(on_exit_val_type)) +} + +pub fn on_exit_func_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_type: VisitorCallback(ctx, FuncType), +) { + BinaryModuleVisitor(..visitor, on_exit_func_type: Some(on_exit_func_type)) +} + +pub fn on_enter_v128_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_v128_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_v128_val_type: Some(on_enter_v128_val_type), + ) +} + +pub fn on_exit_v128_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_v128_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_v128_val_type: Some(on_exit_v128_val_type), + ) +} + +pub fn on_enter_i32_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_i32_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_i32_val_type: Some(on_enter_i32_val_type), + ) +} + +pub fn on_exit_i32_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_i32_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_i32_val_type: Some(on_exit_i32_val_type), + ) +} + +pub fn on_enter_i64_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_i64_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_i64_val_type: Some(on_enter_i64_val_type), + ) +} + +pub fn on_exit_i64_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_i64_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_i64_val_type: Some(on_exit_i64_val_type), + ) +} + +pub fn on_enter_f32_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_f32_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_f32_val_type: Some(on_enter_f32_val_type), + ) +} + +pub fn on_exit_f32_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_f32_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_f32_val_type: Some(on_exit_f32_val_type), + ) +} + +pub fn on_enter_f64_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_f64_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_f64_val_type: Some(on_enter_f64_val_type), + ) +} + +pub fn on_exit_f64_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_f64_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_f64_val_type: Some(on_exit_f64_val_type), + ) +} + +pub fn on_enter_ref_type_val_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_type_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_ref_type_val_type: Some(on_enter_ref_type_val_type), + ) +} + +pub fn on_exit_ref_type_val_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_type_val_type: VisitorCallback(ctx, ValType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_ref_type_val_type: Some(on_exit_ref_type_val_type), + ) +} + +pub fn on_enter_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor(..visitor, on_enter_ref_type: Some(on_enter_ref_type)) +} + +pub fn on_exit_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor(..visitor, on_exit_ref_type: Some(on_exit_ref_type)) +} + +pub fn on_enter_heap_type_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_heap_type_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_heap_type_ref_type: Some(on_enter_heap_type_ref_type), + ) +} + +pub fn on_exit_heap_type_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_heap_type_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_heap_type_ref_type: Some(on_exit_heap_type_ref_type), + ) +} + +pub fn on_enter_any_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_any_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_any_ref_type: Some(on_enter_any_ref_type), + ) +} + +pub fn on_exit_any_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_any_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_any_ref_type: Some(on_exit_any_ref_type), + ) +} + +pub fn on_enter_eq_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_eq_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_eq_ref_type: Some(on_enter_eq_ref_type), + ) +} + +pub fn on_exit_eq_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_eq_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor(..visitor, on_exit_eq_ref_type: Some(on_exit_eq_ref_type)) +} + +pub fn on_enter_i31_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_i31_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_i31_ref_type: Some(on_enter_i31_ref_type), + ) +} + +pub fn on_exit_i31_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_i31_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_i31_ref_type: Some(on_exit_i31_ref_type), + ) +} + +pub fn on_enter_struct_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_struct_ref_type: Some(on_enter_struct_ref_type), + ) +} + +pub fn on_exit_struct_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_struct_ref_type: Some(on_exit_struct_ref_type), + ) +} + +pub fn on_enter_array_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_ref_type: Some(on_enter_array_ref_type), + ) +} + +pub fn on_exit_array_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_ref_type: Some(on_exit_array_ref_type), + ) +} + +pub fn on_enter_func_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_func_ref_type: Some(on_enter_func_ref_type), + ) +} + +pub fn on_exit_func_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_func_ref_type: Some(on_exit_func_ref_type), + ) +} + +pub fn on_enter_extern_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_extern_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_extern_ref_type: Some(on_enter_extern_ref_type), + ) +} + +pub fn on_exit_extern_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_extern_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_extern_ref_type: Some(on_exit_extern_ref_type), + ) +} + +pub fn on_enter_none_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_none_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_none_ref_type: Some(on_enter_none_ref_type), + ) +} + +pub fn on_exit_none_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_none_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_none_ref_type: Some(on_exit_none_ref_type), + ) +} + +pub fn on_enter_no_func_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_no_func_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_no_func_ref_type: Some(on_enter_no_func_ref_type), + ) +} + +pub fn on_exit_no_func_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_no_func_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_no_func_ref_type: Some(on_exit_no_func_ref_type), + ) +} + +pub fn on_enter_no_extern_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_no_extern_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_no_extern_ref_type: Some(on_enter_no_extern_ref_type), + ) +} + +pub fn on_exit_no_extern_ref_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_no_extern_ref_type: VisitorCallback(ctx, RefType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_no_extern_ref_type: Some(on_exit_no_extern_ref_type), + ) +} + +pub fn on_enter_struct_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_type: VisitorCallback(ctx, StructType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_struct_type: Some(on_enter_struct_type), + ) +} + +pub fn on_exit_struct_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_type: VisitorCallback(ctx, StructType), +) { + BinaryModuleVisitor(..visitor, on_exit_struct_type: Some(on_exit_struct_type)) +} + +pub fn on_enter_field_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_field_type: VisitorCallback(ctx, FieldType), +) { + BinaryModuleVisitor(..visitor, on_enter_field_type: Some(on_enter_field_type)) +} + +pub fn on_exit_field_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_field_type: VisitorCallback(ctx, FieldType), +) { + BinaryModuleVisitor(..visitor, on_exit_field_type: Some(on_exit_field_type)) +} + +pub fn on_enter_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_storage_type: Some(on_enter_storage_type), + ) +} + +pub fn on_enter_i8_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_i8_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_i8_storage_type: Some(on_enter_i8_storage_type), + ) +} + +pub fn on_enter_i16_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_i16_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_i16_storage_type: Some(on_enter_i16_storage_type), + ) +} + +pub fn on_enter_val_type_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_val_type_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_val_type_storage_type: Some(on_enter_val_type_storage_type), + ) +} + +pub fn on_exit_i8_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_i8_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_i8_storage_type: Some(on_exit_i8_storage_type), + ) +} + +pub fn on_exit_i16_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_i16_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_i16_storage_type: Some(on_exit_i16_storage_type), + ) +} + +pub fn on_exit_val_type_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_val_type_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_val_type_storage_type: Some(on_exit_val_type_storage_type), + ) +} + +pub fn on_exit_storage_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_storage_type: VisitorCallback(ctx, StorageType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_storage_type: Some(on_exit_storage_type), + ) +} + +pub fn on_enter_array_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_type: VisitorCallback(ctx, ArrayType), +) { + BinaryModuleVisitor(..visitor, on_enter_array_type: Some(on_enter_array_type)) +} + +pub fn on_exit_array_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_type: VisitorCallback(ctx, ArrayType), +) { + BinaryModuleVisitor(..visitor, on_exit_array_type: Some(on_exit_array_type)) +} + +pub fn on_enter_function_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_function_section: VisitorCallback(ctx, Option(FunctionSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_function_section: Some(on_enter_function_section), + ) +} + +pub fn on_exit_function_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_function_section: VisitorCallback(ctx, Option(FunctionSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_function_section: Some(on_exit_function_section), + ) +} + +pub fn on_enter_code_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_code_section: VisitorCallback(ctx, Option(CodeSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_code_section: Some(on_enter_code_section), + ) +} + +pub fn on_exit_code_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_code_section: VisitorCallback(ctx, Option(CodeSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_code_section: Some(on_exit_code_section), + ) +} + +pub fn on_enter_func_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_idx: VisitorCallback(ctx, FuncIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_func_idx: Some(on_enter_func_idx)) +} + +pub fn on_exit_func_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_idx: VisitorCallback(ctx, FuncIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_func_idx: Some(on_exit_func_idx)) +} + +pub fn on_enter_table_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_idx: VisitorCallback(ctx, TableIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_table_idx: Some(on_enter_table_idx)) +} + +pub fn on_exit_table_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_idx: VisitorCallback(ctx, TableIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_table_idx: Some(on_exit_table_idx)) +} + +pub fn on_enter_mem_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_mem_idx: VisitorCallback(ctx, MemIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_mem_idx: Some(on_enter_mem_idx)) +} + +pub fn on_exit_mem_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_mem_idx: VisitorCallback(ctx, MemIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_mem_idx: Some(on_exit_mem_idx)) +} + +pub fn on_enter_global_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_idx: VisitorCallback(ctx, GlobalIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_global_idx: Some(on_enter_global_idx)) +} + +pub fn on_exit_global_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_idx: VisitorCallback(ctx, GlobalIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_global_idx: Some(on_exit_global_idx)) +} + +pub fn on_enter_elem_expressions( + visitor: BinaryModuleVisitor(ctx), + on_enter_elem_expressions: VisitorCallback(ctx, Elem), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_elem_expressions: Some(on_enter_elem_expressions), + ) +} + +pub fn on_exit_elem_expressions( + visitor: BinaryModuleVisitor(ctx), + on_exit_elem_expressions: VisitorCallback(ctx, Elem), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_elem_expressions: Some(on_exit_elem_expressions), + ) +} + +pub fn on_enter_elem_funcs( + visitor: BinaryModuleVisitor(ctx), + on_enter_elem_funcs: VisitorCallback(ctx, Elem), +) { + BinaryModuleVisitor(..visitor, on_enter_elem_funcs: Some(on_enter_elem_funcs)) +} + +pub fn on_exit_elem_funcs( + visitor: BinaryModuleVisitor(ctx), + on_exit_elem_funcs: VisitorCallback(ctx, Elem), +) { + BinaryModuleVisitor(..visitor, on_exit_elem_funcs: Some(on_exit_elem_funcs)) +} + +pub fn on_enter_global_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_section: VisitorCallback(ctx, Option(GlobalSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_global_section: Some(on_enter_global_section), + ) +} + +pub fn on_exit_global_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_section: VisitorCallback(ctx, Option(GlobalSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_global_section: Some(on_exit_global_section), + ) +} + +pub fn on_enter_export_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_export_section: VisitorCallback(ctx, Option(ExportSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_export_section: Some(on_enter_export_section), + ) +} + +pub fn on_exit_export_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_export_section: VisitorCallback(ctx, Option(ExportSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_export_section: Some(on_exit_export_section), + ) +} + +pub fn on_enter_export( + visitor: BinaryModuleVisitor(ctx), + on_enter_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor(..visitor, on_enter_export: Some(on_enter_export)) +} + +pub fn on_exit_export( + visitor: BinaryModuleVisitor(ctx), + on_exit_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor(..visitor, on_exit_export: Some(on_exit_export)) +} + +pub fn on_enter_func_export( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_func_export: Some(on_enter_func_export), + ) +} + +pub fn on_exit_func_export( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor(..visitor, on_exit_func_export: Some(on_exit_func_export)) +} + +pub fn on_enter_table_export( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_table_export: Some(on_enter_table_export), + ) +} + +pub fn on_exit_table_export( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_table_export: Some(on_exit_table_export), + ) +} + +pub fn on_enter_mem_export( + visitor: BinaryModuleVisitor(ctx), + on_enter_mem_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor(..visitor, on_enter_mem_export: Some(on_enter_mem_export)) +} + +pub fn on_exit_mem_export( + visitor: BinaryModuleVisitor(ctx), + on_exit_mem_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor(..visitor, on_exit_mem_export: Some(on_exit_mem_export)) +} + +pub fn on_enter_global_export( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_global_export: Some(on_enter_global_export), + ) +} + +pub fn on_exit_global_export( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_export: VisitorCallback(ctx, Export), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_global_export: Some(on_exit_global_export), + ) +} + +pub fn on_enter_limits( + visitor: BinaryModuleVisitor(ctx), + on_enter_limits: VisitorCallback(ctx, Limits), +) { + BinaryModuleVisitor(..visitor, on_enter_limits: Some(on_enter_limits)) +} + +pub fn on_exit_limits( + visitor: BinaryModuleVisitor(ctx), + on_exit_limits: VisitorCallback(ctx, Limits), +) { + BinaryModuleVisitor(..visitor, on_exit_limits: Some(on_exit_limits)) +} + +pub fn on_enter_expr( + visitor: BinaryModuleVisitor(ctx), + on_enter_expr: VisitorCallback(ctx, Expr), +) { + BinaryModuleVisitor(..visitor, on_enter_expr: Some(on_enter_expr)) +} + +pub fn on_exit_expr( + visitor: BinaryModuleVisitor(ctx), + on_exit_expr: VisitorCallback(ctx, Expr), +) { + BinaryModuleVisitor(..visitor, on_exit_expr: Some(on_exit_expr)) +} + +pub fn on_enter_instruction( + visitor: BinaryModuleVisitor(ctx), + on_enter_instruction: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_instruction: Some(on_enter_instruction), + ) +} + +pub fn on_exit_instruction( + visitor: BinaryModuleVisitor(ctx), + on_exit_instruction: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_instruction: Some(on_exit_instruction)) +} + +pub fn on_enter_element_mode( + visitor: BinaryModuleVisitor(ctx), + on_enter_element_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_element_mode: Some(on_enter_element_mode), + ) +} + +pub fn on_exit_element_mode( + visitor: BinaryModuleVisitor(ctx), + on_exit_element_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_element_mode: Some(on_exit_element_mode), + ) +} + +pub fn on_enter_declarative_elem_mode( + visitor: BinaryModuleVisitor(ctx), + on_enter_declarative_elem_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_declarative_elem_mode: Some(on_enter_declarative_elem_mode), + ) +} + +pub fn on_exit_declarative_elem_mode( + visitor: BinaryModuleVisitor(ctx), + on_exit_declarative_elem_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_declarative_elem_mode: Some(on_exit_declarative_elem_mode), + ) +} + +pub fn on_enter_passive_elem_mode( + visitor: BinaryModuleVisitor(ctx), + on_enter_passive_elem_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_passive_elem_mode: Some(on_enter_passive_elem_mode), + ) +} + +pub fn on_exit_passive_elem_mode( + visitor: BinaryModuleVisitor(ctx), + on_exit_passive_elem_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_passive_elem_mode: Some(on_exit_passive_elem_mode), + ) +} + +pub fn on_enter_active_elem_mode( + visitor: BinaryModuleVisitor(ctx), + on_enter_active_elem_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_active_elem_mode: Some(on_enter_active_elem_mode), + ) +} + +pub fn on_exit_active_elem_mode( + visitor: BinaryModuleVisitor(ctx), + on_exit_active_elem_mode: VisitorCallback(ctx, ElemMode), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_active_elem_mode: Some(on_exit_active_elem_mode), + ) +} + +pub fn on_enter_code( + visitor: BinaryModuleVisitor(ctx), + on_enter_code: VisitorCallback(ctx, Code), +) { + BinaryModuleVisitor(..visitor, on_enter_code: Some(on_enter_code)) +} + +pub fn on_exit_code( + visitor: BinaryModuleVisitor(ctx), + on_exit_code: VisitorCallback(ctx, Code), +) { + BinaryModuleVisitor(..visitor, on_exit_code: Some(on_exit_code)) +} + +pub fn on_enter_locals( + visitor: BinaryModuleVisitor(ctx), + on_enter_locals: VisitorCallback(ctx, Locals), +) { + BinaryModuleVisitor(..visitor, on_enter_locals: Some(on_enter_locals)) +} + +pub fn on_exit_locals( + visitor: BinaryModuleVisitor(ctx), + on_exit_locals: VisitorCallback(ctx, Locals), +) { + BinaryModuleVisitor(..visitor, on_exit_locals: Some(on_exit_locals)) +} + +pub fn on_enter_data_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_data_section: VisitorCallback(ctx, Option(DataSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_data_section: Some(on_enter_data_section), + ) +} + +pub fn on_exit_data_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_data_section: VisitorCallback(ctx, Option(DataSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_data_section: Some(on_exit_data_section), + ) +} + +pub fn on_enter_active_data( + visitor: BinaryModuleVisitor(ctx), + on_enter_active_data: VisitorCallback(ctx, Data), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_active_data: Some(on_enter_active_data), + ) +} + +pub fn on_exit_active_data( + visitor: BinaryModuleVisitor(ctx), + on_exit_active_data: VisitorCallback(ctx, Data), +) { + BinaryModuleVisitor(..visitor, on_exit_active_data: Some(on_exit_active_data)) +} + +pub fn on_enter_passive_data( + visitor: BinaryModuleVisitor(ctx), + on_enter_passive_data: VisitorCallback(ctx, Data), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_passive_data: Some(on_enter_passive_data), + ) +} + +pub fn on_exit_passive_data( + visitor: BinaryModuleVisitor(ctx), + on_exit_passive_data: VisitorCallback(ctx, Data), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_passive_data: Some(on_exit_passive_data), + ) +} + +pub fn on_enter_data( + visitor: BinaryModuleVisitor(ctx), + on_enter_data: VisitorCallback(ctx, Data), +) { + BinaryModuleVisitor(..visitor, on_enter_data: Some(on_enter_data)) +} + +pub fn on_exit_data( + visitor: BinaryModuleVisitor(ctx), + on_exit_data: VisitorCallback(ctx, Data), +) { + BinaryModuleVisitor(..visitor, on_exit_data: Some(on_exit_data)) +} + +pub fn on_enter_data_count_section( + visitor: BinaryModuleVisitor(ctx), + on_enter_data_count_section: VisitorCallback(ctx, Option(DataCountSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_data_count_section: Some(on_enter_data_count_section), + ) +} + +pub fn on_exit_data_count_section( + visitor: BinaryModuleVisitor(ctx), + on_exit_data_count_section: VisitorCallback(ctx, Option(DataCountSection)), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_data_count_section: Some(on_exit_data_count_section), + ) +} + +pub fn on_enter_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor(..visitor, on_enter_heap_type: Some(on_enter_heap_type)) +} + +pub fn on_exit_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor(..visitor, on_exit_heap_type: Some(on_exit_heap_type)) +} + +pub fn on_enter_func_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_func_heap_type: Some(on_enter_func_heap_type), + ) +} + +pub fn on_exit_func_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_func_heap_type: Some(on_exit_func_heap_type), + ) +} + +pub fn on_enter_no_func_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_no_func_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_no_func_heap_type: Some(on_enter_no_func_heap_type), + ) +} + +pub fn on_exit_no_func_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_no_func_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_no_func_heap_type: Some(on_exit_no_func_heap_type), + ) +} + +pub fn on_enter_extern_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_extern_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_extern_heap_type: Some(on_enter_extern_heap_type), + ) +} + +pub fn on_exit_extern_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_extern_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_extern_heap_type: Some(on_exit_extern_heap_type), + ) +} + +pub fn on_enter_no_extern_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_no_extern_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_no_extern_heap_type: Some(on_enter_no_extern_heap_type), + ) +} + +pub fn on_exit_no_extern_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_no_extern_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_no_extern_heap_type: Some(on_exit_no_extern_heap_type), + ) +} + +pub fn on_enter_any_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_any_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_any_heap_type: Some(on_enter_any_heap_type), + ) +} + +pub fn on_exit_any_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_any_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_any_heap_type: Some(on_exit_any_heap_type), + ) +} + +pub fn on_enter_eq_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_eq_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_eq_heap_type: Some(on_enter_eq_heap_type), + ) +} + +pub fn on_exit_eq_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_eq_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_eq_heap_type: Some(on_exit_eq_heap_type), + ) +} + +pub fn on_enter_i31_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_i31_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_i31_heap_type: Some(on_enter_i31_heap_type), + ) +} + +pub fn on_exit_i31_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_i31_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_i31_heap_type: Some(on_exit_i31_heap_type), + ) +} + +pub fn on_enter_struct_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_struct_heap_type: Some(on_enter_struct_heap_type), + ) +} + +pub fn on_exit_struct_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_struct_heap_type: Some(on_exit_struct_heap_type), + ) +} + +pub fn on_enter_array_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_heap_type: Some(on_enter_array_heap_type), + ) +} + +pub fn on_exit_array_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_heap_type: Some(on_exit_array_heap_type), + ) +} + +pub fn on_enter_none_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_none_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_none_heap_type: Some(on_enter_none_heap_type), + ) +} + +pub fn on_exit_none_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_none_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_none_heap_type: Some(on_exit_none_heap_type), + ) +} + +pub fn on_enter_concrete_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_concrete_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_concrete_heap_type: Some(on_enter_concrete_heap_type), + ) +} + +pub fn on_exit_concrete_heap_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_concrete_heap_type: VisitorCallback(ctx, HeapType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_concrete_heap_type: Some(on_exit_concrete_heap_type), + ) +} + +pub fn on_enter_ref_null( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_null: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_ref_null: Some(on_enter_ref_null)) +} + +pub fn on_exit_ref_null( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_null: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_ref_null: Some(on_exit_ref_null)) +} + +pub fn on_enter_ref_func( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_func: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_ref_func: Some(on_enter_ref_func)) +} + +pub fn on_exit_ref_func( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_func: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_ref_func: Some(on_exit_ref_func)) +} + +pub fn on_enter_ref_test( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_test: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_ref_test: Some(on_enter_ref_test)) +} + +pub fn on_exit_ref_test( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_test: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_ref_test: Some(on_exit_ref_test)) +} + +pub fn on_enter_ref_test_nullable( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_test_nullable: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_ref_test_nullable: Some(on_enter_ref_test_nullable), + ) +} + +pub fn on_exit_ref_test_nullable( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_test_nullable: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_ref_test_nullable: Some(on_exit_ref_test_nullable), + ) +} + +pub fn on_enter_ref_cast( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_cast: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_ref_cast: Some(on_enter_ref_cast)) +} + +pub fn on_exit_ref_cast( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_cast: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_ref_cast: Some(on_exit_ref_cast)) +} + +pub fn on_enter_ref_cast_nullable( + visitor: BinaryModuleVisitor(ctx), + on_enter_ref_cast_nullable: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_ref_cast_nullable: Some(on_enter_ref_cast_nullable), + ) +} + +pub fn on_exit_ref_cast_nullable( + visitor: BinaryModuleVisitor(ctx), + on_exit_ref_cast_nullable: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_ref_cast_nullable: Some(on_exit_ref_cast_nullable), + ) +} + +pub fn on_enter_struct_get( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_struct_get: Some(on_enter_struct_get)) +} + +pub fn on_exit_struct_get( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_struct_get: Some(on_exit_struct_get)) +} + +pub fn on_enter_struct_get_s( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_get_s: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_struct_get_s: Some(on_enter_struct_get_s), + ) +} + +pub fn on_exit_struct_get_s( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_get_s: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_struct_get_s: Some(on_exit_struct_get_s), + ) +} + +pub fn on_enter_struct_get_u( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_get_u: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_struct_get_u: Some(on_enter_struct_get_u), + ) +} + +pub fn on_exit_struct_get_u( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_get_u: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_struct_get_u: Some(on_exit_struct_get_u), + ) +} + +pub fn on_enter_struct_set( + visitor: BinaryModuleVisitor(ctx), + on_enter_struct_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_struct_set: Some(on_enter_struct_set)) +} + +pub fn on_exit_struct_set( + visitor: BinaryModuleVisitor(ctx), + on_exit_struct_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_struct_set: Some(on_exit_struct_set)) +} + +pub fn on_enter_array_new( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_new: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_array_new: Some(on_enter_array_new)) +} + +pub fn on_exit_array_new( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_new: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_new: Some(on_exit_array_new)) +} + +pub fn on_enter_array_new_default( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_new_default: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_new_default: Some(on_enter_array_new_default), + ) +} + +pub fn on_exit_array_new_default( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_new_default: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_new_default: Some(on_exit_array_new_default), + ) +} + +pub fn on_enter_array_new_data( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_new_data: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_new_data: Some(on_enter_array_new_data), + ) +} + +pub fn on_exit_array_new_data( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_new_data: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_new_data: Some(on_exit_array_new_data), + ) +} + +pub fn on_enter_array_new_elem( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_new_elem: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_new_elem: Some(on_enter_array_new_elem), + ) +} + +pub fn on_exit_array_new_elem( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_new_elem: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_new_elem: Some(on_exit_array_new_elem), + ) +} + +pub fn on_enter_array_new_fixed( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_new_fixed: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_new_fixed: Some(on_enter_array_new_fixed), + ) +} + +pub fn on_exit_array_new_fixed( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_new_fixed: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_new_fixed: Some(on_exit_array_new_fixed), + ) +} + +pub fn on_enter_array_get( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_array_get: Some(on_enter_array_get)) +} + +pub fn on_exit_array_get( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_get: Some(on_exit_array_get)) +} + +pub fn on_enter_array_get_s( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_get_s: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_get_s: Some(on_enter_array_get_s), + ) +} + +pub fn on_exit_array_get_s( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_get_s: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_get_s: Some(on_exit_array_get_s)) +} + +pub fn on_enter_array_get_u( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_get_u: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_get_u: Some(on_enter_array_get_u), + ) +} + +pub fn on_exit_array_get_u( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_get_u: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_get_u: Some(on_exit_array_get_u)) +} + +pub fn on_enter_array_set( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_array_set: Some(on_enter_array_set)) +} + +pub fn on_exit_array_set( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_set: Some(on_exit_array_set)) +} + +pub fn on_enter_array_fill( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_fill: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_array_fill: Some(on_enter_array_fill)) +} + +pub fn on_exit_array_fill( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_fill: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_fill: Some(on_exit_array_fill)) +} + +pub fn on_enter_array_copy( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_copy: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_array_copy: Some(on_enter_array_copy)) +} + +pub fn on_exit_array_copy( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_copy: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_array_copy: Some(on_exit_array_copy)) +} + +pub fn on_enter_array_init_data( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_init_data: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_init_data: Some(on_enter_array_init_data), + ) +} + +pub fn on_exit_array_init_data( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_init_data: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_init_data: Some(on_exit_array_init_data), + ) +} + +pub fn on_enter_array_init_elem( + visitor: BinaryModuleVisitor(ctx), + on_enter_array_init_elem: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_array_init_elem: Some(on_enter_array_init_elem), + ) +} + +pub fn on_exit_array_init_elem( + visitor: BinaryModuleVisitor(ctx), + on_exit_array_init_elem: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_array_init_elem: Some(on_exit_array_init_elem), + ) +} + +pub fn on_enter_select_t( + visitor: BinaryModuleVisitor(ctx), + on_enter_select_t: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_select_t: Some(on_enter_select_t)) +} + +pub fn on_exit_select_t( + visitor: BinaryModuleVisitor(ctx), + on_exit_select_t: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_select_t: Some(on_exit_select_t)) +} + +pub fn on_enter_local_get( + visitor: BinaryModuleVisitor(ctx), + on_enter_local_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_local_get: Some(on_enter_local_get)) +} + +pub fn on_exit_local_get( + visitor: BinaryModuleVisitor(ctx), + on_exit_local_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_local_get: Some(on_exit_local_get)) +} + +pub fn on_enter_local_set( + visitor: BinaryModuleVisitor(ctx), + on_enter_local_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_local_set: Some(on_enter_local_set)) +} + +pub fn on_exit_local_set( + visitor: BinaryModuleVisitor(ctx), + on_exit_local_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_local_set: Some(on_exit_local_set)) +} + +pub fn on_enter_local_tee( + visitor: BinaryModuleVisitor(ctx), + on_enter_local_tee: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_local_tee: Some(on_enter_local_tee)) +} + +pub fn on_exit_local_tee( + visitor: BinaryModuleVisitor(ctx), + on_exit_local_tee: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_local_tee: Some(on_exit_local_tee)) +} + +pub fn on_enter_global_get( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_global_get: Some(on_enter_global_get)) +} + +pub fn on_exit_global_get( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_global_get: Some(on_exit_global_get)) +} + +pub fn on_enter_global_set( + visitor: BinaryModuleVisitor(ctx), + on_enter_global_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_global_set: Some(on_enter_global_set)) +} + +pub fn on_exit_global_set( + visitor: BinaryModuleVisitor(ctx), + on_exit_global_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_global_set: Some(on_exit_global_set)) +} + +pub fn on_enter_table_get( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_get: Some(on_enter_table_get)) +} + +pub fn on_exit_table_get( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_get: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_get: Some(on_exit_table_get)) +} + +pub fn on_enter_table_set( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_set: Some(on_enter_table_set)) +} + +pub fn on_exit_table_set( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_set: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_set: Some(on_exit_table_set)) +} + +pub fn on_enter_table_size( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_size: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_size: Some(on_enter_table_size)) +} + +pub fn on_exit_table_size( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_size: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_size: Some(on_exit_table_size)) +} + +pub fn on_enter_table_grow( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_grow: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_grow: Some(on_enter_table_grow)) +} + +pub fn on_exit_table_grow( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_grow: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_grow: Some(on_exit_table_grow)) +} + +pub fn on_enter_table_fill( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_fill: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_fill: Some(on_enter_table_fill)) +} + +pub fn on_exit_table_fill( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_fill: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_fill: Some(on_exit_table_fill)) +} + +pub fn on_enter_table_copy( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_copy: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_copy: Some(on_enter_table_copy)) +} + +pub fn on_exit_table_copy( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_copy: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_copy: Some(on_exit_table_copy)) +} + +pub fn on_enter_table_init( + visitor: BinaryModuleVisitor(ctx), + on_enter_table_init: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_table_init: Some(on_enter_table_init)) +} + +pub fn on_exit_table_init( + visitor: BinaryModuleVisitor(ctx), + on_exit_table_init: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_table_init: Some(on_exit_table_init)) +} + +pub fn on_enter_elem_drop( + visitor: BinaryModuleVisitor(ctx), + on_enter_elem_drop: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_elem_drop: Some(on_enter_elem_drop)) +} + +pub fn on_exit_elem_drop( + visitor: BinaryModuleVisitor(ctx), + on_exit_elem_drop: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_elem_drop: Some(on_exit_elem_drop)) +} + +pub fn on_enter_memory_init( + visitor: BinaryModuleVisitor(ctx), + on_enter_memory_init: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_memory_init: Some(on_enter_memory_init), + ) +} + +pub fn on_exit_memory_init( + visitor: BinaryModuleVisitor(ctx), + on_exit_memory_init: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_memory_init: Some(on_exit_memory_init)) +} + +pub fn on_enter_data_drop( + visitor: BinaryModuleVisitor(ctx), + on_enter_data_drop: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_data_drop: Some(on_enter_data_drop)) +} + +pub fn on_exit_data_drop( + visitor: BinaryModuleVisitor(ctx), + on_exit_data_drop: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_data_drop: Some(on_exit_data_drop)) +} + +pub fn on_enter_block( + visitor: BinaryModuleVisitor(ctx), + on_enter_block: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_block: Some(on_enter_block)) +} + +pub fn on_exit_block( + visitor: BinaryModuleVisitor(ctx), + on_exit_block: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_block: Some(on_exit_block)) +} + +pub fn on_enter_loop( + visitor: BinaryModuleVisitor(ctx), + on_enter_loop: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_loop: Some(on_enter_loop)) +} + +pub fn on_exit_loop( + visitor: BinaryModuleVisitor(ctx), + on_exit_loop: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_loop: Some(on_exit_loop)) +} + +pub fn on_enter_if( + visitor: BinaryModuleVisitor(ctx), + on_enter_if: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_if: Some(on_enter_if)) +} + +pub fn on_exit_if( + visitor: BinaryModuleVisitor(ctx), + on_exit_if: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_if: Some(on_exit_if)) +} + +pub fn on_enter_br( + visitor: BinaryModuleVisitor(ctx), + on_enter_br: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_br: Some(on_enter_br)) +} + +pub fn on_exit_br( + visitor: BinaryModuleVisitor(ctx), + on_exit_br: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_br: Some(on_exit_br)) +} + +pub fn on_enter_br_if( + visitor: BinaryModuleVisitor(ctx), + on_enter_br_if: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_br_if: Some(on_enter_br_if)) +} + +pub fn on_exit_br_if( + visitor: BinaryModuleVisitor(ctx), + on_exit_br_if: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_br_if: Some(on_exit_br_if)) +} + +pub fn on_enter_br_table( + visitor: BinaryModuleVisitor(ctx), + on_enter_br_table: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_br_table: Some(on_enter_br_table)) +} + +pub fn on_exit_br_table( + visitor: BinaryModuleVisitor(ctx), + on_exit_br_table: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_br_table: Some(on_exit_br_table)) +} + +pub fn on_enter_br_on_null( + visitor: BinaryModuleVisitor(ctx), + on_enter_br_on_null: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_br_on_null: Some(on_enter_br_on_null)) +} + +pub fn on_exit_br_on_null( + visitor: BinaryModuleVisitor(ctx), + on_exit_br_on_null: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_br_on_null: Some(on_exit_br_on_null)) +} + +pub fn on_enter_br_on_non_null( + visitor: BinaryModuleVisitor(ctx), + on_enter_br_on_non_null: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_br_on_non_null: Some(on_enter_br_on_non_null), + ) +} + +pub fn on_exit_br_on_non_null( + visitor: BinaryModuleVisitor(ctx), + on_exit_br_on_non_null: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_br_on_non_null: Some(on_exit_br_on_non_null), + ) +} + +pub fn on_enter_br_on_cast( + visitor: BinaryModuleVisitor(ctx), + on_enter_br_on_cast: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_br_on_cast: Some(on_enter_br_on_cast)) +} + +pub fn on_exit_br_on_cast( + visitor: BinaryModuleVisitor(ctx), + on_exit_br_on_cast: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_br_on_cast: Some(on_exit_br_on_cast)) +} + +pub fn on_enter_br_on_cast_fail( + visitor: BinaryModuleVisitor(ctx), + on_enter_br_on_cast_fail: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_br_on_cast_fail: Some(on_enter_br_on_cast_fail), + ) +} + +pub fn on_exit_br_on_cast_fail( + visitor: BinaryModuleVisitor(ctx), + on_exit_br_on_cast_fail: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_br_on_cast_fail: Some(on_exit_br_on_cast_fail), + ) +} + +pub fn on_enter_call( + visitor: BinaryModuleVisitor(ctx), + on_enter_call: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_call: Some(on_enter_call)) +} + +pub fn on_exit_call( + visitor: BinaryModuleVisitor(ctx), + on_exit_call: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_call: Some(on_exit_call)) +} + +pub fn on_enter_call_ref( + visitor: BinaryModuleVisitor(ctx), + on_enter_call_ref: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_enter_call_ref: Some(on_enter_call_ref)) +} + +pub fn on_exit_call_ref( + visitor: BinaryModuleVisitor(ctx), + on_exit_call_ref: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_call_ref: Some(on_exit_call_ref)) +} + +pub fn on_enter_call_indirect( + visitor: BinaryModuleVisitor(ctx), + on_enter_call_indirect: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_call_indirect: Some(on_enter_call_indirect), + ) +} + +pub fn on_exit_call_indirect( + visitor: BinaryModuleVisitor(ctx), + on_exit_call_indirect: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_call_indirect: Some(on_exit_call_indirect), + ) +} + +pub fn on_enter_return_call( + visitor: BinaryModuleVisitor(ctx), + on_enter_return_call: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_return_call: Some(on_enter_return_call), + ) +} + +pub fn on_exit_return_call( + visitor: BinaryModuleVisitor(ctx), + on_exit_return_call: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor(..visitor, on_exit_return_call: Some(on_exit_return_call)) +} + +pub fn on_enter_return_call_ref( + visitor: BinaryModuleVisitor(ctx), + on_enter_return_call_ref: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_return_call_ref: Some(on_enter_return_call_ref), + ) +} + +pub fn on_exit_return_call_ref( + visitor: BinaryModuleVisitor(ctx), + on_exit_return_call_ref: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_return_call_ref: Some(on_exit_return_call_ref), + ) +} + +pub fn on_enter_return_call_indirect( + visitor: BinaryModuleVisitor(ctx), + on_enter_return_call_indirect: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_return_call_indirect: Some(on_enter_return_call_indirect), + ) +} + +pub fn on_exit_return_call_indirect( + visitor: BinaryModuleVisitor(ctx), + on_exit_return_call_indirect: VisitorCallback(ctx, Instruction), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_return_call_indirect: Some(on_exit_return_call_indirect), + ) +} + +pub fn on_enter_label_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_label_idx: VisitorCallback(ctx, LabelIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_label_idx: Some(on_enter_label_idx)) +} + +pub fn on_exit_label_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_label_idx: VisitorCallback(ctx, LabelIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_label_idx: Some(on_exit_label_idx)) +} + +pub fn on_enter_block_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor(..visitor, on_enter_block_type: Some(on_enter_block_type)) +} + +pub fn on_exit_block_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor(..visitor, on_exit_block_type: Some(on_exit_block_type)) +} + +pub fn on_enter_void_block_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_void_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_void_block_type: Some(on_enter_void_block_type), + ) +} + +pub fn on_exit_void_block_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_void_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_void_block_type: Some(on_exit_void_block_type), + ) +} + +pub fn on_enter_val_type_block_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_val_type_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_val_type_block_type: Some(on_enter_val_type_block_type), + ) +} + +pub fn on_exit_val_type_block_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_val_type_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_val_type_block_type: Some(on_exit_val_type_block_type), + ) +} + +pub fn on_enter_func_type_block_type( + visitor: BinaryModuleVisitor(ctx), + on_enter_func_type_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor( + ..visitor, + on_enter_func_type_block_type: Some(on_enter_func_type_block_type), + ) +} + +pub fn on_exit_func_type_block_type( + visitor: BinaryModuleVisitor(ctx), + on_exit_func_type_block_type: VisitorCallback(ctx, BlockType), +) { + BinaryModuleVisitor( + ..visitor, + on_exit_func_type_block_type: Some(on_exit_func_type_block_type), + ) +} + +pub fn on_enter_field_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_field_idx: VisitorCallback(ctx, FieldIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_field_idx: Some(on_enter_field_idx)) +} + +pub fn on_exit_field_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_field_idx: VisitorCallback(ctx, FieldIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_field_idx: Some(on_exit_field_idx)) +} + +pub fn on_enter_data_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_data_idx: VisitorCallback(ctx, DataIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_data_idx: Some(on_enter_data_idx)) +} + +pub fn on_exit_data_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_data_idx: VisitorCallback(ctx, DataIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_data_idx: Some(on_exit_data_idx)) +} + +pub fn on_enter_elem_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_elem_idx: VisitorCallback(ctx, ElemIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_elem_idx: Some(on_enter_elem_idx)) +} + +pub fn on_exit_elem_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_elem_idx: VisitorCallback(ctx, ElemIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_elem_idx: Some(on_exit_elem_idx)) +} + +pub fn on_enter_local_idx( + visitor: BinaryModuleVisitor(ctx), + on_enter_local_idx: VisitorCallback(ctx, LocalIDX), +) { + BinaryModuleVisitor(..visitor, on_enter_local_idx: Some(on_enter_local_idx)) +} + +pub fn on_exit_local_idx( + visitor: BinaryModuleVisitor(ctx), + on_exit_local_idx: VisitorCallback(ctx, LocalIDX), +) { + BinaryModuleVisitor(..visitor, on_exit_local_idx: Some(on_exit_local_idx)) +} + +pub fn visit_module( + visitor: BinaryModuleVisitor(ctx), + ctx, + module: BinaryModule, +) -> Result(#(ctx, BinaryModule), String) { + do_visit_module(ctx, module, visitor) +} + +pub fn visit_type_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + type_section: TypeSection, +) -> Result(#(ctx, Option(TypeSection)), String) { + do_visit_type_section(ctx, Some(type_section), visitor) +} + +pub fn visit_rec_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + rec_type: RecType, +) -> Result(#(ctx, RecType), String) { + do_visit_rec_type(ctx, rec_type, visitor) +} + +pub fn visit_sub_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + sub_type: SubType, +) -> Result(#(ctx, SubType), String) { + do_visit_sub_type(ctx, sub_type, visitor) +} + +pub fn visit_type_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + type_idx: TypeIDX, +) -> Result(#(ctx, TypeIDX), String) { + do_visit_type_idx(ctx, type_idx, visitor) +} + +pub fn visit_composite_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + composite_type: CompositeType, +) -> Result(#(ctx, CompositeType), String) { + do_visit_composite_type(ctx, composite_type, visitor) +} + +pub fn visit_def_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + def_type: DefType, +) -> Result(#(ctx, DefType), String) { + do_visit_def_type(ctx, def_type, visitor) +} + +pub fn visit_func_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + func_type: FuncType, +) -> Result(#(ctx, FuncType), String) { + do_visit_func_type(ctx, func_type, visitor) +} + +pub fn visit_val_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + val_type: ValType, +) -> Result(#(ctx, ValType), String) { + do_visit_val_type(ctx, val_type, visitor) +} + +pub fn visit_ref_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + ref_type: RefType, +) -> Result(#(ctx, RefType), String) { + do_visit_ref_type(ctx, ref_type, visitor) +} + +pub fn visit_struct_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + struct_type: StructType, +) -> Result(#(ctx, StructType), String) { + do_visit_struct_type(ctx, struct_type, visitor) +} + +pub fn visit_array_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + array_type: ArrayType, +) -> Result(#(ctx, ArrayType), String) { + do_visit_array_type(ctx, array_type, visitor) +} + +pub fn visit_custom_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + custom_section: CustomSection, +) -> Result(#(ctx, Option(CustomSection)), String) { + do_visit_custom_section(ctx, custom_section, visitor) +} + +pub fn visit_import_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + imports: ImportSection, +) -> Result(#(ctx, Option(ImportSection)), String) { + do_visit_import_section(ctx, Some(imports), visitor) +} + +pub fn visit_import( + visitor: BinaryModuleVisitor(ctx), + ctx, + import_: Import, +) -> Result(#(ctx, Import), String) { + do_visit_import(ctx, import_, visitor) +} + +pub fn visit_function_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + functions: FunctionSection, +) -> Result(#(ctx, Option(FunctionSection)), String) { + do_visit_function_section(ctx, Some(functions), visitor) +} + +pub fn visit_table_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + tables: TableSection, +) -> Result(#(ctx, Option(TableSection)), String) { + do_visit_table_section(ctx, Some(tables), visitor) +} + +pub fn visit_memory_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + memories: MemorySection, +) -> Result(#(ctx, Option(MemorySection)), String) { + do_visit_memory_section(ctx, Some(memories), visitor) +} + +pub fn visit_global_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + globals: GlobalSection, +) -> Result(#(ctx, Option(GlobalSection)), String) { + do_visit_global_section(ctx, Some(globals), visitor) +} + +pub fn visit_global( + visitor: BinaryModuleVisitor(ctx), + ctx, + global: Global, +) -> Result(#(ctx, Global), String) { + do_visit_global(ctx, global, visitor) +} + +pub fn visit_export_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + exports: ExportSection, +) -> Result(#(ctx, Option(ExportSection)), String) { + do_visit_export_section(ctx, Some(exports), visitor) +} + +pub fn visit_export( + visitor: BinaryModuleVisitor(ctx), + ctx, + export: Export, +) -> Result(#(ctx, Export), String) { + do_visit_export(ctx, export, visitor) +} + +pub fn visit_start_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + start: StartSection, +) -> Result(#(ctx, Option(StartSection)), String) { + do_visit_start_section(ctx, Some(start), visitor) +} + +pub fn visit_element_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + element_section: ElementSection, +) -> Result(#(ctx, Option(ElementSection)), String) { + do_visit_element_section(ctx, Some(element_section), visitor) +} + +pub fn visit_element_segment( + visitor: BinaryModuleVisitor(ctx), + ctx, + element_segment: Elem, +) -> Result(#(ctx, Elem), String) { + do_visit_element_segment(ctx, element_segment, visitor) +} + +pub fn visit_element_mode( + visitor: BinaryModuleVisitor(ctx), + ctx, + element_mode: ElemMode, +) -> Result(#(ctx, ElemMode), String) { + do_visit_element_mode(ctx, element_mode, visitor) +} + +pub fn visit_code_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + code_section: CodeSection, +) -> Result(#(ctx, Option(CodeSection)), String) { + do_visit_code_section(ctx, Some(code_section), visitor) +} + +pub fn visit_code( + visitor: BinaryModuleVisitor(ctx), + ctx, + code: Code, +) -> Result(#(ctx, Code), String) { + do_visit_code(ctx, code, visitor) +} + +pub fn visit_locals( + visitor: BinaryModuleVisitor(ctx), + ctx, + locals: Locals, +) -> Result(#(ctx, Locals), String) { + do_visit_locals(ctx, locals, visitor) +} + +pub fn visit_data_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + data_section: DataSection, +) -> Result(#(ctx, Option(DataSection)), String) { + do_visit_data_section(ctx, Some(data_section), visitor) +} + +pub fn visit_data( + visitor: BinaryModuleVisitor(ctx), + ctx, + data: Data, +) -> Result(#(ctx, Data), String) { + do_visit_data(ctx, data, visitor) +} + +pub fn visit_data_count_section( + visitor: BinaryModuleVisitor(ctx), + ctx, + data_count: DataCountSection, +) -> Result(#(ctx, Option(DataCountSection)), String) { + do_visit_data_count_section(ctx, Some(data_count), visitor) +} + +pub fn visit_heap_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + heap_type: HeapType, +) -> Result(#(ctx, HeapType), String) { + do_visit_heap_type(ctx, heap_type, visitor) +} + +pub fn visit_field_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + field_type: FieldType, +) -> Result(#(ctx, FieldType), String) { + do_visit_field_type(ctx, field_type, visitor) +} + +pub fn visit_storage_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + storage_type: StorageType, +) -> Result(#(ctx, StorageType), String) { + do_visit_storage_type(ctx, storage_type, visitor) +} + +pub fn visit_table_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + table_type: TableType, +) -> Result(#(ctx, TableType), String) { + do_visit_table_type(ctx, table_type, visitor) +} + +pub fn visit_limits( + visitor: BinaryModuleVisitor(ctx), + ctx, + limits: Limits, +) -> Result(#(ctx, Limits), String) { + do_visit_limits(ctx, limits, visitor) +} + +pub fn visit_mem_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + mem_type: MemType, +) -> Result(#(ctx, MemType), String) { + do_visit_mem_type(ctx, mem_type, visitor) +} + +pub fn visit_global_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + global_type: GlobalType, +) -> Result(#(ctx, GlobalType), String) { + do_visit_global_type(ctx, global_type, visitor) +} + +pub fn visit_table( + visitor: BinaryModuleVisitor(ctx), + ctx, + table: Table, +) -> Result(#(ctx, Table), String) { + do_visit_table(ctx, table, visitor) +} + +pub fn visit_expr( + visitor: BinaryModuleVisitor(ctx), + ctx, + expr: Expr, +) -> Result(#(ctx, Expr), String) { + do_visit_expr(ctx, expr, visitor) +} + +pub fn visit_instruction( + visitor: BinaryModuleVisitor(ctx), + ctx, + instruction: Instruction, +) -> Result(#(ctx, Instruction), String) { + do_visit_instruction(ctx, instruction, visitor) +} + +pub fn visit_func_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + func_idx: FuncIDX, +) -> Result(#(ctx, FuncIDX), String) { + do_visit_func_idx(ctx, func_idx, visitor) +} + +pub fn visit_table_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + table_idx: TableIDX, +) -> Result(#(ctx, TableIDX), String) { + do_visit_table_idx(ctx, table_idx, visitor) +} + +pub fn visit_mem_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + mem_idx: MemIDX, +) -> Result(#(ctx, MemIDX), String) { + do_visit_mem_idx(ctx, mem_idx, visitor) +} + +pub fn visit_global_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + global_idx: GlobalIDX, +) -> Result(#(ctx, GlobalIDX), String) { + do_visit_global_idx(ctx, global_idx, visitor) +} + +pub fn visit_label_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + label_idx: LabelIDX, +) -> Result(#(ctx, LabelIDX), String) { + do_visit_label_idx(ctx, label_idx, visitor) +} + +pub fn visit_field_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + field_idx: FieldIDX, +) -> Result(#(ctx, FieldIDX), String) { + do_visit_field_idx(ctx, field_idx, visitor) +} + +pub fn visit_data_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + data_idx: DataIDX, +) -> Result(#(ctx, DataIDX), String) { + do_visit_data_idx(ctx, data_idx, visitor) +} + +pub fn visit_elem_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + elem_idx: ElemIDX, +) -> Result(#(ctx, ElemIDX), String) { + do_visit_elem_idx(ctx, elem_idx, visitor) +} + +pub fn visit_local_idx( + visitor: BinaryModuleVisitor(ctx), + ctx, + local_idx: LocalIDX, +) -> Result(#(ctx, LocalIDX), String) { + do_visit_local_idx(ctx, local_idx, visitor) +} + +pub fn visit_block_type( + visitor: BinaryModuleVisitor(ctx), + ctx, + block_type: BlockType, +) -> Result(#(ctx, BlockType), String) { + do_visit_block_type(ctx, block_type, visitor) +} + +pub fn new() { + visitor.empty_visitor +} + +pub type BinaryModuleVisitor(ctx) = + visitor.BinaryModuleVisitor(ctx) diff --git a/test/decode_test.gleam b/test/decode_test.gleam index 3e651d3..3aa8701 100644 --- a/test/decode_test.gleam +++ b/test/decode_test.gleam @@ -4,6 +4,7 @@ import builder/instructions/ref import gleam/bit_array import gleam/bytes_builder import gleam/io +import gleam/list import gleam/option.{type Option, None, Some} import gleam/pair import gleeunit/should @@ -11,7 +12,6 @@ import internal/binary/common import internal/binary/modules import internal/binary/types import internal/binary/values -import internal/finger_tree import internal/structure/modules as structure_modules import internal/structure/numbers import internal/structure/types.{ @@ -19,7 +19,7 @@ import internal/structure/types.{ } as structure_types pub fn func_idx_to_expr(expr: FuncIDX) { - Expr([RefFunc(expr)] |> finger_tree.from_list) + Expr([RefFunc(expr)]) } fn should_equal_helper(val: Result(u, String), expected: u) { @@ -176,13 +176,11 @@ pub fn decode_result_type_test() { <<0>> |> types.decode_result_type |> should.be_ok - |> pair.map_first(finger_tree.to_list) |> should.equal(#([], <<>>)) <<4, 0x7F, 0x7E, 0x7D, 0x7C>> |> types.decode_result_type |> should.be_ok - |> pair.map_first(finger_tree.to_list) |> should.equal( #( [ @@ -269,12 +267,12 @@ pub fn decode_struct_type_test() { <<0>> |> types.decode_struct_type |> should.be_ok - |> should.equal(#(structure_types.StructType(finger_tree.empty), <<>>)) + |> should.equal(#(structure_types.StructType([]), <<>>)) <<6, 0x7F, 0x00, 0x78, 0x00, 0x77, 0x00, 0x7F, 0x01, 0x78, 0x01, 0x77, 0x01>> |> types.decode_struct_type |> should.be_ok - |> pair.map_first(fn(e) { e.ft |> finger_tree.to_list }) + |> pair.map_first(fn(e) { e.ft }) |> should.equal( #( [ @@ -309,25 +307,18 @@ pub fn decode_struct_type_test() { } fn func_type_equals(a: structure_types.FuncType, b: structure_types.FuncType) { - a.parameters - |> finger_tree.to_list - |> should.equal(b.parameters |> finger_tree.to_list) - a.results - |> finger_tree.to_list - |> should.equal(b.results |> finger_tree.to_list) + a |> should.equal(b) } fn struct_type_equals( a: structure_types.StructType, b: structure_types.StructType, ) { - a.ft - |> finger_tree.to_list - |> should.equal(b.ft |> finger_tree.to_list) + a |> should.equal(b) } fn array_type_equals(a: structure_types.ArrayType, b: structure_types.ArrayType) { - a.ft |> should.equal(b.ft) + a |> should.equal(b) } fn composite_type_equals( @@ -362,10 +353,7 @@ fn decode_type_equals_helper( pub fn decode_composite_type_test() { decode_type_equals_helper( <<0x60, 0x00, 0x00>>, - structure_types.FuncCompositeType(structure_types.FuncType( - finger_tree.new(), - finger_tree.new(), - )), + structure_types.FuncCompositeType(structure_types.FuncType([], [])), types.decode_comp_type, composite_type_equals, ) @@ -376,34 +364,32 @@ pub fn decode_composite_type_test() { 0x77, 0x01, >>, structure_types.StructCompositeType( - structure_types.StructType( - finger_tree.from_list([ - structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Const, - ), - structure_types.FieldType( - structure_types.I8StorageType, - structure_types.Const, - ), - structure_types.FieldType( - structure_types.I16StorageType, - structure_types.Const, - ), - structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Var, - ), - structure_types.FieldType( - structure_types.I8StorageType, - structure_types.Var, - ), - structure_types.FieldType( - structure_types.I16StorageType, - structure_types.Var, - ), - ]), - ), + structure_types.StructType([ + structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Const, + ), + structure_types.FieldType( + structure_types.I8StorageType, + structure_types.Const, + ), + structure_types.FieldType( + structure_types.I16StorageType, + structure_types.Const, + ), + structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Var, + ), + structure_types.FieldType( + structure_types.I8StorageType, + structure_types.Var, + ), + structure_types.FieldType( + structure_types.I16StorageType, + structure_types.Var, + ), + ]), ), types.decode_comp_type, composite_type_equals, @@ -434,45 +420,31 @@ pub fn decode_composite_type_test() { } fn do_type_idxs_equal( - a: finger_tree.FingerTree(structure_types.TypeIDX), - b: finger_tree.FingerTree(structure_types.TypeIDX), + a: List(structure_types.TypeIDX), + b: List(structure_types.TypeIDX), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty - -> { - a |> should.equal(b) - Nil - } - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [], [] -> Nil + [a], [b] -> a |> should.equal(b) + [a, ..rest_a], [b, ..rest_b] -> { a |> should.equal(b) do_type_idxs_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil - _, _ -> panic as "TypeIdxs were not equal" + _, _ -> panic as "Type indexes don't match!" } } fn do_func_idxs_equal( - a: finger_tree.FingerTree(structure_types.FuncIDX), - b: finger_tree.FingerTree(structure_types.FuncIDX), + a: List(structure_types.FuncIDX), + b: List(structure_types.FuncIDX), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty - -> { - a |> should.equal(b) - Nil - } - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> a |> should.equal(b) + [a, ..rest_a], [b, ..rest_b] -> { a |> should.equal(b) do_func_idxs_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil - _, _ -> { - io.debug(#("funcs are not equal: ", a, " != ", b)) - panic as "FuncIDXs were not equal" - } + _, _ -> panic as "FuncIDXs were not equal" } } @@ -487,21 +459,15 @@ fn rec_type_equals(a: structure_types.RecType, b: structure_types.RecType) { } fn do_sub_types_equal( - a: finger_tree.FingerTree(structure_types.SubType), - b: finger_tree.FingerTree(structure_types.SubType), + a: List(structure_types.SubType), + b: List(structure_types.SubType), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty - -> { - sub_type_equals(a, b) - Nil - } - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> sub_type_equals(a, b) + [a, ..rest_a], [b, ..rest_b] -> { sub_type_equals(a, b) do_sub_types_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "SubTypes were not equal" } } @@ -510,7 +476,7 @@ pub fn decode_rec_type_test() { let subtype_one = structure_types.SubType( True, - finger_tree.new(), + [], structure_types.ArrayCompositeType( structure_types.ArrayType(structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), @@ -518,8 +484,7 @@ pub fn decode_rec_type_test() { )), ), ) - let rec_type_one = - structure_types.RecType(finger_tree.from_list([subtype_one])) + let rec_type_one = structure_types.RecType([subtype_one]) <<0x5E, 0x7F, 0x00>> |> decode_type_equals_helper( @@ -533,25 +498,18 @@ pub fn decode_rec_type_test() { let subtype_two = structure_types.SubType( False, - finger_tree.from_list([ - structure_types.TypeIDX(idx_one), - structure_types.TypeIDX(idx_two), - ]), + [structure_types.TypeIDX(idx_one), structure_types.TypeIDX(idx_two)], structure_types.StructCompositeType( - structure_types.StructType( - finger_tree.from_list([ - structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Const, - ), - ]), - ), + structure_types.StructType([ + structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Const, + ), + ]), ), ) - let rec_type_two = - structure_types.RecType(finger_tree.from_list([subtype_two])) - + let rec_type_two = structure_types.RecType([subtype_two]) <<0x50, 0x02, 0x01, 0x02, 0x5F, 0x01, 0x7F, 0x00>> |> decode_type_equals_helper( rec_type_two, @@ -563,7 +521,7 @@ pub fn decode_rec_type_test() { 0x4E, 0x02, 0x5E, 0x7F, 0x00, 0x50, 0x02, 0x01, 0x02, 0x5F, 0x01, 0x7F, 0x00, >> |> decode_type_equals_helper( - structure_types.RecType(finger_tree.from_list([subtype_one, subtype_two])), + structure_types.RecType([subtype_one, subtype_two]), types.decode_rec_type, rec_type_equals, ) @@ -626,28 +584,23 @@ fn type_section_equals( } fn do_rec_types_equal( - a: finger_tree.FingerTree(structure_types.RecType), - b: finger_tree.FingerTree(structure_types.RecType), + a: List(structure_types.RecType), + b: List(structure_types.RecType), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty - -> { - rec_type_equals(a, b) - Nil - } - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [], [] -> Nil + [a], [b] -> rec_type_equals(a, b) + [a, ..rest_a], [b, ..rest_b] -> { rec_type_equals(a, b) do_rec_types_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "RecTypes were not equal" } } // 1 type section pub fn decode_type_section_test() { - let empty_type_section = structure_modules.TypeSection(finger_tree.new()) + let empty_type_section = structure_modules.TypeSection([]) <<0x01, 0x01, 0x00>> |> decode_type_equals_helper( @@ -657,26 +610,23 @@ pub fn decode_type_section_test() { ) let array_type_example = - structure_types.RecType( - finger_tree.from_list([ - structure_types.SubType( - True, - finger_tree.new(), - structure_types.ArrayCompositeType( - structure_types.ArrayType(structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Const, - )), - ), + structure_types.RecType([ + structure_types.SubType( + True, + [], + structure_types.ArrayCompositeType( + structure_types.ArrayType(structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Const, + )), ), - ]), - ) + ), + ]) let array_example_type = <<0x5E, 0x7F, 0x00>> let array_example_length = <<0x01>> let example_type_section_length = <<0x04>> - let example_type_section = - structure_modules.TypeSection(finger_tree.from_list([array_type_example])) + let example_type_section = structure_modules.TypeSection([array_type_example]) << 0x01, @@ -703,21 +653,16 @@ fn import_section_equals( } fn do_imports_equal( - a: finger_tree.FingerTree(structure_types.Import), - b: finger_tree.FingerTree(structure_types.Import), + a: List(structure_types.Import), + b: List(structure_types.Import), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty - -> { - import_equals(a, b) - Nil - } - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [], [] -> Nil + [a], [b] -> import_equals(a, b) + [a, ..rest_a], [b, ..rest_b] -> { import_equals(a, b) do_imports_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "Imports were not equal" } } @@ -758,7 +703,7 @@ fn import_equals(a: structure_types.Import, b: structure_types.Import) { // 2 import section pub fn decode_import_section_test() { - let empty_import_section = structure_modules.ImportSection(finger_tree.new()) + let empty_import_section = structure_modules.ImportSection([]) <<0x02, 0x01, 0x00>> |> decode_type_equals_helper( @@ -794,9 +739,7 @@ pub fn decode_import_section_test() { let func_import_bytes_length = bit_array.byte_size(func_import_bytes) let example_import_section = - structure_modules.ImportSection( - finger_tree.from_list([func_import_example]), - ) + structure_modules.ImportSection([func_import_example]) <<0x02, func_import_bytes_length, func_import_bytes:bits>> |> decode_type_equals_helper( Some(example_import_section), @@ -816,10 +759,8 @@ fn function_section_equals( } } -// 3 function section pub fn decode_function_section_test() { - let empty_function_section = - structure_modules.FunctionSection(finger_tree.new()) + let empty_function_section = structure_modules.FunctionSection([]) <<0x03, 0x01, 0x00>> |> decode_type_equals_helper( @@ -828,12 +769,9 @@ pub fn decode_function_section_test() { function_section_equals, ) - let assert Ok(indexes) = - [1, 2, 3, 4] - |> finger_tree.from_list - |> finger_tree.try_map(numbers.u32) + let assert Ok(indexes) = [1, 2, 3, 4] |> list.try_map(numbers.u32) - let indexes = indexes |> finger_tree.map(structure_types.TypeIDX) + let indexes = indexes |> list.map(structure_types.TypeIDX) let function_section = structure_modules.FunctionSection(indexes) @@ -857,15 +795,16 @@ fn table_section_equals( } fn do_tables_equal( - a: finger_tree.FingerTree(structure_types.Table), - b: finger_tree.FingerTree(structure_types.Table), + a: List(structure_types.Table), + b: List(structure_types.Table), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [], [] -> Nil + [a], [b] -> a |> table_equals(b) + [a, ..rest_a], [b, ..rest_b] -> { a |> table_equals(b) do_tables_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "Tables were not equal" } } @@ -917,7 +856,7 @@ fn table_equals(a: structure_types.Table, b: structure_types.Table) { // 4 table section pub fn decode_table_section_test() { - let empty_table_section = structure_modules.TableSection(finger_tree.new()) + let empty_table_section = structure_modules.TableSection([]) <<0x04, 0x01, 0x00>> |> decode_type_equals_helper( @@ -951,7 +890,7 @@ pub fn decode_table_section_test() { second_table_bits |> decode_type_equals_helper( - Some(structure_modules.TableSection(finger_tree.from_list([second_table]))), + Some(structure_modules.TableSection([second_table])), modules.decode_table_section, table_section_equals, ) @@ -974,9 +913,7 @@ pub fn decode_table_section_test() { <<0x04, 0x09, 0x01, table_bytes_three:bits>> |> decode_type_equals_helper( - Some( - structure_modules.TableSection(finger_tree.from_list([table_init_three])), - ), + Some(structure_modules.TableSection([table_init_three])), modules.decode_table_section, table_section_equals, ) @@ -990,15 +927,16 @@ fn mem_types_equals(a: structure_types.MemType, b: structure_types.MemType) { } fn do_mem_types_equal( - a: finger_tree.FingerTree(structure_types.MemType), - b: finger_tree.FingerTree(structure_types.MemType), + a: List(structure_types.MemType), + b: List(structure_types.MemType), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> a |> mem_types_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { a |> mem_types_equals(b) do_mem_types_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "MemoryTypes were not equal" } } @@ -1024,7 +962,7 @@ fn memory_section_equals( // 5 memory section pub fn decode_memory_section_test() { - let empty_memory_section = structure_modules.MemorySection(finger_tree.new()) + let empty_memory_section = structure_modules.MemorySection([]) <<0x05, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1044,9 +982,7 @@ pub fn decode_memory_section_test() { <<0x05, section_length:bits, memory_count:bits, memory_type:bits>> |> decode_type_equals_helper( - Some( - structure_modules.MemorySection(finger_tree.from_list([example_memory])), - ), + Some(structure_modules.MemorySection([example_memory])), modules.decode_memory_section, memory_section_equals, ) @@ -1066,15 +1002,16 @@ fn globals_equals(a: structure_types.Global, b: structure_types.Global) { } fn do_globals_equal( - a: finger_tree.FingerTree(structure_types.Global), - b: finger_tree.FingerTree(structure_types.Global), + a: List(structure_types.Global), + b: List(structure_types.Global), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> a |> globals_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { a |> globals_equals(b) do_globals_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "Globals were not equal" } } @@ -1093,7 +1030,7 @@ fn global_section_equals( // 6 global section pub fn decode_global_section_test() { - let empty_global_section = structure_modules.GlobalSection(finger_tree.new()) + let empty_global_section = structure_modules.GlobalSection([]) <<0x06, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1117,9 +1054,7 @@ pub fn decode_global_section_test() { <<0x06, 0x07, 0x01, 0x7F, 0x01, 0x41, 0xC2, 0x00, 0x0B>> |> decode_type_equals_helper( - Some( - structure_modules.GlobalSection(finger_tree.from_list([example_global])), - ), + Some(structure_modules.GlobalSection([example_global])), modules.decode_global_section, global_section_equals, ) @@ -1156,15 +1091,16 @@ fn exports_equals(a: structure_types.Export, b: structure_types.Export) { } fn do_exports_equal( - a: finger_tree.FingerTree(structure_types.Export), - b: finger_tree.FingerTree(structure_types.Export), + a: List(structure_types.Export), + b: List(structure_types.Export), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> a |> exports_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { a |> exports_equals(b) do_exports_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "Exports were not equal" } } @@ -1182,7 +1118,7 @@ fn export_section_equals( } pub fn decode_export_section_test() { - let empty_export_section = structure_modules.ExportSection(finger_tree.new()) + let empty_export_section = structure_modules.ExportSection([]) <<0x07, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1206,14 +1142,12 @@ pub fn decode_export_section_test() { structure_types.GlobalExport("global", structure_types.GlobalIDX(four)) let export_section = - structure_modules.ExportSection( - finger_tree.from_list([ - func_export, - table_export, - mem_export, - global_export, - ]), - ) + structure_modules.ExportSection([ + func_export, + table_export, + mem_export, + global_export, + ]) << 0x07, 31, // placeholder @@ -1274,16 +1208,17 @@ pub fn decode_start_section_test() { // 9 element section fn do_expressions_equals( - a: finger_tree.FingerTree(structure_types.Expr), - b: finger_tree.FingerTree(structure_types.Expr), + a: List(structure_types.Expr), + b: List(structure_types.Expr), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> a |> expr_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { a |> expr_equals(b) do_expressions_equals(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil - _, _ -> panic as "Expressions were not equal" + _, _ -> panic as "Exports were not equal" } } @@ -1312,15 +1247,16 @@ fn elements_equals(a: structure_types.Elem, b: structure_types.Elem) { } fn do_elements_equal( - a: finger_tree.FingerTree(structure_types.Elem), - b: finger_tree.FingerTree(structure_types.Elem), + a: List(structure_types.Elem), + b: List(structure_types.Elem), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { + case a, b { + [a], [b] -> a |> elements_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { a |> elements_equals(b) do_elements_equal(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "Elements were not equal" } } @@ -1338,8 +1274,7 @@ fn element_section_equals( } pub fn decode_element_section_test() { - let empty_element_section = - structure_modules.ElementSection(finger_tree.new()) + let empty_element_section = structure_modules.ElementSection([]) <<0x09, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1363,7 +1298,7 @@ pub fn decode_element_section_test() { let ref_func = structure_types.HeapTypeRefType(structure_types.FuncHeapType, False) - // Elem(type_: RefType, init: FingerTree(Expr), mode: ElemMode) + // Elem(type_: RefType, init: List(Expr), mode: ElemMode) let ref_null_i31 = structure_types.I31RefType let null_i31 = @@ -1371,17 +1306,15 @@ pub fn decode_element_section_test() { |> ref.null(structure_types.I31HeapType) |> expression.end_unwrap() - let three_null_i31 = finger_tree.from_list([null_i31, null_i31, null_i31]) + let three_null_i31 = [null_i31, null_i31, null_i31] - let three_func_idx = - finger_tree.from_list([ - structure_types.FuncIDX(zero), - structure_types.FuncIDX(one), - structure_types.FuncIDX(two), - ]) + let three_func_idx = [ + structure_types.FuncIDX(zero), + structure_types.FuncIDX(one), + structure_types.FuncIDX(two), + ] - let three_func_idx_expression = - three_func_idx |> finger_tree.map(func_idx_to_expr) + let three_func_idx_expression = three_func_idx |> list.map(func_idx_to_expr) // type 0 -> (ref func) (init: FuncIDX*) Active(TableIDX(0), Offset(offset_fourty_two)) let element_zero = @@ -1583,18 +1516,16 @@ pub fn decode_element_section_test() { ) let element_section = - structure_modules.ElementSection( - finger_tree.from_list([ - element_zero, - element_one, - element_two, - element_three, - element_four, - element_five, - element_six, - element_seven, - ]), - ) + structure_modules.ElementSection([ + element_zero, + element_one, + element_two, + element_three, + element_four, + element_five, + element_six, + element_seven, + ]) let element_section_byte_length = 1 @@ -1646,15 +1577,16 @@ fn locals_equals(a: structure_types.Locals, b: structure_types.Locals) { } fn do_locals_equals( - a: finger_tree.FingerTree(structure_types.Locals), - b: finger_tree.FingerTree(structure_types.Locals), + a: List(structure_types.Locals), + b: List(structure_types.Locals), ) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { - locals_equals(a, b) + case a, b { + [a], [b] -> a |> locals_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { + a |> locals_equals(b) do_locals_equals(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil _, _ -> panic as "Locals were not equal" } } @@ -1665,17 +1597,15 @@ fn codes_equals(a: structure_types.Code, b: structure_types.Code) { expr_equals(a.body, b.body) } -fn do_codes_equals( - a: finger_tree.FingerTree(structure_types.Code), - b: finger_tree.FingerTree(structure_types.Code), -) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { - codes_equals(a, b) +fn do_codes_equals(a: List(structure_types.Code), b: List(structure_types.Code)) { + case a, b { + [a], [b] -> a |> codes_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { + a |> codes_equals(b) do_codes_equals(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil - _, _ -> panic as "Codes were not equal" + _, _ -> panic as "Exports were not equal" } } @@ -1693,27 +1623,22 @@ fn code_section_equals( pub fn code_section_test() { let assert Ok(two) = numbers.u32(2) - let add_locals = - finger_tree.from_list([ - structure_types.Locals(two, structure_types.I32ValType), - ]) + let add_locals = [structure_types.Locals(two, structure_types.I32ValType)] let assert Ok(one) = numbers.i32(1) let assert Ok(forty_one) = numbers.i32(41) let code_section = - structure_modules.CodeSection( - finger_tree.from_list([ - structure_types.Code( - add_locals, - expression.new() - |> i32.const_(forty_one) - |> i32.const_(one) - |> i32.add() - |> expression.end_unwrap(), - ), - ]), - ) + structure_modules.CodeSection([ + structure_types.Code( + add_locals, + expression.new() + |> i32.const_(forty_one) + |> i32.const_(one) + |> i32.add() + |> expression.end_unwrap(), + ), + ]) let code_section_bytes = << 0x0A, 0x0B, @@ -1729,9 +1654,9 @@ pub fn code_section_test() { // 2 i32s // body 0x41, 41, - // i32.const 41 + // i32.const 41 0x41, 1, - // i32.const 1 + // i32.const 1 0x6A, // i32.add 0x0B, @@ -1761,17 +1686,15 @@ fn data_equals(a: structure_types.Data, b: structure_types.Data) { } } -fn do_data_equals( - a: finger_tree.FingerTree(structure_types.Data), - b: finger_tree.FingerTree(structure_types.Data), -) { - case finger_tree.shift(a), finger_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { - data_equals(a, b) +fn do_data_equals(a: List(structure_types.Data), b: List(structure_types.Data)) { + case a, b { + [a], [b] -> a |> data_equals(b) + + [a, ..rest_a], [b, ..rest_b] -> { + a |> data_equals(b) do_data_equals(rest_a, rest_b) } - Error(Nil), Error(Nil) -> Nil - _, _ -> panic as "Data was not equal" + _, _ -> panic as "Datas were not equal" } } @@ -1816,7 +1739,7 @@ pub fn data_section_test() { 0x07, 0x08, 0x09, >>) - let empty_data_section = structure_modules.DataSection(finger_tree.new()) + let empty_data_section = structure_modules.DataSection([]) <<0x0B, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1826,9 +1749,11 @@ pub fn data_section_test() { ) let data_section = - structure_modules.DataSection( - finger_tree.from_list([active_data_zero_idx, passive_data, active_data]), - ) + structure_modules.DataSection([ + active_data_zero_idx, + passive_data, + active_data, + ]) let data_section_bytes = << 0x0B, 23, diff --git a/test/encode_test.gleam b/test/encode_test.gleam index c003f6e..d45c8cb 100644 --- a/test/encode_test.gleam +++ b/test/encode_test.gleam @@ -4,19 +4,19 @@ import builder/instructions/ref import gleam/bit_array import gleam/bytes_builder.{type BytesBuilder} import gleam/io +import gleam/list import gleam/option.{None, Some} import gleeunit/should import internal/binary/common import internal/binary/modules import internal/binary/types import internal/binary/values -import internal/finger_tree import internal/structure/modules as structure_modules import internal/structure/numbers import internal/structure/types.{type FuncIDX, Expr, RefFunc} as structure_types pub fn func_idx_to_expr(expr: FuncIDX) { - Expr([RefFunc(expr)] |> finger_tree.from_list) + Expr([RefFunc(expr)]) } fn should_equal_helper(val: Result(BytesBuilder, String), expected: BitArray) { @@ -174,14 +174,13 @@ pub fn encode_heap_type_ref_type_test() { } pub fn encode_result_type_test() { - let empty = finger_tree.new() - let four = - finger_tree.from_list([ - structure_types.I32ValType, - structure_types.I64ValType, - structure_types.F32ValType, - structure_types.F64ValType, - ]) + let empty = [] + let four = [ + structure_types.I32ValType, + structure_types.I64ValType, + structure_types.F32ValType, + structure_types.F64ValType, + ] bytes_builder.new() |> types.encode_result_type(empty) @@ -245,13 +244,54 @@ pub fn encode_array_type_test() { pub fn encode_struct_type_test() { bytes_builder.new() - |> types.encode_struct_type(structure_types.StructType(finger_tree.new())) + |> types.encode_struct_type(structure_types.StructType([])) |> should_equal_helper(<<0>>) bytes_builder.new() |> types.encode_struct_type( - structure_types.StructType( - finger_tree.from_list([ + structure_types.StructType([ + structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Const, + ), + structure_types.FieldType( + structure_types.I8StorageType, + structure_types.Const, + ), + structure_types.FieldType( + structure_types.I16StorageType, + structure_types.Const, + ), + structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Var, + ), + structure_types.FieldType( + structure_types.I8StorageType, + structure_types.Var, + ), + structure_types.FieldType( + structure_types.I16StorageType, + structure_types.Var, + ), + ]), + ) + |> should_equal_helper(<< + 6, 0x7F, 0x00, 0x78, 0x00, 0x77, 0x00, 0x7F, 0x01, 0x78, 0x01, 0x77, 0x01, + >>) +} + +pub fn encode_composite_type_test() { + bytes_builder.new() + |> types.encode_composite_type( + structure_types.FuncCompositeType(structure_types.FuncType([], [])), + ) + |> should_equal_helper(<<0x60, 0x00, 0x00>>) + + bytes_builder.new() + |> types.encode_composite_type( + structure_types.StructCompositeType( + structure_types.StructType([ structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), structure_types.Const, @@ -279,54 +319,6 @@ pub fn encode_struct_type_test() { ]), ), ) - |> should_equal_helper(<< - 6, 0x7F, 0x00, 0x78, 0x00, 0x77, 0x00, 0x7F, 0x01, 0x78, 0x01, 0x77, 0x01, - >>) -} - -pub fn encode_composite_type_test() { - bytes_builder.new() - |> types.encode_composite_type( - structure_types.FuncCompositeType(structure_types.FuncType( - finger_tree.new(), - finger_tree.new(), - )), - ) - |> should_equal_helper(<<0x60, 0x00, 0x00>>) - - bytes_builder.new() - |> types.encode_composite_type( - structure_types.StructCompositeType( - structure_types.StructType( - finger_tree.from_list([ - structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Const, - ), - structure_types.FieldType( - structure_types.I8StorageType, - structure_types.Const, - ), - structure_types.FieldType( - structure_types.I16StorageType, - structure_types.Const, - ), - structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Var, - ), - structure_types.FieldType( - structure_types.I8StorageType, - structure_types.Var, - ), - structure_types.FieldType( - structure_types.I16StorageType, - structure_types.Var, - ), - ]), - ), - ), - ) |> should_equal_helper(<< 0x5F, 0x06, 0x7F, 0x00, 0x78, 0x00, 0x77, 0x00, 0x7F, 0x01, 0x78, 0x01, 0x77, 0x01, @@ -359,7 +351,7 @@ pub fn encode_rec_type_test() { let subtype_one = structure_types.SubType( True, - finger_tree.new(), + [], structure_types.ArrayCompositeType( structure_types.ArrayType(structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), @@ -369,9 +361,7 @@ pub fn encode_rec_type_test() { ) bytes_builder.new() - |> types.encode_rec_type( - structure_types.RecType(finger_tree.from_list([subtype_one])), - ) + |> types.encode_rec_type(structure_types.RecType([subtype_one])) |> should_equal_helper(<<0x5E, 0x7F, 0x00>>) let assert Ok(idx_one) = numbers.u32(1) @@ -379,32 +369,23 @@ pub fn encode_rec_type_test() { let subtype_two = structure_types.SubType( False, - finger_tree.from_list([ - structure_types.TypeIDX(idx_one), - structure_types.TypeIDX(idx_two), - ]), + [structure_types.TypeIDX(idx_one), structure_types.TypeIDX(idx_two)], structure_types.StructCompositeType( - structure_types.StructType( - finger_tree.from_list([ - structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Const, - ), - ]), - ), + structure_types.StructType([ + structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Const, + ), + ]), ), ) bytes_builder.new() - |> types.encode_rec_type( - structure_types.RecType(finger_tree.from_list([subtype_two])), - ) + |> types.encode_rec_type(structure_types.RecType([subtype_two])) |> should_equal_helper(<<0x50, 0x02, 0x01, 0x02, 0x5F, 0x01, 0x7F, 0x00>>) bytes_builder.new() - |> types.encode_rec_type( - structure_types.RecType(finger_tree.from_list([subtype_one, subtype_two])), - ) + |> types.encode_rec_type(structure_types.RecType([subtype_one, subtype_two])) |> should_equal_helper(<< 0x4E, 0x02, 0x5E, 0x7F, 0x00, 0x50, 0x02, 0x01, 0x02, 0x5F, 0x01, 0x7F, 0x00, >>) @@ -439,33 +420,30 @@ pub fn custom_section_test() { } pub fn type_section_test() { - let empty_type_section = structure_modules.TypeSection(finger_tree.new()) + let empty_type_section = structure_modules.TypeSection([]) bytes_builder.new() |> modules.encode_type_section(empty_type_section) |> should_equal_helper(<<0x01, 0x01, 0x00>>) let array_type_example = - structure_types.RecType( - finger_tree.from_list([ - structure_types.SubType( - True, - finger_tree.new(), - structure_types.ArrayCompositeType( - structure_types.ArrayType(structure_types.FieldType( - structure_types.ValTypeStorageType(structure_types.I32ValType), - structure_types.Const, - )), - ), + structure_types.RecType([ + structure_types.SubType( + True, + [], + structure_types.ArrayCompositeType( + structure_types.ArrayType(structure_types.FieldType( + structure_types.ValTypeStorageType(structure_types.I32ValType), + structure_types.Const, + )), ), - ]), - ) + ), + ]) let array_example_type = <<0x5E, 0x7F, 0x00>> let array_example_length = <<0x01>> let example_type_section_length = <<0x04>> - let example_type_section = - structure_modules.TypeSection(finger_tree.from_list([array_type_example])) + let example_type_section = structure_modules.TypeSection([array_type_example]) bytes_builder.new() |> modules.encode_type_section(example_type_section) @@ -478,7 +456,7 @@ pub fn type_section_test() { } pub fn import_section_test() { - let empty_import_section = structure_modules.ImportSection(finger_tree.new()) + let empty_import_section = structure_modules.ImportSection([]) bytes_builder.new() |> modules.encode_import_section(empty_import_section) @@ -511,9 +489,7 @@ pub fn import_section_test() { let func_import_bytes_length = bit_array.byte_size(func_import_bytes) let example_import_section = - structure_modules.ImportSection( - finger_tree.from_list([func_import_example]), - ) + structure_modules.ImportSection([func_import_example]) bytes_builder.new() |> modules.encode_import_section(example_import_section) @@ -525,19 +501,15 @@ pub fn import_section_test() { } pub fn function_section_test() { - let empty_function_section = - structure_modules.FunctionSection(finger_tree.new()) + let empty_function_section = structure_modules.FunctionSection([]) bytes_builder.new() |> modules.encode_function_section(empty_function_section) |> should_equal_helper(<<0x03, 0x01, 0x00>>) - let assert Ok(indexes) = - [1, 2, 3, 4] - |> finger_tree.from_list - |> finger_tree.try_map(numbers.u32) + let assert Ok(indexes) = [1, 2, 3, 4] |> list.try_map(numbers.u32) - let indexes = indexes |> finger_tree.map(structure_types.TypeIDX) + let indexes = indexes |> list.map(structure_types.TypeIDX) let function_section = structure_modules.FunctionSection(indexes) @@ -547,7 +519,7 @@ pub fn function_section_test() { } pub fn table_section_test() { - let empty_table_section = structure_modules.TableSection(finger_tree.new()) + let empty_table_section = structure_modules.TableSection([]) bytes_builder.new() |> modules.encode_table_section(empty_table_section) @@ -568,7 +540,7 @@ pub fn table_section_test() { bytes_builder.new() |> modules.encode_table_section( - structure_modules.TableSection(finger_tree.from_list([example_table])), + structure_modules.TableSection([example_table]), ) |> should_equal_helper(<< 0x04, @@ -580,7 +552,7 @@ pub fn table_section_test() { let expr = expression.new() |> ref.null(structure_types.ArrayHeapType) - // + // |> expression.end_unwrap() let example_table_init = @@ -595,13 +567,13 @@ pub fn table_section_test() { bytes_builder.new() |> modules.encode_table_section( - structure_modules.TableSection(finger_tree.from_list([example_table_init])), + structure_modules.TableSection([example_table_init]), ) |> should_equal_helper(<<0x04, 0x09, 0x01, example_table_init_bytes:bits>>) } pub fn memory_section_test() { - let empty_memory_section = structure_modules.MemorySection(finger_tree.new()) + let empty_memory_section = structure_modules.MemorySection([]) bytes_builder.new() |> modules.encode_memory_section(empty_memory_section) @@ -618,7 +590,7 @@ pub fn memory_section_test() { bytes_builder.new() |> modules.encode_memory_section( - structure_modules.MemorySection(finger_tree.from_list([example_memory])), + structure_modules.MemorySection([example_memory]), ) |> should_equal_helper(<< 0x05, @@ -629,7 +601,7 @@ pub fn memory_section_test() { } pub fn global_section_test() { - let empty_global_section = structure_modules.GlobalSection(finger_tree.new()) + let empty_global_section = structure_modules.GlobalSection([]) bytes_builder.new() |> modules.encode_global_section(empty_global_section) @@ -648,8 +620,7 @@ pub fn global_section_test() { |> expression.end_unwrap(), ) - let global_section = - structure_modules.GlobalSection(finger_tree.from_list([example_global])) + let global_section = structure_modules.GlobalSection([example_global]) let global_section_bytes = << 0x06, 0x07, 0x01, 0x7F, 0x01, 0x41, 0xC2, 0x00, 0x0B, >> @@ -659,7 +630,7 @@ pub fn global_section_test() { } pub fn export_section_test() { - let empty_export_section = structure_modules.ExportSection(finger_tree.new()) + let empty_export_section = structure_modules.ExportSection([]) bytes_builder.new() |> modules.encode_export_section(empty_export_section) @@ -680,14 +651,12 @@ pub fn export_section_test() { structure_types.GlobalExport("global", structure_types.GlobalIDX(four)) let export_section = - structure_modules.ExportSection( - finger_tree.from_list([ - func_export, - table_export, - mem_export, - global_export, - ]), - ) + structure_modules.ExportSection([ + func_export, + table_export, + mem_export, + global_export, + ]) let export_section_bytes = << 0x07, 31, // placeholder @@ -730,8 +699,7 @@ pub fn start_section_test() { } pub fn element_section_test() { - let empty_element_section = - structure_modules.ElementSection(finger_tree.new()) + let empty_element_section = structure_modules.ElementSection([]) bytes_builder.new() |> modules.encode_element_section(empty_element_section) @@ -752,7 +720,7 @@ pub fn element_section_test() { let ref_func = structure_types.HeapTypeRefType(structure_types.FuncHeapType, False) - // Elem(type_: RefType, init: FingerTree(Expr), mode: ElemMode) + // Elem(type_: RefType, init: List(Expr), mode: ElemMode) let ref_null_i31 = structure_types.HeapTypeRefType(structure_types.I31HeapType, True) @@ -761,17 +729,15 @@ pub fn element_section_test() { |> ref.null(structure_types.I31HeapType) |> expression.end_unwrap() - let three_null_i31 = finger_tree.from_list([null_i31, null_i31, null_i31]) + let three_null_i31 = [null_i31, null_i31, null_i31] - let three_func_idx = - finger_tree.from_list([ - structure_types.FuncIDX(zero), - structure_types.FuncIDX(one), - structure_types.FuncIDX(two), - ]) + let three_func_idx = [ + structure_types.FuncIDX(zero), + structure_types.FuncIDX(one), + structure_types.FuncIDX(two), + ] - let three_func_idx_expression = - three_func_idx |> finger_tree.map(func_idx_to_expr) + let three_func_idx_expression = three_func_idx |> list.map(func_idx_to_expr) // type 0 -> (ref func) (init: FuncIDX*) Active(TableIDX(0), Offset(offset_fourty_two)) let element_zero = @@ -944,18 +910,16 @@ pub fn element_section_test() { |> should_equal_helper(element_seven_bytes) let element_section = - structure_modules.ElementSection( - finger_tree.from_list([ - element_zero, - element_one, - element_two, - element_three, - element_four, - element_five, - element_six, - element_seven, - ]), - ) + structure_modules.ElementSection([ + element_zero, + element_one, + element_two, + element_three, + element_four, + element_five, + element_six, + element_seven, + ]) let element_section_byte_length = 1 @@ -1000,27 +964,22 @@ pub fn element_section_test() { pub fn code_section_test() { let assert Ok(two) = numbers.u32(2) - let add_locals = - finger_tree.from_list([ - structure_types.Locals(two, structure_types.I32ValType), - ]) + let add_locals = [structure_types.Locals(two, structure_types.I32ValType)] let assert Ok(one) = numbers.i32(1) let assert Ok(forty_one) = numbers.i32(41) let code_section = - structure_modules.CodeSection( - finger_tree.from_list([ - structure_types.Code( - add_locals, - expression.new() - |> i32.const_(forty_one) - |> i32.const_(one) - |> i32.add() - |> expression.end_unwrap(), - ), - ]), - ) + structure_modules.CodeSection([ + structure_types.Code( + add_locals, + expression.new() + |> i32.const_(forty_one) + |> i32.const_(one) + |> i32.add() + |> expression.end_unwrap(), + ), + ]) let code_section_bytes = << 0x0A, 0x0B, @@ -1036,9 +995,9 @@ pub fn code_section_test() { // 2 i32s // body 0x41, 41, - // i32.const 41 + // i32.const 41 0x41, 1, - // i32.const 1 + // i32.const 1 0x6A, // i32.add 0x0B, @@ -1079,16 +1038,18 @@ pub fn data_section_test() { 0x07, 0x08, 0x09, >>) - let empty_data_section = structure_modules.DataSection(finger_tree.new()) + let empty_data_section = structure_modules.DataSection([]) bytes_builder.new() |> modules.encode_data_section(empty_data_section) |> should_equal_helper(<<0x0B, 0x01, 0x00>>) let data_section = - structure_modules.DataSection( - finger_tree.from_list([active_data_zero_idx, passive_data, active_data]), - ) + structure_modules.DataSection([ + active_data_zero_idx, + passive_data, + active_data, + ]) let data_section_bytes = << 0x0B, 23, diff --git a/test/instruction_test.gleam b/test/instruction_test.gleam index c2a41e8..5441cac 100644 --- a/test/instruction_test.gleam +++ b/test/instruction_test.gleam @@ -6,7 +6,6 @@ import gleam/string import gleeunit/should import ieee_float import internal/binary/types -import internal/finger_tree import internal/structure/numbers import internal/structure/types as structure_types import pprint @@ -116,19 +115,16 @@ pub fn br_table_test() { let label_c = structure_types.LabelIDX(label_c) let label_list = [label_a, label_b, label_c] - let labels = finger_tree.from_list(label_list) + let labels = label_list let assert Ok(#( structure_types.BrTable(actual_labels, actual_label_default), <<>>, )) = types.decode_instruction(<<0x0E, 3, 1, 2, 3, 42>>) - actual_labels - |> finger_tree.to_list - |> should.equal(label_list) + actual_labels |> should.equal(label_list) - actual_label_default - |> should.equal(label_default) + actual_label_default |> should.equal(label_default) let assert Ok(builder) = types.encode_instruction( @@ -204,7 +200,7 @@ pub fn block_test() { let drop = structure_types.Drop let instruction_list = [local_get1, local_get2, i32_add, drop] - let block_body = structure_types.Expr(finger_tree.from_list(instruction_list)) + let block_body = structure_types.Expr(instruction_list) let assert Ok(#( structure_types.Block( @@ -219,7 +215,6 @@ pub fn block_test() { |> should.equal(structure_types.VoidBlockType) actual_block_body - |> finger_tree.to_list |> should.equal(instruction_list) let assert Ok(builder) = @@ -255,16 +250,14 @@ pub fn loop_test() { )) = types.decode_instruction(<<0x03, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>) - block_body - |> finger_tree.to_list - |> should.equal(instruction_list) + block_body |> should.equal(instruction_list) let assert Ok(builder) = types.encode_instruction( bytes_builder.new(), structure_types.Loop( structure_types.VoidBlockType, - structure_types.Expr(instruction_list |> finger_tree.from_list), + structure_types.Expr(instruction_list), ), ) @@ -284,17 +277,21 @@ pub fn if_test() { let drop = structure_types.Drop let instruction_list = [local_get1, local_get2, i32_add, drop] - let block_body = finger_tree.from_list(instruction_list) + let block_body = instruction_list let assert Ok(#( - structure_types.If(structure_types.VoidBlockType, block_body, None), + structure_types.If(structure_types.VoidBlockType, result_body, None), <<>>, )) = types.decode_instruction(<<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>) - block_body +<<<<<<< HEAD + result_body |> should.equal(instruction_list) +======= + result_body |> finger_tree.to_list |> should.equal(instruction_list) +>>>>>>> 5b7120c (Final push 0.0.1 (#3)) let assert Ok(builder) = types.encode_instruction( @@ -313,7 +310,7 @@ pub fn if_else_test() { let local_get1 = structure_types.LocalGet(local_idx1) let drop = structure_types.Drop - let block_body = finger_tree.from_list([local_get1, drop]) + let block_body = [local_get1, drop] round_trip( structure_types.If( @@ -884,14 +881,12 @@ pub fn select_t_test() { structure_types.F32ValType, structure_types.F64ValType, ] - let val_types = finger_tree.from_list(val_types_list) + let val_types = val_types_list let assert Ok(#(structure_types.SelectT(actual_val_types), <<>>)) = types.decode_instruction(<<0x1C, 0x04, 0x7F, 0x7E, 0x7D, 0x7C>>) - actual_val_types - |> finger_tree.to_list - |> should.equal(val_types_list) + actual_val_types |> should.equal(val_types_list) let assert Ok(builder) = types.encode_instruction( diff --git a/test/shinecoder_test.gleam b/test/shine_coder_test.gleam similarity index 100% rename from test/shinecoder_test.gleam rename to test/shine_coder_test.gleam diff --git a/test/visitor/block_type_test.gleam b/test/visitor/block_type_test.gleam new file mode 100644 index 0000000..34fc92f --- /dev/null +++ b/test/visitor/block_type_test.gleam @@ -0,0 +1,43 @@ +import builder/module +import builder/types/block_type +import builder/types/val_type +import gleam/option.{None} +import visitor +import visitor/visit_test_variant + +pub fn visit_val_type_storage_type_test() { + visit_test_variant.run( + block_type.val_type(val_type.i32), + visitor.on_enter_block_type, + visitor.on_exit_block_type, + visitor.on_enter_val_type_block_type, + visitor.on_exit_val_type_block_type, + visitor.visit_block_type, + None, + ) +} + +pub fn visit_void_block_type_test() { + visit_test_variant.run( + block_type.void, + visitor.on_enter_block_type, + visitor.on_exit_block_type, + visitor.on_enter_void_block_type, + visitor.on_exit_void_block_type, + visitor.visit_block_type, + None, + ) +} + +pub fn visit_func_type_block_type_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + block_type.func_type(type_idx), + visitor.on_enter_block_type, + visitor.on_exit_block_type, + visitor.on_enter_func_type_block_type, + visitor.on_exit_func_type_block_type, + visitor.visit_block_type, + None, + ) +} diff --git a/test/visitor/composite_type_test.gleam b/test/visitor/composite_type_test.gleam new file mode 100644 index 0000000..e53a8b6 --- /dev/null +++ b/test/visitor/composite_type_test.gleam @@ -0,0 +1,44 @@ +import builder/types/composite_type +import builder/types/field_type +import gleam/option.{None} +import visitor +import visitor/visit_test_variant + +pub fn visit_func_composite_type() { + let func_type = composite_type.func_type([], []) + visit_test_variant.run( + func_type, + visitor.on_enter_composite_type, + visitor.on_exit_composite_type, + visitor.on_enter_func_composite_type, + visitor.on_exit_func_composite_type, + visitor.visit_composite_type, + None, + ) +} + +pub fn visit_struct_composite_type() { + let struct_type = composite_type.struct_type([]) + visit_test_variant.run( + struct_type, + visitor.on_enter_composite_type, + visitor.on_exit_composite_type, + visitor.on_enter_struct_composite_type, + visitor.on_exit_struct_composite_type, + visitor.visit_composite_type, + None, + ) +} + +pub fn visit_array_composite_type() { + let array_type = composite_type.array_type(field_type.i16) + visit_test_variant.run( + array_type, + visitor.on_enter_composite_type, + visitor.on_exit_composite_type, + visitor.on_enter_array_composite_type, + visitor.on_exit_array_composite_type, + visitor.visit_composite_type, + None, + ) +} diff --git a/test/visitor/heap_type_test.gleam b/test/visitor/heap_type_test.gleam new file mode 100644 index 0000000..12e2dfa --- /dev/null +++ b/test/visitor/heap_type_test.gleam @@ -0,0 +1,142 @@ +import builder/module +import gleam/option.{None} +import internal/structure/types.{ + AnyHeapType, ArrayHeapType, ConcreteHeapType, EqHeapType, ExternHeapType, + FuncHeapType, I31HeapType, NoExternHeapType, NoFuncHeapType, NoneHeapType, + StructHeapType, +} +import visitor +import visitor/visit_test_variant + +pub fn visit_func_heap_type_test() { + visit_test_variant.run( + FuncHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_func_heap_type, + visitor.on_exit_func_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_no_func_heap_type_test() { + visit_test_variant.run( + NoFuncHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_no_func_heap_type, + visitor.on_exit_no_func_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_extern_heap_type_test() { + visit_test_variant.run( + ExternHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_extern_heap_type, + visitor.on_exit_extern_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_no_extern_heap_type_test() { + visit_test_variant.run( + NoExternHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_no_extern_heap_type, + visitor.on_exit_no_extern_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_any_heap_type_test() { + visit_test_variant.run( + AnyHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_any_heap_type, + visitor.on_exit_any_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_eq_heap_type_test() { + visit_test_variant.run( + EqHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_eq_heap_type, + visitor.on_exit_eq_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_i31_heap_type_test() { + visit_test_variant.run( + I31HeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_i31_heap_type, + visitor.on_exit_i31_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_struct_heap_type_test() { + visit_test_variant.run( + StructHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_struct_heap_type, + visitor.on_exit_struct_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_array_heap_type_test() { + visit_test_variant.run( + ArrayHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_array_heap_type, + visitor.on_exit_array_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_none_heap_type_test() { + visit_test_variant.run( + NoneHeapType, + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_none_heap_type, + visitor.on_exit_none_heap_type, + visitor.visit_heap_type, + None, + ) +} + +pub fn visit_concrete_heap_type_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ConcreteHeapType(type_idx), + visitor.on_enter_heap_type, + visitor.on_exit_heap_type, + visitor.on_enter_concrete_heap_type, + visitor.on_exit_concrete_heap_type, + visitor.visit_heap_type, + None, + ) +} diff --git a/test/visitor/instruction_test.gleam b/test/visitor/instruction_test.gleam new file mode 100644 index 0000000..fa95f23 --- /dev/null +++ b/test/visitor/instruction_test.gleam @@ -0,0 +1,774 @@ +import builder/expression +import builder/instructions/control +import builder/instructions/i32 +import builder/module +import builder/types/block_type +import gleam/option.{None} +import internal/structure/types.{ + ArrayCopy, ArrayFill, ArrayGet, ArrayGetS, ArrayGetU, ArrayInitData, + ArrayInitElem, ArrayNew, ArrayNewData, ArrayNewDefault, ArrayNewElem, + ArrayNewFixed, ArraySet, Block, Br, BrIf, BrOnCast, BrOnCastFail, BrOnNonNull, + BrOnNull, BrTable, Call, CallIndirect, CallRef, DataDrop, ElemDrop, F32ValType, + F64ValType, GlobalGet, GlobalSet, I31HeapType, I31RefType, I32ValType, + I64ValType, If, LocalGet, LocalSet, LocalTee, Loop, MemoryInit, Nop, RefCast, + RefCastNullable, RefFunc, RefNull, RefTest, RefTestNullable, ReturnCall, + ReturnCallIndirect, ReturnCallRef, SelectT, StructGet, StructGetS, StructGetU, + StructSet, TableCopy, TableFill, TableGet, TableGrow, TableInit, TableSet, + TableSize, +} +import values +import visitor +import visitor/visit_test_variant + +pub fn visit_ref_null_test() { + let heap_type = I31HeapType + visit_test_variant.run( + RefNull(heap_type), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_ref_null, + visitor.on_exit_ref_null, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_ref_func_test() { + let assert Ok(func_idx) = module.func_idx(42) + visit_test_variant.run( + RefFunc(func_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_ref_func, + visitor.on_exit_ref_func, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_ref_test_test() { + let heap_type = I31HeapType + visit_test_variant.run( + RefTest(heap_type), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_ref_test, + visitor.on_exit_ref_test, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_ref_test_nullable_test() { + let heap_type = I31HeapType + visit_test_variant.run( + RefTestNullable(heap_type), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_ref_test_nullable, + visitor.on_exit_ref_test_nullable, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_ref_cast_test() { + let heap_type = I31HeapType + visit_test_variant.run( + RefCast(heap_type), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_ref_cast, + visitor.on_exit_ref_cast, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_ref_cast_nullable_test() { + let heap_type = I31HeapType + visit_test_variant.run( + RefCastNullable(heap_type), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_ref_cast_nullable, + visitor.on_exit_ref_cast_nullable, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_struct_get_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(field_idx) = module.field_idx(12) + visit_test_variant.run( + StructGet(type_idx, field_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_struct_get, + visitor.on_exit_struct_get, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_struct_get_s_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(field_idx) = module.field_idx(12) + visit_test_variant.run( + StructGetS(type_idx, field_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_struct_get_s, + visitor.on_exit_struct_get_s, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_struct_get_u_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(field_idx) = module.field_idx(12) + visit_test_variant.run( + StructGetU(type_idx, field_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_struct_get_u, + visitor.on_exit_struct_get_u, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_struct_set_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(field_idx) = module.field_idx(12) + visit_test_variant.run( + StructSet(type_idx, field_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_struct_set, + visitor.on_exit_struct_set, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_new_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArrayNew(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_new, + visitor.on_exit_array_new, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_new_default_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArrayNewDefault(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_new_default, + visitor.on_exit_array_new_default, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_new_data_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(data_idx) = module.data_idx(12) + visit_test_variant.run( + ArrayNewData(type_idx, data_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_new_data, + visitor.on_exit_array_new_data, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_new_elem_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(elem_idx) = module.elem_idx(12) + visit_test_variant.run( + ArrayNewElem(type_idx, elem_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_new_elem, + visitor.on_exit_array_new_elem, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_new_fixed_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(size) = values.u32(12) + visit_test_variant.run( + ArrayNewFixed(type_idx, size), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_new_fixed, + visitor.on_exit_array_new_fixed, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_get_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArrayGet(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_get, + visitor.on_exit_array_get, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_get_s_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArrayGetS(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_get_s, + visitor.on_exit_array_get_s, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_get_u_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArrayGetU(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_get_u, + visitor.on_exit_array_get_u, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_set_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArraySet(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_set, + visitor.on_exit_array_set, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_fill_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ArrayFill(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_fill, + visitor.on_exit_array_fill, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_copy_test() { + let assert Ok(type_idx1) = module.type_idx(42) + let assert Ok(type_idx2) = module.type_idx(43) + visit_test_variant.run( + ArrayCopy(type_idx1, type_idx2), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_copy, + visitor.on_exit_array_copy, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_init_data_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(data_idx) = module.data_idx(12) + visit_test_variant.run( + ArrayInitData(type_idx, data_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_init_data, + visitor.on_exit_array_init_data, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_array_init_elem_test() { + let assert Ok(type_idx) = module.type_idx(42) + let assert Ok(elem_idx) = module.elem_idx(12) + visit_test_variant.run( + ArrayInitElem(type_idx, elem_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_array_init_elem, + visitor.on_exit_array_init_elem, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_select_t_test() { + let val_types = [I32ValType, I64ValType, F32ValType, F64ValType] + + visit_test_variant.run( + SelectT(val_types), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_select_t, + visitor.on_exit_select_t, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_local_get_test() { + let assert Ok(local_idx) = module.local_idx(42) + visit_test_variant.run( + LocalGet(local_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_local_get, + visitor.on_exit_local_get, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_local_set_test() { + let assert Ok(local_idx) = module.local_idx(42) + visit_test_variant.run( + LocalSet(local_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_local_set, + visitor.on_exit_local_set, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_local_tee_test() { + let assert Ok(local_idx) = module.local_idx(42) + visit_test_variant.run( + LocalTee(local_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_local_tee, + visitor.on_exit_local_tee, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_global_get_test() { + let assert Ok(global_idx) = module.global_idx(42) + visit_test_variant.run( + GlobalGet(global_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_global_get, + visitor.on_exit_global_get, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_global_set_test() { + let assert Ok(global_idx) = module.global_idx(42) + visit_test_variant.run( + GlobalSet(global_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_global_set, + visitor.on_exit_global_set, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_get_test() { + let assert Ok(table_idx) = module.table_idx(42) + visit_test_variant.run( + TableGet(table_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_get, + visitor.on_exit_table_get, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_set_test() { + let assert Ok(table_idx) = module.table_idx(42) + visit_test_variant.run( + TableSet(table_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_set, + visitor.on_exit_table_set, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_size_test() { + let assert Ok(table_idx) = module.table_idx(42) + visit_test_variant.run( + TableSize(table_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_size, + visitor.on_exit_table_size, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_grow_test() { + let assert Ok(table_idx) = module.table_idx(42) + visit_test_variant.run( + TableGrow(table_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_grow, + visitor.on_exit_table_grow, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_fill_test() { + let assert Ok(table_idx) = module.table_idx(42) + visit_test_variant.run( + TableFill(table_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_fill, + visitor.on_exit_table_fill, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_copy_test() { + let assert Ok(table_idx) = module.table_idx(42) + let assert Ok(src_idx) = module.table_idx(43) + visit_test_variant.run( + TableCopy(table_idx, src_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_copy, + visitor.on_exit_table_copy, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_table_init_test() { + // TableInit(elem: ElemIDX, idx: TableIDX) + let assert Ok(elem_idx) = module.elem_idx(42) + let assert Ok(table_idx) = module.table_idx(43) + visit_test_variant.run( + TableInit(elem_idx, table_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_table_init, + visitor.on_exit_table_init, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_elem_drop_test() { + let assert Ok(elem_idx) = module.elem_idx(42) + visit_test_variant.run( + ElemDrop(elem_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_elem_drop, + visitor.on_exit_elem_drop, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_memory_init_test() { + let assert Ok(data_idx) = module.data_idx(42) + visit_test_variant.run( + MemoryInit(data_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_memory_init, + visitor.on_exit_memory_init, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_data_drop_test() { + let assert Ok(data_idx) = module.data_idx(42) + visit_test_variant.run( + DataDrop(data_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_data_drop, + visitor.on_exit_data_drop, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_block_test() { + let assert Ok(fourty_one) = values.i32(41) + let assert Ok(one) = values.i32(1) + let body = + expression.new() + |> i32.const_(fourty_one) + |> i32.const_(one) + |> i32.add + |> control.drop + |> expression.end_unwrap + + visit_test_variant.run( + Block(block_type.void, body), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_block, + visitor.on_exit_block, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_loop_test() { + let body = + expression.new() + |> control.nop + |> expression.end_unwrap + + visit_test_variant.run( + Loop(block_type.void, body), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_loop, + visitor.on_exit_loop, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_if_test() { + visit_test_variant.run( + If(block_type.void, [Nop], None), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_if, + visitor.on_exit_if, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_test() { + let assert Ok(label_idx) = module.label_idx(42) + visit_test_variant.run( + Br(label_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br, + visitor.on_exit_br, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_if_test() { + let assert Ok(label_idx) = module.label_idx(42) + visit_test_variant.run( + BrIf(label_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br_if, + visitor.on_exit_br_if, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_table_test() { + let assert Ok(label_idx1) = module.label_idx(42) + let assert Ok(label_idx2) = module.label_idx(43) + let assert Ok(label_idx3) = module.label_idx(44) + let assert Ok(label_idx4) = module.label_idx(45) + let assert Ok(label_idx5) = module.label_idx(46) + let assert Ok(default_label) = module.label_idx(47) + let labels = [label_idx1, label_idx2, label_idx3, label_idx4, label_idx5] + visit_test_variant.run( + BrTable(labels, default_label), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br_table, + visitor.on_exit_br_table, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_on_null_test() { + let assert Ok(label_idx) = module.label_idx(42) + visit_test_variant.run( + BrOnNull(label_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br_on_null, + visitor.on_exit_br_on_null, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_on_non_null_test() { + let assert Ok(label_idx) = module.label_idx(42) + visit_test_variant.run( + BrOnNonNull(label_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br_on_non_null, + visitor.on_exit_br_on_non_null, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_on_cast_test() { + let assert Ok(label_idx) = module.label_idx(42) + let ref_type1 = I31RefType + let ref_type2 = I31RefType + visit_test_variant.run( + BrOnCast(label_idx, ref_type1, ref_type2), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br_on_cast, + visitor.on_exit_br_on_cast, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_br_on_cast_fail_test() { + let assert Ok(label_idx) = module.label_idx(42) + let ref_type1 = I31RefType + let ref_type2 = I31RefType + visit_test_variant.run( + BrOnCastFail(label_idx, ref_type1, ref_type2), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_br_on_cast_fail, + visitor.on_exit_br_on_cast_fail, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_call_test() { + let assert Ok(func_idx) = module.func_idx(42) + visit_test_variant.run( + Call(func_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_call, + visitor.on_exit_call, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_call_ref_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + CallRef(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_call_ref, + visitor.on_exit_call_ref, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_call_indirect_test() { + let assert Ok(table_idx) = module.table_idx(42) + let assert Ok(type_idx) = module.type_idx(12) + visit_test_variant.run( + CallIndirect(table_idx, type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_call_indirect, + visitor.on_exit_call_indirect, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_return_call_test() { + let assert Ok(func_idx) = module.func_idx(42) + visit_test_variant.run( + ReturnCall(func_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_return_call, + visitor.on_exit_return_call, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_return_call_ref_test() { + let assert Ok(type_idx) = module.type_idx(42) + visit_test_variant.run( + ReturnCallRef(type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_return_call_ref, + visitor.on_exit_return_call_ref, + visitor.visit_instruction, + None, + ) +} + +pub fn visit_return_call_indirect_test() { + let assert Ok(table_idx) = module.table_idx(42) + let assert Ok(type_idx) = module.type_idx(12) + visit_test_variant.run( + ReturnCallIndirect(table_idx, type_idx), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_return_call_indirect, + visitor.on_exit_return_call_indirect, + visitor.visit_instruction, + None, + ) +} diff --git a/test/visitor/ref_type_test.gleam b/test/visitor/ref_type_test.gleam new file mode 100644 index 0000000..b1945bc --- /dev/null +++ b/test/visitor/ref_type_test.gleam @@ -0,0 +1,141 @@ +import gleam/option.{None} +import internal/structure/types.{ + AnyRefType, ArrayRefType, EqRefType, ExternRefType, FuncRefType, + HeapTypeRefType, I31HeapType, I31RefType, NoExternRefType, NoFuncRefType, + NoneRefType, StructRefType, +} +import visitor +import visitor/visit_test_variant + +pub fn visit_any_ref_type_test() { + visit_test_variant.run( + AnyRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_any_ref_type, + visitor.on_exit_any_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_eq_ref_type_test() { + visit_test_variant.run( + EqRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_eq_ref_type, + visitor.on_exit_eq_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_i31_ref_type_test() { + visit_test_variant.run( + I31RefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_i31_ref_type, + visitor.on_exit_i31_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_struct_ref_type_test() { + visit_test_variant.run( + StructRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_struct_ref_type, + visitor.on_exit_struct_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_array_ref_type_test() { + visit_test_variant.run( + ArrayRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_array_ref_type, + visitor.on_exit_array_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_func_ref_type_test() { + visit_test_variant.run( + FuncRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_func_ref_type, + visitor.on_exit_func_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_extern_ref_type_test() { + visit_test_variant.run( + ExternRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_extern_ref_type, + visitor.on_exit_extern_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_none_ref_type_test() { + visit_test_variant.run( + NoneRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_none_ref_type, + visitor.on_exit_none_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_no_func_ref_type_test() { + visit_test_variant.run( + NoFuncRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_no_func_ref_type, + visitor.on_exit_no_func_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_no_extern_ref_type_test() { + visit_test_variant.run( + NoExternRefType, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_no_extern_ref_type, + visitor.on_exit_no_extern_ref_type, + visitor.visit_ref_type, + None, + ) +} + +pub fn visit_heap_type_ref_type_test() { + let value = HeapTypeRefType(I31HeapType, False) + visit_test_variant.run( + value, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + visitor.on_enter_heap_type_ref_type, + visitor.on_exit_heap_type_ref_type, + visitor.visit_ref_type, + None, + ) +} diff --git a/test/visitor/storage_type_test.gleam b/test/visitor/storage_type_test.gleam new file mode 100644 index 0000000..0767b4b --- /dev/null +++ b/test/visitor/storage_type_test.gleam @@ -0,0 +1,40 @@ +import builder/types/storage_type +import gleam/option.{None} +import visitor +import visitor/visit_test_variant + +pub fn visit_i8_storage_type_test() { + visit_test_variant.run( + storage_type.i8, + visitor.on_enter_storage_type, + visitor.on_exit_storage_type, + visitor.on_enter_i8_storage_type, + visitor.on_exit_i8_storage_type, + visitor.visit_storage_type, + None, + ) +} + +pub fn visit_i16_storage_type_test() { + visit_test_variant.run( + storage_type.i16, + visitor.on_enter_storage_type, + visitor.on_exit_storage_type, + visitor.on_enter_i16_storage_type, + visitor.on_exit_i16_storage_type, + visitor.visit_storage_type, + None, + ) +} + +pub fn visit_val_type_storage_type_test() { + visit_test_variant.run( + storage_type.i32, + visitor.on_enter_storage_type, + visitor.on_exit_storage_type, + visitor.on_enter_val_type_storage_type, + visitor.on_exit_val_type_storage_type, + visitor.visit_storage_type, + None, + ) +} diff --git a/test/visitor/val_type.gleam b/test/visitor/val_type.gleam new file mode 100644 index 0000000..9bef1c2 --- /dev/null +++ b/test/visitor/val_type.gleam @@ -0,0 +1,85 @@ +import gleam/option.{None} +import internal/structure/types.{ + F32ValType, F64ValType, I31RefType, I32ValType, I64ValType, RefTypeValType, + V128ValType, +} +import visitor +import visitor/visit_test_variant + +pub fn visit_v128_val_type_test() { + let value = V128ValType + visit_test_variant.run( + value, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + visitor.on_enter_v128_val_type, + visitor.on_exit_v128_val_type, + visitor.visit_val_type, + None, + ) +} + +pub fn visit_i32_val_type_test() { + let value = I32ValType + visit_test_variant.run( + value, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + visitor.on_enter_i32_val_type, + visitor.on_exit_i32_val_type, + visitor.visit_val_type, + None, + ) +} + +pub fn visit_i64_val_type_test() { + let value = I64ValType + visit_test_variant.run( + value, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + visitor.on_enter_i64_val_type, + visitor.on_exit_i64_val_type, + visitor.visit_val_type, + None, + ) +} + +pub fn visit_f32_val_type_test() { + let value = F32ValType + visit_test_variant.run( + value, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + visitor.on_enter_f32_val_type, + visitor.on_exit_f32_val_type, + visitor.visit_val_type, + None, + ) +} + +pub fn visit_f64_val_type_test() { + let value = F64ValType + visit_test_variant.run( + value, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + visitor.on_enter_f64_val_type, + visitor.on_exit_f64_val_type, + visitor.visit_val_type, + None, + ) +} + +pub fn visit_ref_type_val_type_test() { + let value = RefTypeValType(I31RefType) + visit_test_variant.run( + value, + visitor.on_enter_val_type, + visitor.on_exit_val_type, + visitor.on_enter_ref_type_val_type, + visitor.on_exit_ref_type_val_type, + visitor.visit_val_type, + None, + ) +} diff --git a/test/visitor/visit_test_variant.gleam b/test/visitor/visit_test_variant.gleam new file mode 100644 index 0000000..df2a078 --- /dev/null +++ b/test/visitor/visit_test_variant.gleam @@ -0,0 +1,82 @@ +import gleam/option.{type Option, None, Some} +import gleeunit/should +import visitor.{type BinaryModuleVisitor} + +type VisitCallback(u) = + fn(VisitorContext, u) -> Result(#(VisitorContext, u), String) + +type VisitorContext = + #(Int, Int, Int, Int) + +type VisitorEventCallback(u) = + fn(BinaryModuleVisitor(VisitorContext), VisitCallback(u)) -> + BinaryModuleVisitor(VisitorContext) + +type DoVisitCallback(u) = + fn(BinaryModuleVisitor(VisitorContext), VisitorContext, u) -> + Result(#(VisitorContext, u), String) + +pub fn run( + expected_value: u, + on_enter_type: VisitorEventCallback(u), + on_exit_type: VisitorEventCallback(u), + on_enter_variant: VisitorEventCallback(u), + on_exit_variant: VisitorEventCallback(u), + visit_func: DoVisitCallback(u), + equality_callback: Option(fn(u, u) -> Bool), +) { + let start_context = #(0, 0, 0, 0) + let expected_context = #(1, 1, 1, 1) + let #(actual_context, actual_value) = + visitor.new() + |> on_enter_type(fn(ctx, actual_value) { + case actual_value == expected_value { + True -> { + let #(a, b, c, d) = ctx + Ok(#(#(a + 1, b, c, d), actual_value)) + } + False -> Ok(#(ctx, actual_value)) + } + }) + |> on_exit_type(fn(ctx, actual_value) { + case actual_value == expected_value { + True -> { + let #(a, b, c, d) = ctx + Ok(#(#(a, b + 1, c, d), actual_value)) + } + False -> Ok(#(ctx, actual_value)) + } + }) + |> on_enter_variant(fn(ctx, actual_value) { + case actual_value == expected_value { + True -> { + let #(a, b, c, d) = ctx + Ok(#(#(a, b, c + 1, d), actual_value)) + } + False -> Ok(#(ctx, actual_value)) + } + }) + |> on_exit_variant(fn(ctx, actual_value) { + case actual_value == expected_value { + True -> { + let #(a, b, c, d) = ctx + Ok(#(#(a, b, c, d + 1), actual_value)) + } + False -> Ok(#(ctx, actual_value)) + } + }) + |> visit_func(start_context, expected_value) + |> should.be_ok + + actual_context + |> should.equal(expected_context) + + case equality_callback { + Some(equality_callback) -> + equality_callback(expected_value, actual_value) + |> should.be_true + None -> + { expected_value == actual_value } + |> should.be_true + } +}