From 6fe8449771bb26fb3745493a28c81c40b2c805bc Mon Sep 17 00:00:00 2001 From: jtenner Date: Wed, 4 Sep 2024 12:31:57 -0400 Subject: [PATCH 01/16] Fix unused variable in if tests --- test/instruction_test.gleam | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/instruction_test.gleam b/test/instruction_test.gleam index c2a41e8..21e2569 100644 --- a/test/instruction_test.gleam +++ b/test/instruction_test.gleam @@ -287,12 +287,12 @@ pub fn if_test() { let block_body = finger_tree.from_list(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 + result_body |> finger_tree.to_list |> should.equal(instruction_list) From 7d90e4b909f4560c6c8a4e853345b6bb8712fe6b Mon Sep 17 00:00:00 2001 From: jtenner Date: Wed, 4 Sep 2024 14:58:56 -0400 Subject: [PATCH 02/16] Potential 0.0.1 release Co-authored-by: Rishit Chaudhary --- CODE_OF_CONDUCT.md | 73 ++++++++ README.md | 11 +- gleam.toml | 2 +- src/builder/instructions/README.md | 17 ++ src/builder/instructions/any.gleam | 1 + src/builder/instructions/array.gleam | 8 +- src/builder/module.gleam | 175 +++++++++++++++-- src/internal/finger_tree.gleam | 13 +- src/internal/structure/types.gleam | 197 ++++++-------------- src/internal/validation/README.md | 14 ++ src/{shinecoder.gleam => shine_coder.gleam} | 2 +- 11 files changed, 345 insertions(+), 168 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 src/builder/instructions/README.md create mode 100644 src/internal/validation/README.md rename src/{shinecoder.gleam => shine_coder.gleam} (94%) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..3296375 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at louis at lpil.uk. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org 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..cdb7e15 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 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/module.gleam b/src/builder/module.gleam index aec40ff..fc5b450 100644 --- a/src/builder/module.gleam +++ b/src/builder/module.gleam @@ -12,18 +12,22 @@ 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, + 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, + 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( @@ -451,6 +455,7 @@ fn add_to_optional_list(items: Option(FingerTree(u)), item: u) { } } +/// Add a new concrete Recursive Type to the TypeSection. pub fn add_type(module: BinaryModule, type_: RecType) { let BinaryModule(types: types, ..) = module case types { @@ -467,6 +472,60 @@ pub fn add_type(module: BinaryModule, type_: RecType) { } } +/// Add a new concrete FuncType to the TypeSection. +pub fn add_func_type( + module: BinaryModule, + parameters: List(ValType), + results: List(ValType), +) { + let 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))) +} + +/// Add a new concrete ArrayType to the TypeSection +pub fn add_array_type(module: BinaryModule, element_type: FieldType) { + let array_type = + SubType( + False, + finger_tree.empty, + ArrayCompositeType(ArrayType(element_type)), + ) + add_type(module, RecType(finger_tree.single(array_type))) +} + +// Add a new StructType to the TypeSection +pub fn add_struct_type(module: BinaryModule, fields: List(FieldType)) { + let struct_type = + SubType( + False, + finger_tree.empty, + StructCompositeType(StructType(finger_tree.from_list(fields))), + ) + + add_type(module, RecType(finger_tree.single(struct_type))) +} + +// Add a new StructType to the TypeSection that is marked as "final" +pub fn add_final_struct_type(module: BinaryModule, fields: List(FieldType)) { + let struct_type = + SubType( + True, + finger_tree.empty, + StructCompositeType(StructType(finger_tree.from_list(fields))), + ) + + add_type(module, RecType(finger_tree.single(struct_type))) +} + /// 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 @@ -586,7 +645,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, @@ -623,7 +682,17 @@ pub fn import_memory( } } -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( @@ -641,8 +710,17 @@ pub fn add_function_type(module: BinaryModule, type_: TypeIDX) { } } -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( @@ -657,6 +735,9 @@ pub fn add_table(module: BinaryModule, table: 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 { @@ -669,8 +750,18 @@ pub fn add_memory(module: BinaryModule, memory: MemType) { } } -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( @@ -693,6 +784,8 @@ 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 { @@ -718,6 +811,8 @@ pub fn export_func(module: BinaryModule, name: String, func: FuncIDX) { } } +/// 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 { @@ -745,6 +840,11 @@ pub fn export_table(module: BinaryModule, name: String, table: TableIDX) { } } +/// Export a memory to the module. The memory is given by it's index into the memory section, +/// and it's name. +/// +/// 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 { @@ -772,6 +872,8 @@ pub fn export_memory(module: BinaryModule, name: String, memory: MemIDX) { } } +/// 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 { @@ -799,10 +901,13 @@ pub fn export_global(module: BinaryModule, name: String, global: GlobalIDX) { } } +/// 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, @@ -841,6 +946,7 @@ pub fn active_funcs_element_segment( } } +/// 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 { @@ -874,6 +980,7 @@ pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) } } +/// 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), @@ -910,6 +1017,9 @@ pub fn declarative_funcs_element_segment( } } +/// 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, @@ -950,6 +1060,8 @@ pub fn active_element_segment( } } +/// 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, @@ -988,6 +1100,8 @@ pub fn passive_element_segment( } } +/// 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, @@ -1056,7 +1170,9 @@ fn do_concatenate_locals( } } -/// 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 @@ -1076,6 +1192,8 @@ pub fn add_code(module: BinaryModule, locals: List(ValType), body: Expr) { } } +/// 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, @@ -1104,6 +1222,8 @@ pub fn add_active_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 { @@ -1122,10 +1242,13 @@ pub fn add_passive_data(module: BinaryModule, data: BitArray) { } } +/// 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 +1256,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 +1264,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 +1272,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 +1280,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 +1288,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 +1296,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 +1304,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 +1312,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 +1320,24 @@ pub fn func_idx(idx: Int) { } } +/// 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/internal/finger_tree.gleam b/src/internal/finger_tree.gleam index e5d27ae..9a9517a 100644 --- a/src/internal/finger_tree.gleam +++ b/src/internal/finger_tree.gleam @@ -1,6 +1,9 @@ +//// Link to FingerTree description: https://www.staff.city.ac.uk/~ross/papers/FingerTree.html + import gleam/option.{type Option, None, Some} import gleam/result +/// Finger tree implementation pub opaque type FingerTree(u) { Empty Single(u) @@ -305,11 +308,6 @@ 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) } @@ -569,6 +567,11 @@ pub fn map_index(tree: FingerTree(u), f: fn(u, Int) -> v) -> FingerTree(v) { tree |> push(f(item, index)) } +pub fn map(tree: FingerTree(u), f: fn(u) -> v) -> FingerTree(v) { + use tree, a <- reducel(tree, Empty) + tree |> push(f(a)) +} + pub fn set(tree: FingerTree(u), target_index: Int, target_item: u) { case tree |> size { n if n > target_index -> Error(Nil) diff --git a/src/internal/structure/types.gleam b/src/internal/structure/types.gleam index c57f338..2c53fd2 100644 --- a/src/internal/structure/types.gleam +++ b/src/internal/structure/types.gleam @@ -6,6 +6,7 @@ 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 } @@ -153,9 +157,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 } } @@ -364,72 +371,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) } @@ -961,7 +911,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, @@ -1591,21 +1541,22 @@ pub fn get_instruction_type( } } -/// 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)) } -/// 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)) 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 +1564,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 +/// 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 +1621,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 +1631,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) } -/// 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 +1653,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/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() From f84d15dd973c86461eccae7e4d6075832552f1cd Mon Sep 17 00:00:00 2001 From: jtenner Date: Wed, 4 Sep 2024 15:05:14 -0400 Subject: [PATCH 03/16] fix test filename, add formatting --- test/{shinecoder_test.gleam => shine_coder_test.gleam} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{shinecoder_test.gleam => shine_coder_test.gleam} (100%) 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 From b9fc44c555683532b7181679d977fa417086eccf Mon Sep 17 00:00:00 2001 From: jtenner Date: Wed, 4 Sep 2024 19:04:37 -0400 Subject: [PATCH 04/16] Start visitor pattern work --- src/internal/validation/common.gleam | 40 ++ src/internal/validation/module.gleam | 27 ++ src/internal/validation/types.gleam | 6 + src/internal/visitor.gleam | 674 +++++++++++++++++++++++++++ 4 files changed, 747 insertions(+) create mode 100644 src/internal/validation/common.gleam create mode 100644 src/internal/validation/module.gleam create mode 100644 src/internal/validation/types.gleam create mode 100644 src/internal/visitor.gleam diff --git a/src/internal/validation/common.gleam b/src/internal/validation/common.gleam new file mode 100644 index 0000000..10f20c2 --- /dev/null +++ b/src/internal/validation/common.gleam @@ -0,0 +1,40 @@ +import gleam/option.{type Option, None} +import internal/finger_tree.{type FingerTree} +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: FingerTree(DefType), + funcs: FingerTree(DefType), + tables: FingerTree(TableType), + mems: FingerTree(MemType), + globals: FingerTree(GlobalType), + elems: FingerTree(Elem), + data: FingerTree(Data), + locals: FingerTree(Locals), + labels: FingerTree(FingerTree(ValType)), + return: Option(FingerTree(ValType)), + refs: FingerTree(FuncIDX), + ) +} + +pub const empty_context = Context( + types: finger_tree.empty, + funcs: finger_tree.empty, + tables: finger_tree.empty, + mems: finger_tree.empty, + globals: finger_tree.empty, + elems: finger_tree.empty, + data: finger_tree.empty, + locals: finger_tree.empty, + labels: finger_tree.empty, + return: None, + refs: finger_tree.empty, +) + +pub fn roll_rec_types(rec_type: RecType) -> FingerTree(DefType) { + todo +} diff --git a/src/internal/validation/module.gleam b/src/internal/validation/module.gleam new file mode 100644 index 0000000..8391c11 --- /dev/null +++ b/src/internal/validation/module.gleam @@ -0,0 +1,27 @@ +import gleam/option.{type Option, None, Some} +import gleam/result +import internal/finger_tree +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.{validate_rec_type} 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: finger_tree.append(ctx_prime.types, def_types)) + use _ <- result.map(validate_rec_type(ctx, rec_type)) + ctx +} + +pub fn validate_module(module: BinaryModule) { + use context <- result.try(case module.types { + Some(TypeSection(types)) -> + finger_tree.try_reducel(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..c0acfa7 --- /dev/null +++ b/src/internal/validation/types.gleam @@ -0,0 +1,6 @@ +import internal/structure/types.{type RecType} +import internal/validation/common.{type Context} + +pub fn validate_rec_type(ctx: Context, rec_type: RecType) -> Result(Nil, String) { + todo +} diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam new file mode 100644 index 0000000..f4a1c82 --- /dev/null +++ b/src/internal/visitor.gleam @@ -0,0 +1,674 @@ +import gleam/option.{type Option, None, Some} +import gleam/result.{map, try} +import internal/finger_tree.{type FingerTree} +import internal/structure/modules.{ + type BinaryModule, type CustomSection, type TypeSection, BinaryModule, + TypeSection, +} +import internal/structure/types.{ + type ArrayType, type CompositeType, type DefType, type FuncType, type HeapType, + type RecType, type RefType, type StructType, type SubType, type TypeIDX, + type ValType, AnyRefType, ArrayCompositeType, ArrayRefType, DefType, + DefTypeReference, EqRefType, ExternRefType, F32ValType, F64ValType, + FuncCompositeType, FuncRefType, FuncType, HeapTypeRefType, I31RefType, + I32ValType, I64ValType, NoExternRefType, NoFuncRefType, NoneRefType, RecType, + RecTypeIDX, RefTypeValType, StructCompositeType, StructRefType, SubType, + TypeIDX, V128ValType, +} + +pub type VisitorCallback(ctx, element) = + fn(ctx, element) -> Result(#(ctx, element), String) + +pub type BinaryModuleVisitor(ctx) { + BinaryModuleVisitor( + on_enter_module: Option(VisitorCallback(ctx, BinaryModule)), + on_exit_module: Option(VisitorCallback(ctx, BinaryModule)), + on_enter_type_section: Option(VisitorCallback(ctx, Option(TypeSection))), + on_exit_type_section: Option(VisitorCallback(ctx, Option(TypeSection))), + 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)), + ) +} + +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_imports( + 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_functions( + 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_tables(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_memories( + 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_globals( + 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_exports( + 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(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_elements( + 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(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(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( + 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)) + } +} + +pub fn do_visit_type_section( + ctx: context, + type_section: Option(TypeSection), + visitor: BinaryModuleVisitor(context), +) { + use #(ctx, type_section) <- try(do_visit( + ctx, + type_section, + visitor.on_enter_type_section, + )) + + use #(ctx, type_section) <- try(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)) + }) + + do_visit(ctx, type_section, visitor.on_exit_type_section) +} + +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: FingerTree(element), + visitor: BinaryModuleVisitor(ctx), + do_visit_callback: fn(ctx, element, BinaryModuleVisitor(ctx)) -> + Result(#(ctx, element), String), +) { + use #(ctx, elements, _) <- map( + finger_tree.try_reducel( + elements, + #(ctx, finger_tree.empty, visitor), + fn(acc, element) { + let #(ctx, acc, visitor) = acc + use #(ctx, element) <- map(do_visit_callback(ctx, element, visitor)) + #(ctx, acc |> finger_tree.push(element), visitor) + }, + ), + ) + + #(ctx, elements) +} + +pub fn do_visit_rec_type( + ctx, + rec_type: RecType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, RecType), String) { + use #(ctx, rec_type) <- try(do_visit(ctx, rec_type, visitor.on_enter_rec_type)) + + use #(ctx, sub_types) <- try(do_visit_element_list( + ctx, + rec_type.sub_types, + visitor, + do_visit_sub_type, + )) + + let rec_type = RecType(sub_types) + + do_visit(ctx, rec_type, visitor.on_exit_rec_type) +} + +pub fn do_visit_sub_type( + ctx, + sub_type, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, SubType), String) { + use #(ctx, SubType(final, t, ct)) <- try(do_visit( + ctx, + sub_type, + visitor.on_enter_sub_type, + )) + + use #(ctx, t) <- try(do_visit_element_list(ctx, t, visitor, do_visit_type_idx)) + + use #(ctx, ct) <- try(do_visit_composite_type(ctx, ct, visitor)) + + let sub_type = SubType(final, t, ct) + do_visit(ctx, sub_type, visitor.on_exit_sub_type) +} + +pub fn do_visit_type_idx( + ctx, + type_idx: TypeIDX, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, TypeIDX), String) { + use #(ctx, type_idx) <- try(do_visit(ctx, type_idx, visitor.on_enter_type_idx)) + + use #(ctx, type_idx) <- try(case type_idx { + TypeIDX(_) -> Ok(#(ctx, type_idx)) + RecTypeIDX(_) -> do_visit(ctx, type_idx, visitor.on_enter_rec_type_idx) + DefTypeReference(_) -> + do_visit(ctx, type_idx, visitor.on_enter_def_type_reference) + }) + + use #(ctx, type_idx) <- try(case type_idx { + DefTypeReference(dt) -> { + use #(ctx, dt) <- map(do_visit_def_type(ctx, dt, visitor)) + + #(ctx, DefTypeReference(dt)) + } + _ -> Ok(#(ctx, type_idx)) + }) + + do_visit(ctx, type_idx, visitor.on_exit_type_idx) +} + +pub fn do_visit_composite_type( + ctx, + composite_type: CompositeType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, CompositeType), String) { + use #(ctx, composite_type) <- try(do_visit( + ctx, + composite_type, + visitor.on_enter_composite_type, + )) + + use #(ctx, composite_type) <- try(case composite_type { + FuncCompositeType(_) -> + do_visit(ctx, composite_type, visitor.on_enter_func_composite_type) + StructCompositeType(_) -> + do_visit(ctx, composite_type, visitor.on_enter_struct_composite_type) + ArrayCompositeType(_) -> + do_visit(ctx, composite_type, visitor.on_enter_array_composite_type) + }) + + use #(ctx, composite_type) <- try(case composite_type { + FuncCompositeType(ty) -> { + use #(ctx, ty) <- map(do_visit_func_type(ctx, ty, visitor)) + #(ctx, FuncCompositeType(ty)) + } + StructCompositeType(ty) -> { + use #(ctx, ty) <- map(do_visit_struct_type(ctx, ty, visitor)) + #(ctx, StructCompositeType(ty)) + } + ArrayCompositeType(ty) -> { + use #(ctx, ty) <- map(do_visit_array_type(ctx, ty, visitor)) + #(ctx, ArrayCompositeType(ty)) + } + }) + + use #(ctx, composite_type) <- try(case composite_type { + FuncCompositeType(_) -> + do_visit(ctx, composite_type, visitor.on_exit_func_composite_type) + StructCompositeType(_) -> + do_visit(ctx, composite_type, visitor.on_exit_struct_composite_type) + ArrayCompositeType(_) -> + do_visit(ctx, composite_type, visitor.on_exit_array_composite_type) + }) + + do_visit(ctx, composite_type, visitor.on_exit_composite_type) +} + +pub fn do_visit_def_type( + ctx, + def_type: DefType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, DefType), String) { + use #(ctx, DefType(rec_type, idx)) <- try(do_visit( + ctx, + def_type, + visitor.on_enter_def_type, + )) + + use #(ctx, rec_type) <- try(do_visit_rec_type(ctx, rec_type, visitor)) + + let def_type = DefType(rec_type, idx) + do_visit(ctx, def_type, visitor.on_exit_def_type) +} + +pub fn do_visit_func_type( + ctx, + func_type: FuncType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, FuncType), String) { + use #(ctx, FuncType(parameters, results)) <- try(do_visit( + ctx, + func_type, + visitor.on_enter_func_type, + )) + + use #(ctx, parameters) <- try(do_visit_element_list( + ctx, + parameters, + visitor, + do_visit_val_type, + )) + + use #(ctx, results) <- try(do_visit_element_list( + ctx, + results, + visitor, + do_visit_val_type, + )) + + let func_type = FuncType(parameters, results) + do_visit(ctx, func_type, visitor.on_exit_func_type) +} + +pub fn do_visit_val_type( + ctx, + val_type: ValType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, ValType), String) { + use #(ctx, val_type) <- try(do_visit(ctx, val_type, visitor.on_enter_val_type)) + + use #(ctx, val_type) <- try(case val_type { + V128ValType -> do_visit(ctx, val_type, visitor.on_enter_v128_val_type) + I32ValType -> do_visit(ctx, val_type, visitor.on_enter_i32_val_type) + I64ValType -> do_visit(ctx, val_type, visitor.on_enter_i64_val_type) + F32ValType -> do_visit(ctx, val_type, visitor.on_enter_f32_val_type) + F64ValType -> do_visit(ctx, val_type, visitor.on_enter_f64_val_type) + RefTypeValType(_) -> + do_visit(ctx, val_type, visitor.on_enter_ref_type_val_type) + _ -> Ok(#(ctx, val_type)) + }) + + use #(ctx, val_type) <- try(case val_type { + RefTypeValType(rt) -> { + use #(ctx, rt) <- map(do_visit_ref_type(ctx, rt, visitor)) + + #(ctx, RefTypeValType(rt)) + } + _ -> Ok(#(ctx, val_type)) + }) + + use #(ctx, val_type) <- try(case val_type { + V128ValType -> do_visit(ctx, val_type, visitor.on_exit_v128_val_type) + I32ValType -> do_visit(ctx, val_type, visitor.on_exit_i32_val_type) + I64ValType -> do_visit(ctx, val_type, visitor.on_exit_i64_val_type) + F32ValType -> do_visit(ctx, val_type, visitor.on_exit_f32_val_type) + F64ValType -> do_visit(ctx, val_type, visitor.on_exit_f64_val_type) + RefTypeValType(_) -> + do_visit(ctx, val_type, visitor.on_exit_ref_type_val_type) + _ -> Ok(#(ctx, val_type)) + }) + + do_visit(ctx, val_type, visitor.on_exit_val_type) +} + +pub fn do_visit_ref_type( + ctx, + ref_type: RefType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, RefType), String) { + use #(ctx, rt) <- try(do_visit(ctx, ref_type, visitor.on_enter_ref_type)) + + use #(ctx, rt) <- try(case rt { + HeapTypeRefType(_, _) -> + do_visit(ctx, rt, visitor.on_enter_heap_type_ref_type) + AnyRefType -> do_visit(ctx, rt, visitor.on_enter_any_ref_type) + EqRefType -> do_visit(ctx, rt, visitor.on_enter_eq_ref_type) + I31RefType -> do_visit(ctx, rt, visitor.on_enter_i31_ref_type) + StructRefType -> do_visit(ctx, rt, visitor.on_enter_struct_ref_type) + ArrayRefType -> do_visit(ctx, rt, visitor.on_enter_array_ref_type) + FuncRefType -> do_visit(ctx, rt, visitor.on_enter_func_ref_type) + ExternRefType -> do_visit(ctx, rt, visitor.on_enter_extern_ref_type) + NoneRefType -> do_visit(ctx, rt, visitor.on_enter_none_ref_type) + NoFuncRefType -> do_visit(ctx, rt, visitor.on_enter_no_func_ref_type) + NoExternRefType -> do_visit(ctx, rt, visitor.on_enter_no_extern_ref_type) + }) + + use #(ctx, rt) <- try(case rt { + HeapTypeRefType(ht, mut) -> { + use #(ctx, ht) <- map(do_visit_heap_type(ctx, ht, visitor)) + #(ctx, HeapTypeRefType(ht, mut)) + } + _ -> Ok(#(ctx, rt)) + }) + + use #(ctx, rt) <- try(case rt { + HeapTypeRefType(_, _) -> + do_visit(ctx, rt, visitor.on_exit_heap_type_ref_type) + AnyRefType -> do_visit(ctx, rt, visitor.on_exit_any_ref_type) + EqRefType -> do_visit(ctx, rt, visitor.on_exit_eq_ref_type) + I31RefType -> do_visit(ctx, rt, visitor.on_exit_i31_ref_type) + StructRefType -> do_visit(ctx, rt, visitor.on_exit_struct_ref_type) + ArrayRefType -> do_visit(ctx, rt, visitor.on_exit_array_ref_type) + FuncRefType -> do_visit(ctx, rt, visitor.on_exit_func_ref_type) + ExternRefType -> do_visit(ctx, rt, visitor.on_exit_extern_ref_type) + NoneRefType -> do_visit(ctx, rt, visitor.on_exit_none_ref_type) + NoFuncRefType -> do_visit(ctx, rt, visitor.on_exit_no_func_ref_type) + NoExternRefType -> do_visit(ctx, rt, visitor.on_exit_no_extern_ref_type) + }) + + do_visit(ctx, rt, visitor.on_exit_ref_type) +} + +pub fn do_visit_struct_type( + ctx, + struct_type: StructType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, StructType), String) { + todo +} + +pub fn do_visit_array_type( + ctx, + array_type: ArrayType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, ArrayType), String) { + todo +} + +pub fn do_visit_custom_sections( + ctx, + custom_sections: Option(FingerTree(CustomSection)), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(FingerTree(CustomSection))), String) { + todo +} + +pub fn do_visit_imports( + ctx, + imports: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_functions( + ctx, + functions: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_tables( + ctx, + tables: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_memories( + ctx, + memories: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_globals( + ctx, + globals: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_exports( + ctx, + exports: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_start( + ctx, + start: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_elements( + ctx, + elements: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_code( + ctx, + code: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_data( + ctx, + data: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_data_count( + ctx, + data_count: section, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, section), String) { + todo +} + +pub fn do_visit_heap_type( + ctx, + heap_type: HeapType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, HeapType), String) { + todo +} From d8d72988de27ee4f573be29b779133b20b76fb91 Mon Sep 17 00:00:00 2001 From: jtenner Date: Thu, 5 Sep 2024 01:15:58 -0400 Subject: [PATCH 05/16] more visitor pattern things --- src/internal/visitor.gleam | 1066 +++++++++++++++++++++++++++++------- 1 file changed, 873 insertions(+), 193 deletions(-) diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam index f4a1c82..2abf719 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -2,18 +2,26 @@ import gleam/option.{type Option, None, Some} import gleam/result.{map, try} import internal/finger_tree.{type FingerTree} import internal/structure/modules.{ - type BinaryModule, type CustomSection, type TypeSection, BinaryModule, - TypeSection, + type BinaryModule, type CustomSection, type ExportSection, + type FunctionSection, type GlobalSection, type ImportSection, + type MemorySection, type TableSection, type TypeSection, BinaryModule, + ExportSection, FunctionSection, GlobalSection, ImportSection, MemorySection, + TableSection, TypeSection, } import internal/structure/types.{ - type ArrayType, type CompositeType, type DefType, type FuncType, type HeapType, - type RecType, type RefType, type StructType, type SubType, type TypeIDX, - type ValType, AnyRefType, ArrayCompositeType, ArrayRefType, DefType, - DefTypeReference, EqRefType, ExternRefType, F32ValType, F64ValType, - FuncCompositeType, FuncRefType, FuncType, HeapTypeRefType, I31RefType, - I32ValType, I64ValType, NoExternRefType, NoFuncRefType, NoneRefType, RecType, - RecTypeIDX, RefTypeValType, StructCompositeType, StructRefType, SubType, - TypeIDX, V128ValType, + type ArrayType, type CompositeType, type DefType, type Export, type Expr, + type FieldType, type FuncType, type Global, type GlobalType, type HeapType, + type Import, type Instruction, type Limits, type MemType, type RecType, + type RefType, type StorageType, type StructType, type SubType, type Table, + type TableType, type TypeIDX, type ValType, AnyRefType, ArrayCompositeType, + ArrayRefType, ArrayType, DefType, DefTypeReference, EqRefType, Expr, + ExternRefType, F32ValType, F64ValType, FieldType, FuncCompositeType, + FuncExport, FuncImport, FuncRefType, FuncType, Global, GlobalExport, + GlobalImport, GlobalType, HeapTypeRefType, I16StorageType, I31RefType, + I32ValType, I64ValType, I8StorageType, Limits, MemExport, MemImport, MemType, + NoExternRefType, NoFuncRefType, NoneRefType, RecType, RecTypeIDX, + RefTypeValType, StructCompositeType, StructRefType, StructType, SubType, Table, + TableExport, TableImport, TableType, TypeIDX, V128ValType, ValTypeStorageType, } pub type VisitorCallback(ctx, element) = @@ -23,8 +31,36 @@ 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_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)), @@ -87,6 +123,46 @@ pub type BinaryModuleVisitor(ctx) { 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_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)), ) } @@ -250,34 +326,6 @@ pub fn do_visit_module( } } -pub fn do_visit_type_section( - ctx: context, - type_section: Option(TypeSection), - visitor: BinaryModuleVisitor(context), -) { - use #(ctx, type_section) <- try(do_visit( - ctx, - type_section, - visitor.on_enter_type_section, - )) - - use #(ctx, type_section) <- try(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)) - }) - - do_visit(ctx, type_section, visitor.on_exit_type_section) -} - fn do_visit(ctx, element, visitor: Option(VisitorCallback(ctx, element))) { case visitor { Some(f) -> f(ctx, element) @@ -307,23 +355,53 @@ fn do_visit_element_list( #(ctx, elements) } +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) <- try(do_visit(ctx, rec_type, visitor.on_enter_rec_type)) + use #(ctx, rec_type) <- enter( + ctx, + rec_type, + visitor.on_enter_rec_type, + visitor.on_exit_rec_type, + ) - use #(ctx, sub_types) <- try(do_visit_element_list( + use #(ctx, sub_types) <- map(do_visit_element_list( ctx, rec_type.sub_types, visitor, do_visit_sub_type, )) - let rec_type = RecType(sub_types) - - do_visit(ctx, rec_type, visitor.on_exit_rec_type) + #(ctx, RecType(sub_types)) } pub fn do_visit_sub_type( @@ -331,18 +409,15 @@ pub fn do_visit_sub_type( sub_type, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, SubType), String) { - use #(ctx, SubType(final, t, ct)) <- try(do_visit( + 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) <- try(do_visit_composite_type(ctx, ct, visitor)) - - let sub_type = SubType(final, t, ct) - do_visit(ctx, sub_type, visitor.on_exit_sub_type) + use #(ctx, ct) <- map(do_visit_composite_type(ctx, ct, visitor)) + #(ctx, SubType(final, t, ct)) } pub fn do_visit_type_idx( @@ -350,25 +425,32 @@ pub fn do_visit_type_idx( type_idx: TypeIDX, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, TypeIDX), String) { - use #(ctx, type_idx) <- try(do_visit(ctx, type_idx, visitor.on_enter_type_idx)) + use #(ctx, type_idx) <- enter( + ctx, + type_idx, + visitor.on_enter_type_idx, + visitor.on_exit_type_idx, + ) - use #(ctx, type_idx) <- try(case type_idx { + case type_idx { TypeIDX(_) -> Ok(#(ctx, type_idx)) - RecTypeIDX(_) -> do_visit(ctx, type_idx, visitor.on_enter_rec_type_idx) + RecTypeIDX(_) -> + enter( + ctx, + type_idx, + visitor.on_enter_rec_type_idx, + visitor.on_exit_rec_type_idx, + Ok, + ) DefTypeReference(_) -> - do_visit(ctx, type_idx, visitor.on_enter_def_type_reference) - }) - - use #(ctx, type_idx) <- try(case type_idx { - DefTypeReference(dt) -> { - use #(ctx, dt) <- map(do_visit_def_type(ctx, dt, visitor)) - - #(ctx, DefTypeReference(dt)) - } - _ -> Ok(#(ctx, type_idx)) - }) - - do_visit(ctx, type_idx, visitor.on_exit_type_idx) + enter( + ctx, + type_idx, + visitor.on_enter_def_type_reference, + visitor.on_exit_def_type_reference, + Ok, + ) + } } pub fn do_visit_composite_type( @@ -376,46 +458,60 @@ pub fn do_visit_composite_type( composite_type: CompositeType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, CompositeType), String) { - use #(ctx, composite_type) <- try(do_visit( + use #(ctx, composite_type) <- enter( ctx, composite_type, visitor.on_enter_composite_type, - )) + visitor.on_exit_composite_type, + ) - use #(ctx, composite_type) <- try(case composite_type { - FuncCompositeType(_) -> - do_visit(ctx, composite_type, visitor.on_enter_func_composite_type) - StructCompositeType(_) -> - do_visit(ctx, composite_type, visitor.on_enter_struct_composite_type) - ArrayCompositeType(_) -> - do_visit(ctx, composite_type, visitor.on_enter_array_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, + _, + ) + } - use #(ctx, composite_type) <- try(case composite_type { - FuncCompositeType(ty) -> { - use #(ctx, ty) <- map(do_visit_func_type(ctx, ty, visitor)) - #(ctx, FuncCompositeType(ty)) + case composite_type { + FuncCompositeType(func_type) -> { + use #(ctx, func_type) <- map(do_visit_func_type(ctx, func_type, visitor)) + #(ctx, FuncCompositeType(func_type)) } - StructCompositeType(ty) -> { - use #(ctx, ty) <- map(do_visit_struct_type(ctx, ty, visitor)) - #(ctx, StructCompositeType(ty)) + StructCompositeType(struct_type) -> { + use #(ctx, struct_type) <- map(do_visit_struct_type( + ctx, + struct_type, + visitor, + )) + #(ctx, StructCompositeType(struct_type)) } - ArrayCompositeType(ty) -> { - use #(ctx, ty) <- map(do_visit_array_type(ctx, ty, visitor)) - #(ctx, ArrayCompositeType(ty)) + ArrayCompositeType(array_type) -> { + use #(ctx, array_type) <- map(do_visit_array_type( + ctx, + array_type, + visitor, + )) + #(ctx, ArrayCompositeType(array_type)) } - }) - - use #(ctx, composite_type) <- try(case composite_type { - FuncCompositeType(_) -> - do_visit(ctx, composite_type, visitor.on_exit_func_composite_type) - StructCompositeType(_) -> - do_visit(ctx, composite_type, visitor.on_exit_struct_composite_type) - ArrayCompositeType(_) -> - do_visit(ctx, composite_type, visitor.on_exit_array_composite_type) - }) - - do_visit(ctx, composite_type, visitor.on_exit_composite_type) + } } pub fn do_visit_def_type( @@ -423,16 +519,16 @@ pub fn do_visit_def_type( def_type: DefType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, DefType), String) { - use #(ctx, DefType(rec_type, idx)) <- try(do_visit( + use #(ctx, DefType(rec_type, idx)) <- enter( ctx, def_type, visitor.on_enter_def_type, - )) + visitor.on_exit_def_type, + ) - use #(ctx, rec_type) <- try(do_visit_rec_type(ctx, rec_type, visitor)) + use #(ctx, rec_type) <- map(do_visit_rec_type(ctx, rec_type, visitor)) - let def_type = DefType(rec_type, idx) - do_visit(ctx, def_type, visitor.on_exit_def_type) + #(ctx, DefType(rec_type, idx)) } pub fn do_visit_func_type( @@ -440,11 +536,12 @@ pub fn do_visit_func_type( func_type: FuncType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, FuncType), String) { - use #(ctx, FuncType(parameters, results)) <- try(do_visit( + 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, @@ -453,15 +550,14 @@ pub fn do_visit_func_type( do_visit_val_type, )) - use #(ctx, results) <- try(do_visit_element_list( + use #(ctx, results) <- map(do_visit_element_list( ctx, results, visitor, do_visit_val_type, )) - let func_type = FuncType(parameters, results) - do_visit(ctx, func_type, visitor.on_exit_func_type) + #(ctx, FuncType(parameters, results)) } pub fn do_visit_val_type( @@ -469,40 +565,68 @@ pub fn do_visit_val_type( val_type: ValType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, ValType), String) { - use #(ctx, val_type) <- try(do_visit(ctx, val_type, visitor.on_enter_val_type)) - - use #(ctx, val_type) <- try(case val_type { - V128ValType -> do_visit(ctx, val_type, visitor.on_enter_v128_val_type) - I32ValType -> do_visit(ctx, val_type, visitor.on_enter_i32_val_type) - I64ValType -> do_visit(ctx, val_type, visitor.on_enter_i64_val_type) - F32ValType -> do_visit(ctx, val_type, visitor.on_enter_f32_val_type) - F64ValType -> do_visit(ctx, val_type, visitor.on_enter_f64_val_type) - RefTypeValType(_) -> - do_visit(ctx, val_type, visitor.on_enter_ref_type_val_type) - _ -> Ok(#(ctx, val_type)) - }) + 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)), _) + } - use #(ctx, val_type) <- try(case 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)) - }) - - use #(ctx, val_type) <- try(case val_type { - V128ValType -> do_visit(ctx, val_type, visitor.on_exit_v128_val_type) - I32ValType -> do_visit(ctx, val_type, visitor.on_exit_i32_val_type) - I64ValType -> do_visit(ctx, val_type, visitor.on_exit_i64_val_type) - F32ValType -> do_visit(ctx, val_type, visitor.on_exit_f32_val_type) - F64ValType -> do_visit(ctx, val_type, visitor.on_exit_f64_val_type) - RefTypeValType(_) -> - do_visit(ctx, val_type, visitor.on_exit_ref_type_val_type) - _ -> Ok(#(ctx, val_type)) - }) - - do_visit(ctx, val_type, visitor.on_exit_val_type) + } } pub fn do_visit_ref_type( @@ -510,47 +634,100 @@ pub fn do_visit_ref_type( ref_type: RefType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, RefType), String) { - use #(ctx, rt) <- try(do_visit(ctx, ref_type, visitor.on_enter_ref_type)) - - use #(ctx, rt) <- try(case rt { - HeapTypeRefType(_, _) -> - do_visit(ctx, rt, visitor.on_enter_heap_type_ref_type) - AnyRefType -> do_visit(ctx, rt, visitor.on_enter_any_ref_type) - EqRefType -> do_visit(ctx, rt, visitor.on_enter_eq_ref_type) - I31RefType -> do_visit(ctx, rt, visitor.on_enter_i31_ref_type) - StructRefType -> do_visit(ctx, rt, visitor.on_enter_struct_ref_type) - ArrayRefType -> do_visit(ctx, rt, visitor.on_enter_array_ref_type) - FuncRefType -> do_visit(ctx, rt, visitor.on_enter_func_ref_type) - ExternRefType -> do_visit(ctx, rt, visitor.on_enter_extern_ref_type) - NoneRefType -> do_visit(ctx, rt, visitor.on_enter_none_ref_type) - NoFuncRefType -> do_visit(ctx, rt, visitor.on_enter_no_func_ref_type) - NoExternRefType -> do_visit(ctx, rt, visitor.on_enter_no_extern_ref_type) - }) + use #(ctx, ref_type) <- enter( + ctx, + ref_type, + visitor.on_enter_ref_type, + visitor.on_exit_ref_type, + ) - use #(ctx, rt) <- try(case rt { + 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, rt)) - }) - - use #(ctx, rt) <- try(case rt { - HeapTypeRefType(_, _) -> - do_visit(ctx, rt, visitor.on_exit_heap_type_ref_type) - AnyRefType -> do_visit(ctx, rt, visitor.on_exit_any_ref_type) - EqRefType -> do_visit(ctx, rt, visitor.on_exit_eq_ref_type) - I31RefType -> do_visit(ctx, rt, visitor.on_exit_i31_ref_type) - StructRefType -> do_visit(ctx, rt, visitor.on_exit_struct_ref_type) - ArrayRefType -> do_visit(ctx, rt, visitor.on_exit_array_ref_type) - FuncRefType -> do_visit(ctx, rt, visitor.on_exit_func_ref_type) - ExternRefType -> do_visit(ctx, rt, visitor.on_exit_extern_ref_type) - NoneRefType -> do_visit(ctx, rt, visitor.on_exit_none_ref_type) - NoFuncRefType -> do_visit(ctx, rt, visitor.on_exit_no_func_ref_type) - NoExternRefType -> do_visit(ctx, rt, visitor.on_exit_no_extern_ref_type) - }) - - do_visit(ctx, rt, visitor.on_exit_ref_type) + _ -> Ok(#(ctx, ref_type)) + } } pub fn do_visit_struct_type( @@ -558,7 +735,20 @@ pub fn do_visit_struct_type( struct_type: StructType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, StructType), String) { - todo + 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( @@ -566,7 +756,15 @@ pub fn do_visit_array_type( array_type: ArrayType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, ArrayType), String) { - todo + 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( @@ -574,55 +772,353 @@ pub fn do_visit_custom_sections( custom_sections: Option(FingerTree(CustomSection)), visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, Option(FingerTree(CustomSection))), String) { - todo + case custom_sections { + Some(custom_sections) -> + do_visit_custom_sections_filter( + ctx, + custom_sections, + finger_tree.empty, + visitor, + ) + _ -> Ok(#(ctx, custom_sections)) + } +} + +fn do_visit_custom_sections_filter( + ctx, + custom_sections: FingerTree(CustomSection), + acc: FingerTree(CustomSection), + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Option(FingerTree(CustomSection))), String) { + case finger_tree.shift(custom_sections) { + Ok(#(custom_section, custom_sections)) -> { + use #(ctx, custom_section) <- try(do_visit_custom_section( + ctx, + custom_section, + visitor, + )) + case custom_section { + Some(custom_section) -> + do_visit_custom_sections_filter( + ctx, + custom_sections, + finger_tree.push(acc, custom_section), + visitor, + ) + None -> + do_visit_custom_sections_filter(ctx, custom_sections, acc, visitor) + } + } + _ -> Ok(#(ctx, Some(acc))) + } +} + +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_imports( ctx, - imports: section, + import_section: Option(ImportSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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_functions( ctx, - functions: section, + section: Option(FunctionSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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_tables( ctx, - tables: section, + table_section: Option(TableSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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_memories( ctx, - memories: section, + memories: Option(MemorySection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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_globals( ctx, - globals: section, + globals: Option(GlobalSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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_exports( ctx, - exports: section, + exports: Option(ExportSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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( @@ -672,3 +1168,187 @@ pub fn do_visit_heap_type( ) -> Result(#(ctx, HeapType), String) { todo } + +pub fn do_visit_field_type( + ctx, + field_type: FieldType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, FieldType), String) { + use #(ctx, FieldType(st, mut)) <- try(do_visit( + ctx, + field_type, + visitor.on_enter_field_type, + )) + + use #(ctx, st) <- try(do_visit_storage_type(ctx, st, visitor)) + + let field_type = FieldType(st, mut) + do_visit(ctx, field_type, visitor.on_exit_field_type) +} + +pub fn do_visit_storage_type( + ctx, + storage_type: StorageType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, StorageType), String) { + use #(ctx, storage_type) <- try(do_visit( + ctx, + storage_type, + visitor.on_enter_storage_type, + )) + + use #(ctx, storage_type) <- try(case storage_type { + I8StorageType -> + do_visit(ctx, storage_type, visitor.on_enter_i8_storage_type) + I16StorageType -> + do_visit(ctx, storage_type, visitor.on_enter_i16_storage_type) + ValTypeStorageType(_) -> + do_visit(ctx, storage_type, visitor.on_enter_val_type_storage_type) + }) + + use #(ctx, storage_type) <- try(case storage_type { + ValTypeStorageType(vt) -> { + use #(ctx, vt) <- map(do_visit_val_type(ctx, vt, visitor)) + #(ctx, ValTypeStorageType(vt)) + } + a -> Ok(#(ctx, a)) + }) + + use #(ctx, storage_type) <- try(case storage_type { + I8StorageType -> + do_visit(ctx, storage_type, visitor.on_exit_i8_storage_type) + I16StorageType -> + do_visit(ctx, storage_type, visitor.on_exit_i16_storage_type) + ValTypeStorageType(_) -> + do_visit(ctx, storage_type, visitor.on_exit_val_type_storage_type) + }) + + do_visit(ctx, storage_type, visitor.on_exit_storage_type) +} + +pub fn do_visit_table_type( + ctx, + table_type: TableType, + visitor: BinaryModuleVisitor(ctx), +) { + use #(ctx, TableType(rt, limits)) <- try(do_visit( + ctx, + table_type, + visitor.on_enter_table_type, + )) + + use #(ctx, rt) <- try(do_visit_ref_type(ctx, rt, visitor)) + use #(ctx, limits) <- try(do_visit_limits(ctx, limits, visitor)) + + let table_type = TableType(rt, limits) + do_visit(ctx, table_type, visitor.on_exit_table_type) +} + +pub fn do_visit_limits( + ctx, + limits: Limits, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Limits), String) { + use #(ctx, limits) <- try(do_visit(ctx, limits, visitor.on_enter_limits)) + do_visit(ctx, limits, visitor.on_exit_limits) +} + +pub fn do_visit_mem_type( + ctx, + mem_type: MemType, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, MemType), String) { + use #(ctx, MemType(limits)) <- try(do_visit( + ctx, + mem_type, + visitor.on_enter_mem_type, + )) + use #(ctx, limits) <- try(do_visit_limits(ctx, limits, visitor)) + let mem_type = MemType(limits) + do_visit(ctx, mem_type, visitor.on_exit_mem_type) +} + +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)) <- try(do_visit( + ctx, + table, + visitor.on_enter_table, + )) + + use #(ctx, table_type) <- try(do_visit_table_type(ctx, table_type, visitor)) + + use #(ctx, init_expr) <- try(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) + do_visit(ctx, table, visitor.on_exit_table) +} + +pub fn do_visit_expr(ctx, expr: Expr, visitor: BinaryModuleVisitor(ctx)) { + 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, + ) + + todo +} + +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) +} From f502d5997a83b33836e2774db927e816b68b26ec Mon Sep 17 00:00:00 2001 From: jtenner Date: Thu, 5 Sep 2024 15:51:01 -0400 Subject: [PATCH 06/16] More Visitor Pattern Things Co-authored-by: Rishit Chaudhary --- src/internal/structure/types.gleam | 1 - src/internal/visitor.gleam | 1661 +++++++++++++- src/visitor.gleam | 3228 ++++++++++++++++++++++++++++ 3 files changed, 4777 insertions(+), 113 deletions(-) create mode 100644 src/visitor.gleam diff --git a/src/internal/structure/types.gleam b/src/internal/structure/types.gleam index 2c53fd2..9031048 100644 --- a/src/internal/structure/types.gleam +++ b/src/internal/structure/types.gleam @@ -900,7 +900,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) diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam index 2abf719..33c011f 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -1,27 +1,46 @@ +import gleam/list import gleam/option.{type Option, None, Some} import gleam/result.{map, try} import internal/finger_tree.{type FingerTree} import internal/structure/modules.{ - type BinaryModule, type CustomSection, type ExportSection, + type BinaryModule, type CodeSection, type CustomSection, type DataCountSection, + type DataSection, type ElementSection, type ExportSection, type FunctionSection, type GlobalSection, type ImportSection, - type MemorySection, type TableSection, type TypeSection, BinaryModule, - ExportSection, FunctionSection, GlobalSection, ImportSection, MemorySection, + 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 CompositeType, type DefType, type Export, type Expr, - type FieldType, type FuncType, type Global, type GlobalType, type HeapType, - type Import, type Instruction, type Limits, type MemType, type RecType, - type RefType, type StorageType, type StructType, type SubType, type Table, - type TableType, type TypeIDX, type ValType, AnyRefType, ArrayCompositeType, - ArrayRefType, ArrayType, DefType, DefTypeReference, EqRefType, Expr, + 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, FuncImport, FuncRefType, FuncType, Global, GlobalExport, - GlobalImport, GlobalType, HeapTypeRefType, I16StorageType, I31RefType, - I32ValType, I64ValType, I8StorageType, Limits, MemExport, MemImport, MemType, - NoExternRefType, NoFuncRefType, NoneRefType, RecType, RecTypeIDX, - RefTypeValType, StructCompositeType, StructRefType, StructType, SubType, Table, - TableExport, TableImport, TableType, TypeIDX, V128ValType, ValTypeStorageType, + 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) = @@ -41,6 +60,16 @@ pub type BinaryModuleVisitor(ctx) { 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)), @@ -143,6 +172,20 @@ pub type BinaryModuleVisitor(ctx) { 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))), @@ -163,6 +206,184 @@ pub type BinaryModuleVisitor(ctx) { 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)), ) } @@ -197,7 +418,7 @@ pub fn do_visit_module( module.custom_1, visitor, )) - use #(ctx, imports) <- result.try(do_visit_imports( + use #(ctx, imports) <- result.try(do_visit_import_section( ctx, module.imports, visitor, @@ -207,7 +428,7 @@ pub fn do_visit_module( module.custom_2, visitor, )) - use #(ctx, functions) <- result.try(do_visit_functions( + use #(ctx, functions) <- result.try(do_visit_function_section( ctx, module.functions, visitor, @@ -217,13 +438,17 @@ pub fn do_visit_module( module.custom_3, visitor, )) - use #(ctx, tables) <- result.try(do_visit_tables(ctx, module.tables, 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_memories( + use #(ctx, memories) <- result.try(do_visit_memory_section( ctx, module.memories, visitor, @@ -233,7 +458,7 @@ pub fn do_visit_module( module.custom_5, visitor, )) - use #(ctx, globals) <- result.try(do_visit_globals( + use #(ctx, globals) <- result.try(do_visit_global_section( ctx, module.globals, visitor, @@ -243,7 +468,7 @@ pub fn do_visit_module( module.custom_6, visitor, )) - use #(ctx, exports) <- result.try(do_visit_exports( + use #(ctx, exports) <- result.try(do_visit_export_section( ctx, module.exports, visitor, @@ -253,13 +478,17 @@ pub fn do_visit_module( module.custom_7, visitor, )) - use #(ctx, start) <- result.try(do_visit_start(ctx, module.start, 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_elements( + use #(ctx, elements) <- result.try(do_visit_element_section( ctx, module.elements, visitor, @@ -269,19 +498,27 @@ pub fn do_visit_module( module.custom_9, visitor, )) - use #(ctx, code) <- result.try(do_visit_code(ctx, module.code, 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(ctx, module.data, 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( + use #(ctx, data_count) <- result.try(do_visit_data_count_section( ctx, module.data_count, visitor, @@ -827,7 +1064,7 @@ pub fn do_visit_custom_section( ) } -pub fn do_visit_imports( +pub fn do_visit_import_section( ctx, import_section: Option(ImportSection), visitor: BinaryModuleVisitor(ctx), @@ -920,7 +1157,7 @@ pub fn do_visit_import(ctx, import_: Import, visitor: BinaryModuleVisitor(ctx)) } } -pub fn do_visit_functions( +pub fn do_visit_function_section( ctx, section: Option(FunctionSection), visitor: BinaryModuleVisitor(ctx), @@ -945,7 +1182,7 @@ pub fn do_visit_functions( } } -pub fn do_visit_tables( +pub fn do_visit_table_section( ctx, table_section: Option(TableSection), visitor: BinaryModuleVisitor(ctx), @@ -971,7 +1208,7 @@ pub fn do_visit_tables( } } -pub fn do_visit_memories( +pub fn do_visit_memory_section( ctx, memories: Option(MemorySection), visitor: BinaryModuleVisitor(ctx), @@ -996,7 +1233,7 @@ pub fn do_visit_memories( } } -pub fn do_visit_globals( +pub fn do_visit_global_section( ctx, globals: Option(GlobalSection), visitor: BinaryModuleVisitor(ctx), @@ -1022,8 +1259,12 @@ pub fn do_visit_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(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)) @@ -1031,7 +1272,7 @@ pub fn do_visit_global(ctx, global: Global, visitor: BinaryModuleVisitor(ctx)) { #(ctx, Global(global_type, init)) } -pub fn do_visit_exports( +pub fn do_visit_export_section( ctx, exports: Option(ExportSection), visitor: BinaryModuleVisitor(ctx), @@ -1121,44 +1362,302 @@ pub fn do_visit_export(ctx, export: Export, visitor: BinaryModuleVisitor(ctx)) { } } -pub fn do_visit_start( +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, - start: section, + mode: ElemMode, visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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_elements( +pub fn do_visit_code_section( ctx, - elements: section, + code: Option(CodeSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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: section, + 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, section), String) { - todo +) -> 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: section, + data: Data, visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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( +pub fn do_visit_data_count_section( ctx, - data_count: section, + data_count_section: Option(DataCountSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, section), String) { - todo +) -> 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( @@ -1166,7 +1665,102 @@ pub fn do_visit_heap_type( heap_type: HeapType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, HeapType), String) { - todo + 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( @@ -1174,16 +1768,14 @@ pub fn do_visit_field_type( field_type: FieldType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, FieldType), String) { - use #(ctx, FieldType(st, mut)) <- try(do_visit( + use #(ctx, FieldType(storage_type, mut)) <- enter( ctx, field_type, visitor.on_enter_field_type, - )) - - use #(ctx, st) <- try(do_visit_storage_type(ctx, st, visitor)) - - let field_type = FieldType(st, mut) - do_visit(ctx, field_type, visitor.on_exit_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( @@ -1191,39 +1783,45 @@ pub fn do_visit_storage_type( storage_type: StorageType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, StorageType), String) { - use #(ctx, storage_type) <- try(do_visit( + use #(ctx, storage_type) <- enter( ctx, storage_type, visitor.on_enter_storage_type, - )) + visitor.on_exit_storage_type, + ) - use #(ctx, storage_type) <- try(case storage_type { - I8StorageType -> - do_visit(ctx, storage_type, visitor.on_enter_i8_storage_type) - I16StorageType -> - do_visit(ctx, storage_type, visitor.on_enter_i16_storage_type) - ValTypeStorageType(_) -> - do_visit(ctx, storage_type, visitor.on_enter_val_type_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, + _, + ) + } - use #(ctx, storage_type) <- try(case 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)) - }) - - use #(ctx, storage_type) <- try(case storage_type { - I8StorageType -> - do_visit(ctx, storage_type, visitor.on_exit_i8_storage_type) - I16StorageType -> - do_visit(ctx, storage_type, visitor.on_exit_i16_storage_type) - ValTypeStorageType(_) -> - do_visit(ctx, storage_type, visitor.on_exit_val_type_storage_type) - }) - - do_visit(ctx, storage_type, visitor.on_exit_storage_type) + } } pub fn do_visit_table_type( @@ -1231,17 +1829,18 @@ pub fn do_visit_table_type( table_type: TableType, visitor: BinaryModuleVisitor(ctx), ) { - use #(ctx, TableType(rt, limits)) <- try(do_visit( + 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) <- try(do_visit_limits(ctx, limits, visitor)) + use #(ctx, limits) <- map(do_visit_limits(ctx, limits, visitor)) let table_type = TableType(rt, limits) - do_visit(ctx, table_type, visitor.on_exit_table_type) + #(ctx, table_type) } pub fn do_visit_limits( @@ -1249,8 +1848,7 @@ pub fn do_visit_limits( limits: Limits, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, Limits), String) { - use #(ctx, limits) <- try(do_visit(ctx, limits, visitor.on_enter_limits)) - do_visit(ctx, limits, visitor.on_exit_limits) + enter(ctx, limits, visitor.on_enter_limits, visitor.on_exit_limits, Ok) } pub fn do_visit_mem_type( @@ -1258,14 +1856,15 @@ pub fn do_visit_mem_type( mem_type: MemType, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, MemType), String) { - use #(ctx, MemType(limits)) <- try(do_visit( + use #(ctx, MemType(limits)) <- enter( ctx, mem_type, visitor.on_enter_mem_type, - )) - use #(ctx, limits) <- try(do_visit_limits(ctx, limits, visitor)) - let mem_type = MemType(limits) - do_visit(ctx, mem_type, visitor.on_exit_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( @@ -1289,15 +1888,16 @@ pub fn do_visit_table( table: Table, visitor: BinaryModuleVisitor(ctx), ) -> Result(#(ctx, Table), String) { - use #(ctx, Table(table_type, init_expr)) <- try(do_visit( + 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) <- try(case init_expr { + 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)) @@ -1306,10 +1906,14 @@ pub fn do_visit_table( }) let table = Table(table_type, init_expr) - do_visit(ctx, table, visitor.on_exit_table) + #(ctx, table) } -pub fn do_visit_expr(ctx, expr: Expr, visitor: BinaryModuleVisitor(ctx)) { +pub fn do_visit_expr( + ctx, + expr: Expr, + visitor: BinaryModuleVisitor(ctx), +) -> Result(#(ctx, Expr), String) { use #(ctx, Expr(body)) <- enter( ctx, expr, @@ -1323,6 +1927,7 @@ pub fn do_visit_expr(ctx, expr: Expr, visitor: BinaryModuleVisitor(ctx)) { visitor, do_visit_instruction, )) + #(ctx, Expr(body)) } @@ -1338,17 +1943,849 @@ pub fn do_visit_instruction( visitor.on_exit_instruction, ) - todo -} - -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) + 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, DataDrop(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/visitor.gleam b/src/visitor.gleam new file mode 100644 index 0000000..f429ec8 --- /dev/null +++ b/src/visitor.gleam @@ -0,0 +1,3228 @@ +import gleam/option.{type Option, Some} +import internal/finger_tree +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 BinaryModuleVisitor, 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_custom_sections, + 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) +} From 76bf5bf7b1b7a676920f3f88854d4bc5eaa9df15 Mon Sep 17 00:00:00 2001 From: jtenner Date: Thu, 5 Sep 2024 18:57:09 -0400 Subject: [PATCH 07/16] test visitor functions --- src/builder/types/block_type.gleam | 14 + src/builder/types/rec_type.gleam | 10 +- src/internal/visitor.gleam | 328 ++++++++++++++ src/visitor.gleam | 22 +- test/visitor/block_type_test.gleam | 89 ++++ test/visitor_test.gleam | 699 +++++++++++++++++++++++++++++ 6 files changed, 1153 insertions(+), 9 deletions(-) create mode 100644 src/builder/types/block_type.gleam create mode 100644 test/visitor/block_type_test.gleam create mode 100644 test/visitor_test.gleam diff --git a/src/builder/types/block_type.gleam b/src/builder/types/block_type.gleam new file mode 100644 index 0000000..ae230c4 --- /dev/null +++ b/src/builder/types/block_type.gleam @@ -0,0 +1,14 @@ +import internal/structure/types.{ + type BlockType, 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/rec_type.gleam b/src/builder/types/rec_type.gleam index 43e8c2a..a28c9c5 100644 --- a/src/builder/types/rec_type.gleam +++ b/src/builder/types/rec_type.gleam @@ -1,6 +1,6 @@ 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, } @@ -9,6 +9,14 @@ pub fn from_sub_types(sub_types: List(SubType)) { RecType(sub_types |> finger_tree.from_list) } +pub fn from_func_type(func_type: FuncType) { + RecType( + finger_tree.from_list([ + SubType(True, finger_tree.new(), FuncCompositeType(func_type)), + ]), + ) +} + pub fn func_type(parameters: List(ValType), results: List(ValType)) { RecType( finger_tree.from_list([ diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam index 33c011f..001fe11 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -1,3 +1,4 @@ +import gleam/io import gleam/list import gleam/option.{type Option, None, Some} import gleam/result.{map, try} @@ -46,6 +47,333 @@ import internal/structure/types.{ 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)), diff --git a/src/visitor.gleam b/src/visitor.gleam index f429ec8..33aee7c 100644 --- a/src/visitor.gleam +++ b/src/visitor.gleam @@ -1,5 +1,4 @@ import gleam/option.{type Option, Some} -import internal/finger_tree import internal/structure/modules.{ type BinaryModule, type CodeSection, type CustomSection, type DataCountSection, type DataSection, type ElementSection, type ExportSection, @@ -17,13 +16,13 @@ import internal/structure/types.{ type TableType, type TypeIDX, type ValType, } import internal/visitor.{ - type BinaryModuleVisitor, 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_custom_sections, - 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, + 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, @@ -3226,3 +3225,10 @@ pub fn visit_block_type( ) -> 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/visitor/block_type_test.gleam b/test/visitor/block_type_test.gleam new file mode 100644 index 0000000..67d42ae --- /dev/null +++ b/test/visitor/block_type_test.gleam @@ -0,0 +1,89 @@ +import builder/module +import builder/types/block_type +import builder/types/val_type +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) + +fn do_visit_test( + 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), +) { + let start_context = #(0, 0, 0, 0) + let expected_context = #(1, 1, 1, 1) + visitor.new() + |> on_enter_type(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a + 1, b, c, d), actual_value)) + }) + |> on_exit_type(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a, b + 1, c, d), actual_value)) + }) + |> on_enter_variant(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a, b, c + 1, d), actual_value)) + }) + |> on_exit_variant(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a, b, c, d + 1), actual_value)) + }) + |> visit_func(start_context, expected_value) + |> should.be_ok + |> should.equal(#(expected_context, expected_value)) +} + +pub fn visit_val_type_storage_type_test() { + do_visit_test( + 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, + ) +} + +pub fn visit_void_block_type_test() { + do_visit_test( + 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, + ) +} + +pub fn visit_func_type_block_type_test() { + let assert Ok(type_idx) = module.type_idx(42) + do_visit_test( + block_type.func_type(type_idx), + 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, + ) +} diff --git a/test/visitor_test.gleam b/test/visitor_test.gleam new file mode 100644 index 0000000..4be0bd5 --- /dev/null +++ b/test/visitor_test.gleam @@ -0,0 +1,699 @@ +import builder/types/block_type +import gleeunit/should +import visitor + +pub fn visit_binary_module_test() { + todo +} + +pub fn visit_code_section_test() { + todo +} + +pub fn visit_data_section_test() { + todo +} + +pub fn visit_element_section_test() { + todo +} + +pub fn visit_export_section_test() { + todo +} + +pub fn visit_function_section_test() { + todo +} + +pub fn visit_global_section_test() { + todo +} + +pub fn visit_import_section_test() { + todo +} + +pub fn visit_memory_section_test() { + todo +} + +pub fn visit_start_section_test() { + todo +} + +pub fn visit_table_section_test() { + todo +} + +pub fn visit_type_section_test() { + todo +} + +pub fn visit_type_array_type_test() { + todo +} + +pub fn visit_type_code_test() { + todo +} + +pub fn visit_type_composite_type_test() { + todo +} + +pub fn visit_type_data_test() { + todo +} + +pub fn visit_type_data_idx_test() { + todo +} + +pub fn visit_type_def_type_test() { + todo +} + +pub fn visit_type_elem_test() { + todo +} + +pub fn visit_type_elem_idx_test() { + todo +} + +pub fn visit_type_elem_mode_test() { + todo +} + +pub fn visit_type_export_test() { + todo +} + +pub fn visit_type_expr_test() { + todo +} + +pub fn visit_type_field_idx_test() { + todo +} + +pub fn visit_type_field_type_test() { + todo +} + +pub fn visit_type_func_idx_test() { + todo +} + +pub fn visit_type_func_type_test() { + todo +} + +pub fn visit_type_global_test() { + todo +} + +pub fn visit_type_global_idx_test() { + todo +} + +pub fn visit_type_global_type_test() { + todo +} + +pub fn visit_type_heap_type_test() { + todo +} + +pub fn visit_type_import_test() { + todo +} + +pub fn visit_type_instruction_test() { + todo +} + +pub fn visit_type_label_idx_test() { + todo +} + +pub fn visit_type_limits_test() { + todo +} + +pub fn visit_type_local_idx_test() { + todo +} + +pub fn visit_type_locals_test() { + todo +} + +pub fn visit_type_mem_idx_test() { + todo +} + +pub fn visit_type_mem_type_test() { + todo +} + +pub fn visit_type_rec_type_test() { + todo +} + +pub fn visit_type_ref_type_test() { + todo +} + +pub fn visit_type_storage_type_test() { + todo +} + +pub fn visit_type_struct_type_test() { + todo +} + +pub fn visit_type_sub_type_test() { + todo +} + +pub fn visit_type_table_test() { + todo +} + +pub fn visit_type_table_idx_test() { + todo +} + +pub fn visit_type_table_type_test() { + todo +} + +pub fn visit_type_type_idx_test() { + todo +} + +pub fn visit_type_val_type_test() { + todo +} + +pub fn visit_active_data_test() { + todo +} + +pub fn visit_active_elem_mode_test() { + todo +} + +pub fn visit_any_heap_type_test() { + todo +} + +pub fn visit_any_ref_type_test() { + todo +} + +pub fn visit_array_composite_type_test() { + todo +} + +pub fn visit_array_copy_test() { + todo +} + +pub fn visit_array_fill_test() { + todo +} + +pub fn visit_array_get_test() { + todo +} + +pub fn visit_array_get_s_test() { + todo +} + +pub fn visit_array_get_u_test() { + todo +} + +pub fn visit_array_heap_type_test() { + todo +} + +pub fn visit_array_init_data_test() { + todo +} + +pub fn visit_array_init_elem_test() { + todo +} + +pub fn visit_array_new_test() { + todo +} + +pub fn visit_array_new_data_test() { + todo +} + +pub fn visit_array_new_default_test() { + todo +} + +pub fn visit_array_new_elem_test() { + todo +} + +pub fn visit_array_new_fixed_test() { + todo +} + +pub fn visit_array_ref_type_test() { + todo +} + +pub fn visit_array_set_test() { + todo +} + +pub fn visit_array_type_test() { + todo +} + +pub fn visit_block_test() { + todo +} + +pub fn visit_br_test() { + todo +} + +pub fn visit_br_if_test() { + todo +} + +pub fn visit_br_on_cast_test() { + todo +} + +pub fn visit_br_on_cast_fail_test() { + todo +} + +pub fn visit_br_on_non_null_test() { + todo +} + +pub fn visit_br_on_null_test() { + todo +} + +pub fn visit_br_table_test() { + todo +} + +pub fn visit_call_test() { + todo +} + +pub fn visit_call_indirect_test() { + todo +} + +pub fn visit_call_ref_test() { + todo +} + +pub fn visit_code_test() { + todo +} + +pub fn visit_concrete_heap_type_test() { + todo +} + +pub fn visit_data_drop_test() { + todo +} + +pub fn visit_declarative_elem_mode_test() { + todo +} + +pub fn visit_def_type_test() { + todo +} + +pub fn visit_def_type_reference_test() { + todo +} + +pub fn visit_elem_drop_test() { + todo +} + +pub fn visit_elem_expressions_test() { + todo +} + +pub fn visit_elem_funcs_test() { + todo +} + +pub fn visit_eq_heap_type_test() { + todo +} + +pub fn visit_eq_ref_type_test() { + todo +} + +pub fn visit_expr_test() { + todo +} + +pub fn visit_extern_heap_type_test() { + todo +} + +pub fn visit_extern_ref_type_test() { + todo +} + +pub fn visit_f32_val_type_test() { + todo +} + +pub fn visit_f64_val_type_test() { + todo +} + +pub fn visit_field_type_test() { + todo +} + +pub fn visit_func_composite_type_test() { + todo +} + +pub fn visit_func_export_test() { + todo +} + +pub fn visit_func_heap_type_test() { + todo +} + +pub fn visit_func_import_test() { + todo +} + +pub fn visit_func_ref_type_test() { + todo +} + +pub fn visit_func_type_test() { + todo +} + +pub fn visit_global_test() { + todo +} + +pub fn visit_global_export_test() { + todo +} + +pub fn visit_global_get_test() { + todo +} + +pub fn visit_global_import_test() { + todo +} + +pub fn visit_global_set_test() { + todo +} + +pub fn visit_global_type_test() { + todo +} + +pub fn visit_heap_type_ref_type_test() { + todo +} + +pub fn visit_i16_storage_type_test() { + todo +} + +pub fn visit_i31_heap_type_test() { + todo +} + +pub fn visit_i31_ref_type_test() { + todo +} + +pub fn visit_i32_val_type_test() { + todo +} + +pub fn visit_i64_val_type_test() { + todo +} + +pub fn visit_i8_storage_type_test() { + todo +} + +pub fn visit_if_test() { + todo +} + +pub fn visit_label_idx_test() { + todo +} + +pub fn visit_limits_test() { + todo +} + +pub fn visit_local_get_test() { + todo +} + +pub fn visit_local_set_test() { + todo +} + +pub fn visit_local_tee_test() { + todo +} + +pub fn visit_locals_test() { + todo +} + +pub fn visit_loop_test() { + todo +} + +pub fn visit_mem_export_test() { + todo +} + +pub fn visit_mem_idx_test() { + todo +} + +pub fn visit_mem_import_test() { + todo +} + +pub fn visit_mem_type_test() { + todo +} + +pub fn visit_memory_init_test() { + todo +} + +pub fn visit_no_extern_heap_type_test() { + todo +} + +pub fn visit_no_extern_ref_type_test() { + todo +} + +pub fn visit_no_func_heap_type_test() { + todo +} + +pub fn visit_no_func_ref_type_test() { + todo +} + +pub fn visit_none_heap_type_test() { + todo +} + +pub fn visit_none_ref_type_test() { + todo +} + +pub fn visit_passive_data_test() { + todo +} + +pub fn visit_passive_elem_mode_test() { + todo +} + +pub fn visit_rec_type_test() { + todo +} + +pub fn visit_rec_type_idx_test() { + todo +} + +pub fn visit_ref_cast_test() { + todo +} + +pub fn visit_ref_cast_nullable_test() { + todo +} + +pub fn visit_ref_func_test() { + todo +} + +pub fn visit_ref_null_test() { + todo +} + +pub fn visit_ref_test_test() { + todo +} + +pub fn visit_ref_test_nullable_test() { + todo +} + +pub fn visit_ref_type_val_type_test() { + todo +} + +pub fn visit_return_call_test() { + todo +} + +pub fn visit_return_call_indirect_test() { + todo +} + +pub fn visit_return_call_ref_test() { + todo +} + +pub fn visit_select_t_test() { + todo +} + +pub fn visit_struct_composite_type_test() { + todo +} + +pub fn visit_struct_get_test() { + todo +} + +pub fn visit_struct_get_s_test() { + todo +} + +pub fn visit_struct_get_u_test() { + todo +} + +pub fn visit_struct_heap_type_test() { + todo +} + +pub fn visit_struct_ref_type_test() { + todo +} + +pub fn visit_struct_set_test() { + todo +} + +pub fn visit_struct_type_test() { + todo +} + +pub fn visit_sub_type_test() { + todo +} + +pub fn visit_table_test() { + todo +} + +pub fn visit_table_copy_test() { + todo +} + +pub fn visit_table_export_test() { + todo +} + +pub fn visit_table_fill_test() { + todo +} + +pub fn visit_table_get_test() { + todo +} + +pub fn visit_table_grow_test() { + todo +} + +pub fn visit_table_import_test() { + todo +} + +pub fn visit_table_init_test() { + todo +} + +pub fn visit_table_set_test() { + todo +} + +pub fn visit_table_size_test() { + todo +} + +pub fn visit_table_type_test() { + todo +} + +pub fn visit_type_idx_test() { + todo +} + +pub fn visit_v128_val_type_test() { + todo +} + +pub fn visit_val_type_storage_type_test() { + todo +} From ca892b93b288b46091a1ed07aa3c706a3bdecc53 Mon Sep 17 00:00:00 2001 From: jtenner Date: Fri, 6 Sep 2024 11:10:19 -0400 Subject: [PATCH 08/16] More tests --- .vscode/settings.json | 38 +- src/builder/module.gleam | 33 +- src/internal/structure/types.gleam | 40 +- src/values.gleam | 60 +++ test/visitor/block_type_test.gleam | 64 +-- test/visitor/heap_type_test.gleam | 130 +++++ test/visitor/instruction_test.gleam | 730 ++++++++++++++++++++++++++ test/visitor/ref_type_test.gleam | 130 +++++ test/visitor/val_type.gleam | 78 +++ test/visitor/visit_test_variant.gleam | 52 ++ test/visitor_test.gleam | 699 ------------------------ 11 files changed, 1238 insertions(+), 816 deletions(-) create mode 100644 src/values.gleam create mode 100644 test/visitor/heap_type_test.gleam create mode 100644 test/visitor/instruction_test.gleam create mode 100644 test/visitor/ref_type_test.gleam create mode 100644 test/visitor/val_type.gleam create mode 100644 test/visitor/visit_test_variant.gleam delete mode 100644 test/visitor_test.gleam 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/src/builder/module.gleam b/src/builder/module.gleam index fc5b450..5c4bc37 100644 --- a/src/builder/module.gleam +++ b/src/builder/module.gleam @@ -17,10 +17,10 @@ import internal/structure/types.{ type RecType, type RefType, type Table, type TableIDX, type TableType, type TypeIDX, type ValType, ActiveData, ActiveElemMode, ArrayCompositeType, ArrayType, Code, Const, DataIDX, DeclarativeElemMode, ElemExpressions, - 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, + 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, StructCompositeType, StructType, SubType, Table, TableExport, TableIDX, TableImport, TableType, TypeIDX, Var, } @@ -1320,6 +1320,15 @@ pub fn func_idx(idx: Int) { } } +/// 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) + } +} + /// 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. @@ -1341,3 +1350,19 @@ pub fn encode(module: BinaryModule) { pub fn decode(module: BitArray) { modules.decode_module(module) } + +/// ShineCoder's FingerTree is an efficient data structure for +/// storing and manipulating the ends of ordered vector data. +/// This function takes a list and converts it into an opaque +/// FingerTree. +pub fn to_vector(values: List(u)) { + values |> finger_tree.from_list +} + +/// ShineCoder's FingerTree is an efficient data structure for +/// storing and manipulating the ends of ordered vector data. +/// This function takes a FingerTree and converts it into a +/// normal List. +pub fn to_list(values: FingerTree(u)) { + values |> finger_tree.to_list +} diff --git a/src/internal/structure/types.gleam b/src/internal/structure/types.gleam index 9031048..12c6394 100644 --- a/src/internal/structure/types.gleam +++ b/src/internal/structure/types.gleam @@ -78,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 @@ -115,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) 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/test/visitor/block_type_test.gleam b/test/visitor/block_type_test.gleam index 67d42ae..5c99ad2 100644 --- a/test/visitor/block_type_test.gleam +++ b/test/visitor/block_type_test.gleam @@ -1,61 +1,11 @@ import builder/module import builder/types/block_type import builder/types/val_type -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) - -fn do_visit_test( - 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), -) { - let start_context = #(0, 0, 0, 0) - let expected_context = #(1, 1, 1, 1) - visitor.new() - |> on_enter_type(fn(ctx, actual_value) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a + 1, b, c, d), actual_value)) - }) - |> on_exit_type(fn(ctx, actual_value) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a, b + 1, c, d), actual_value)) - }) - |> on_enter_variant(fn(ctx, actual_value) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a, b, c + 1, d), actual_value)) - }) - |> on_exit_variant(fn(ctx, actual_value) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a, b, c, d + 1), actual_value)) - }) - |> visit_func(start_context, expected_value) - |> should.be_ok - |> should.equal(#(expected_context, expected_value)) -} +import visitor +import visitor/visit_test_variant pub fn visit_val_type_storage_type_test() { - do_visit_test( + visit_test_variant.run( block_type.val_type(val_type.i32), visitor.on_enter_block_type, visitor.on_exit_block_type, @@ -66,7 +16,7 @@ pub fn visit_val_type_storage_type_test() { } pub fn visit_void_block_type_test() { - do_visit_test( + visit_test_variant.run( block_type.void, visitor.on_enter_block_type, visitor.on_exit_block_type, @@ -78,12 +28,12 @@ pub fn visit_void_block_type_test() { pub fn visit_func_type_block_type_test() { let assert Ok(type_idx) = module.type_idx(42) - do_visit_test( + visit_test_variant.run( block_type.func_type(type_idx), visitor.on_enter_block_type, visitor.on_exit_block_type, - visitor.on_enter_void_block_type, - visitor.on_exit_void_block_type, + visitor.on_enter_func_type_block_type, + visitor.on_exit_func_type_block_type, visitor.visit_block_type, ) } diff --git a/test/visitor/heap_type_test.gleam b/test/visitor/heap_type_test.gleam new file mode 100644 index 0000000..c41f4aa --- /dev/null +++ b/test/visitor/heap_type_test.gleam @@ -0,0 +1,130 @@ +import builder/module +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} diff --git a/test/visitor/instruction_test.gleam b/test/visitor/instruction_test.gleam new file mode 100644 index 0000000..107f349 --- /dev/null +++ b/test/visitor/instruction_test.gleam @@ -0,0 +1,730 @@ +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/finger_tree +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_func, + visitor.visit_instruction, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +pub fn visit_select_t_test() { + let val_types = + [I32ValType, I64ValType, F32ValType, F64ValType] + |> module.to_vector + visit_test_variant.run( + SelectT(val_types), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_select_t, + visitor.on_exit_ref_func, + visitor.visit_instruction, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +pub fn visit_if_test() { + let if_block = finger_tree.from_list([Nop]) + + visit_test_variant.run( + If(block_type.void, if_block, None), + visitor.on_enter_instruction, + visitor.on_exit_instruction, + visitor.on_enter_if, + visitor.on_exit_if, + visitor.visit_instruction, + ) +} + +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, + ) +} + +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, + ) +} + +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 = + finger_tree.from_list([ + 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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} diff --git a/test/visitor/ref_type_test.gleam b/test/visitor/ref_type_test.gleam new file mode 100644 index 0000000..3ceb108 --- /dev/null +++ b/test/visitor/ref_type_test.gleam @@ -0,0 +1,130 @@ +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} diff --git a/test/visitor/val_type.gleam b/test/visitor/val_type.gleam new file mode 100644 index 0000000..6ad89f9 --- /dev/null +++ b/test/visitor/val_type.gleam @@ -0,0 +1,78 @@ +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} + +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, + ) +} diff --git a/test/visitor/visit_test_variant.gleam b/test/visitor/visit_test_variant.gleam new file mode 100644 index 0000000..1ede5ac --- /dev/null +++ b/test/visitor/visit_test_variant.gleam @@ -0,0 +1,52 @@ +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), +) { + let start_context = #(0, 0, 0, 0) + let expected_context = #(1, 1, 1, 1) + visitor.new() + |> on_enter_type(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a + 1, b, c, d), actual_value)) + }) + |> on_exit_type(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a, b + 1, c, d), actual_value)) + }) + |> on_enter_variant(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a, b, c + 1, d), actual_value)) + }) + |> on_exit_variant(fn(ctx, actual_value) { + let #(a, b, c, d) = ctx + actual_value |> should.equal(expected_value) + Ok(#(#(a, b, c, d + 1), actual_value)) + }) + |> visit_func(start_context, expected_value) + |> should.be_ok + |> should.equal(#(expected_context, expected_value)) +} diff --git a/test/visitor_test.gleam b/test/visitor_test.gleam deleted file mode 100644 index 4be0bd5..0000000 --- a/test/visitor_test.gleam +++ /dev/null @@ -1,699 +0,0 @@ -import builder/types/block_type -import gleeunit/should -import visitor - -pub fn visit_binary_module_test() { - todo -} - -pub fn visit_code_section_test() { - todo -} - -pub fn visit_data_section_test() { - todo -} - -pub fn visit_element_section_test() { - todo -} - -pub fn visit_export_section_test() { - todo -} - -pub fn visit_function_section_test() { - todo -} - -pub fn visit_global_section_test() { - todo -} - -pub fn visit_import_section_test() { - todo -} - -pub fn visit_memory_section_test() { - todo -} - -pub fn visit_start_section_test() { - todo -} - -pub fn visit_table_section_test() { - todo -} - -pub fn visit_type_section_test() { - todo -} - -pub fn visit_type_array_type_test() { - todo -} - -pub fn visit_type_code_test() { - todo -} - -pub fn visit_type_composite_type_test() { - todo -} - -pub fn visit_type_data_test() { - todo -} - -pub fn visit_type_data_idx_test() { - todo -} - -pub fn visit_type_def_type_test() { - todo -} - -pub fn visit_type_elem_test() { - todo -} - -pub fn visit_type_elem_idx_test() { - todo -} - -pub fn visit_type_elem_mode_test() { - todo -} - -pub fn visit_type_export_test() { - todo -} - -pub fn visit_type_expr_test() { - todo -} - -pub fn visit_type_field_idx_test() { - todo -} - -pub fn visit_type_field_type_test() { - todo -} - -pub fn visit_type_func_idx_test() { - todo -} - -pub fn visit_type_func_type_test() { - todo -} - -pub fn visit_type_global_test() { - todo -} - -pub fn visit_type_global_idx_test() { - todo -} - -pub fn visit_type_global_type_test() { - todo -} - -pub fn visit_type_heap_type_test() { - todo -} - -pub fn visit_type_import_test() { - todo -} - -pub fn visit_type_instruction_test() { - todo -} - -pub fn visit_type_label_idx_test() { - todo -} - -pub fn visit_type_limits_test() { - todo -} - -pub fn visit_type_local_idx_test() { - todo -} - -pub fn visit_type_locals_test() { - todo -} - -pub fn visit_type_mem_idx_test() { - todo -} - -pub fn visit_type_mem_type_test() { - todo -} - -pub fn visit_type_rec_type_test() { - todo -} - -pub fn visit_type_ref_type_test() { - todo -} - -pub fn visit_type_storage_type_test() { - todo -} - -pub fn visit_type_struct_type_test() { - todo -} - -pub fn visit_type_sub_type_test() { - todo -} - -pub fn visit_type_table_test() { - todo -} - -pub fn visit_type_table_idx_test() { - todo -} - -pub fn visit_type_table_type_test() { - todo -} - -pub fn visit_type_type_idx_test() { - todo -} - -pub fn visit_type_val_type_test() { - todo -} - -pub fn visit_active_data_test() { - todo -} - -pub fn visit_active_elem_mode_test() { - todo -} - -pub fn visit_any_heap_type_test() { - todo -} - -pub fn visit_any_ref_type_test() { - todo -} - -pub fn visit_array_composite_type_test() { - todo -} - -pub fn visit_array_copy_test() { - todo -} - -pub fn visit_array_fill_test() { - todo -} - -pub fn visit_array_get_test() { - todo -} - -pub fn visit_array_get_s_test() { - todo -} - -pub fn visit_array_get_u_test() { - todo -} - -pub fn visit_array_heap_type_test() { - todo -} - -pub fn visit_array_init_data_test() { - todo -} - -pub fn visit_array_init_elem_test() { - todo -} - -pub fn visit_array_new_test() { - todo -} - -pub fn visit_array_new_data_test() { - todo -} - -pub fn visit_array_new_default_test() { - todo -} - -pub fn visit_array_new_elem_test() { - todo -} - -pub fn visit_array_new_fixed_test() { - todo -} - -pub fn visit_array_ref_type_test() { - todo -} - -pub fn visit_array_set_test() { - todo -} - -pub fn visit_array_type_test() { - todo -} - -pub fn visit_block_test() { - todo -} - -pub fn visit_br_test() { - todo -} - -pub fn visit_br_if_test() { - todo -} - -pub fn visit_br_on_cast_test() { - todo -} - -pub fn visit_br_on_cast_fail_test() { - todo -} - -pub fn visit_br_on_non_null_test() { - todo -} - -pub fn visit_br_on_null_test() { - todo -} - -pub fn visit_br_table_test() { - todo -} - -pub fn visit_call_test() { - todo -} - -pub fn visit_call_indirect_test() { - todo -} - -pub fn visit_call_ref_test() { - todo -} - -pub fn visit_code_test() { - todo -} - -pub fn visit_concrete_heap_type_test() { - todo -} - -pub fn visit_data_drop_test() { - todo -} - -pub fn visit_declarative_elem_mode_test() { - todo -} - -pub fn visit_def_type_test() { - todo -} - -pub fn visit_def_type_reference_test() { - todo -} - -pub fn visit_elem_drop_test() { - todo -} - -pub fn visit_elem_expressions_test() { - todo -} - -pub fn visit_elem_funcs_test() { - todo -} - -pub fn visit_eq_heap_type_test() { - todo -} - -pub fn visit_eq_ref_type_test() { - todo -} - -pub fn visit_expr_test() { - todo -} - -pub fn visit_extern_heap_type_test() { - todo -} - -pub fn visit_extern_ref_type_test() { - todo -} - -pub fn visit_f32_val_type_test() { - todo -} - -pub fn visit_f64_val_type_test() { - todo -} - -pub fn visit_field_type_test() { - todo -} - -pub fn visit_func_composite_type_test() { - todo -} - -pub fn visit_func_export_test() { - todo -} - -pub fn visit_func_heap_type_test() { - todo -} - -pub fn visit_func_import_test() { - todo -} - -pub fn visit_func_ref_type_test() { - todo -} - -pub fn visit_func_type_test() { - todo -} - -pub fn visit_global_test() { - todo -} - -pub fn visit_global_export_test() { - todo -} - -pub fn visit_global_get_test() { - todo -} - -pub fn visit_global_import_test() { - todo -} - -pub fn visit_global_set_test() { - todo -} - -pub fn visit_global_type_test() { - todo -} - -pub fn visit_heap_type_ref_type_test() { - todo -} - -pub fn visit_i16_storage_type_test() { - todo -} - -pub fn visit_i31_heap_type_test() { - todo -} - -pub fn visit_i31_ref_type_test() { - todo -} - -pub fn visit_i32_val_type_test() { - todo -} - -pub fn visit_i64_val_type_test() { - todo -} - -pub fn visit_i8_storage_type_test() { - todo -} - -pub fn visit_if_test() { - todo -} - -pub fn visit_label_idx_test() { - todo -} - -pub fn visit_limits_test() { - todo -} - -pub fn visit_local_get_test() { - todo -} - -pub fn visit_local_set_test() { - todo -} - -pub fn visit_local_tee_test() { - todo -} - -pub fn visit_locals_test() { - todo -} - -pub fn visit_loop_test() { - todo -} - -pub fn visit_mem_export_test() { - todo -} - -pub fn visit_mem_idx_test() { - todo -} - -pub fn visit_mem_import_test() { - todo -} - -pub fn visit_mem_type_test() { - todo -} - -pub fn visit_memory_init_test() { - todo -} - -pub fn visit_no_extern_heap_type_test() { - todo -} - -pub fn visit_no_extern_ref_type_test() { - todo -} - -pub fn visit_no_func_heap_type_test() { - todo -} - -pub fn visit_no_func_ref_type_test() { - todo -} - -pub fn visit_none_heap_type_test() { - todo -} - -pub fn visit_none_ref_type_test() { - todo -} - -pub fn visit_passive_data_test() { - todo -} - -pub fn visit_passive_elem_mode_test() { - todo -} - -pub fn visit_rec_type_test() { - todo -} - -pub fn visit_rec_type_idx_test() { - todo -} - -pub fn visit_ref_cast_test() { - todo -} - -pub fn visit_ref_cast_nullable_test() { - todo -} - -pub fn visit_ref_func_test() { - todo -} - -pub fn visit_ref_null_test() { - todo -} - -pub fn visit_ref_test_test() { - todo -} - -pub fn visit_ref_test_nullable_test() { - todo -} - -pub fn visit_ref_type_val_type_test() { - todo -} - -pub fn visit_return_call_test() { - todo -} - -pub fn visit_return_call_indirect_test() { - todo -} - -pub fn visit_return_call_ref_test() { - todo -} - -pub fn visit_select_t_test() { - todo -} - -pub fn visit_struct_composite_type_test() { - todo -} - -pub fn visit_struct_get_test() { - todo -} - -pub fn visit_struct_get_s_test() { - todo -} - -pub fn visit_struct_get_u_test() { - todo -} - -pub fn visit_struct_heap_type_test() { - todo -} - -pub fn visit_struct_ref_type_test() { - todo -} - -pub fn visit_struct_set_test() { - todo -} - -pub fn visit_struct_type_test() { - todo -} - -pub fn visit_sub_type_test() { - todo -} - -pub fn visit_table_test() { - todo -} - -pub fn visit_table_copy_test() { - todo -} - -pub fn visit_table_export_test() { - todo -} - -pub fn visit_table_fill_test() { - todo -} - -pub fn visit_table_get_test() { - todo -} - -pub fn visit_table_grow_test() { - todo -} - -pub fn visit_table_import_test() { - todo -} - -pub fn visit_table_init_test() { - todo -} - -pub fn visit_table_set_test() { - todo -} - -pub fn visit_table_size_test() { - todo -} - -pub fn visit_table_type_test() { - todo -} - -pub fn visit_type_idx_test() { - todo -} - -pub fn visit_v128_val_type_test() { - todo -} - -pub fn visit_val_type_storage_type_test() { - todo -} From 5f18d1e26562f93980487fc21e5c69909cf37361 Mon Sep 17 00:00:00 2001 From: jtenner Date: Fri, 6 Sep 2024 16:44:16 -0400 Subject: [PATCH 09/16] more --- src/builder/types/composite_type.gleam | 29 +++++++++++++++++ test/visitor/composite_type_test.gleam | 44 ++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/builder/types/composite_type.gleam create mode 100644 test/visitor/composite_type_test.gleam diff --git a/src/builder/types/composite_type.gleam b/src/builder/types/composite_type.gleam new file mode 100644 index 0000000..6659399 --- /dev/null +++ b/src/builder/types/composite_type.gleam @@ -0,0 +1,29 @@ +import internal/finger_tree +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( + finger_tree.from_list(parameters), + finger_tree.from_list(results), + )) +} + +pub fn struct_type(fields: List(FieldType)) { + StructCompositeType(StructType(finger_tree.from_list(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/test/visitor/composite_type_test.gleam b/test/visitor/composite_type_test.gleam new file mode 100644 index 0000000..96d96a3 --- /dev/null +++ b/test/visitor/composite_type_test.gleam @@ -0,0 +1,44 @@ +import builder/types/composite_type +import builder/types/field_type + +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, + ) +} + +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, + ) +} + +pub fn visit_array_composite_type() { + // I cleaned up the imports :) + // I can take any random type I want, right? + // Well... for now I'll take i16 + 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, + ) +} From f6635d1b4e2023d8a50473d13f64c811addf873d Mon Sep 17 00:00:00 2001 From: jtenner Date: Sat, 7 Sep 2024 10:23:19 -0400 Subject: [PATCH 10/16] saving my work --- src/internal/structure/equality.gleam | 73 ++++++++++++++++++++++++++ src/internal/visitor.gleam | 9 +--- test/visitor/composite_type_test.gleam | 3 -- test/visitor/instruction_test.gleam | 2 +- test/visitor/visit_test_variant.gleam | 40 +++++++++----- 5 files changed, 104 insertions(+), 23 deletions(-) create mode 100644 src/internal/structure/equality.gleam diff --git a/src/internal/structure/equality.gleam b/src/internal/structure/equality.gleam new file mode 100644 index 0000000..204f679 --- /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/visitor.gleam b/src/internal/visitor.gleam index 001fe11..6f6f7e3 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -1,5 +1,3 @@ -import gleam/io -import gleam/list import gleam/option.{type Option, None, Some} import gleam/result.{map, try} import internal/finger_tree.{type FingerTree} @@ -43,6 +41,7 @@ import internal/structure/types.{ TableGrow, TableImport, TableInit, TableSet, TableSize, TableType, TypeIDX, V128ValType, ValTypeBlockType, ValTypeStorageType, VoidBlockType, } +import pprint pub type VisitorCallback(ctx, element) = fn(ctx, element) -> Result(#(ctx, element), String) @@ -916,7 +915,6 @@ fn do_visit_element_list( }, ), ) - #(ctx, elements) } @@ -940,7 +938,6 @@ pub fn do_visit_type_section( visitor, do_visit_rec_type, )) - #(ctx, Some(TypeSection(types))) } None -> Ok(#(ctx, None)) @@ -958,14 +955,12 @@ pub fn do_visit_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)) } @@ -2836,7 +2831,7 @@ pub fn do_visit_instruction( } MemoryInit(data_idx) -> { use #(ctx, data_idx) <- map(do_visit_data_idx(ctx, data_idx, visitor)) - #(ctx, DataDrop(data_idx)) + #(ctx, MemoryInit(data_idx)) } DataDrop(data_idx) -> { use #(ctx, data_idx) <- map(do_visit_data_idx(ctx, data_idx, visitor)) diff --git a/test/visitor/composite_type_test.gleam b/test/visitor/composite_type_test.gleam index 96d96a3..d1ab65f 100644 --- a/test/visitor/composite_type_test.gleam +++ b/test/visitor/composite_type_test.gleam @@ -29,9 +29,6 @@ pub fn visit_struct_composite_type() { } pub fn visit_array_composite_type() { - // I cleaned up the imports :) - // I can take any random type I want, right? - // Well... for now I'll take i16 let array_type = composite_type.array_type(field_type.i16) visit_test_variant.run( array_type, diff --git a/test/visitor/instruction_test.gleam b/test/visitor/instruction_test.gleam index 107f349..84e3fd5 100644 --- a/test/visitor/instruction_test.gleam +++ b/test/visitor/instruction_test.gleam @@ -28,7 +28,7 @@ pub fn visit_ref_null_test() { visitor.on_enter_instruction, visitor.on_exit_instruction, visitor.on_enter_ref_null, - visitor.on_exit_ref_func, + visitor.on_exit_ref_null, visitor.visit_instruction, ) } diff --git a/test/visitor/visit_test_variant.gleam b/test/visitor/visit_test_variant.gleam index 1ede5ac..20df594 100644 --- a/test/visitor/visit_test_variant.gleam +++ b/test/visitor/visit_test_variant.gleam @@ -27,24 +27,40 @@ pub fn run( let expected_context = #(1, 1, 1, 1) visitor.new() |> on_enter_type(fn(ctx, actual_value) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a + 1, b, c, d), 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) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a, b + 1, c, d), 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) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a, b, c + 1, d), 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) { - let #(a, b, c, d) = ctx - actual_value |> should.equal(expected_value) - Ok(#(#(a, b, c, d + 1), 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 From ac29e95fd86cccfd616b3c5460191d098c1f9526 Mon Sep 17 00:00:00 2001 From: jtenner Date: Fri, 13 Sep 2024 16:05:23 -0400 Subject: [PATCH 11/16] More --- gleam.toml | 1 + manifest.toml | 8 +- src/builder/expression.gleam | 60 +-- src/builder/instructions/control.gleam | 6 +- src/builder/module.gleam | 181 ++++--- src/builder/types/composite_type.gleam | 8 +- src/builder/types/func_type.gleam | 6 +- src/builder/types/rec_type.gleam | 24 +- src/builder/types/storage_type.gleam | 23 + src/builder/types/struct_type.gleam | 44 +- src/internal/binary/common.gleam | 14 +- src/internal/binary/modules.gleam | 12 +- src/internal/binary/types.gleam | 38 +- src/internal/finger_tree.gleam | 625 ------------------------- src/internal/structure/equality.gleam | 136 +++--- src/internal/structure/modules.gleam | 105 +++-- src/internal/structure/types.gleam | 245 +++++----- src/internal/validation/common.gleam | 46 +- src/internal/validation/module.gleam | 6 +- src/internal/visitor.gleam | 26 +- test/decode_test.gleam | 197 ++++---- test/encode_test.gleam | 91 ++-- test/instruction_test.gleam | 24 +- test/visitor/block_type_test.gleam | 4 + test/visitor/composite_type_test.gleam | 5 +- test/visitor/heap_type_test.gleam | 12 + test/visitor/instruction_test.gleam | 81 +++- test/visitor/ref_type_test.gleam | 13 +- test/visitor/storage_type_test.gleam | 40 ++ test/visitor/val_type.gleam | 7 + test/visitor/visit_test_variant.gleam | 87 ++-- 31 files changed, 863 insertions(+), 1312 deletions(-) create mode 100644 src/builder/types/storage_type.gleam delete mode 100644 src/internal/finger_tree.gleam create mode 100644 test/visitor/storage_type_test.gleam diff --git a/gleam.toml b/gleam.toml index cdb7e15..d853e41 100644 --- a/gleam.toml +++ b/gleam.toml @@ -17,6 +17,7 @@ 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" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index c378ccb..51e75e4 100644 --- a/manifest.toml +++ b/manifest.toml @@ -4,11 +4,12 @@ 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 = "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" }, ] @@ -17,4 +18,5 @@ gleam_stdlib = { version = ">= 0.34.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..36bd2e1 100644 --- a/src/builder/expression.gleam +++ b/src/builder/expression.gleam @@ -1,41 +1,41 @@ 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, } +import shine_tree.{type ShineTree} type BlockDefinition { EmptyTop - OuterMostBlock(instructions: FingerTree(Instruction)) - IfBlock(bt: BlockType, instructions: FingerTree(Instruction)) + OuterMostBlock(instructions: ShineTree(Instruction)) + IfBlock(bt: BlockType, instructions: ShineTree(Instruction)) ElseBlock( bt: BlockType, - if_instructions: FingerTree(Instruction), - else_instructions: FingerTree(Instruction), + if_instructions: ShineTree(Instruction), + else_instructions: ShineTree(Instruction), ) - LoopBlock(bt: BlockType, instructions: FingerTree(Instruction)) - InlineBlock(bt: BlockType, instructions: FingerTree(Instruction)) + LoopBlock(bt: BlockType, instructions: ShineTree(Instruction)) + InlineBlock(bt: BlockType, instructions: ShineTree(Instruction)) } pub opaque type ExpressionBuilder { ExpressionBuilder( result: Option(Expr), top: BlockDefinition, - block_stack: FingerTree(BlockDefinition), + block_stack: ShineTree(BlockDefinition), ) } pub fn new() -> ExpressionBuilder { - ExpressionBuilder(None, OuterMostBlock(finger_tree.empty), finger_tree.empty) + ExpressionBuilder(None, OuterMostBlock(shine_tree.empty), shine_tree.empty) } pub fn begin_if(builder: ExpressionBuilder, bt: BlockType) -> ExpressionBuilder { let ExpressionBuilder(result, top, block_stack) = builder ExpressionBuilder( result, - IfBlock(bt, finger_tree.empty), + IfBlock(bt, shine_tree.empty), block_stack - |> finger_tree.push(top), + |> shine_tree.push(top), ) } @@ -44,7 +44,7 @@ pub fn begin_else(builder: ExpressionBuilder) { IfBlock(bt, instructions) -> ExpressionBuilder( ..builder, - top: ElseBlock(bt, instructions, finger_tree.empty), + top: ElseBlock(bt, instructions, shine_tree.empty), ) EmptyTop -> panic as "Stack state underflow" _ -> panic as "Invalid stack state, cannot start else block" @@ -57,9 +57,9 @@ pub fn begin_loop( ) -> ExpressionBuilder { ExpressionBuilder( builder.result, - LoopBlock(bt, finger_tree.empty), + LoopBlock(bt, shine_tree.empty), builder.block_stack - |> finger_tree.push(builder.top), + |> shine_tree.push(builder.top), ) } @@ -69,16 +69,16 @@ pub fn begin_block( ) -> ExpressionBuilder { ExpressionBuilder( builder.result, - InlineBlock(bt, finger_tree.empty), + InlineBlock(bt, shine_tree.empty), builder.block_stack - |> finger_tree.push(builder.top), + |> shine_tree.push(builder.top), ) } pub fn end(builder: ExpressionBuilder) { case builder { ExpressionBuilder(None, OuterMostBlock(instructions), block_stack) - if block_stack == finger_tree.empty + if block_stack == shine_tree.empty -> Ok(ExpressionBuilder(Some(Expr(instructions)), EmptyTop, block_stack)) ExpressionBuilder(None, IfBlock(bt, if_instructions), block_stack) -> do_append(block_stack, If(bt, if_instructions, None)) @@ -98,16 +98,16 @@ pub fn end(builder: ExpressionBuilder) { } fn do_append( - next_stack: FingerTree(BlockDefinition), + next_stack: ShineTree(BlockDefinition), next_instruction: Instruction, ) { - case next_stack |> finger_tree.pop() { + case next_stack |> shine_tree.pop() { Ok(#(OuterMostBlock(outer_instructions), next_stack)) -> Ok(ExpressionBuilder( None, OuterMostBlock( outer_instructions - |> finger_tree.push(next_instruction), + |> shine_tree.push(next_instruction), ), next_stack, )) @@ -117,7 +117,7 @@ fn do_append( None, IfBlock( outer_bt, - outer_if_instructions |> finger_tree.push(next_instruction), + outer_if_instructions |> shine_tree.push(next_instruction), ), next_stack, )) @@ -130,7 +130,7 @@ fn do_append( ElseBlock( outer_bt, outer_if_instructions, - outer_else_instructions |> finger_tree.push(next_instruction), + outer_else_instructions |> shine_tree.push(next_instruction), ), next_stack, )) @@ -140,7 +140,7 @@ fn do_append( None, LoopBlock( outer_bt, - outer_instructions |> finger_tree.push(next_instruction), + outer_instructions |> shine_tree.push(next_instruction), ), next_stack, )) @@ -150,7 +150,7 @@ fn do_append( None, InlineBlock( outer_bt, - outer_instructions |> finger_tree.push(next_instruction), + outer_instructions |> shine_tree.push(next_instruction), ), next_stack, )) @@ -163,13 +163,13 @@ pub fn push(builder: ExpressionBuilder, inst: Instruction) { OuterMostBlock(instructions) -> ExpressionBuilder( None, - OuterMostBlock(instructions |> finger_tree.push(inst)), + OuterMostBlock(instructions |> shine_tree.push(inst)), builder.block_stack, ) IfBlock(bt, instructions) -> ExpressionBuilder( None, - IfBlock(bt, instructions |> finger_tree.push(inst)), + IfBlock(bt, instructions |> shine_tree.push(inst)), builder.block_stack, ) ElseBlock(bt, if_instructions, else_instructions) -> @@ -178,20 +178,20 @@ pub fn push(builder: ExpressionBuilder, inst: Instruction) { ElseBlock( bt, if_instructions, - else_instructions |> finger_tree.push(inst), + else_instructions |> shine_tree.push(inst), ), builder.block_stack, ) LoopBlock(bt, instructions) -> ExpressionBuilder( None, - LoopBlock(bt, instructions |> finger_tree.push(inst)), + LoopBlock(bt, instructions |> shine_tree.push(inst)), builder.block_stack, ) InlineBlock(bt, instructions) -> ExpressionBuilder( None, - InlineBlock(bt, instructions |> finger_tree.push(inst)), + InlineBlock(bt, instructions |> shine_tree.push(inst)), builder.block_stack, ) _ -> panic as "Expression completed, cannot push instruction" @@ -201,7 +201,7 @@ pub fn push(builder: ExpressionBuilder, inst: Instruction) { pub fn end_unwrap(builder) { case builder { ExpressionBuilder(None, OuterMostBlock(instructions), stack) - if stack == finger_tree.empty + if stack == shine_tree.empty -> Expr(instructions) _ -> panic as "Unable to unwrap, invalid expression state" } diff --git a/src/builder/instructions/control.gleam b/src/builder/instructions/control.gleam index 8fc240e..881c2ea 100644 --- a/src/builder/instructions/control.gleam +++ b/src/builder/instructions/control.gleam @@ -1,11 +1,11 @@ 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, BrOnNull, BrTable, Call, CallIndirect, CallRef, Drop, Nop, Return, ReturnCall, ReturnCallIndirect, ReturnCallRef, Select, SelectT, Unreachable, } +import shine_tree.{type ShineTree} pub fn return(builder: ExpressionBuilder) { builder @@ -36,7 +36,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: ShineTree(ValType)) { builder |> expression.push(SelectT(val_type)) } @@ -135,7 +135,7 @@ pub fn br_on_null(builder: ExpressionBuilder, label_idx: LabelIDX) { pub fn br_table( builder: ExpressionBuilder, - labels: FingerTree(LabelIDX), + labels: ShineTree(LabelIDX), default: LabelIDX, ) { builder diff --git a/src/builder/module.gleam b/src/builder/module.gleam index 5c4bc37..9a8fce4 100644 --- a/src/builder/module.gleam +++ b/src/builder/module.gleam @@ -1,7 +1,6 @@ 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, @@ -24,6 +23,7 @@ import internal/structure/types.{ StructCompositeType, StructType, SubType, Table, TableExport, TableIDX, TableImport, TableType, TypeIDX, Var, } +import shine_tree.{type ShineTree} pub const new = structure_modules.binary_module_new @@ -448,10 +448,10 @@ 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(ShineTree(u)), item: u) { case items { - Some(items) -> Some(finger_tree.push(items, item)) - None -> Some(finger_tree.single(item)) + Some(items) -> Some(shine_tree.push(items, item)) + None -> Some(shine_tree.single(item)) } } @@ -460,14 +460,11 @@ 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_))), - ) + BinaryModule(..module, types: Some(TypeSection(shine_tree.single(type_)))) Some(TypeSection(types)) -> BinaryModule( ..module, - types: Some(TypeSection(finger_tree.push(types, type_))), + types: Some(TypeSection(shine_tree.push(types, type_))), ) } } @@ -481,14 +478,14 @@ pub fn add_func_type( let func_type = SubType( False, - finger_tree.empty, + shine_tree.empty, FuncCompositeType(FuncType( - finger_tree.from_list(parameters), - finger_tree.from_list(results), + shine_tree.from_list(parameters), + shine_tree.from_list(results), )), ) - add_type(module, RecType(finger_tree.single(func_type))) + add_type(module, RecType(shine_tree.single(func_type))) } /// Add a new concrete ArrayType to the TypeSection @@ -496,10 +493,10 @@ pub fn add_array_type(module: BinaryModule, element_type: FieldType) { let array_type = SubType( False, - finger_tree.empty, + shine_tree.empty, ArrayCompositeType(ArrayType(element_type)), ) - add_type(module, RecType(finger_tree.single(array_type))) + add_type(module, RecType(shine_tree.single(array_type))) } // Add a new StructType to the TypeSection @@ -507,11 +504,11 @@ pub fn add_struct_type(module: BinaryModule, fields: List(FieldType)) { let struct_type = SubType( False, - finger_tree.empty, - StructCompositeType(StructType(finger_tree.from_list(fields))), + shine_tree.empty, + StructCompositeType(StructType(shine_tree.from_list(fields))), ) - add_type(module, RecType(finger_tree.single(struct_type))) + add_type(module, RecType(shine_tree.single(struct_type))) } // Add a new StructType to the TypeSection that is marked as "final" @@ -519,11 +516,11 @@ pub fn add_final_struct_type(module: BinaryModule, fields: List(FieldType)) { let struct_type = SubType( True, - finger_tree.empty, - StructCompositeType(StructType(finger_tree.from_list(fields))), + shine_tree.empty, + StructCompositeType(StructType(shine_tree.from_list(fields))), ) - add_type(module, RecType(finger_tree.single(struct_type))) + add_type(module, RecType(shine_tree.single(struct_type))) } /// Import a function from the host. The module_name and name are used to identify the @@ -542,9 +539,7 @@ pub fn import_func( BinaryModule( ..module, imports: Some( - ImportSection( - finger_tree.single(FuncImport(module_name, name, type_)), - ), + ImportSection(shine_tree.single(FuncImport(module_name, name, type_))), ), ) @@ -552,7 +547,7 @@ pub fn import_func( BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( + ImportSection(shine_tree.push( imports, FuncImport(module_name, name, type_), )), @@ -584,7 +579,7 @@ pub fn import_global( ..module, imports: Some( ImportSection( - finger_tree.single(GlobalImport( + shine_tree.single(GlobalImport( module_name, name, GlobalType(vt, mut), @@ -596,7 +591,7 @@ pub fn import_global( BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( + ImportSection(shine_tree.push( imports, GlobalImport(module_name, name, GlobalType(vt, mut)), )), @@ -622,7 +617,7 @@ pub fn import_table( ..module, imports: Some( ImportSection( - finger_tree.single(TableImport( + shine_tree.single(TableImport( module_name, name, TableType(ref_type, limits), @@ -634,7 +629,7 @@ pub fn import_table( BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( + ImportSection(shine_tree.push( imports, TableImport(module_name, name, TableType(ref_type, limits)), )), @@ -661,7 +656,7 @@ pub fn import_memory( ..module, imports: Some( ImportSection( - finger_tree.single(MemImport( + shine_tree.single(MemImport( module_name, name, MemType(Limits(min, max)), @@ -673,7 +668,7 @@ pub fn import_memory( BinaryModule( ..module, imports: Some( - ImportSection(finger_tree.push( + ImportSection(shine_tree.push( imports, MemImport(module_name, name, MemType(Limits(min, max))), )), @@ -697,13 +692,13 @@ pub fn append_function_type_index(module: BinaryModule, type_: TypeIDX) { BinaryModule(functions: None, ..), TypeIDX(_) -> BinaryModule( ..module, - functions: Some(FunctionSection(finger_tree.single(type_))), + functions: Some(FunctionSection(shine_tree.single(type_))), ) BinaryModule(functions: Some(FunctionSection(functions)), ..), TypeIDX(_) -> BinaryModule( ..module, - functions: Some(FunctionSection(finger_tree.push(functions, type_))), + functions: Some(FunctionSection(shine_tree.push(functions, type_))), ) _, _ -> panic as "Invalid type index" @@ -725,12 +720,12 @@ pub fn add_table( None -> BinaryModule( ..module, - tables: Some(TableSection(finger_tree.single(table))), + tables: Some(TableSection(shine_tree.single(table))), ) Some(TableSection(tables)) -> BinaryModule( ..module, - tables: Some(TableSection(finger_tree.push(tables, table))), + tables: Some(TableSection(shine_tree.push(tables, table))), ) } } @@ -744,7 +739,7 @@ pub fn add_memory(module: BinaryModule, memory: MemType) { None -> BinaryModule( ..module, - memories: Some(MemorySection(finger_tree.single(memory))), + memories: Some(MemorySection(shine_tree.single(memory))), ) _ -> panic as "Only one memory is allowed per module." } @@ -766,12 +761,12 @@ pub fn add_global(module: BinaryModule, vt: ValType, mut: Bool, init: Expr) { None -> BinaryModule( ..module, - globals: Some(GlobalSection(finger_tree.single(global))), + globals: Some(GlobalSection(shine_tree.single(global))), ) Some(GlobalSection(globals)) -> BinaryModule( ..module, - globals: Some(GlobalSection(finger_tree.push(globals, global))), + globals: Some(GlobalSection(shine_tree.push(globals, global))), ) } } @@ -792,19 +787,19 @@ pub fn export_func(module: BinaryModule, name: String, func: FuncIDX) { None -> BinaryModule( ..module, - exports: Some(ExportSection(finger_tree.single(FuncExport(name, func)))), + exports: Some(ExportSection(shine_tree.single(FuncExport(name, func)))), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( + |> shine_tree.try_foldl( set.new() |> set.insert(name), unique_export_name, ) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, FuncExport(name, func))), + ExportSection(shine_tree.push(exports, FuncExport(name, func))), ), ) } @@ -820,20 +815,20 @@ pub fn export_table(module: BinaryModule, name: String, table: TableIDX) { BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.single(TableExport(name, table))), + ExportSection(shine_tree.single(TableExport(name, table))), ), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( + |> shine_tree.try_foldl( set.new() |> set.insert(name), unique_export_name, ) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, TableExport(name, table))), + ExportSection(shine_tree.push(exports, TableExport(name, table))), ), ) } @@ -851,21 +846,19 @@ pub fn export_memory(module: BinaryModule, name: String, memory: MemIDX) { None -> BinaryModule( ..module, - exports: Some( - ExportSection(finger_tree.single(MemExport(name, memory))), - ), + exports: Some(ExportSection(shine_tree.single(MemExport(name, memory)))), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( + |> shine_tree.try_foldl( set.new() |> set.insert(name), unique_export_name, ) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, MemExport(name, memory))), + ExportSection(shine_tree.push(exports, MemExport(name, memory))), ), ) } @@ -881,20 +874,20 @@ pub fn export_global(module: BinaryModule, name: String, global: GlobalIDX) { BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.single(GlobalExport(name, global))), + ExportSection(shine_tree.single(GlobalExport(name, global))), ), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> finger_tree.try_reducel( + |> shine_tree.try_foldl( set.new() |> set.insert(name), unique_export_name, ) BinaryModule( ..module, exports: Some( - ExportSection(finger_tree.push(exports, GlobalExport(name, global))), + ExportSection(shine_tree.push(exports, GlobalExport(name, global))), ), ) } @@ -921,9 +914,9 @@ pub fn active_funcs_element_segment( ..module, elements: Some( ElementSection( - finger_tree.single(ElemFuncs( + shine_tree.single(ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + shine_tree.from_list(funcs), ActiveElemMode(table_index, offset), )), ), @@ -933,11 +926,11 @@ pub fn active_funcs_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( + ElementSection(shine_tree.push( elements, ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + shine_tree.from_list(funcs), ActiveElemMode(table_index, offset), ), )), @@ -955,9 +948,9 @@ pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) ..module, elements: Some( ElementSection( - finger_tree.single(ElemFuncs( + shine_tree.single(ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + shine_tree.from_list(funcs), PassiveElemMode, )), ), @@ -967,11 +960,11 @@ pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( + ElementSection(shine_tree.push( elements, ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + shine_tree.from_list(funcs), PassiveElemMode, ), )), @@ -992,9 +985,9 @@ pub fn declarative_funcs_element_segment( ..module, elements: Some( ElementSection( - finger_tree.single(ElemFuncs( + shine_tree.single(ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + shine_tree.from_list(funcs), DeclarativeElemMode, )), ), @@ -1004,11 +997,11 @@ pub fn declarative_funcs_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( + ElementSection(shine_tree.push( elements, ElemFuncs( HeapTypeRefType(FuncHeapType, False), - finger_tree.from_list(funcs), + shine_tree.from_list(funcs), DeclarativeElemMode, ), )), @@ -1034,9 +1027,9 @@ pub fn active_element_segment( ..module, elements: Some( ElementSection( - finger_tree.single(ElemExpressions( + shine_tree.single(ElemExpressions( ref_type, - finger_tree.from_list(exprs), + shine_tree.from_list(exprs), ActiveElemMode(table_index, offset), )), ), @@ -1047,11 +1040,11 @@ pub fn active_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( + ElementSection(shine_tree.push( elements, ElemExpressions( ref_type, - finger_tree.from_list(exprs), + shine_tree.from_list(exprs), ActiveElemMode(table_index, offset), ), )), @@ -1074,9 +1067,9 @@ pub fn passive_element_segment( ..module, elements: Some( ElementSection( - finger_tree.single(ElemExpressions( + shine_tree.single(ElemExpressions( ref_type, - finger_tree.from_list(exprs), + shine_tree.from_list(exprs), PassiveElemMode, )), ), @@ -1087,11 +1080,11 @@ pub fn passive_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( + ElementSection(shine_tree.push( elements, ElemExpressions( ref_type, - finger_tree.from_list(exprs), + shine_tree.from_list(exprs), PassiveElemMode, ), )), @@ -1114,9 +1107,9 @@ pub fn declarative_element_segment( ..module, elements: Some( ElementSection( - finger_tree.single(ElemExpressions( + shine_tree.single(ElemExpressions( ref_type, - finger_tree.from_list(exprs), + shine_tree.from_list(exprs), DeclarativeElemMode, )), ), @@ -1127,11 +1120,11 @@ pub fn declarative_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(finger_tree.push( + ElementSection(shine_tree.push( elements, ElemExpressions( ref_type, - finger_tree.from_list(exprs), + shine_tree.from_list(exprs), DeclarativeElemMode, ), )), @@ -1142,14 +1135,14 @@ 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)) + [] -> shine_tree.empty + [a, ..rest] -> do_concatenate_locals(rest, shine_tree.empty, #(1, a)) } } fn do_concatenate_locals( locals: List(ValType), - acc: FingerTree(Locals), + acc: ShineTree(Locals), current: #(Int, ValType), ) { case locals, current { @@ -1159,13 +1152,13 @@ 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, shine_tree.push(acc, locals), #(1, val_type)) } [], #(count, current_type) -> { let assert Ok(count) = u32(count) let locals = Locals(count, current_type) - finger_tree.push(acc, locals) + shine_tree.push(acc, locals) } } } @@ -1182,12 +1175,12 @@ pub fn add_code(module: BinaryModule, locals: List(ValType), body: Expr) { None -> BinaryModule( ..module, - code: Some(CodeSection(finger_tree.single(Code(locals, body)))), + code: Some(CodeSection(shine_tree.single(Code(locals, body)))), ) Some(CodeSection(code)) -> BinaryModule( ..module, - code: Some(CodeSection(finger_tree.push(code, Code(locals, body)))), + code: Some(CodeSection(shine_tree.push(code, Code(locals, body)))), ) } } @@ -1206,14 +1199,14 @@ pub fn add_active_data( BinaryModule( ..module, data: Some( - DataSection(finger_tree.single(ActiveData(mem_idx, offset, data))), + DataSection(shine_tree.single(ActiveData(mem_idx, offset, data))), ), ) Some(DataSection(data_section)) -> BinaryModule( ..module, data: Some( - DataSection(finger_tree.push( + DataSection(shine_tree.push( data_section, ActiveData(mem_idx, offset, data), )), @@ -1230,13 +1223,13 @@ pub fn add_passive_data(module: BinaryModule, data: BitArray) { None -> BinaryModule( ..module, - data: Some(DataSection(finger_tree.single(PassiveData(data)))), + data: Some(DataSection(shine_tree.single(PassiveData(data)))), ) Some(DataSection(data_section)) -> BinaryModule( ..module, data: Some( - DataSection(finger_tree.push(data_section, PassiveData(data))), + DataSection(shine_tree.push(data_section, PassiveData(data))), ), ) } @@ -1351,18 +1344,18 @@ pub fn decode(module: BitArray) { modules.decode_module(module) } -/// ShineCoder's FingerTree is an efficient data structure for +/// ShineCoder's ShineTree is an efficient data structure for /// storing and manipulating the ends of ordered vector data. /// This function takes a list and converts it into an opaque -/// FingerTree. +/// ShineTree. pub fn to_vector(values: List(u)) { - values |> finger_tree.from_list + values |> shine_tree.from_list } -/// ShineCoder's FingerTree is an efficient data structure for +/// ShineCoder's ShineTree is an efficient data structure for /// storing and manipulating the ends of ordered vector data. -/// This function takes a FingerTree and converts it into a +/// This function takes a ShineTree and converts it into a /// normal List. -pub fn to_list(values: FingerTree(u)) { - values |> finger_tree.to_list +pub fn to_list(values: ShineTree(u)) { + values |> shine_tree.to_list } diff --git a/src/builder/types/composite_type.gleam b/src/builder/types/composite_type.gleam index 6659399..0f3c29a 100644 --- a/src/builder/types/composite_type.gleam +++ b/src/builder/types/composite_type.gleam @@ -1,9 +1,9 @@ -import internal/finger_tree import internal/structure/types.{ type FieldType, type FuncType, type StructType, type ValType, ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, StructCompositeType, StructType, } +import shine_tree pub fn from_func_type(func_type: FuncType) { FuncCompositeType(func_type) @@ -11,13 +11,13 @@ pub fn from_func_type(func_type: FuncType) { pub fn func_type(parameters: List(ValType), results: List(ValType)) { FuncCompositeType(FuncType( - finger_tree.from_list(parameters), - finger_tree.from_list(results), + shine_tree.from_list(parameters), + shine_tree.from_list(results), )) } pub fn struct_type(fields: List(FieldType)) { - StructCompositeType(StructType(finger_tree.from_list(fields))) + StructCompositeType(StructType(shine_tree.from_list(fields))) } pub fn from_struct_type(struct_type: StructType) { diff --git a/src/builder/types/func_type.gleam b/src/builder/types/func_type.gleam index a5085f6..881c5ad 100644 --- a/src/builder/types/func_type.gleam +++ b/src/builder/types/func_type.gleam @@ -1,11 +1,11 @@ -import internal/finger_tree import internal/structure/types.{type ValType, FuncType} +import shine_tree /// 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), + shine_tree.from_list(param_types), + shine_tree.from_list(result_types), ) } diff --git a/src/builder/types/rec_type.gleam b/src/builder/types/rec_type.gleam index a28c9c5..b5554b6 100644 --- a/src/builder/types/rec_type.gleam +++ b/src/builder/types/rec_type.gleam @@ -1,31 +1,31 @@ -import internal/finger_tree import internal/structure/types.{ type FieldType, type FuncType, type StructType, type SubType, type ValType, ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, RecType, StructCompositeType, StructType, SubType, } +import shine_tree pub fn from_sub_types(sub_types: List(SubType)) { - RecType(sub_types |> finger_tree.from_list) + RecType(sub_types |> shine_tree.from_list) } pub fn from_func_type(func_type: FuncType) { RecType( - finger_tree.from_list([ - SubType(True, finger_tree.new(), FuncCompositeType(func_type)), + shine_tree.from_list([ + SubType(True, shine_tree.empty, FuncCompositeType(func_type)), ]), ) } pub fn func_type(parameters: List(ValType), results: List(ValType)) { RecType( - finger_tree.from_list([ + shine_tree.from_list([ SubType( True, - finger_tree.new(), + shine_tree.empty, FuncCompositeType(FuncType( - finger_tree.from_list(parameters), - finger_tree.from_list(results), + shine_tree.from_list(parameters), + shine_tree.from_list(results), )), ), ]), @@ -34,18 +34,18 @@ pub fn func_type(parameters: List(ValType), results: List(ValType)) { pub fn from_struct_type(struct_type: StructType) { RecType( - finger_tree.from_list([ - SubType(True, finger_tree.new(), StructCompositeType(struct_type)), + shine_tree.from_list([ + SubType(True, shine_tree.empty, StructCompositeType(struct_type)), ]), ) } pub fn array_type(element_type: FieldType) { RecType( - finger_tree.from_list([ + shine_tree.from_list([ SubType( True, - finger_tree.new(), + shine_tree.empty, 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..95c5333 --- /dev/null +++ b/src/builder/types/storage_type.gleam @@ -0,0 +1,23 @@ +import internal/structure/types.{ + F32ValType, F64ValType, I16StorageType, I32ValType, I64ValType, I8StorageType, + RefTypeValType, V128ValType, ValTypeStorageType, + type RefType, +} + +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..aa93e85 100644 --- a/src/builder/types/struct_type.gleam +++ b/src/builder/types/struct_type.gleam @@ -1,22 +1,22 @@ -import internal/finger_tree import internal/structure/types.{ type RefType, type StructType, type TypeIDX, ConcreteHeapType, Const, F32ValType, F64ValType, FieldType, HeapTypeRefType, I16StorageType, I32ValType, I64ValType, I8StorageType, RefTypeValType, StructType, TypeIDX, V128ValType, ValTypeStorageType, Var, } +import shine_tree /// Create an empty Struct type /// https://webassembly.github.io/gc/core/syntax/types.html#aggregate-types pub fn new() { - StructType(finger_tree.empty) + StructType(shine_tree.empty) } /// 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)), + |> shine_tree.push(FieldType(I8StorageType, Const)), ) } @@ -24,7 +24,7 @@ pub fn i8_field(struct_type: StructType) { pub fn i8_mut_field(struct_type: StructType) { StructType( struct_type.ft - |> finger_tree.push(FieldType(I8StorageType, Var)), + |> shine_tree.push(FieldType(I8StorageType, Var)), ) } @@ -32,7 +32,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)), + |> shine_tree.push(FieldType(I16StorageType, Const)), ) } @@ -40,7 +40,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)), + |> shine_tree.push(FieldType(I16StorageType, Var)), ) } @@ -48,7 +48,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(I32ValType), Const)), ) } @@ -56,7 +56,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(I32ValType), Var)), ) } @@ -64,7 +64,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(I64ValType), Const)), ) } @@ -72,7 +72,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(I64ValType), Var)), ) } @@ -80,7 +80,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(F32ValType), Const)), ) } @@ -88,7 +88,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(F32ValType), Var)), ) } @@ -96,7 +96,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(F64ValType), Const)), ) } @@ -104,7 +104,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(F64ValType), Var)), ) } @@ -112,7 +112,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(V128ValType), Const)), ) } @@ -120,7 +120,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)), + |> shine_tree.push(FieldType(ValTypeStorageType(V128ValType), Var)), ) } @@ -128,7 +128,7 @@ 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( + |> shine_tree.push(FieldType( ValTypeStorageType(RefTypeValType(ref_type)), Const, )), @@ -139,7 +139,7 @@ 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( + |> shine_tree.push(FieldType( ValTypeStorageType(RefTypeValType(ref_type)), Var, )), @@ -152,7 +152,7 @@ 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( + |> shine_tree.push(FieldType( ValTypeStorageType( RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), False)), ), @@ -167,7 +167,7 @@ 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( + |> shine_tree.push(FieldType( ValTypeStorageType( RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), False)), ), @@ -185,7 +185,7 @@ pub fn from_type_index_nullable_field( ) { StructType( struct_type.ft - |> finger_tree.push(FieldType( + |> shine_tree.push(FieldType( ValTypeStorageType( RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), True)), ), @@ -203,7 +203,7 @@ pub fn from_type_index_nullable_mut_field( ) { StructType( struct_type.ft - |> finger_tree.push(FieldType( + |> shine_tree.push(FieldType( ValTypeStorageType( RefTypeValType(HeapTypeRefType(ConcreteHeapType(type_idx), True)), ), diff --git a/src/internal/binary/common.gleam b/src/internal/binary/common.gleam index 72294e9..a98342e 100644 --- a/src/internal/binary/common.gleam +++ b/src/internal/binary/common.gleam @@ -5,21 +5,21 @@ 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} +import shine_tree.{type ShineTree} /// Encode a vector of items using the given encoding function pub fn encode_vec( builder: BytesBuilder, - items: FingerTree(u), + items: ShineTree(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(shine_tree.size(items) |> u32) builder |> encode_u32(size) // this function is a loop over the items in the vector - |> finger_tree.try_reducel(items, _, encode_fn) + |> shine_tree.try_foldl(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, shine_tree.empty, 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: ShineTree(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 |> shine_tree.push(val), decode_fn) } } } diff --git a/src/internal/binary/modules.gleam b/src/internal/binary/modules.gleam index 77e06e5..5677a05 100644 --- a/src/internal/binary/modules.gleam +++ b/src/internal/binary/modules.gleam @@ -11,7 +11,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, @@ -29,6 +28,7 @@ import internal/structure/types.{ GlobalExport, GlobalImport, HeapTypeRefType, Locals, MemExport, MemImport, PassiveData, PassiveElemMode, Table, TableExport, TableIDX, TableImport, } as structure_types +import shine_tree.{type ShineTree} /// The magic header bytes of every web assembly module const wasm_magic = <<0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00>> @@ -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, shine_tree.empty) } fn do_decode_custom_section(rest: BitArray) { @@ -642,10 +642,10 @@ 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: ShineTree(CustomSection)) { case decode_custom_section(bits) { Ok(#(Some(section), rest)) -> - do_decode_custom_sections(rest, acc |> finger_tree.push(section)) + do_decode_custom_sections(rest, acc |> shine_tree.push(section)) _ -> Ok(#(Some(acc), bits)) } } @@ -655,11 +655,11 @@ fn do_decode_custom_sections(bits: BitArray, acc: FingerTree(CustomSection)) { /// exhausted. pub fn encode_custom_sections( builder: BytesBuilder, - sections: Option(FingerTree(CustomSection)), + sections: Option(ShineTree(CustomSection)), ) { case sections { Some(sections) -> - finger_tree.try_reducel(sections, builder, encode_custom_section) + shine_tree.try_foldl(sections, builder, encode_custom_section) None -> Ok(builder) } } diff --git a/src/internal/binary/types.gleam b/src/internal/binary/types.gleam index 1ae5816..157c124 100644 --- a/src/internal/binary/types.gleam +++ b/src/internal/binary/types.gleam @@ -7,7 +7,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, @@ -113,6 +112,7 @@ import internal/structure/types.{ lane_16, lane_2, lane_4, lane_8, } import pprint +import shine_tree.{type ShineTree} /// Decode a lane index (u32) from the given bit array, and assert it's /// less than 16. @@ -379,7 +379,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), + result_type: ShineTree(ValType), ) { builder |> common.encode_vec(result_type, encode_val_type) } @@ -560,7 +560,7 @@ pub fn decode_rec_type(bits: BitArray) { } _ -> { use #(st, rest) <- result.map(decode_sub_type(bits)) - #(RecType(finger_tree.from_list([st])), rest) + #(RecType(shine_tree.from_list([st])), rest) } } } @@ -570,9 +570,9 @@ pub fn decode_rec_type(bits: BitArray) { /// 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 { + case rec_type.sub_types |> shine_tree.size { 1 -> - case rec_type.sub_types |> finger_tree.shift { + case rec_type.sub_types |> shine_tree.shift { Ok(#(sub_type, _)) -> encode_sub_type(builder, sub_type) Error(_) -> Error("Invalid recursive type") } @@ -605,7 +605,7 @@ 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, shine_tree.empty, ct), rest) } } } @@ -618,7 +618,7 @@ pub fn decode_sub_type(bits: BitArray) { /// 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 { + case sub_type.final, sub_type.t |> shine_tree.size { True, 0 -> builder |> encode_composite_type(sub_type.ct) True, _ -> { use builder <- result.try( @@ -960,27 +960,27 @@ pub fn encode_expression( /// until the list is empty. pub fn do_encode_instructions( builder: BytesBuilder, - insts: FingerTree(Instruction), + insts: ShineTree(Instruction), ) -> Result(BytesBuilder, String) { insts - |> finger_tree.try_reducel(builder, encode_instruction) + |> shine_tree.try_foldl(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, shine_tree.empty) } fn do_decode_expression( bits: BitArray, - acc: FingerTree(Instruction), + acc: ShineTree(Instruction), ) -> Result(#(Expr, BitArray), String) { case bits { <<0x0B, rest:bits>> -> Ok(#(Expr(acc), rest)) _ -> { use #(inst, rest) <- result.try(decode_instruction(bits)) - do_decode_expression(rest, acc |> finger_tree.push(inst)) + do_decode_expression(rest, acc |> shine_tree.push(inst)) } } } @@ -994,16 +994,16 @@ fn do_decode_expression( fn do_decode_if_instruction( bits: BitArray, bt: BlockType, - acc: FingerTree(Instruction), + acc: ShineTree(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) + do_decode_else_instruction(rest, bt, acc, shine_tree.empty) } _ -> { 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, acc |> shine_tree.push(inst)) } } } @@ -1014,8 +1014,8 @@ fn do_decode_if_instruction( fn do_decode_else_instruction( bits: BitArray, bt: BlockType, - if_acc: FingerTree(Instruction), - else_acc: FingerTree(Instruction), + if_acc: ShineTree(Instruction), + else_acc: ShineTree(Instruction), ) -> Result(#(Instruction, BitArray), String) { case bits { <<0x0B, rest:bits>> -> Ok(#(If(bt, if_acc, Some(else_acc)), rest)) @@ -1025,7 +1025,7 @@ fn do_decode_else_instruction( rest, bt, if_acc, - else_acc |> finger_tree.push(inst), + else_acc |> shine_tree.push(inst), ) } } @@ -2293,7 +2293,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, shine_tree.empty) } <<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 9a9517a..0000000 --- a/src/internal/finger_tree.gleam +++ /dev/null @@ -1,625 +0,0 @@ -//// Link to FingerTree description: https://www.staff.city.ac.uk/~ross/papers/FingerTree.html - -import gleam/option.{type Option, None, Some} -import gleam/result - -/// Finger tree implementation -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 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 map(tree: FingerTree(u), f: fn(u) -> v) -> FingerTree(v) { - use tree, a <- reducel(tree, Empty) - tree |> push(f(a)) -} - -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 index 204f679..47d7c11 100644 --- a/src/internal/structure/equality.gleam +++ b/src/internal/structure/equality.gleam @@ -1,73 +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 +// 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 RecTypeContext = +// Option(#(BinaryModule, Int)) -pub type EqualityElement { - EqualityHeapType(heap_type1: HeapType, heap_type2: HeapType) - EqualityTypeIDX(type_idx1: TypeIDX, type_idx2: TypeIDX) -} +// 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 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 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() - } - } -} +// 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..24a8b57 100644 --- a/src/internal/structure/modules.gleam +++ b/src/internal/structure/modules.gleam @@ -1,73 +1,76 @@ 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, type Import, type MemType, type RecType, type Table, type TypeIDX, } +import shine_tree.{type ShineTree} /// This type represents a BinaryModule, which is a structural representation of a WebAssembly module, /// rather than a conceptual one. This type is used internally to be an encoding/decoding interface /// for web assembly targets. pub type BinaryModule { BinaryModule( - custom_0: Option(FingerTree(CustomSection)), + custom_0: Option(ShineTree(CustomSection)), types: Option(TypeSection), - custom_1: Option(FingerTree(CustomSection)), + custom_1: Option(ShineTree(CustomSection)), imports: Option(ImportSection), - custom_2: Option(FingerTree(CustomSection)), + custom_2: Option(ShineTree(CustomSection)), functions: Option(FunctionSection), - custom_3: Option(FingerTree(CustomSection)), + custom_3: Option(ShineTree(CustomSection)), tables: Option(TableSection), - custom_4: Option(FingerTree(CustomSection)), + custom_4: Option(ShineTree(CustomSection)), memories: Option(MemorySection), - custom_5: Option(FingerTree(CustomSection)), + custom_5: Option(ShineTree(CustomSection)), globals: Option(GlobalSection), - custom_6: Option(FingerTree(CustomSection)), + custom_6: Option(ShineTree(CustomSection)), exports: Option(ExportSection), - custom_7: Option(FingerTree(CustomSection)), + custom_7: Option(ShineTree(CustomSection)), start: Option(StartSection), - custom_8: Option(FingerTree(CustomSection)), + custom_8: Option(ShineTree(CustomSection)), elements: Option(ElementSection), - custom_9: Option(FingerTree(CustomSection)), + custom_9: Option(ShineTree(CustomSection)), code: Option(CodeSection), - custom_10: Option(FingerTree(CustomSection)), + custom_10: Option(ShineTree(CustomSection)), data: Option(DataSection), - custom_11: Option(FingerTree(CustomSection)), + custom_11: Option(ShineTree(CustomSection)), data_count: Option(DataCountSection), - custom_12: Option(FingerTree(CustomSection)), + custom_12: Option(ShineTree(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 +83,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: ShineTree(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: ShineTree(Import)) } /// The WebAssembly function section is not a list of function declarations. Rather, it @@ -95,7 +98,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: ShineTree(TypeIDX)) } /// WebAssembly modules can declare tables which are pre-allocated arrays of values that @@ -103,27 +106,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: ShineTree(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: ShineTree(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: ShineTree(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: ShineTree(Export)) } /// The WebAssembly start section specifies the index of the function to be called when the @@ -139,7 +142,7 @@ pub type StartSection { /// 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: ShineTree(Elem)) } /// WebAssembly modules can declare callable functions called "Code"s which define the shape @@ -148,14 +151,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: ShineTree(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: ShineTree(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 12c6394..344c0da 100644 --- a/src/internal/structure/types.gleam +++ b/src/internal/structure/types.gleam @@ -1,10 +1,10 @@ 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, } +import shine_tree.{type ShineTree} /// Get the lane_16 indx nvalue as an integer pub fn unwrap_lane_16(val: LaneIDX16) { @@ -173,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: ShineTree(ValType), results: ShineTree(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: ShineTree(ValType), results: ShineTree(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: ShineTree(FieldType)) } /// An array type describes an array with the given field type. @@ -239,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: ShineTree(SubType)) } /// An index into an array of types, either a recursive type, a module subtype, or a @@ -293,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: ShineTree(TypeIDX), ct: CompositeType) } /// A definition of a limit range, which has a minimum, and an optional maximum which defaults @@ -781,7 +781,7 @@ pub type Instruction { ExternConvertAny Drop Select - SelectT(vt: FingerTree(ValType)) + SelectT(vt: ShineTree(ValType)) LocalGet(idx: LocalIDX) LocalSet(idx: LocalIDX) LocalTee(idx: LocalIDX) @@ -852,12 +852,12 @@ pub type Instruction { Loop(bt: BlockType, instructions: Expr) If( bt: BlockType, - instructions: FingerTree(Instruction), - else_instructions: Option(FingerTree(Instruction)), + instructions: ShineTree(Instruction), + else_instructions: Option(ShineTree(Instruction)), ) Br(label: LabelIDX) BrIf(label: LabelIDX) - BrTable(labels: FingerTree(LabelIDX), default: LabelIDX) + BrTable(labels: ShineTree(LabelIDX), default: LabelIDX) BrOnNull(label: LabelIDX) BrOnNonNull(label: LabelIDX) BrOnCast(label: LabelIDX, rt1: RefType, rt2: RefType) @@ -885,17 +885,17 @@ pub fn get_instruction_type( End | Else -> Error(Nil) I64Const(_) -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([I64ValType]))) + Ok(InstructionType(shine_tree.empty, shine_tree.from_list([I64ValType]))) I32Const(_) | ArrayLen | I31GetS | I31GetU -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([I32ValType]))) + Ok(InstructionType(shine_tree.empty, shine_tree.from_list([I32ValType]))) F64Const(_) -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([F64ValType]))) + Ok(InstructionType(shine_tree.empty, shine_tree.from_list([F64ValType]))) F32Const(_) -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([F32ValType]))) + Ok(InstructionType(shine_tree.empty, shine_tree.from_list([F32ValType]))) I64Popcnt | I64Ctz | I64Clz | I64Extend32S | I64Extend16S | I64Extend8S -> Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([I64ValType]), + shine_tree.from_list([I64ValType]), + shine_tree.from_list([I64ValType]), )) I32Popcnt | I32Ctz @@ -910,18 +910,18 @@ pub fn get_instruction_type( | I32Load8U(_) | MemoryGrow -> Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([I32ValType]), + shine_tree.from_list([I32ValType]), )) F64Nearest | F64Trunc | F64Floor | F64Ceil | F64Sqrt | F64Neg | F64Abs -> Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([F64ValType]), + shine_tree.from_list([F64ValType]), + shine_tree.from_list([F64ValType]), )) F32Nearest | F32Trunc | F32Floor | F32Ceil | F32Sqrt | F32Neg | F32Abs -> Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([F32ValType]), + shine_tree.from_list([F32ValType]), + shine_tree.from_list([F32ValType]), )) I64Rotr | I64Rotl @@ -939,8 +939,8 @@ pub fn get_instruction_type( | I64Sub | I64Add -> Ok(InstructionType( - finger_tree.from_list([I64ValType, I64ValType]), - finger_tree.from_list([I64ValType]), + shine_tree.from_list([I64ValType, I64ValType]), + shine_tree.from_list([I64ValType]), )) I32Rotr | I32Rotl @@ -968,23 +968,23 @@ pub fn get_instruction_type( | I32Ne | I32Eq -> Ok(InstructionType( - finger_tree.from_list([I32ValType, I32ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([I32ValType, I32ValType]), + shine_tree.from_list([I32ValType]), )) F64Copysign | F64Max | F64Min | F64Div | F64Mul | F64Sub | F64Add -> Ok(InstructionType( - finger_tree.from_list([F64ValType, F64ValType]), - finger_tree.from_list([F64ValType]), + shine_tree.from_list([F64ValType, F64ValType]), + shine_tree.from_list([F64ValType]), )) F32Copysign | F32Max | F32Min | F32Div | F32Mul | F32Sub | F32Add -> Ok(InstructionType( - finger_tree.from_list([F32ValType, F32ValType]), - finger_tree.from_list([F32ValType]), + shine_tree.from_list([F32ValType, F32ValType]), + shine_tree.from_list([F32ValType]), )) I64Eqz | I32WrapI64 -> Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([I64ValType]), + shine_tree.from_list([I32ValType]), )) I64GeS | I64GeU @@ -997,19 +997,19 @@ pub fn get_instruction_type( | I64Ne | I64Eq -> Ok(InstructionType( - finger_tree.from_list([I64ValType, I64ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([I64ValType, I64ValType]), + shine_tree.from_list([I32ValType]), )) F64Ge | F64Le | F64Gt | F64Lt | F64Ne | F64Eq -> Ok(InstructionType( - finger_tree.from_list([F64ValType, F64ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([F64ValType, F64ValType]), + shine_tree.from_list([I32ValType]), )) F32Ge | F32Le | F32Gt | F32Lt | F32Ne | F32Eq -> Ok(InstructionType( - finger_tree.from_list([F32ValType, F32ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([F32ValType, F32ValType]), + shine_tree.from_list([I32ValType]), )) I64ExtendI32S | I64ExtendI32U @@ -1021,8 +1021,8 @@ pub fn get_instruction_type( | I64Load32S(_) | I64Load32U(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([I64ValType]), + shine_tree.from_list([I32ValType]), + shine_tree.from_list([I64ValType]), )) I64TruncF64S | I64TruncF64U @@ -1030,18 +1030,18 @@ pub fn get_instruction_type( | I64TruncSatF64U | I64ReinterpretF64 -> Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([I64ValType]), + shine_tree.from_list([F64ValType]), + shine_tree.from_list([I64ValType]), )) I64TruncF32S | I64TruncF32U | I64TruncSatF32S | I64TruncSatF32U -> Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([I64ValType]), + shine_tree.from_list([F32ValType]), + shine_tree.from_list([I64ValType]), )) I32TruncF64S | I32TruncF64U | I32TruncSatF64S | I32TruncSatF64U -> Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([F64ValType]), + shine_tree.from_list([I32ValType]), )) I32TruncF32S | I32TruncF32U @@ -1049,44 +1049,41 @@ pub fn get_instruction_type( | I32TruncSatF32U | I32ReinterpretF32 -> Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([F32ValType]), + shine_tree.from_list([I32ValType]), )) F32DemoteF64 -> Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([F64ValType]), + shine_tree.from_list([F32ValType]), + shine_tree.from_list([F64ValType]), )) F64PromoteF32 -> Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([F32ValType]), + shine_tree.from_list([F64ValType]), + shine_tree.from_list([F32ValType]), )) F64ConvertI64S | F64ConvertI64U | F64ReinterpretI64 -> Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([F64ValType]), + shine_tree.from_list([I64ValType]), + shine_tree.from_list([F64ValType]), )) F64ConvertI32S | F64ConvertI32U | F64Load(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([F64ValType]), + shine_tree.from_list([I32ValType]), + shine_tree.from_list([F64ValType]), )) F32ConvertI64S | F32ConvertI64U -> Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([F32ValType]), + shine_tree.from_list([I64ValType]), + shine_tree.from_list([F32ValType]), )) F32ConvertI32S | F32ConvertI32U | F32ReinterpretI32 | F32Load(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([F32ValType]), + shine_tree.from_list([I32ValType]), + shine_tree.from_list([F32ValType]), )) V128Const(_) -> - Ok(InstructionType( - finger_tree.new(), - finger_tree.from_list([V128ValType]), - )) + Ok(InstructionType(shine_tree.empty, shine_tree.from_list([V128ValType]))) V128Not | I64x2Neg | I64x2Abs @@ -1126,8 +1123,8 @@ pub fn get_instruction_type( | F64x2ConvertLowI32x4U | F64x2PromoteLowF32x4 -> Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType]), )) V128Xor | V128AndNot @@ -1263,13 +1260,13 @@ pub fn get_instruction_type( | F32x4Add | I64x2Mul -> Ok(InstructionType( - finger_tree.from_list([V128ValType, V128ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType, V128ValType]), + shine_tree.from_list([V128ValType]), )) V128Bitselect -> Ok(InstructionType( - finger_tree.from_list([V128ValType, V128ValType, V128ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType, V128ValType, V128ValType]), + shine_tree.from_list([V128ValType]), )) V128AnyTrue | I8x16ExtractLaneS(_) @@ -1285,8 +1282,8 @@ pub fn get_instruction_type( | I16x8Bitmask | I8x16Bitmask -> Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([V128ValType]), + shine_tree.from_list([I32ValType]), )) I32x4Splat | I16x8Splat @@ -1305,43 +1302,43 @@ pub fn get_instruction_type( | V128Load16Splat(_) | V128Load8Splat(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([I32ValType]), + shine_tree.from_list([V128ValType]), )) I64x2Splat -> Ok(InstructionType( - finger_tree.from_list([I64ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([I64ValType]), + shine_tree.from_list([V128ValType]), )) F32x4Splat -> Ok(InstructionType( - finger_tree.from_list([F32ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([F32ValType]), + shine_tree.from_list([V128ValType]), )) F64x2Splat -> Ok(InstructionType( - finger_tree.from_list([F64ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([F64ValType]), + shine_tree.from_list([V128ValType]), )) I64x2ExtractLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([I64ValType]), + shine_tree.from_list([V128ValType]), + shine_tree.from_list([I64ValType]), )) I32x4ExtractLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([I32ValType]), + shine_tree.from_list([V128ValType]), + shine_tree.from_list([I32ValType]), )) F32x4ExtractLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([F32ValType]), + shine_tree.from_list([V128ValType]), + shine_tree.from_list([F32ValType]), )) F64x2ExtractLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType]), - finger_tree.from_list([F64ValType]), + shine_tree.from_list([V128ValType]), + shine_tree.from_list([F64ValType]), )) I8x16ReplaceLane(_) | I16x8ReplaceLane(_) @@ -1359,25 +1356,25 @@ pub fn get_instruction_type( | I8x16ShrU | I8x16Shl -> Ok(InstructionType( - finger_tree.from_list([V128ValType, I32ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType, I32ValType]), + shine_tree.from_list([V128ValType]), )) I64x2ReplaceLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType, I64ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType, I64ValType]), + shine_tree.from_list([V128ValType]), )) F32x4ReplaceLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType, F32ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType, F32ValType]), + shine_tree.from_list([V128ValType]), )) F64x2ReplaceLane(_) -> Ok(InstructionType( - finger_tree.from_list([V128ValType, F64ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([V128ValType, F64ValType]), + shine_tree.from_list([V128ValType]), )) - Nop -> Ok(InstructionType(finger_tree.new(), finger_tree.new())) + Nop -> Ok(InstructionType(shine_tree.empty, shine_tree.empty)) // TODO: Each of these instructions need to be implemented and checked RefFunc(_) @@ -1445,38 +1442,38 @@ pub fn get_instruction_type( RefI31 -> Ok(InstructionType( - finger_tree.new(), - finger_tree.from_list([RefTypeValType(I31RefType)]), + shine_tree.empty, + shine_tree.from_list([RefTypeValType(I31RefType)]), )) AnyConvertExtern -> Ok(InstructionType( - finger_tree.from_list([RefTypeValType(ExternRefType)]), - finger_tree.from_list([RefTypeValType(AnyRefType)]), + shine_tree.from_list([RefTypeValType(ExternRefType)]), + shine_tree.from_list([RefTypeValType(AnyRefType)]), )) ExternConvertAny -> Ok(InstructionType( - finger_tree.from_list([RefTypeValType(AnyRefType)]), - finger_tree.from_list([RefTypeValType(ExternRefType)]), + shine_tree.from_list([RefTypeValType(AnyRefType)]), + shine_tree.from_list([RefTypeValType(ExternRefType)]), )) I64Store(_) | I64Store16(_) | I64Store8(_) | I64Store32(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, I64ValType]), - finger_tree.new(), + shine_tree.from_list([I32ValType, I64ValType]), + shine_tree.empty, )) I32Store(_) | I32Store16(_) | I32Store8(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, I32ValType]), - finger_tree.new(), + shine_tree.from_list([I32ValType, I32ValType]), + shine_tree.empty, )) F64Store(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, F64ValType]), - finger_tree.new(), + shine_tree.from_list([I32ValType, F64ValType]), + shine_tree.empty, )) F32Store(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, F32ValType]), - finger_tree.new(), + shine_tree.from_list([I32ValType, F32ValType]), + shine_tree.empty, )) V128Store(_) | V128Store8Lane(_, _) @@ -1484,38 +1481,38 @@ pub fn get_instruction_type( | V128Store32Lane(_, _) | V128Store64Lane(_, _) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, V128ValType]), - finger_tree.new(), + shine_tree.from_list([I32ValType, V128ValType]), + shine_tree.empty, )) V128Load8Lane(_, _) | V128Load16Lane(_, _) | V128Load32Lane(_, _) | V128Load64Lane(_, _) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, V128ValType]), - finger_tree.from_list([V128ValType]), + shine_tree.from_list([I32ValType, V128ValType]), + shine_tree.from_list([V128ValType]), )) MemorySize -> - Ok(InstructionType(finger_tree.new(), finger_tree.from_list([I32ValType]))) + Ok(InstructionType(shine_tree.empty, shine_tree.from_list([I32ValType]))) MemoryFill | MemoryCopy | MemoryInit(_) -> Ok(InstructionType( - finger_tree.from_list([I32ValType, I32ValType, I32ValType]), - finger_tree.new(), + shine_tree.from_list([I32ValType, I32ValType, I32ValType]), + shine_tree.empty, )) - DataDrop(_) -> Ok(InstructionType(finger_tree.new(), finger_tree.new())) + DataDrop(_) -> Ok(InstructionType(shine_tree.empty, shine_tree.empty)) } } /// An expression is a "End" [0x0B] terminated sequence of instructions that describe a /// calculated value. pub type Expr { - Expr(insts: FingerTree(Instruction)) + Expr(insts: ShineTree(Instruction)) } /// 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 |> shine_tree.get(idx)) st.ct } @@ -1563,8 +1560,8 @@ pub type Global { /// 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) + ElemFuncs(type_: RefType, init: ShineTree(FuncIDX), mode: ElemMode) + ElemExpressions(type_: RefType, init: ShineTree(Expr), mode: ElemMode) } /// An element segment defines a sequence of expressions used to describe items that can be used in a @@ -1598,7 +1595,7 @@ pub type Export { /// A WebAssembly function body defined by it's locals and an expression. pub type Code { - Code(locals: FingerTree(Locals), body: Expr) + Code(locals: ShineTree(Locals), body: Expr) } /// Data segments can be used to initialize a range of memory from a static vector of bytes. diff --git a/src/internal/validation/common.gleam b/src/internal/validation/common.gleam index 10f20c2..c6cf996 100644 --- a/src/internal/validation/common.gleam +++ b/src/internal/validation/common.gleam @@ -1,40 +1,40 @@ import gleam/option.{type Option, None} -import internal/finger_tree.{type FingerTree} import internal/structure/types.{ type Data, type DefType, type Elem, type FuncIDX, type GlobalType, type Locals, type MemType, type RecType, type TableType, type ValType, } +import shine_tree.{type ShineTree} pub type Context { Context( - types: FingerTree(DefType), - funcs: FingerTree(DefType), - tables: FingerTree(TableType), - mems: FingerTree(MemType), - globals: FingerTree(GlobalType), - elems: FingerTree(Elem), - data: FingerTree(Data), - locals: FingerTree(Locals), - labels: FingerTree(FingerTree(ValType)), - return: Option(FingerTree(ValType)), - refs: FingerTree(FuncIDX), + types: ShineTree(DefType), + funcs: ShineTree(DefType), + tables: ShineTree(TableType), + mems: ShineTree(MemType), + globals: ShineTree(GlobalType), + elems: ShineTree(Elem), + data: ShineTree(Data), + locals: ShineTree(Locals), + labels: ShineTree(ShineTree(ValType)), + return: Option(ShineTree(ValType)), + refs: ShineTree(FuncIDX), ) } pub const empty_context = Context( - types: finger_tree.empty, - funcs: finger_tree.empty, - tables: finger_tree.empty, - mems: finger_tree.empty, - globals: finger_tree.empty, - elems: finger_tree.empty, - data: finger_tree.empty, - locals: finger_tree.empty, - labels: finger_tree.empty, + types: shine_tree.empty, + funcs: shine_tree.empty, + tables: shine_tree.empty, + mems: shine_tree.empty, + globals: shine_tree.empty, + elems: shine_tree.empty, + data: shine_tree.empty, + locals: shine_tree.empty, + labels: shine_tree.empty, return: None, - refs: finger_tree.empty, + refs: shine_tree.empty, ) -pub fn roll_rec_types(rec_type: RecType) -> FingerTree(DefType) { +pub fn roll_rec_types(rec_type: RecType) -> ShineTree(DefType) { todo } diff --git a/src/internal/validation/module.gleam b/src/internal/validation/module.gleam index 8391c11..295fe40 100644 --- a/src/internal/validation/module.gleam +++ b/src/internal/validation/module.gleam @@ -1,17 +1,17 @@ import gleam/option.{type Option, None, Some} import gleam/result -import internal/finger_tree 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.{validate_rec_type} as _validation_types +import shine_tree pub fn validate_type(ctx_prime: Context, rec_type: RecType) { let def_types = rec_type |> roll_rec_types let ctx = - Context(..ctx_prime, types: finger_tree.append(ctx_prime.types, def_types)) + Context(..ctx_prime, types: shine_tree.append(ctx_prime.types, def_types)) use _ <- result.map(validate_rec_type(ctx, rec_type)) ctx } @@ -19,7 +19,7 @@ pub fn validate_type(ctx_prime: Context, rec_type: RecType) { pub fn validate_module(module: BinaryModule) { use context <- result.try(case module.types { Some(TypeSection(types)) -> - finger_tree.try_reducel(types, empty_context, validate_type) + shine_tree.try_foldl(types, empty_context, validate_type) None -> Ok(empty_context) }) diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam index 6f6f7e3..0862033 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -1,6 +1,5 @@ import gleam/option.{type Option, None, Some} import gleam/result.{map, try} -import internal/finger_tree.{type FingerTree} import internal/structure/modules.{ type BinaryModule, type CodeSection, type CustomSection, type DataCountSection, type DataSection, type ElementSection, type ExportSection, @@ -42,6 +41,7 @@ import internal/structure/types.{ V128ValType, ValTypeBlockType, ValTypeStorageType, VoidBlockType, } import pprint +import shine_tree.{type ShineTree} pub type VisitorCallback(ctx, element) = fn(ctx, element) -> Result(#(ctx, element), String) @@ -899,19 +899,19 @@ fn do_visit(ctx, element, visitor: Option(VisitorCallback(ctx, element))) { fn do_visit_element_list( ctx, - elements: FingerTree(element), + elements: ShineTree(element), visitor: BinaryModuleVisitor(ctx), do_visit_callback: fn(ctx, element, BinaryModuleVisitor(ctx)) -> Result(#(ctx, element), String), ) { use #(ctx, elements, _) <- map( - finger_tree.try_reducel( + shine_tree.try_foldl( elements, - #(ctx, finger_tree.empty, visitor), + #(ctx, shine_tree.empty, visitor), fn(acc, element) { let #(ctx, acc, visitor) = acc use #(ctx, element) <- map(do_visit_callback(ctx, element, visitor)) - #(ctx, acc |> finger_tree.push(element), visitor) + #(ctx, acc |> shine_tree.push(element), visitor) }, ), ) @@ -1329,15 +1329,15 @@ pub fn do_visit_array_type( pub fn do_visit_custom_sections( ctx, - custom_sections: Option(FingerTree(CustomSection)), + custom_sections: Option(ShineTree(CustomSection)), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, Option(FingerTree(CustomSection))), String) { +) -> Result(#(ctx, Option(ShineTree(CustomSection))), String) { case custom_sections { Some(custom_sections) -> do_visit_custom_sections_filter( ctx, custom_sections, - finger_tree.empty, + shine_tree.empty, visitor, ) _ -> Ok(#(ctx, custom_sections)) @@ -1346,11 +1346,11 @@ pub fn do_visit_custom_sections( fn do_visit_custom_sections_filter( ctx, - custom_sections: FingerTree(CustomSection), - acc: FingerTree(CustomSection), + custom_sections: ShineTree(CustomSection), + acc: ShineTree(CustomSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, Option(FingerTree(CustomSection))), String) { - case finger_tree.shift(custom_sections) { +) -> Result(#(ctx, Option(ShineTree(CustomSection))), String) { + case shine_tree.shift(custom_sections) { Ok(#(custom_section, custom_sections)) -> { use #(ctx, custom_section) <- try(do_visit_custom_section( ctx, @@ -1362,7 +1362,7 @@ fn do_visit_custom_sections_filter( do_visit_custom_sections_filter( ctx, custom_sections, - finger_tree.push(acc, custom_section), + shine_tree.push(acc, custom_section), visitor, ) None -> diff --git a/test/decode_test.gleam b/test/decode_test.gleam index 3e651d3..53ffbe8 100644 --- a/test/decode_test.gleam +++ b/test/decode_test.gleam @@ -11,15 +11,15 @@ 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, FuncImport, GlobalImport, MemImport, RefFunc, TableImport, } as structure_types +import shine_tree pub fn func_idx_to_expr(expr: FuncIDX) { - Expr([RefFunc(expr)] |> finger_tree.from_list) + Expr([RefFunc(expr)] |> shine_tree.from_list) } fn should_equal_helper(val: Result(u, String), expected: u) { @@ -176,13 +176,13 @@ pub fn decode_result_type_test() { <<0>> |> types.decode_result_type |> should.be_ok - |> pair.map_first(finger_tree.to_list) + |> pair.map_first(shine_tree.to_list) |> should.equal(#([], <<>>)) <<4, 0x7F, 0x7E, 0x7D, 0x7C>> |> types.decode_result_type |> should.be_ok - |> pair.map_first(finger_tree.to_list) + |> pair.map_first(shine_tree.to_list) |> should.equal( #( [ @@ -269,12 +269,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(shine_tree.empty), <<>>)) <<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 |> shine_tree.to_list }) |> should.equal( #( [ @@ -310,11 +310,11 @@ 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) + |> shine_tree.to_list + |> should.equal(b.parameters |> shine_tree.to_list) a.results - |> finger_tree.to_list - |> should.equal(b.results |> finger_tree.to_list) + |> shine_tree.to_list + |> should.equal(b.results |> shine_tree.to_list) } fn struct_type_equals( @@ -322,8 +322,8 @@ fn struct_type_equals( b: structure_types.StructType, ) { a.ft - |> finger_tree.to_list - |> should.equal(b.ft |> finger_tree.to_list) + |> shine_tree.to_list + |> should.equal(b.ft |> shine_tree.to_list) } fn array_type_equals(a: structure_types.ArrayType, b: structure_types.ArrayType) { @@ -363,8 +363,8 @@ 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(), + shine_tree.empty, + shine_tree.empty, )), types.decode_comp_type, composite_type_equals, @@ -377,7 +377,7 @@ pub fn decode_composite_type_test() { >>, structure_types.StructCompositeType( structure_types.StructType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), structure_types.Const, @@ -434,12 +434,12 @@ 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: shine_tree.ShineTree(structure_types.TypeIDX), + b: shine_tree.ShineTree(structure_types.TypeIDX), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty + if rest_a == shine_tree.empty && rest_b == shine_tree.empty -> { a |> should.equal(b) Nil @@ -454,12 +454,12 @@ fn do_type_idxs_equal( } fn do_func_idxs_equal( - a: finger_tree.FingerTree(structure_types.FuncIDX), - b: finger_tree.FingerTree(structure_types.FuncIDX), + a: shine_tree.ShineTree(structure_types.FuncIDX), + b: shine_tree.ShineTree(structure_types.FuncIDX), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty + if rest_a == shine_tree.empty && rest_b == shine_tree.empty -> { a |> should.equal(b) Nil @@ -487,12 +487,12 @@ 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: shine_tree.ShineTree(structure_types.SubType), + b: shine_tree.ShineTree(structure_types.SubType), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty + if rest_a == shine_tree.empty && rest_b == shine_tree.empty -> { sub_type_equals(a, b) Nil @@ -510,7 +510,7 @@ pub fn decode_rec_type_test() { let subtype_one = structure_types.SubType( True, - finger_tree.new(), + shine_tree.empty, structure_types.ArrayCompositeType( structure_types.ArrayType(structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), @@ -519,7 +519,7 @@ pub fn decode_rec_type_test() { ), ) let rec_type_one = - structure_types.RecType(finger_tree.from_list([subtype_one])) + structure_types.RecType(shine_tree.from_list([subtype_one])) <<0x5E, 0x7F, 0x00>> |> decode_type_equals_helper( @@ -533,13 +533,13 @@ pub fn decode_rec_type_test() { let subtype_two = structure_types.SubType( False, - finger_tree.from_list([ + shine_tree.from_list([ structure_types.TypeIDX(idx_one), structure_types.TypeIDX(idx_two), ]), structure_types.StructCompositeType( structure_types.StructType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), structure_types.Const, @@ -550,7 +550,7 @@ pub fn decode_rec_type_test() { ) let rec_type_two = - structure_types.RecType(finger_tree.from_list([subtype_two])) + structure_types.RecType(shine_tree.from_list([subtype_two])) <<0x50, 0x02, 0x01, 0x02, 0x5F, 0x01, 0x7F, 0x00>> |> decode_type_equals_helper( @@ -563,7 +563,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(shine_tree.from_list([subtype_one, subtype_two])), types.decode_rec_type, rec_type_equals, ) @@ -626,12 +626,12 @@ fn type_section_equals( } fn do_rec_types_equal( - a: finger_tree.FingerTree(structure_types.RecType), - b: finger_tree.FingerTree(structure_types.RecType), + a: shine_tree.ShineTree(structure_types.RecType), + b: shine_tree.ShineTree(structure_types.RecType), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty + if rest_a == shine_tree.empty && rest_b == shine_tree.empty -> { rec_type_equals(a, b) Nil @@ -647,7 +647,7 @@ fn do_rec_types_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(shine_tree.empty) <<0x01, 0x01, 0x00>> |> decode_type_equals_helper( @@ -658,10 +658,10 @@ pub fn decode_type_section_test() { let array_type_example = structure_types.RecType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.SubType( True, - finger_tree.new(), + shine_tree.empty, structure_types.ArrayCompositeType( structure_types.ArrayType(structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), @@ -676,7 +676,7 @@ pub fn decode_type_section_test() { let example_type_section_length = <<0x04>> let example_type_section = - structure_modules.TypeSection(finger_tree.from_list([array_type_example])) + structure_modules.TypeSection(shine_tree.from_list([array_type_example])) << 0x01, @@ -703,12 +703,12 @@ fn import_section_equals( } fn do_imports_equal( - a: finger_tree.FingerTree(structure_types.Import), - b: finger_tree.FingerTree(structure_types.Import), + a: shine_tree.ShineTree(structure_types.Import), + b: shine_tree.ShineTree(structure_types.Import), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == finger_tree.empty && rest_b == finger_tree.empty + if rest_a == shine_tree.empty && rest_b == shine_tree.empty -> { import_equals(a, b) Nil @@ -758,7 +758,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(shine_tree.empty) <<0x02, 0x01, 0x00>> |> decode_type_equals_helper( @@ -794,9 +794,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(shine_tree.from_list([func_import_example])) <<0x02, func_import_bytes_length, func_import_bytes:bits>> |> decode_type_equals_helper( Some(example_import_section), @@ -819,7 +817,7 @@ fn function_section_equals( // 3 function section pub fn decode_function_section_test() { let empty_function_section = - structure_modules.FunctionSection(finger_tree.new()) + structure_modules.FunctionSection(shine_tree.empty) <<0x03, 0x01, 0x00>> |> decode_type_equals_helper( @@ -830,10 +828,10 @@ pub fn decode_function_section_test() { let assert Ok(indexes) = [1, 2, 3, 4] - |> finger_tree.from_list - |> finger_tree.try_map(numbers.u32) + |> shine_tree.from_list + |> shine_tree.try_map(numbers.u32) - let indexes = indexes |> finger_tree.map(structure_types.TypeIDX) + let indexes = indexes |> shine_tree.map(structure_types.TypeIDX) let function_section = structure_modules.FunctionSection(indexes) @@ -857,10 +855,10 @@ fn table_section_equals( } fn do_tables_equal( - a: finger_tree.FingerTree(structure_types.Table), - b: finger_tree.FingerTree(structure_types.Table), + a: shine_tree.ShineTree(structure_types.Table), + b: shine_tree.ShineTree(structure_types.Table), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { a |> table_equals(b) do_tables_equal(rest_a, rest_b) @@ -917,7 +915,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(shine_tree.empty) <<0x04, 0x01, 0x00>> |> decode_type_equals_helper( @@ -951,7 +949,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(shine_tree.from_list([second_table]))), modules.decode_table_section, table_section_equals, ) @@ -975,7 +973,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])), + structure_modules.TableSection(shine_tree.from_list([table_init_three])), ), modules.decode_table_section, table_section_equals, @@ -990,10 +988,10 @@ 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: shine_tree.ShineTree(structure_types.MemType), + b: shine_tree.ShineTree(structure_types.MemType), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { a |> mem_types_equals(b) do_mem_types_equal(rest_a, rest_b) @@ -1024,7 +1022,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(shine_tree.empty) <<0x05, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1045,7 +1043,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])), + structure_modules.MemorySection(shine_tree.from_list([example_memory])), ), modules.decode_memory_section, memory_section_equals, @@ -1066,10 +1064,10 @@ 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: shine_tree.ShineTree(structure_types.Global), + b: shine_tree.ShineTree(structure_types.Global), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { a |> globals_equals(b) do_globals_equal(rest_a, rest_b) @@ -1093,7 +1091,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(shine_tree.empty) <<0x06, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1118,7 +1116,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])), + structure_modules.GlobalSection(shine_tree.from_list([example_global])), ), modules.decode_global_section, global_section_equals, @@ -1156,10 +1154,10 @@ 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: shine_tree.ShineTree(structure_types.Export), + b: shine_tree.ShineTree(structure_types.Export), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { a |> exports_equals(b) do_exports_equal(rest_a, rest_b) @@ -1182,7 +1180,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(shine_tree.empty) <<0x07, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1207,7 +1205,7 @@ pub fn decode_export_section_test() { let export_section = structure_modules.ExportSection( - finger_tree.from_list([ + shine_tree.from_list([ func_export, table_export, mem_export, @@ -1274,10 +1272,10 @@ 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: shine_tree.ShineTree(structure_types.Expr), + b: shine_tree.ShineTree(structure_types.Expr), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { a |> expr_equals(b) do_expressions_equals(rest_a, rest_b) @@ -1312,10 +1310,10 @@ 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: shine_tree.ShineTree(structure_types.Elem), + b: shine_tree.ShineTree(structure_types.Elem), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { a |> elements_equals(b) do_elements_equal(rest_a, rest_b) @@ -1338,8 +1336,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(shine_tree.empty) <<0x09, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1363,7 +1360,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: ShineTree(Expr), mode: ElemMode) let ref_null_i31 = structure_types.I31RefType let null_i31 = @@ -1371,17 +1368,17 @@ 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 = shine_tree.from_list([null_i31, null_i31, null_i31]) let three_func_idx = - finger_tree.from_list([ + shine_tree.from_list([ 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) + three_func_idx |> shine_tree.map(func_idx_to_expr) // type 0 -> (ref func) (init: FuncIDX*) Active(TableIDX(0), Offset(offset_fourty_two)) let element_zero = @@ -1584,7 +1581,7 @@ pub fn decode_element_section_test() { let element_section = structure_modules.ElementSection( - finger_tree.from_list([ + shine_tree.from_list([ element_zero, element_one, element_two, @@ -1646,10 +1643,10 @@ 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: shine_tree.ShineTree(structure_types.Locals), + b: shine_tree.ShineTree(structure_types.Locals), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { locals_equals(a, b) do_locals_equals(rest_a, rest_b) @@ -1666,10 +1663,10 @@ fn codes_equals(a: structure_types.Code, b: structure_types.Code) { } fn do_codes_equals( - a: finger_tree.FingerTree(structure_types.Code), - b: finger_tree.FingerTree(structure_types.Code), + a: shine_tree.ShineTree(structure_types.Code), + b: shine_tree.ShineTree(structure_types.Code), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { codes_equals(a, b) do_codes_equals(rest_a, rest_b) @@ -1694,7 +1691,7 @@ fn code_section_equals( pub fn code_section_test() { let assert Ok(two) = numbers.u32(2) let add_locals = - finger_tree.from_list([ + shine_tree.from_list([ structure_types.Locals(two, structure_types.I32ValType), ]) @@ -1703,7 +1700,7 @@ pub fn code_section_test() { let code_section = structure_modules.CodeSection( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.Code( add_locals, expression.new() @@ -1762,10 +1759,10 @@ 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), + a: shine_tree.ShineTree(structure_types.Data), + b: shine_tree.ShineTree(structure_types.Data), ) { - case finger_tree.shift(a), finger_tree.shift(b) { + case shine_tree.shift(a), shine_tree.shift(b) { Ok(#(a, rest_a)), Ok(#(b, rest_b)) -> { data_equals(a, b) do_data_equals(rest_a, rest_b) @@ -1816,7 +1813,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(shine_tree.empty) <<0x0B, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1827,7 +1824,7 @@ pub fn data_section_test() { let data_section = structure_modules.DataSection( - finger_tree.from_list([active_data_zero_idx, passive_data, active_data]), + shine_tree.from_list([active_data_zero_idx, passive_data, active_data]), ) let data_section_bytes = << diff --git a/test/encode_test.gleam b/test/encode_test.gleam index c003f6e..188d8eb 100644 --- a/test/encode_test.gleam +++ b/test/encode_test.gleam @@ -10,13 +10,13 @@ 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 +import shine_tree pub fn func_idx_to_expr(expr: FuncIDX) { - Expr([RefFunc(expr)] |> finger_tree.from_list) + Expr([RefFunc(expr)] |> shine_tree.from_list) } fn should_equal_helper(val: Result(BytesBuilder, String), expected: BitArray) { @@ -174,9 +174,9 @@ pub fn encode_heap_type_ref_type_test() { } pub fn encode_result_type_test() { - let empty = finger_tree.new() + let empty = shine_tree.empty let four = - finger_tree.from_list([ + shine_tree.from_list([ structure_types.I32ValType, structure_types.I64ValType, structure_types.F32ValType, @@ -245,13 +245,13 @@ 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(shine_tree.empty)) |> should_equal_helper(<<0>>) bytes_builder.new() |> types.encode_struct_type( structure_types.StructType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), structure_types.Const, @@ -288,8 +288,8 @@ 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(), + shine_tree.empty, + shine_tree.empty, )), ) |> should_equal_helper(<<0x60, 0x00, 0x00>>) @@ -298,7 +298,7 @@ pub fn encode_composite_type_test() { |> types.encode_composite_type( structure_types.StructCompositeType( structure_types.StructType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), structure_types.Const, @@ -359,7 +359,7 @@ pub fn encode_rec_type_test() { let subtype_one = structure_types.SubType( True, - finger_tree.new(), + shine_tree.empty, structure_types.ArrayCompositeType( structure_types.ArrayType(structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), @@ -370,7 +370,7 @@ pub fn encode_rec_type_test() { bytes_builder.new() |> types.encode_rec_type( - structure_types.RecType(finger_tree.from_list([subtype_one])), + structure_types.RecType(shine_tree.from_list([subtype_one])), ) |> should_equal_helper(<<0x5E, 0x7F, 0x00>>) @@ -379,13 +379,13 @@ pub fn encode_rec_type_test() { let subtype_two = structure_types.SubType( False, - finger_tree.from_list([ + shine_tree.from_list([ structure_types.TypeIDX(idx_one), structure_types.TypeIDX(idx_two), ]), structure_types.StructCompositeType( structure_types.StructType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), structure_types.Const, @@ -397,13 +397,13 @@ pub fn encode_rec_type_test() { bytes_builder.new() |> types.encode_rec_type( - structure_types.RecType(finger_tree.from_list([subtype_two])), + structure_types.RecType(shine_tree.from_list([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])), + structure_types.RecType(shine_tree.from_list([subtype_one, subtype_two])), ) |> should_equal_helper(<< 0x4E, 0x02, 0x5E, 0x7F, 0x00, 0x50, 0x02, 0x01, 0x02, 0x5F, 0x01, 0x7F, 0x00, @@ -439,7 +439,7 @@ 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(shine_tree.empty) bytes_builder.new() |> modules.encode_type_section(empty_type_section) @@ -447,10 +447,10 @@ pub fn type_section_test() { let array_type_example = structure_types.RecType( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.SubType( True, - finger_tree.new(), + shine_tree.empty, structure_types.ArrayCompositeType( structure_types.ArrayType(structure_types.FieldType( structure_types.ValTypeStorageType(structure_types.I32ValType), @@ -465,7 +465,7 @@ pub fn type_section_test() { let example_type_section_length = <<0x04>> let example_type_section = - structure_modules.TypeSection(finger_tree.from_list([array_type_example])) + structure_modules.TypeSection(shine_tree.from_list([array_type_example])) bytes_builder.new() |> modules.encode_type_section(example_type_section) @@ -478,7 +478,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(shine_tree.empty) bytes_builder.new() |> modules.encode_import_section(empty_import_section) @@ -511,9 +511,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(shine_tree.from_list([func_import_example])) bytes_builder.new() |> modules.encode_import_section(example_import_section) @@ -526,7 +524,7 @@ pub fn import_section_test() { pub fn function_section_test() { let empty_function_section = - structure_modules.FunctionSection(finger_tree.new()) + structure_modules.FunctionSection(shine_tree.empty) bytes_builder.new() |> modules.encode_function_section(empty_function_section) @@ -534,10 +532,10 @@ pub fn function_section_test() { let assert Ok(indexes) = [1, 2, 3, 4] - |> finger_tree.from_list - |> finger_tree.try_map(numbers.u32) + |> shine_tree.from_list + |> shine_tree.try_map(numbers.u32) - let indexes = indexes |> finger_tree.map(structure_types.TypeIDX) + let indexes = indexes |> shine_tree.map(structure_types.TypeIDX) let function_section = structure_modules.FunctionSection(indexes) @@ -547,7 +545,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(shine_tree.empty) bytes_builder.new() |> modules.encode_table_section(empty_table_section) @@ -568,7 +566,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(shine_tree.from_list([example_table])), ) |> should_equal_helper(<< 0x04, @@ -595,13 +593,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(shine_tree.from_list([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(shine_tree.empty) bytes_builder.new() |> modules.encode_memory_section(empty_memory_section) @@ -618,7 +616,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(shine_tree.from_list([example_memory])), ) |> should_equal_helper(<< 0x05, @@ -629,7 +627,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(shine_tree.empty) bytes_builder.new() |> modules.encode_global_section(empty_global_section) @@ -649,7 +647,7 @@ pub fn global_section_test() { ) let global_section = - structure_modules.GlobalSection(finger_tree.from_list([example_global])) + structure_modules.GlobalSection(shine_tree.from_list([example_global])) let global_section_bytes = << 0x06, 0x07, 0x01, 0x7F, 0x01, 0x41, 0xC2, 0x00, 0x0B, >> @@ -659,7 +657,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(shine_tree.empty) bytes_builder.new() |> modules.encode_export_section(empty_export_section) @@ -681,7 +679,7 @@ pub fn export_section_test() { let export_section = structure_modules.ExportSection( - finger_tree.from_list([ + shine_tree.from_list([ func_export, table_export, mem_export, @@ -730,8 +728,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(shine_tree.empty) bytes_builder.new() |> modules.encode_element_section(empty_element_section) @@ -752,7 +749,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: ShineTree(Expr), mode: ElemMode) let ref_null_i31 = structure_types.HeapTypeRefType(structure_types.I31HeapType, True) @@ -761,17 +758,17 @@ 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 = shine_tree.from_list([null_i31, null_i31, null_i31]) let three_func_idx = - finger_tree.from_list([ + shine_tree.from_list([ 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) + three_func_idx |> shine_tree.map(func_idx_to_expr) // type 0 -> (ref func) (init: FuncIDX*) Active(TableIDX(0), Offset(offset_fourty_two)) let element_zero = @@ -945,7 +942,7 @@ pub fn element_section_test() { let element_section = structure_modules.ElementSection( - finger_tree.from_list([ + shine_tree.from_list([ element_zero, element_one, element_two, @@ -1001,7 +998,7 @@ pub fn element_section_test() { pub fn code_section_test() { let assert Ok(two) = numbers.u32(2) let add_locals = - finger_tree.from_list([ + shine_tree.from_list([ structure_types.Locals(two, structure_types.I32ValType), ]) @@ -1010,7 +1007,7 @@ pub fn code_section_test() { let code_section = structure_modules.CodeSection( - finger_tree.from_list([ + shine_tree.from_list([ structure_types.Code( add_locals, expression.new() @@ -1079,7 +1076,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(shine_tree.empty) bytes_builder.new() |> modules.encode_data_section(empty_data_section) @@ -1087,7 +1084,7 @@ pub fn data_section_test() { let data_section = structure_modules.DataSection( - finger_tree.from_list([active_data_zero_idx, passive_data, active_data]), + shine_tree.from_list([active_data_zero_idx, passive_data, active_data]), ) let data_section_bytes = << diff --git a/test/instruction_test.gleam b/test/instruction_test.gleam index 21e2569..c581bfc 100644 --- a/test/instruction_test.gleam +++ b/test/instruction_test.gleam @@ -6,10 +6,10 @@ 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 +import shine_tree fn round_trip( expected_inst: structure_types.Instruction, @@ -116,7 +116,7 @@ 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 = shine_tree.from_list(label_list) let assert Ok(#( structure_types.BrTable(actual_labels, actual_label_default), @@ -124,7 +124,7 @@ pub fn br_table_test() { )) = types.decode_instruction(<<0x0E, 3, 1, 2, 3, 42>>) actual_labels - |> finger_tree.to_list + |> shine_tree.to_list |> should.equal(label_list) actual_label_default @@ -204,7 +204,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(shine_tree.from_list(instruction_list)) let assert Ok(#( structure_types.Block( @@ -219,7 +219,7 @@ pub fn block_test() { |> should.equal(structure_types.VoidBlockType) actual_block_body - |> finger_tree.to_list + |> shine_tree.to_list |> should.equal(instruction_list) let assert Ok(builder) = @@ -256,7 +256,7 @@ pub fn loop_test() { types.decode_instruction(<<0x03, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>) block_body - |> finger_tree.to_list + |> shine_tree.to_list |> should.equal(instruction_list) let assert Ok(builder) = @@ -264,7 +264,7 @@ pub fn loop_test() { bytes_builder.new(), structure_types.Loop( structure_types.VoidBlockType, - structure_types.Expr(instruction_list |> finger_tree.from_list), + structure_types.Expr(instruction_list |> shine_tree.from_list), ), ) @@ -284,7 +284,7 @@ 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 = shine_tree.from_list(instruction_list) let assert Ok(#( structure_types.If(structure_types.VoidBlockType, result_body, None), @@ -293,7 +293,7 @@ pub fn if_test() { types.decode_instruction(<<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>) result_body - |> finger_tree.to_list + |> shine_tree.to_list |> should.equal(instruction_list) let assert Ok(builder) = @@ -313,7 +313,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 = shine_tree.from_list([local_get1, drop]) round_trip( structure_types.If( @@ -884,13 +884,13 @@ pub fn select_t_test() { structure_types.F32ValType, structure_types.F64ValType, ] - let val_types = finger_tree.from_list(val_types_list) + let val_types = shine_tree.from_list(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 + |> shine_tree.to_list |> should.equal(val_types_list) let assert Ok(builder) = diff --git a/test/visitor/block_type_test.gleam b/test/visitor/block_type_test.gleam index 5c99ad2..34fc92f 100644 --- a/test/visitor/block_type_test.gleam +++ b/test/visitor/block_type_test.gleam @@ -1,6 +1,7 @@ import builder/module import builder/types/block_type import builder/types/val_type +import gleam/option.{None} import visitor import visitor/visit_test_variant @@ -12,6 +13,7 @@ pub fn visit_val_type_storage_type_test() { visitor.on_enter_val_type_block_type, visitor.on_exit_val_type_block_type, visitor.visit_block_type, + None, ) } @@ -23,6 +25,7 @@ pub fn visit_void_block_type_test() { visitor.on_enter_void_block_type, visitor.on_exit_void_block_type, visitor.visit_block_type, + None, ) } @@ -35,5 +38,6 @@ pub fn visit_func_type_block_type_test() { 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 index d1ab65f..e53a8b6 100644 --- a/test/visitor/composite_type_test.gleam +++ b/test/visitor/composite_type_test.gleam @@ -1,6 +1,6 @@ import builder/types/composite_type import builder/types/field_type - +import gleam/option.{None} import visitor import visitor/visit_test_variant @@ -13,6 +13,7 @@ pub fn visit_func_composite_type() { visitor.on_enter_func_composite_type, visitor.on_exit_func_composite_type, visitor.visit_composite_type, + None, ) } @@ -25,6 +26,7 @@ pub fn visit_struct_composite_type() { visitor.on_enter_struct_composite_type, visitor.on_exit_struct_composite_type, visitor.visit_composite_type, + None, ) } @@ -37,5 +39,6 @@ pub fn visit_array_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 index c41f4aa..8aba80b 100644 --- a/test/visitor/heap_type_test.gleam +++ b/test/visitor/heap_type_test.gleam @@ -6,6 +6,7 @@ import internal/structure/types.{ } import visitor import visitor/visit_test_variant +import gleam/option.{None} pub fn visit_func_heap_type_test() { visit_test_variant.run( @@ -15,6 +16,7 @@ pub fn visit_func_heap_type_test() { visitor.on_enter_func_heap_type, visitor.on_exit_func_heap_type, visitor.visit_heap_type, + None, ) } @@ -26,6 +28,7 @@ pub fn visit_no_func_heap_type_test() { visitor.on_enter_no_func_heap_type, visitor.on_exit_no_func_heap_type, visitor.visit_heap_type, + None, ) } @@ -37,6 +40,7 @@ pub fn visit_extern_heap_type_test() { visitor.on_enter_extern_heap_type, visitor.on_exit_extern_heap_type, visitor.visit_heap_type, + None, ) } @@ -48,6 +52,7 @@ pub fn visit_no_extern_heap_type_test() { visitor.on_enter_no_extern_heap_type, visitor.on_exit_no_extern_heap_type, visitor.visit_heap_type, + None, ) } @@ -59,6 +64,7 @@ pub fn visit_any_heap_type_test() { visitor.on_enter_any_heap_type, visitor.on_exit_any_heap_type, visitor.visit_heap_type, + None, ) } @@ -70,6 +76,7 @@ pub fn visit_eq_heap_type_test() { visitor.on_enter_eq_heap_type, visitor.on_exit_eq_heap_type, visitor.visit_heap_type, + None, ) } @@ -81,6 +88,7 @@ pub fn visit_i31_heap_type_test() { visitor.on_enter_i31_heap_type, visitor.on_exit_i31_heap_type, visitor.visit_heap_type, + None, ) } @@ -92,6 +100,7 @@ pub fn visit_struct_heap_type_test() { visitor.on_enter_struct_heap_type, visitor.on_exit_struct_heap_type, visitor.visit_heap_type, + None, ) } @@ -103,6 +112,7 @@ pub fn visit_array_heap_type_test() { visitor.on_enter_array_heap_type, visitor.on_exit_array_heap_type, visitor.visit_heap_type, + None, ) } @@ -114,6 +124,7 @@ pub fn visit_none_heap_type_test() { visitor.on_enter_none_heap_type, visitor.on_exit_none_heap_type, visitor.visit_heap_type, + None, ) } @@ -126,5 +137,6 @@ pub fn visit_concrete_heap_type_test() { 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 index 84e3fd5..fb2694d 100644 --- a/test/visitor/instruction_test.gleam +++ b/test/visitor/instruction_test.gleam @@ -3,8 +3,7 @@ import builder/instructions/control import builder/instructions/i32 import builder/module import builder/types/block_type -import gleam/option.{None} -import internal/finger_tree +import gleam/option.{None, Some} import internal/structure/types.{ ArrayCopy, ArrayFill, ArrayGet, ArrayGetS, ArrayGetU, ArrayInitData, ArrayInitElem, ArrayNew, ArrayNewData, ArrayNewDefault, ArrayNewElem, @@ -17,6 +16,7 @@ import internal/structure/types.{ StructSet, TableCopy, TableFill, TableGet, TableGrow, TableInit, TableSet, TableSize, } +import shine_tree import values import visitor import visitor/visit_test_variant @@ -30,6 +30,7 @@ pub fn visit_ref_null_test() { visitor.on_enter_ref_null, visitor.on_exit_ref_null, visitor.visit_instruction, + None, ) } @@ -42,6 +43,7 @@ pub fn visit_ref_func_test() { visitor.on_enter_ref_func, visitor.on_exit_ref_func, visitor.visit_instruction, + None, ) } @@ -54,6 +56,7 @@ pub fn visit_ref_test_test() { visitor.on_enter_ref_test, visitor.on_exit_ref_test, visitor.visit_instruction, + None, ) } @@ -66,6 +69,7 @@ pub fn visit_ref_test_nullable_test() { visitor.on_enter_ref_test_nullable, visitor.on_exit_ref_test_nullable, visitor.visit_instruction, + None, ) } @@ -78,6 +82,7 @@ pub fn visit_ref_cast_test() { visitor.on_enter_ref_cast, visitor.on_exit_ref_cast, visitor.visit_instruction, + None, ) } @@ -90,6 +95,7 @@ pub fn visit_ref_cast_nullable_test() { visitor.on_enter_ref_cast_nullable, visitor.on_exit_ref_cast_nullable, visitor.visit_instruction, + None, ) } @@ -103,6 +109,7 @@ pub fn visit_struct_get_test() { visitor.on_enter_struct_get, visitor.on_exit_struct_get, visitor.visit_instruction, + None, ) } @@ -116,6 +123,7 @@ pub fn visit_struct_get_s_test() { visitor.on_enter_struct_get_s, visitor.on_exit_struct_get_s, visitor.visit_instruction, + None, ) } @@ -129,6 +137,7 @@ pub fn visit_struct_get_u_test() { visitor.on_enter_struct_get_u, visitor.on_exit_struct_get_u, visitor.visit_instruction, + None, ) } @@ -142,6 +151,7 @@ pub fn visit_struct_set_test() { visitor.on_enter_struct_set, visitor.on_exit_struct_set, visitor.visit_instruction, + None, ) } @@ -154,6 +164,7 @@ pub fn visit_array_new_test() { visitor.on_enter_array_new, visitor.on_exit_array_new, visitor.visit_instruction, + None, ) } @@ -166,6 +177,7 @@ pub fn visit_array_new_default_test() { visitor.on_enter_array_new_default, visitor.on_exit_array_new_default, visitor.visit_instruction, + None, ) } @@ -179,6 +191,7 @@ pub fn visit_array_new_data_test() { visitor.on_enter_array_new_data, visitor.on_exit_array_new_data, visitor.visit_instruction, + None, ) } @@ -192,6 +205,7 @@ pub fn visit_array_new_elem_test() { visitor.on_enter_array_new_elem, visitor.on_exit_array_new_elem, visitor.visit_instruction, + None, ) } @@ -205,6 +219,7 @@ pub fn visit_array_new_fixed_test() { visitor.on_enter_array_new_fixed, visitor.on_exit_array_new_fixed, visitor.visit_instruction, + None, ) } @@ -217,6 +232,7 @@ pub fn visit_array_get_test() { visitor.on_enter_array_get, visitor.on_exit_array_get, visitor.visit_instruction, + None, ) } @@ -229,6 +245,7 @@ pub fn visit_array_get_s_test() { visitor.on_enter_array_get_s, visitor.on_exit_array_get_s, visitor.visit_instruction, + None, ) } @@ -241,6 +258,7 @@ pub fn visit_array_get_u_test() { visitor.on_enter_array_get_u, visitor.on_exit_array_get_u, visitor.visit_instruction, + None, ) } @@ -253,6 +271,7 @@ pub fn visit_array_set_test() { visitor.on_enter_array_set, visitor.on_exit_array_set, visitor.visit_instruction, + None, ) } @@ -265,6 +284,7 @@ pub fn visit_array_fill_test() { visitor.on_enter_array_fill, visitor.on_exit_array_fill, visitor.visit_instruction, + None, ) } @@ -278,6 +298,7 @@ pub fn visit_array_copy_test() { visitor.on_enter_array_copy, visitor.on_exit_array_copy, visitor.visit_instruction, + None, ) } @@ -291,6 +312,7 @@ pub fn visit_array_init_data_test() { visitor.on_enter_array_init_data, visitor.on_exit_array_init_data, visitor.visit_instruction, + None, ) } @@ -304,6 +326,7 @@ pub fn visit_array_init_elem_test() { visitor.on_enter_array_init_elem, visitor.on_exit_array_init_elem, visitor.visit_instruction, + None, ) } @@ -316,8 +339,15 @@ pub fn visit_select_t_test() { visitor.on_enter_instruction, visitor.on_exit_instruction, visitor.on_enter_select_t, - visitor.on_exit_ref_func, + visitor.on_exit_select_t, visitor.visit_instruction, + Some(fn(actual, expected) { + case actual, expected { + SelectT(actual_val_types), SelectT(expected_val_types) -> + shine_tree.equals(actual_val_types, expected_val_types) + a, b -> a == b + } + }), ) } @@ -330,6 +360,7 @@ pub fn visit_local_get_test() { visitor.on_enter_local_get, visitor.on_exit_local_get, visitor.visit_instruction, + None, ) } @@ -342,6 +373,7 @@ pub fn visit_local_set_test() { visitor.on_enter_local_set, visitor.on_exit_local_set, visitor.visit_instruction, + None, ) } @@ -354,6 +386,7 @@ pub fn visit_local_tee_test() { visitor.on_enter_local_tee, visitor.on_exit_local_tee, visitor.visit_instruction, + None, ) } @@ -366,6 +399,7 @@ pub fn visit_global_get_test() { visitor.on_enter_global_get, visitor.on_exit_global_get, visitor.visit_instruction, + None, ) } @@ -378,6 +412,7 @@ pub fn visit_global_set_test() { visitor.on_enter_global_set, visitor.on_exit_global_set, visitor.visit_instruction, + None, ) } @@ -390,6 +425,7 @@ pub fn visit_table_get_test() { visitor.on_enter_table_get, visitor.on_exit_table_get, visitor.visit_instruction, + None, ) } @@ -402,6 +438,7 @@ pub fn visit_table_set_test() { visitor.on_enter_table_set, visitor.on_exit_table_set, visitor.visit_instruction, + None, ) } @@ -414,6 +451,7 @@ pub fn visit_table_size_test() { visitor.on_enter_table_size, visitor.on_exit_table_size, visitor.visit_instruction, + None, ) } @@ -426,6 +464,7 @@ pub fn visit_table_grow_test() { visitor.on_enter_table_grow, visitor.on_exit_table_grow, visitor.visit_instruction, + None, ) } @@ -438,6 +477,7 @@ pub fn visit_table_fill_test() { visitor.on_enter_table_fill, visitor.on_exit_table_fill, visitor.visit_instruction, + None, ) } @@ -451,6 +491,7 @@ pub fn visit_table_copy_test() { visitor.on_enter_table_copy, visitor.on_exit_table_copy, visitor.visit_instruction, + None, ) } @@ -465,6 +506,7 @@ pub fn visit_table_init_test() { visitor.on_enter_table_init, visitor.on_exit_table_init, visitor.visit_instruction, + None, ) } @@ -477,6 +519,7 @@ pub fn visit_elem_drop_test() { visitor.on_enter_elem_drop, visitor.on_exit_elem_drop, visitor.visit_instruction, + None, ) } @@ -489,6 +532,7 @@ pub fn visit_memory_init_test() { visitor.on_enter_memory_init, visitor.on_exit_memory_init, visitor.visit_instruction, + None, ) } @@ -501,6 +545,7 @@ pub fn visit_data_drop_test() { visitor.on_enter_data_drop, visitor.on_exit_data_drop, visitor.visit_instruction, + None, ) } @@ -522,6 +567,7 @@ pub fn visit_block_test() { visitor.on_enter_block, visitor.on_exit_block, visitor.visit_instruction, + None, ) } @@ -538,11 +584,12 @@ pub fn visit_loop_test() { visitor.on_enter_loop, visitor.on_exit_loop, visitor.visit_instruction, + None, ) } pub fn visit_if_test() { - let if_block = finger_tree.from_list([Nop]) + let if_block = shine_tree.from_list([Nop]) visit_test_variant.run( If(block_type.void, if_block, None), @@ -551,6 +598,7 @@ pub fn visit_if_test() { visitor.on_enter_if, visitor.on_exit_if, visitor.visit_instruction, + None, ) } @@ -563,6 +611,7 @@ pub fn visit_br_test() { visitor.on_enter_br, visitor.on_exit_br, visitor.visit_instruction, + None, ) } @@ -575,6 +624,7 @@ pub fn visit_br_if_test() { visitor.on_enter_br_if, visitor.on_exit_br_if, visitor.visit_instruction, + None, ) } @@ -586,7 +636,7 @@ pub fn visit_br_table_test() { let assert Ok(label_idx5) = module.label_idx(46) let assert Ok(default_label) = module.label_idx(47) let labels = - finger_tree.from_list([ + shine_tree.from_list([ label_idx1, label_idx2, label_idx3, @@ -600,6 +650,17 @@ pub fn visit_br_table_test() { visitor.on_enter_br_table, visitor.on_exit_br_table, visitor.visit_instruction, + Some(fn(actual, expected) { + case actual, expected { + BrTable(actual_labels, actual_default), + BrTable(expected_labels, expected_default) + -> { + shine_tree.equals(actual_labels, expected_labels) + && actual_default == expected_default + } + a, b -> a == b + } + }), ) } @@ -612,6 +673,7 @@ pub fn visit_br_on_null_test() { visitor.on_enter_br_on_null, visitor.on_exit_br_on_null, visitor.visit_instruction, + None, ) } @@ -624,6 +686,7 @@ pub fn visit_br_on_non_null_test() { visitor.on_enter_br_on_non_null, visitor.on_exit_br_on_non_null, visitor.visit_instruction, + None, ) } @@ -638,6 +701,7 @@ pub fn visit_br_on_cast_test() { visitor.on_enter_br_on_cast, visitor.on_exit_br_on_cast, visitor.visit_instruction, + None, ) } @@ -652,6 +716,7 @@ pub fn visit_br_on_cast_fail_test() { visitor.on_enter_br_on_cast_fail, visitor.on_exit_br_on_cast_fail, visitor.visit_instruction, + None, ) } @@ -664,6 +729,7 @@ pub fn visit_call_test() { visitor.on_enter_call, visitor.on_exit_call, visitor.visit_instruction, + None, ) } @@ -676,6 +742,7 @@ pub fn visit_call_ref_test() { visitor.on_enter_call_ref, visitor.on_exit_call_ref, visitor.visit_instruction, + None, ) } @@ -689,6 +756,7 @@ pub fn visit_call_indirect_test() { visitor.on_enter_call_indirect, visitor.on_exit_call_indirect, visitor.visit_instruction, + None, ) } @@ -701,6 +769,7 @@ pub fn visit_return_call_test() { visitor.on_enter_return_call, visitor.on_exit_return_call, visitor.visit_instruction, + None, ) } @@ -713,6 +782,7 @@ pub fn visit_return_call_ref_test() { visitor.on_enter_return_call_ref, visitor.on_exit_return_call_ref, visitor.visit_instruction, + None, ) } @@ -726,5 +796,6 @@ pub fn visit_return_call_indirect_test() { 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 index 3ceb108..b1945bc 100644 --- a/test/visitor/ref_type_test.gleam +++ b/test/visitor/ref_type_test.gleam @@ -1,9 +1,9 @@ +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 @@ -15,6 +15,7 @@ pub fn visit_any_ref_type_test() { visitor.on_enter_any_ref_type, visitor.on_exit_any_ref_type, visitor.visit_ref_type, + None, ) } @@ -26,6 +27,7 @@ pub fn visit_eq_ref_type_test() { visitor.on_enter_eq_ref_type, visitor.on_exit_eq_ref_type, visitor.visit_ref_type, + None, ) } @@ -37,6 +39,7 @@ pub fn visit_i31_ref_type_test() { visitor.on_enter_i31_ref_type, visitor.on_exit_i31_ref_type, visitor.visit_ref_type, + None, ) } @@ -48,6 +51,7 @@ pub fn visit_struct_ref_type_test() { visitor.on_enter_struct_ref_type, visitor.on_exit_struct_ref_type, visitor.visit_ref_type, + None, ) } @@ -59,6 +63,7 @@ pub fn visit_array_ref_type_test() { visitor.on_enter_array_ref_type, visitor.on_exit_array_ref_type, visitor.visit_ref_type, + None, ) } @@ -70,6 +75,7 @@ pub fn visit_func_ref_type_test() { visitor.on_enter_func_ref_type, visitor.on_exit_func_ref_type, visitor.visit_ref_type, + None, ) } @@ -81,6 +87,7 @@ pub fn visit_extern_ref_type_test() { visitor.on_enter_extern_ref_type, visitor.on_exit_extern_ref_type, visitor.visit_ref_type, + None, ) } @@ -92,6 +99,7 @@ pub fn visit_none_ref_type_test() { visitor.on_enter_none_ref_type, visitor.on_exit_none_ref_type, visitor.visit_ref_type, + None, ) } @@ -103,6 +111,7 @@ pub fn visit_no_func_ref_type_test() { visitor.on_enter_no_func_ref_type, visitor.on_exit_no_func_ref_type, visitor.visit_ref_type, + None, ) } @@ -114,6 +123,7 @@ pub fn visit_no_extern_ref_type_test() { visitor.on_enter_no_extern_ref_type, visitor.on_exit_no_extern_ref_type, visitor.visit_ref_type, + None, ) } @@ -126,5 +136,6 @@ pub fn visit_heap_type_ref_type_test() { 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 index 6ad89f9..a52767d 100644 --- a/test/visitor/val_type.gleam +++ b/test/visitor/val_type.gleam @@ -2,6 +2,7 @@ import internal/structure/types.{ F32ValType, F64ValType, I31RefType, I32ValType, I64ValType, RefTypeValType, V128ValType, } +import gleam/option.{None} import visitor import visitor/visit_test_variant @@ -14,6 +15,7 @@ pub fn visit_v128_val_type_test() { visitor.on_enter_v128_val_type, visitor.on_exit_v128_val_type, visitor.visit_val_type, + None, ) } @@ -26,6 +28,7 @@ pub fn visit_i32_val_type_test() { visitor.on_enter_i32_val_type, visitor.on_exit_i32_val_type, visitor.visit_val_type, + None, ) } @@ -38,6 +41,7 @@ pub fn visit_i64_val_type_test() { visitor.on_enter_i64_val_type, visitor.on_exit_i64_val_type, visitor.visit_val_type, + None, ) } @@ -50,6 +54,7 @@ pub fn visit_f32_val_type_test() { visitor.on_enter_f32_val_type, visitor.on_exit_f32_val_type, visitor.visit_val_type, + None, ) } @@ -62,6 +67,7 @@ pub fn visit_f64_val_type_test() { visitor.on_enter_f64_val_type, visitor.on_exit_f64_val_type, visitor.visit_val_type, + None, ) } @@ -74,5 +80,6 @@ pub fn visit_ref_type_val_type_test() { 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 index 20df594..e5b8636 100644 --- a/test/visitor/visit_test_variant.gleam +++ b/test/visitor/visit_test_variant.gleam @@ -1,4 +1,6 @@ +import gleam/option.{type Option, None, Some} import gleeunit/should +import shine_tree import visitor.{type BinaryModuleVisitor} type VisitCallback(u) = @@ -22,47 +24,60 @@ pub fn run( 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) - 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)) + 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)) } - 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)) + }) + |> 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)) } - 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)) + }) + |> 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)) } - 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)) + }) + |> 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)) } - False -> Ok(#(ctx, actual_value)) - } - }) - |> visit_func(start_context, expected_value) - |> should.be_ok - |> should.equal(#(expected_context, expected_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 + } } From 0d02db84f4637770163e8fed7c5e42035d99b2cf Mon Sep 17 00:00:00 2001 From: jtenner Date: Mon, 16 Sep 2024 15:08:09 -0400 Subject: [PATCH 12/16] List refactor, fix test functions, remove ShineTree for 'forward facing' binary CST api --- src/builder/expression.gleam | 146 ++++---- src/builder/instructions/control.gleam | 5 +- src/builder/module.gleam | 395 ++++++++------------ src/builder/types/block_type.gleam | 3 +- src/builder/types/composite_type.gleam | 8 +- src/builder/types/func_type.gleam | 6 +- src/builder/types/rec_type.gleam | 38 +- src/builder/types/storage_type.gleam | 5 +- src/builder/types/struct_type.gleam | 97 ++--- src/internal/binary/common.gleam | 16 +- src/internal/binary/modules.gleam | 75 ++-- src/internal/binary/types.gleam | 131 +++---- src/internal/structure/modules.gleam | 49 ++- src/internal/structure/types.gleam | 333 +++++------------ src/internal/validation/common.gleam | 45 ++- src/internal/validation/module.gleam | 9 +- src/internal/visitor.gleam | 50 ++- test/decode_test.gleam | 478 +++++++++++-------------- test/encode_test.gleam | 306 +++++++--------- test/instruction_test.gleam | 33 +- test/visitor/heap_type_test.gleam | 2 +- test/visitor/instruction_test.gleam | 41 +-- test/visitor/val_type.gleam | 2 +- test/visitor/visit_test_variant.gleam | 1 - 24 files changed, 886 insertions(+), 1388 deletions(-) diff --git a/src/builder/expression.gleam b/src/builder/expression.gleam index 36bd2e1..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/structure/types.{ type BlockType, type Expr, type Instruction, Block, Expr, If, Loop, } -import shine_tree.{type ShineTree} type BlockDefinition { EmptyTop - OuterMostBlock(instructions: ShineTree(Instruction)) - IfBlock(bt: BlockType, instructions: ShineTree(Instruction)) + OuterMostBlock(instructions: List(Instruction)) + IfBlock(bt: BlockType, instructions: List(Instruction)) ElseBlock( bt: BlockType, - if_instructions: ShineTree(Instruction), - else_instructions: ShineTree(Instruction), + if_instructions: List(Instruction), + else_instructions: List(Instruction), ) - LoopBlock(bt: BlockType, instructions: ShineTree(Instruction)) - InlineBlock(bt: BlockType, instructions: ShineTree(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: ShineTree(BlockDefinition), + block_stack: List(BlockDefinition), ) } pub fn new() -> ExpressionBuilder { - ExpressionBuilder(None, OuterMostBlock(shine_tree.empty), shine_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, shine_tree.empty), - block_stack - |> shine_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, shine_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, shine_tree.empty), - builder.block_stack - |> shine_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, shine_tree.empty), - builder.block_stack - |> shine_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 == shine_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: ShineTree(BlockDefinition), - next_instruction: Instruction, -) { - case next_stack |> shine_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 - |> shine_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 |> shine_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 |> shine_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 |> shine_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 |> shine_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 |> shine_tree.push(inst)), + OuterMostBlock([inst, ..instructions]), builder.block_stack, ) IfBlock(bt, instructions) -> ExpressionBuilder( None, - IfBlock(bt, instructions |> shine_tree.push(inst)), + IfBlock(bt, [inst, ..instructions]), builder.block_stack, ) ElseBlock(bt, if_instructions, else_instructions) -> ExpressionBuilder( None, - ElseBlock( - bt, - if_instructions, - else_instructions |> shine_tree.push(inst), - ), + ElseBlock(bt, if_instructions, else_instructions |> list.append([inst])), builder.block_stack, ) LoopBlock(bt, instructions) -> ExpressionBuilder( None, - LoopBlock(bt, instructions |> shine_tree.push(inst)), + LoopBlock(bt, [inst, ..instructions]), builder.block_stack, ) InlineBlock(bt, instructions) -> ExpressionBuilder( None, - InlineBlock(bt, instructions |> shine_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 == shine_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/control.gleam b/src/builder/instructions/control.gleam index 881c2ea..56a3fe0 100644 --- a/src/builder/instructions/control.gleam +++ b/src/builder/instructions/control.gleam @@ -5,7 +5,6 @@ import internal/structure/types.{ BrOnNull, BrTable, Call, CallIndirect, CallRef, Drop, Nop, Return, ReturnCall, ReturnCallIndirect, ReturnCallRef, Select, SelectT, Unreachable, } -import shine_tree.{type ShineTree} pub fn return(builder: ExpressionBuilder) { builder @@ -36,7 +35,7 @@ pub fn select(builder: ExpressionBuilder) { |> expression.push(Select) } -pub fn select_t(builder: ExpressionBuilder, val_type: ShineTree(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: ShineTree(LabelIDX), + labels: List(LabelIDX), default: LabelIDX, ) { builder diff --git a/src/builder/module.gleam b/src/builder/module.gleam index 9a8fce4..6ed0dd4 100644 --- a/src/builder/module.gleam +++ b/src/builder/module.gleam @@ -1,3 +1,4 @@ +import gleam/list import gleam/option.{type Option, None, Some} import gleam/set.{type Set} import internal/binary/modules @@ -23,7 +24,6 @@ import internal/structure/types.{ StructCompositeType, StructType, SubType, Table, TableExport, TableIDX, TableImport, TableType, TypeIDX, Var, } -import shine_tree.{type ShineTree} pub const new = structure_modules.binary_module_new @@ -448,10 +448,10 @@ pub fn custom_section(module: BinaryModule, name: String, data: BitArray) { } } -fn add_to_optional_list(items: Option(ShineTree(u)), item: u) { +fn add_to_optional_list(items: Option(List(u)), item: u) { case items { - Some(items) -> Some(shine_tree.push(items, item)) - None -> Some(shine_tree.single(item)) + Some(items) -> Some(items |> list.append([item])) + None -> Some([item]) } } @@ -459,12 +459,11 @@ fn add_to_optional_list(items: Option(ShineTree(u)), item: u) { pub fn add_type(module: BinaryModule, type_: RecType) { let BinaryModule(types: types, ..) = module case types { - None -> - BinaryModule(..module, types: Some(TypeSection(shine_tree.single(type_)))) + None -> BinaryModule(..module, types: Some(TypeSection([type_]))) Some(TypeSection(types)) -> BinaryModule( ..module, - types: Some(TypeSection(shine_tree.push(types, type_))), + types: Some(TypeSection(list.append(types, [type_]))), ) } } @@ -476,51 +475,30 @@ pub fn add_func_type( results: List(ValType), ) { let func_type = - SubType( - False, - shine_tree.empty, - FuncCompositeType(FuncType( - shine_tree.from_list(parameters), - shine_tree.from_list(results), - )), - ) + SubType(False, [], FuncCompositeType(FuncType(parameters, results))) - add_type(module, RecType(shine_tree.single(func_type))) + add_type(module, RecType([func_type])) } /// Add a new concrete ArrayType to the TypeSection pub fn add_array_type(module: BinaryModule, element_type: FieldType) { let array_type = - SubType( - False, - shine_tree.empty, - ArrayCompositeType(ArrayType(element_type)), - ) - add_type(module, RecType(shine_tree.single(array_type))) + SubType(False, [], ArrayCompositeType(ArrayType(element_type))) + add_type(module, RecType([array_type])) } // Add a new StructType to the TypeSection pub fn add_struct_type(module: BinaryModule, fields: List(FieldType)) { - let struct_type = - SubType( - False, - shine_tree.empty, - StructCompositeType(StructType(shine_tree.from_list(fields))), - ) + let struct_type = SubType(False, [], StructCompositeType(StructType(fields))) - add_type(module, RecType(shine_tree.single(struct_type))) + add_type(module, RecType([struct_type])) } // Add a new StructType to the TypeSection that is marked as "final" pub fn add_final_struct_type(module: BinaryModule, fields: List(FieldType)) { - let struct_type = - SubType( - True, - shine_tree.empty, - StructCompositeType(StructType(shine_tree.from_list(fields))), - ) + let struct_type = SubType(True, [], StructCompositeType(StructType(fields))) - add_type(module, RecType(shine_tree.single(struct_type))) + add_type(module, RecType([struct_type])) } /// Import a function from the host. The module_name and name are used to identify the @@ -538,19 +516,16 @@ pub fn import_func( None, TypeIDX(_) -> BinaryModule( ..module, - imports: Some( - ImportSection(shine_tree.single(FuncImport(module_name, name, type_))), - ), + imports: Some(ImportSection([FuncImport(module_name, name, type_)])), ) Some(ImportSection(imports)), TypeIDX(_) -> BinaryModule( ..module, imports: Some( - ImportSection(shine_tree.push( - imports, - FuncImport(module_name, name, type_), - )), + ImportSection( + list.append(imports, [FuncImport(module_name, name, type_)]), + ), ), ) @@ -578,24 +553,16 @@ pub fn import_global( BinaryModule( ..module, imports: Some( - ImportSection( - shine_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(shine_tree.push( - imports, - GlobalImport(module_name, name, GlobalType(vt, mut)), - )), - ), + imports: Some(ImportSection( + imports + |> list.append([GlobalImport(module_name, name, GlobalType(vt, mut))]), + )), ) } } @@ -616,23 +583,20 @@ pub fn import_table( BinaryModule( ..module, imports: Some( - ImportSection( - shine_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(shine_tree.push( - imports, - TableImport(module_name, name, TableType(ref_type, limits)), - )), + ImportSection( + list.append(imports, [ + TableImport(module_name, name, TableType(ref_type, limits)), + ]), + ), ), ) } @@ -655,23 +619,20 @@ pub fn import_memory( BinaryModule( ..module, imports: Some( - ImportSection( - shine_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(shine_tree.push( - imports, - MemImport(module_name, name, MemType(Limits(min, max))), - )), + ImportSection( + list.append(imports, [ + MemImport(module_name, name, MemType(Limits(min, max))), + ]), + ), ), ) } @@ -690,15 +651,12 @@ pub fn import_memory( pub fn append_function_type_index(module: BinaryModule, type_: TypeIDX) { case module, type_ { BinaryModule(functions: None, ..), TypeIDX(_) -> - BinaryModule( - ..module, - functions: Some(FunctionSection(shine_tree.single(type_))), - ) + BinaryModule(..module, functions: Some(FunctionSection([type_]))) BinaryModule(functions: Some(FunctionSection(functions)), ..), TypeIDX(_) -> BinaryModule( ..module, - functions: Some(FunctionSection(shine_tree.push(functions, type_))), + functions: Some(FunctionSection(list.append(functions, [type_]))), ) _, _ -> panic as "Invalid type index" @@ -717,15 +675,11 @@ pub fn add_table( let BinaryModule(tables: tables, ..) = module let table = Table(TableType(ref_type, Limits(min, max)), init) case tables { - None -> - BinaryModule( - ..module, - tables: Some(TableSection(shine_tree.single(table))), - ) + None -> BinaryModule(..module, tables: Some(TableSection([table]))) Some(TableSection(tables)) -> BinaryModule( ..module, - tables: Some(TableSection(shine_tree.push(tables, table))), + tables: Some(TableSection(list.append(tables, [table]))), ) } } @@ -736,11 +690,7 @@ pub fn add_table( pub fn add_memory(module: BinaryModule, memory: MemType) { let BinaryModule(memories: memories, ..) = module case memories { - None -> - BinaryModule( - ..module, - memories: Some(MemorySection(shine_tree.single(memory))), - ) + None -> BinaryModule(..module, memories: Some(MemorySection([memory]))) _ -> panic as "Only one memory is allowed per module." } } @@ -758,15 +708,11 @@ pub fn add_global(module: BinaryModule, vt: ValType, mut: Bool, init: Expr) { init, ) case globals { - None -> - BinaryModule( - ..module, - globals: Some(GlobalSection(shine_tree.single(global))), - ) + None -> BinaryModule(..module, globals: Some(GlobalSection([global]))) Some(GlobalSection(globals)) -> BinaryModule( ..module, - globals: Some(GlobalSection(shine_tree.push(globals, global))), + globals: Some(GlobalSection(list.append(globals, [global]))), ) } } @@ -787,19 +733,16 @@ pub fn export_func(module: BinaryModule, name: String, func: FuncIDX) { None -> BinaryModule( ..module, - exports: Some(ExportSection(shine_tree.single(FuncExport(name, func)))), + exports: Some(ExportSection([FuncExport(name, func)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> shine_tree.try_foldl( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(shine_tree.push(exports, FuncExport(name, func))), + ExportSection(list.append(exports, [FuncExport(name, func)])), ), ) } @@ -814,21 +757,16 @@ pub fn export_table(module: BinaryModule, name: String, table: TableIDX) { None -> BinaryModule( ..module, - exports: Some( - ExportSection(shine_tree.single(TableExport(name, table))), - ), + exports: Some(ExportSection([TableExport(name, table)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> shine_tree.try_foldl( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(shine_tree.push(exports, TableExport(name, table))), + ExportSection(list.append(exports, [TableExport(name, table)])), ), ) } @@ -837,7 +775,7 @@ pub fn export_table(module: BinaryModule, name: String, table: TableIDX) { /// Export a memory to the module. The memory is given by it's index into the memory section, /// and it's name. -/// +/// /// 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) { @@ -846,19 +784,16 @@ pub fn export_memory(module: BinaryModule, name: String, memory: MemIDX) { None -> BinaryModule( ..module, - exports: Some(ExportSection(shine_tree.single(MemExport(name, memory)))), + exports: Some(ExportSection([MemExport(name, memory)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> shine_tree.try_foldl( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(shine_tree.push(exports, MemExport(name, memory))), + ExportSection(list.append(exports, [MemExport(name, memory)])), ), ) } @@ -873,21 +808,16 @@ pub fn export_global(module: BinaryModule, name: String, global: GlobalIDX) { None -> BinaryModule( ..module, - exports: Some( - ExportSection(shine_tree.single(GlobalExport(name, global))), - ), + exports: Some(ExportSection([GlobalExport(name, global)])), ) Some(ExportSection(exports)) -> { let assert Ok(_) = exports - |> shine_tree.try_foldl( - set.new() |> set.insert(name), - unique_export_name, - ) + |> list.try_fold(set.new() |> set.insert(name), unique_export_name) BinaryModule( ..module, exports: Some( - ExportSection(shine_tree.push(exports, GlobalExport(name, global))), + ExportSection(list.append(exports, [GlobalExport(name, global)])), ), ) } @@ -913,27 +843,28 @@ pub fn active_funcs_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - shine_tree.single(ElemFuncs( + ElementSection([ + ElemFuncs( HeapTypeRefType(FuncHeapType, False), - shine_tree.from_list(funcs), + funcs, ActiveElemMode(table_index, offset), - )), - ), + ), + ]), ), ) Some(ElementSection(elements)) -> BinaryModule( ..module, elements: Some( - ElementSection(shine_tree.push( - elements, - ElemFuncs( - HeapTypeRefType(FuncHeapType, False), - shine_tree.from_list(funcs), - ActiveElemMode(table_index, offset), - ), - )), + ElementSection( + list.append(elements, [ + ElemFuncs( + HeapTypeRefType(FuncHeapType, False), + funcs, + ActiveElemMode(table_index, offset), + ), + ]), + ), ), ) } @@ -947,27 +878,28 @@ pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) BinaryModule( ..module, elements: Some( - ElementSection( - shine_tree.single(ElemFuncs( + ElementSection([ + ElemFuncs( HeapTypeRefType(FuncHeapType, False), - shine_tree.from_list(funcs), + funcs, PassiveElemMode, - )), - ), + ), + ]), ), ) Some(ElementSection(elements)) -> BinaryModule( ..module, elements: Some( - ElementSection(shine_tree.push( - elements, - ElemFuncs( - HeapTypeRefType(FuncHeapType, False), - shine_tree.from_list(funcs), - PassiveElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemFuncs( + HeapTypeRefType(FuncHeapType, False), + funcs, + PassiveElemMode, + ), + ]), + ), ), ) } @@ -984,27 +916,28 @@ pub fn declarative_funcs_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - shine_tree.single(ElemFuncs( + ElementSection([ + ElemFuncs( HeapTypeRefType(FuncHeapType, False), - shine_tree.from_list(funcs), + funcs, DeclarativeElemMode, - )), - ), + ), + ]), ), ) Some(ElementSection(elements)) -> BinaryModule( ..module, elements: Some( - ElementSection(shine_tree.push( - elements, - ElemFuncs( - HeapTypeRefType(FuncHeapType, False), - shine_tree.from_list(funcs), - DeclarativeElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemFuncs( + HeapTypeRefType(FuncHeapType, False), + funcs, + DeclarativeElemMode, + ), + ]), + ), ), ) } @@ -1026,13 +959,13 @@ pub fn active_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - shine_tree.single(ElemExpressions( + ElementSection([ + ElemExpressions( ref_type, - shine_tree.from_list(exprs), + exprs, ActiveElemMode(table_index, offset), - )), - ), + ), + ]), ), ) } @@ -1040,14 +973,15 @@ pub fn active_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(shine_tree.push( - elements, - ElemExpressions( - ref_type, - shine_tree.from_list(exprs), - ActiveElemMode(table_index, offset), - ), - )), + ElementSection( + list.append(elements, [ + ElemExpressions( + ref_type, + exprs, + ActiveElemMode(table_index, offset), + ), + ]), + ), ), ) } @@ -1066,13 +1000,7 @@ pub fn passive_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - shine_tree.single(ElemExpressions( - ref_type, - shine_tree.from_list(exprs), - PassiveElemMode, - )), - ), + ElementSection([ElemExpressions(ref_type, exprs, PassiveElemMode)]), ), ) } @@ -1080,14 +1008,11 @@ pub fn passive_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(shine_tree.push( - elements, - ElemExpressions( - ref_type, - shine_tree.from_list(exprs), - PassiveElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemExpressions(ref_type, exprs, PassiveElemMode), + ]), + ), ), ) } @@ -1106,13 +1031,7 @@ pub fn declarative_element_segment( BinaryModule( ..module, elements: Some( - ElementSection( - shine_tree.single(ElemExpressions( - ref_type, - shine_tree.from_list(exprs), - DeclarativeElemMode, - )), - ), + ElementSection([ElemExpressions(ref_type, exprs, DeclarativeElemMode)]), ), ) } @@ -1120,14 +1039,11 @@ pub fn declarative_element_segment( BinaryModule( ..module, elements: Some( - ElementSection(shine_tree.push( - elements, - ElemExpressions( - ref_type, - shine_tree.from_list(exprs), - DeclarativeElemMode, - ), - )), + ElementSection( + list.append(elements, [ + ElemExpressions(ref_type, exprs, DeclarativeElemMode), + ]), + ), ), ) } @@ -1135,14 +1051,17 @@ pub fn declarative_element_segment( fn concatenate_locals(locals: List(ValType)) { case locals { - [] -> shine_tree.empty - [a, ..rest] -> do_concatenate_locals(rest, shine_tree.empty, #(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: ShineTree(Locals), + acc: List(Locals), current: #(Int, ValType), ) { case locals, current { @@ -1152,13 +1071,13 @@ fn do_concatenate_locals( let assert Ok(count) = u32(count) let locals = Locals(count, current_type) - do_concatenate_locals(rest, shine_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) - shine_tree.push(acc, locals) + [locals, ..acc] |> list.reverse } } } @@ -1173,14 +1092,11 @@ pub fn add_code(module: BinaryModule, locals: List(ValType), body: Expr) { case code { None -> - BinaryModule( - ..module, - code: Some(CodeSection(shine_tree.single(Code(locals, body)))), - ) + BinaryModule(..module, code: Some(CodeSection([Code(locals, body)]))) Some(CodeSection(code)) -> BinaryModule( ..module, - code: Some(CodeSection(shine_tree.push(code, Code(locals, body)))), + code: Some(CodeSection(list.append(code, [Code(locals, body)]))), ) } } @@ -1198,18 +1114,15 @@ pub fn add_active_data( None -> BinaryModule( ..module, - data: Some( - DataSection(shine_tree.single(ActiveData(mem_idx, offset, data))), - ), + data: Some(DataSection([ActiveData(mem_idx, offset, data)])), ) Some(DataSection(data_section)) -> BinaryModule( ..module, data: Some( - DataSection(shine_tree.push( - data_section, - ActiveData(mem_idx, offset, data), - )), + DataSection( + list.append(data_section, [ActiveData(mem_idx, offset, data)]), + ), ), ) } @@ -1220,17 +1133,11 @@ pub fn add_active_data( pub fn add_passive_data(module: BinaryModule, data: BitArray) { let BinaryModule(data: data_section, ..) = module case data_section { - None -> - BinaryModule( - ..module, - data: Some(DataSection(shine_tree.single(PassiveData(data)))), - ) + None -> BinaryModule(..module, data: Some(DataSection([PassiveData(data)]))) Some(DataSection(data_section)) -> BinaryModule( ..module, - data: Some( - DataSection(shine_tree.push(data_section, PassiveData(data))), - ), + data: Some(DataSection(list.append(data_section, [PassiveData(data)]))), ) } } @@ -1343,19 +1250,3 @@ pub fn encode(module: BinaryModule) { pub fn decode(module: BitArray) { modules.decode_module(module) } - -/// ShineCoder's ShineTree is an efficient data structure for -/// storing and manipulating the ends of ordered vector data. -/// This function takes a list and converts it into an opaque -/// ShineTree. -pub fn to_vector(values: List(u)) { - values |> shine_tree.from_list -} - -/// ShineCoder's ShineTree is an efficient data structure for -/// storing and manipulating the ends of ordered vector data. -/// This function takes a ShineTree and converts it into a -/// normal List. -pub fn to_list(values: ShineTree(u)) { - values |> shine_tree.to_list -} diff --git a/src/builder/types/block_type.gleam b/src/builder/types/block_type.gleam index ae230c4..06ec340 100644 --- a/src/builder/types/block_type.gleam +++ b/src/builder/types/block_type.gleam @@ -1,6 +1,5 @@ import internal/structure/types.{ - type BlockType, type TypeIDX, type ValType, FuncTypeBlockType, - ValTypeBlockType, VoidBlockType, + type TypeIDX, type ValType, FuncTypeBlockType, ValTypeBlockType, VoidBlockType, } pub const void = VoidBlockType diff --git a/src/builder/types/composite_type.gleam b/src/builder/types/composite_type.gleam index 0f3c29a..f619cf4 100644 --- a/src/builder/types/composite_type.gleam +++ b/src/builder/types/composite_type.gleam @@ -3,21 +3,17 @@ import internal/structure/types.{ ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, StructCompositeType, StructType, } -import shine_tree pub fn from_func_type(func_type: FuncType) { FuncCompositeType(func_type) } pub fn func_type(parameters: List(ValType), results: List(ValType)) { - FuncCompositeType(FuncType( - shine_tree.from_list(parameters), - shine_tree.from_list(results), - )) + FuncCompositeType(FuncType(parameters, results)) } pub fn struct_type(fields: List(FieldType)) { - StructCompositeType(StructType(shine_tree.from_list(fields))) + StructCompositeType(StructType(fields)) } pub fn from_struct_type(struct_type: StructType) { diff --git a/src/builder/types/func_type.gleam b/src/builder/types/func_type.gleam index 881c5ad..5c56d53 100644 --- a/src/builder/types/func_type.gleam +++ b/src/builder/types/func_type.gleam @@ -1,11 +1,7 @@ import internal/structure/types.{type ValType, FuncType} -import shine_tree /// 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( - shine_tree.from_list(param_types), - shine_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 b5554b6..31eb704 100644 --- a/src/builder/types/rec_type.gleam +++ b/src/builder/types/rec_type.gleam @@ -3,51 +3,23 @@ import internal/structure/types.{ ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, RecType, StructCompositeType, StructType, SubType, } -import shine_tree pub fn from_sub_types(sub_types: List(SubType)) { - RecType(sub_types |> shine_tree.from_list) + RecType(sub_types) } pub fn from_func_type(func_type: FuncType) { - RecType( - shine_tree.from_list([ - SubType(True, shine_tree.empty, FuncCompositeType(func_type)), - ]), - ) + RecType([SubType(True, [], FuncCompositeType(func_type))]) } pub fn func_type(parameters: List(ValType), results: List(ValType)) { - RecType( - shine_tree.from_list([ - SubType( - True, - shine_tree.empty, - FuncCompositeType(FuncType( - shine_tree.from_list(parameters), - shine_tree.from_list(results), - )), - ), - ]), - ) + RecType([SubType(True, [], FuncCompositeType(FuncType(parameters, results)))]) } pub fn from_struct_type(struct_type: StructType) { - RecType( - shine_tree.from_list([ - SubType(True, shine_tree.empty, StructCompositeType(struct_type)), - ]), - ) + RecType([SubType(True, [], StructCompositeType(struct_type))]) } pub fn array_type(element_type: FieldType) { - RecType( - shine_tree.from_list([ - SubType( - True, - shine_tree.empty, - 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 index 95c5333..e63998a 100644 --- a/src/builder/types/storage_type.gleam +++ b/src/builder/types/storage_type.gleam @@ -1,7 +1,6 @@ import internal/structure/types.{ - F32ValType, F64ValType, I16StorageType, I32ValType, I64ValType, I8StorageType, - RefTypeValType, V128ValType, ValTypeStorageType, - type RefType, + type RefType, F32ValType, F64ValType, I16StorageType, I32ValType, I64ValType, + I8StorageType, RefTypeValType, V128ValType, ValTypeStorageType, } pub const i8 = I8StorageType diff --git a/src/builder/types/struct_type.gleam b/src/builder/types/struct_type.gleam index aa93e85..0c113db 100644 --- a/src/builder/types/struct_type.gleam +++ b/src/builder/types/struct_type.gleam @@ -1,30 +1,27 @@ +import gleam/list import internal/structure/types.{ type RefType, type StructType, type TypeIDX, ConcreteHeapType, Const, F32ValType, F64ValType, FieldType, HeapTypeRefType, I16StorageType, I32ValType, I64ValType, I8StorageType, RefTypeValType, StructType, TypeIDX, V128ValType, ValTypeStorageType, Var, } -import shine_tree /// Create an empty Struct type /// https://webassembly.github.io/gc/core/syntax/types.html#aggregate-types pub fn new() { - StructType(shine_tree.empty) + StructType([]) } /// Add an immutable `i8` field to the struct pub fn i8_field(struct_type: StructType) { - StructType( - struct_type.ft - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 - |> shine_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 a98342e..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/structure/numbers.{u32, unwrap_u32} -import shine_tree.{type ShineTree} /// Encode a vector of items using the given encoding function pub fn encode_vec( builder: BytesBuilder, - items: ShineTree(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(shine_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 - |> shine_tree.try_foldl(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, shine_tree.empty, 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: ShineTree(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 |> shine_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 5677a05..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} @@ -28,7 +29,6 @@ import internal/structure/types.{ GlobalExport, GlobalImport, HeapTypeRefType, Locals, MemExport, MemImport, PassiveData, PassiveElemMode, Table, TableExport, TableIDX, TableImport, } as structure_types -import shine_tree.{type ShineTree} /// The magic header bytes of every web assembly module const wasm_magic = <<0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00>> @@ -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, shine_tree.empty) + 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: ShineTree(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 |> shine_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: ShineTree(CustomSection)) { /// exhausted. pub fn encode_custom_sections( builder: BytesBuilder, - sections: Option(ShineTree(CustomSection)), + sections: Option(List(CustomSection)), ) { case sections { - Some(sections) -> - shine_tree.try_foldl(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 157c124..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 @@ -112,7 +113,6 @@ import internal/structure/types.{ lane_16, lane_2, lane_4, lane_8, } import pprint -import shine_tree.{type ShineTree} /// Decode a lane index (u32) from the given bit array, and assert it's /// less than 16. @@ -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: ShineTree(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(shine_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 |> shine_tree.size { - 1 -> - case rec_type.sub_types |> shine_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, shine_tree.empty, 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 |> shine_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: ShineTree(Instruction), + insts: List(Instruction), ) -> Result(BytesBuilder, String) { insts - |> shine_tree.try_foldl(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, shine_tree.empty) + do_decode_expression(bits, []) } fn do_decode_expression( bits: BitArray, - acc: ShineTree(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 |> shine_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: ShineTree(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, shine_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 |> shine_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: ShineTree(Instruction), - else_acc: ShineTree(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 |> shine_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, shine_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/structure/modules.gleam b/src/internal/structure/modules.gleam index 24a8b57..33df07d 100644 --- a/src/internal/structure/modules.gleam +++ b/src/internal/structure/modules.gleam @@ -4,38 +4,37 @@ import internal/structure/types.{ type Code, type Data, type Elem, type Export, type FuncIDX, type Global, type Import, type MemType, type RecType, type Table, type TypeIDX, } -import shine_tree.{type ShineTree} /// This type represents a BinaryModule, which is a structural representation of a WebAssembly module, /// rather than a conceptual one. This type is used internally to be an encoding/decoding interface /// for web assembly targets. pub type BinaryModule { BinaryModule( - custom_0: Option(ShineTree(CustomSection)), + custom_0: Option(List(CustomSection)), types: Option(TypeSection), - custom_1: Option(ShineTree(CustomSection)), + custom_1: Option(List(CustomSection)), imports: Option(ImportSection), - custom_2: Option(ShineTree(CustomSection)), + custom_2: Option(List(CustomSection)), functions: Option(FunctionSection), - custom_3: Option(ShineTree(CustomSection)), + custom_3: Option(List(CustomSection)), tables: Option(TableSection), - custom_4: Option(ShineTree(CustomSection)), + custom_4: Option(List(CustomSection)), memories: Option(MemorySection), - custom_5: Option(ShineTree(CustomSection)), + custom_5: Option(List(CustomSection)), globals: Option(GlobalSection), - custom_6: Option(ShineTree(CustomSection)), + custom_6: Option(List(CustomSection)), exports: Option(ExportSection), - custom_7: Option(ShineTree(CustomSection)), + custom_7: Option(List(CustomSection)), start: Option(StartSection), - custom_8: Option(ShineTree(CustomSection)), + custom_8: Option(List(CustomSection)), elements: Option(ElementSection), - custom_9: Option(ShineTree(CustomSection)), + custom_9: Option(List(CustomSection)), code: Option(CodeSection), - custom_10: Option(ShineTree(CustomSection)), + custom_10: Option(List(CustomSection)), data: Option(DataSection), - custom_11: Option(ShineTree(CustomSection)), + custom_11: Option(List(CustomSection)), data_count: Option(DataCountSection), - custom_12: Option(ShineTree(CustomSection)), + custom_12: Option(List(CustomSection)), ) } @@ -83,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: ShineTree(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: ShineTree(Import)) + ImportSection(imports: List(Import)) } /// The WebAssembly function section is not a list of function declarations. Rather, it @@ -98,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: ShineTree(TypeIDX)) + FunctionSection(funcs: List(TypeIDX)) } /// WebAssembly modules can declare tables which are pre-allocated arrays of values that @@ -106,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: ShineTree(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: ShineTree(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: ShineTree(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: ShineTree(Export)) + ExportSection(exports: List(Export)) } /// The WebAssembly start section specifies the index of the function to be called when the @@ -138,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: ShineTree(Elem)) + ElementSection(elems: List(Elem)) } /// WebAssembly modules can declare callable functions called "Code"s which define the shape @@ -151,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: ShineTree(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: ShineTree(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 344c0da..d016538 100644 --- a/src/internal/structure/types.gleam +++ b/src/internal/structure/types.gleam @@ -1,10 +1,10 @@ +import gleam/list import gleam/option.{type Option} import gleam/result import internal/structure/common.{between} import internal/structure/numbers.{ type F32, type F64, type I32, type I64, type U32, type V128Value, } -import shine_tree.{type ShineTree} /// Get the lane_16 indx nvalue as an integer pub fn unwrap_lane_16(val: LaneIDX16) { @@ -173,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: ShineTree(ValType), results: ShineTree(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: ShineTree(ValType), results: ShineTree(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: ShineTree(FieldType)) + StructType(ft: List(FieldType)) } /// An array type describes an array with the given field type. @@ -194,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) @@ -239,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: ShineTree(SubType)) + RecType(sub_types: List(SubType)) } /// An index into an array of types, either a recursive type, a module subtype, or a @@ -293,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: ShineTree(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 @@ -781,7 +781,7 @@ pub type Instruction { ExternConvertAny Drop Select - SelectT(vt: ShineTree(ValType)) + SelectT(vt: List(ValType)) LocalGet(idx: LocalIDX) LocalSet(idx: LocalIDX) LocalTee(idx: LocalIDX) @@ -852,12 +852,12 @@ pub type Instruction { Loop(bt: BlockType, instructions: Expr) If( bt: BlockType, - instructions: ShineTree(Instruction), - else_instructions: Option(ShineTree(Instruction)), + instructions: List(Instruction), + else_instructions: Option(List(Instruction)), ) Br(label: LabelIDX) BrIf(label: LabelIDX) - BrTable(labels: ShineTree(LabelIDX), default: LabelIDX) + BrTable(labels: List(LabelIDX), default: LabelIDX) BrOnNull(label: LabelIDX) BrOnNonNull(label: LabelIDX) BrOnCast(label: LabelIDX, rt1: RefType, rt2: RefType) @@ -884,19 +884,13 @@ pub fn get_instruction_type( case instruction { End | Else -> Error(Nil) - I64Const(_) -> - Ok(InstructionType(shine_tree.empty, shine_tree.from_list([I64ValType]))) + I64Const(_) -> Ok(InstructionType([], [I64ValType])) I32Const(_) | ArrayLen | I31GetS | I31GetU -> - Ok(InstructionType(shine_tree.empty, shine_tree.from_list([I32ValType]))) - F64Const(_) -> - Ok(InstructionType(shine_tree.empty, shine_tree.from_list([F64ValType]))) - F32Const(_) -> - Ok(InstructionType(shine_tree.empty, shine_tree.from_list([F32ValType]))) + Ok(InstructionType([], [I32ValType])) + F64Const(_) -> Ok(InstructionType([], [F64ValType])) + F32Const(_) -> Ok(InstructionType([], [F32ValType])) I64Popcnt | I64Ctz | I64Clz | I64Extend32S | I64Extend16S | I64Extend8S -> - Ok(InstructionType( - shine_tree.from_list([I64ValType]), - shine_tree.from_list([I64ValType]), - )) + Ok(InstructionType([I64ValType], [I64ValType])) I32Popcnt | I32Ctz | I32Clz @@ -908,21 +902,11 @@ pub fn get_instruction_type( | I32Load16U(_) | I32Load8S(_) | I32Load8U(_) - | MemoryGrow -> - Ok(InstructionType( - shine_tree.from_list([I32ValType]), - shine_tree.from_list([I32ValType]), - )) + | MemoryGrow -> Ok(InstructionType([I32ValType], [I32ValType])) F64Nearest | F64Trunc | F64Floor | F64Ceil | F64Sqrt | F64Neg | F64Abs -> - Ok(InstructionType( - shine_tree.from_list([F64ValType]), - shine_tree.from_list([F64ValType]), - )) + Ok(InstructionType([F64ValType], [F64ValType])) F32Nearest | F32Trunc | F32Floor | F32Ceil | F32Sqrt | F32Neg | F32Abs -> - Ok(InstructionType( - shine_tree.from_list([F32ValType]), - shine_tree.from_list([F32ValType]), - )) + Ok(InstructionType([F32ValType], [F32ValType])) I64Rotr | I64Rotl | I64ShrS @@ -937,11 +921,7 @@ pub fn get_instruction_type( | I64DivU | I64Mul | I64Sub - | I64Add -> - Ok(InstructionType( - shine_tree.from_list([I64ValType, I64ValType]), - shine_tree.from_list([I64ValType]), - )) + | I64Add -> Ok(InstructionType([I64ValType, I64ValType], [I64ValType])) I32Rotr | I32Rotl | I32ShrS @@ -966,26 +946,12 @@ pub fn get_instruction_type( | I32LtS | I32LtU | I32Ne - | I32Eq -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, I32ValType]), - shine_tree.from_list([I32ValType]), - )) + | I32Eq -> Ok(InstructionType([I32ValType, I32ValType], [I32ValType])) F64Copysign | F64Max | F64Min | F64Div | F64Mul | F64Sub | F64Add -> - Ok(InstructionType( - shine_tree.from_list([F64ValType, F64ValType]), - shine_tree.from_list([F64ValType]), - )) + Ok(InstructionType([F64ValType, F64ValType], [F64ValType])) F32Copysign | F32Max | F32Min | F32Div | F32Mul | F32Sub | F32Add -> - Ok(InstructionType( - shine_tree.from_list([F32ValType, F32ValType]), - shine_tree.from_list([F32ValType]), - )) - I64Eqz | I32WrapI64 -> - Ok(InstructionType( - shine_tree.from_list([I64ValType]), - shine_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F32ValType, F32ValType], [F32ValType])) + I64Eqz | I32WrapI64 -> Ok(InstructionType([I64ValType], [I32ValType])) I64GeS | I64GeU | I64LeS @@ -995,22 +961,12 @@ pub fn get_instruction_type( | I64LtS | I64LtU | I64Ne - | I64Eq -> - Ok(InstructionType( - shine_tree.from_list([I64ValType, I64ValType]), - shine_tree.from_list([I32ValType]), - )) + | I64Eq -> Ok(InstructionType([I64ValType, I64ValType], [I32ValType])) F64Ge | F64Le | F64Gt | F64Lt | F64Ne | F64Eq -> - Ok(InstructionType( - shine_tree.from_list([F64ValType, F64ValType]), - shine_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F64ValType, F64ValType], [I32ValType])) F32Ge | F32Le | F32Gt | F32Lt | F32Ne | F32Eq -> - Ok(InstructionType( - shine_tree.from_list([F32ValType, F32ValType]), - shine_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F32ValType, F32ValType], [I32ValType])) I64ExtendI32S | I64ExtendI32U | I64Load(_) @@ -1019,71 +975,32 @@ pub fn get_instruction_type( | I64Load8S(_) | I64Load8U(_) | I64Load32S(_) - | I64Load32U(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType]), - shine_tree.from_list([I64ValType]), - )) + | I64Load32U(_) -> Ok(InstructionType([I32ValType], [I64ValType])) I64TruncF64S | I64TruncF64U | I64TruncSatF64S | I64TruncSatF64U - | I64ReinterpretF64 -> - Ok(InstructionType( - shine_tree.from_list([F64ValType]), - shine_tree.from_list([I64ValType]), - )) + | I64ReinterpretF64 -> Ok(InstructionType([F64ValType], [I64ValType])) I64TruncF32S | I64TruncF32U | I64TruncSatF32S | I64TruncSatF32U -> - Ok(InstructionType( - shine_tree.from_list([F32ValType]), - shine_tree.from_list([I64ValType]), - )) + Ok(InstructionType([F32ValType], [I64ValType])) I32TruncF64S | I32TruncF64U | I32TruncSatF64S | I32TruncSatF64U -> - Ok(InstructionType( - shine_tree.from_list([F64ValType]), - shine_tree.from_list([I32ValType]), - )) + Ok(InstructionType([F64ValType], [I32ValType])) I32TruncF32S | I32TruncF32U | I32TruncSatF32S | I32TruncSatF32U - | I32ReinterpretF32 -> - Ok(InstructionType( - shine_tree.from_list([F32ValType]), - shine_tree.from_list([I32ValType]), - )) - F32DemoteF64 -> - Ok(InstructionType( - shine_tree.from_list([F32ValType]), - shine_tree.from_list([F64ValType]), - )) - F64PromoteF32 -> - Ok(InstructionType( - shine_tree.from_list([F64ValType]), - shine_tree.from_list([F32ValType]), - )) + | I32ReinterpretF32 -> Ok(InstructionType([F32ValType], [I32ValType])) + F32DemoteF64 -> Ok(InstructionType([F32ValType], [F64ValType])) + F64PromoteF32 -> Ok(InstructionType([F64ValType], [F32ValType])) F64ConvertI64S | F64ConvertI64U | F64ReinterpretI64 -> - Ok(InstructionType( - shine_tree.from_list([I64ValType]), - shine_tree.from_list([F64ValType]), - )) + Ok(InstructionType([I64ValType], [F64ValType])) F64ConvertI32S | F64ConvertI32U | F64Load(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType]), - shine_tree.from_list([F64ValType]), - )) + Ok(InstructionType([I32ValType], [F64ValType])) F32ConvertI64S | F32ConvertI64U -> - Ok(InstructionType( - shine_tree.from_list([I64ValType]), - shine_tree.from_list([F32ValType]), - )) + Ok(InstructionType([I64ValType], [F32ValType])) F32ConvertI32S | F32ConvertI32U | F32ReinterpretI32 | F32Load(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType]), - shine_tree.from_list([F32ValType]), - )) - V128Const(_) -> - Ok(InstructionType(shine_tree.empty, shine_tree.from_list([V128ValType]))) + Ok(InstructionType([I32ValType], [F32ValType])) + V128Const(_) -> Ok(InstructionType([], [V128ValType])) V128Not | I64x2Neg | I64x2Abs @@ -1121,11 +1038,7 @@ pub fn get_instruction_type( | F32x4DemoteF64x2Zero | F64x2ConvertLowI32x4S | F64x2ConvertLowI32x4U - | F64x2PromoteLowF32x4 -> - Ok(InstructionType( - shine_tree.from_list([V128ValType]), - shine_tree.from_list([V128ValType]), - )) + | F64x2PromoteLowF32x4 -> Ok(InstructionType([V128ValType], [V128ValType])) V128Xor | V128AndNot | V128Or @@ -1258,16 +1171,11 @@ pub fn get_instruction_type( | F32x4Mul | F32x4Sub | F32x4Add - | I64x2Mul -> - Ok(InstructionType( - shine_tree.from_list([V128ValType, V128ValType]), - shine_tree.from_list([V128ValType]), - )) + | I64x2Mul -> Ok(InstructionType([V128ValType, V128ValType], [V128ValType])) V128Bitselect -> - Ok(InstructionType( - shine_tree.from_list([V128ValType, V128ValType, V128ValType]), - shine_tree.from_list([V128ValType]), - )) + Ok( + InstructionType([V128ValType, V128ValType, V128ValType], [V128ValType]), + ) V128AnyTrue | I8x16ExtractLaneS(_) | I16x8ExtractLaneS(_) @@ -1280,11 +1188,7 @@ pub fn get_instruction_type( | I64x2Bitmask | I32x4Bitmask | I16x8Bitmask - | I8x16Bitmask -> - Ok(InstructionType( - shine_tree.from_list([V128ValType]), - shine_tree.from_list([I32ValType]), - )) + | I8x16Bitmask -> Ok(InstructionType([V128ValType], [I32ValType])) I32x4Splat | I16x8Splat | I8x16Splat @@ -1300,46 +1204,14 @@ pub fn get_instruction_type( | V128Load64Splat(_) | V128Load32Splat(_) | V128Load16Splat(_) - | V128Load8Splat(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType]), - shine_tree.from_list([V128ValType]), - )) - I64x2Splat -> - Ok(InstructionType( - shine_tree.from_list([I64ValType]), - shine_tree.from_list([V128ValType]), - )) - F32x4Splat -> - Ok(InstructionType( - shine_tree.from_list([F32ValType]), - shine_tree.from_list([V128ValType]), - )) - F64x2Splat -> - Ok(InstructionType( - shine_tree.from_list([F64ValType]), - shine_tree.from_list([V128ValType]), - )) - I64x2ExtractLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType]), - shine_tree.from_list([I64ValType]), - )) - I32x4ExtractLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType]), - shine_tree.from_list([I32ValType]), - )) - F32x4ExtractLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType]), - shine_tree.from_list([F32ValType]), - )) - F64x2ExtractLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType]), - shine_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(_) @@ -1354,27 +1226,14 @@ pub fn get_instruction_type( | I16x8Shl | I8x16ShrS | I8x16ShrU - | I8x16Shl -> - Ok(InstructionType( - shine_tree.from_list([V128ValType, I32ValType]), - shine_tree.from_list([V128ValType]), - )) + | I8x16Shl -> Ok(InstructionType([V128ValType, I32ValType], [V128ValType])) I64x2ReplaceLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType, I64ValType]), - shine_tree.from_list([V128ValType]), - )) + Ok(InstructionType([V128ValType, I64ValType], [V128ValType])) F32x4ReplaceLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType, F32ValType]), - shine_tree.from_list([V128ValType]), - )) + Ok(InstructionType([V128ValType, F32ValType], [V128ValType])) F64x2ReplaceLane(_) -> - Ok(InstructionType( - shine_tree.from_list([V128ValType, F64ValType]), - shine_tree.from_list([V128ValType]), - )) - Nop -> Ok(InstructionType(shine_tree.empty, shine_tree.empty)) + Ok(InstructionType([V128ValType, F64ValType], [V128ValType])) + Nop -> Ok(InstructionType([], [])) // TODO: Each of these instructions need to be implemented and checked RefFunc(_) @@ -1440,79 +1299,53 @@ pub fn get_instruction_type( | StructNew(_) | StructNewDefault(_) -> todo - RefI31 -> - Ok(InstructionType( - shine_tree.empty, - shine_tree.from_list([RefTypeValType(I31RefType)]), - )) + RefI31 -> Ok(InstructionType([], [RefTypeValType(I31RefType)])) AnyConvertExtern -> - Ok(InstructionType( - shine_tree.from_list([RefTypeValType(ExternRefType)]), - shine_tree.from_list([RefTypeValType(AnyRefType)]), - )) + Ok( + InstructionType([RefTypeValType(ExternRefType)], [ + RefTypeValType(AnyRefType), + ]), + ) ExternConvertAny -> - Ok(InstructionType( - shine_tree.from_list([RefTypeValType(AnyRefType)]), - shine_tree.from_list([RefTypeValType(ExternRefType)]), - )) + Ok( + InstructionType([RefTypeValType(AnyRefType)], [ + RefTypeValType(ExternRefType), + ]), + ) I64Store(_) | I64Store16(_) | I64Store8(_) | I64Store32(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, I64ValType]), - shine_tree.empty, - )) + Ok(InstructionType([I32ValType, I64ValType], [])) I32Store(_) | I32Store16(_) | I32Store8(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, I32ValType]), - shine_tree.empty, - )) - F64Store(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, F64ValType]), - shine_tree.empty, - )) - F32Store(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, F32ValType]), - shine_tree.empty, - )) + Ok(InstructionType([I32ValType, I32ValType], [])) + F64Store(_) -> Ok(InstructionType([I32ValType, F64ValType], [])) + F32Store(_) -> Ok(InstructionType([I32ValType, F32ValType], [])) V128Store(_) | V128Store8Lane(_, _) | V128Store16Lane(_, _) | V128Store32Lane(_, _) | V128Store64Lane(_, _) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, V128ValType]), - shine_tree.empty, - )) + Ok(InstructionType([I32ValType, V128ValType], [])) V128Load8Lane(_, _) | V128Load16Lane(_, _) | V128Load32Lane(_, _) | V128Load64Lane(_, _) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, V128ValType]), - shine_tree.from_list([V128ValType]), - )) - MemorySize -> - Ok(InstructionType(shine_tree.empty, shine_tree.from_list([I32ValType]))) + Ok(InstructionType([I32ValType, V128ValType], [V128ValType])) + MemorySize -> Ok(InstructionType([], [I32ValType])) MemoryFill | MemoryCopy | MemoryInit(_) -> - Ok(InstructionType( - shine_tree.from_list([I32ValType, I32ValType, I32ValType]), - shine_tree.empty, - )) - DataDrop(_) -> Ok(InstructionType(shine_tree.empty, shine_tree.empty)) + Ok(InstructionType([I32ValType, I32ValType, I32ValType], [])) + DataDrop(_) -> Ok(InstructionType([], [])) } } /// An expression is a "End" [0x0B] terminated sequence of instructions that describe a /// calculated value. pub type Expr { - Expr(insts: ShineTree(Instruction)) + Expr(insts: List(Instruction)) } /// 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 |> shine_tree.get(idx)) + use st <- result.map(st |> list.drop(idx) |> list.first) st.ct } @@ -1560,8 +1393,8 @@ pub type Global { /// used to initialize tables. /// Please see: https://webassembly.github.io/gc/core/syntax/modules.html#element-segments pub type Elem { - ElemFuncs(type_: RefType, init: ShineTree(FuncIDX), mode: ElemMode) - ElemExpressions(type_: RefType, init: ShineTree(Expr), mode: ElemMode) + 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 @@ -1595,7 +1428,7 @@ pub type Export { /// A WebAssembly function body defined by it's locals and an expression. pub type Code { - Code(locals: ShineTree(Locals), body: Expr) + Code(locals: List(Locals), body: Expr) } /// Data segments can be used to initialize a range of memory from a static vector of bytes. diff --git a/src/internal/validation/common.gleam b/src/internal/validation/common.gleam index c6cf996..272b75c 100644 --- a/src/internal/validation/common.gleam +++ b/src/internal/validation/common.gleam @@ -3,38 +3,37 @@ import internal/structure/types.{ type Data, type DefType, type Elem, type FuncIDX, type GlobalType, type Locals, type MemType, type RecType, type TableType, type ValType, } -import shine_tree.{type ShineTree} pub type Context { Context( - types: ShineTree(DefType), - funcs: ShineTree(DefType), - tables: ShineTree(TableType), - mems: ShineTree(MemType), - globals: ShineTree(GlobalType), - elems: ShineTree(Elem), - data: ShineTree(Data), - locals: ShineTree(Locals), - labels: ShineTree(ShineTree(ValType)), - return: Option(ShineTree(ValType)), - refs: ShineTree(FuncIDX), + 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: shine_tree.empty, - funcs: shine_tree.empty, - tables: shine_tree.empty, - mems: shine_tree.empty, - globals: shine_tree.empty, - elems: shine_tree.empty, - data: shine_tree.empty, - locals: shine_tree.empty, - labels: shine_tree.empty, + types: [], + funcs: [], + tables: [], + mems: [], + globals: [], + elems: [], + data: [], + locals: [], + labels: [], return: None, - refs: shine_tree.empty, + refs: [], ) -pub fn roll_rec_types(rec_type: RecType) -> ShineTree(DefType) { +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 index 295fe40..7f4d29e 100644 --- a/src/internal/validation/module.gleam +++ b/src/internal/validation/module.gleam @@ -1,4 +1,5 @@ -import gleam/option.{type Option, None, Some} +import gleam/list +import gleam/option.{None, Some} import gleam/result import internal/structure/modules.{type BinaryModule, TypeSection} import internal/structure/types.{type RecType} @@ -6,12 +7,10 @@ import internal/validation/common.{ type Context, Context, empty_context, roll_rec_types, } import internal/validation/types.{validate_rec_type} as _validation_types -import shine_tree pub fn validate_type(ctx_prime: Context, rec_type: RecType) { let def_types = rec_type |> roll_rec_types - let ctx = - Context(..ctx_prime, types: shine_tree.append(ctx_prime.types, def_types)) + let ctx = Context(..ctx_prime, types: list.append(ctx_prime.types, def_types)) use _ <- result.map(validate_rec_type(ctx, rec_type)) ctx } @@ -19,7 +18,7 @@ pub fn validate_type(ctx_prime: Context, rec_type: RecType) { pub fn validate_module(module: BinaryModule) { use context <- result.try(case module.types { Some(TypeSection(types)) -> - shine_tree.try_foldl(types, empty_context, validate_type) + list.try_fold(types, empty_context, validate_type) None -> Ok(empty_context) }) diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam index 0862033..907985d 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -1,3 +1,4 @@ +import gleam/list import gleam/option.{type Option, None, Some} import gleam/result.{map, try} import internal/structure/modules.{ @@ -41,7 +42,6 @@ import internal/structure/types.{ V128ValType, ValTypeBlockType, ValTypeStorageType, VoidBlockType, } import pprint -import shine_tree.{type ShineTree} pub type VisitorCallback(ctx, element) = fn(ctx, element) -> Result(#(ctx, element), String) @@ -899,23 +899,19 @@ fn do_visit(ctx, element, visitor: Option(VisitorCallback(ctx, element))) { fn do_visit_element_list( ctx, - elements: ShineTree(element), + elements: List(element), visitor: BinaryModuleVisitor(ctx), do_visit_callback: fn(ctx, element, BinaryModuleVisitor(ctx)) -> Result(#(ctx, element), String), ) { use #(ctx, elements, _) <- map( - shine_tree.try_foldl( - elements, - #(ctx, shine_tree.empty, visitor), - fn(acc, element) { - let #(ctx, acc, visitor) = acc - use #(ctx, element) <- map(do_visit_callback(ctx, element, visitor)) - #(ctx, acc |> shine_tree.push(element), visitor) - }, - ), + 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) + #(ctx, elements |> list.reverse) } pub fn do_visit_type_section( @@ -1329,47 +1325,43 @@ pub fn do_visit_array_type( pub fn do_visit_custom_sections( ctx, - custom_sections: Option(ShineTree(CustomSection)), + custom_sections: Option(List(CustomSection)), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, Option(ShineTree(CustomSection))), String) { +) -> Result(#(ctx, Option(List(CustomSection))), String) { case custom_sections { Some(custom_sections) -> - do_visit_custom_sections_filter( - ctx, - custom_sections, - shine_tree.empty, - visitor, - ) + do_visit_custom_sections_filter(ctx, custom_sections, [], visitor) _ -> Ok(#(ctx, custom_sections)) } } fn do_visit_custom_sections_filter( ctx, - custom_sections: ShineTree(CustomSection), - acc: ShineTree(CustomSection), + custom_sections: List(CustomSection), + acc: List(CustomSection), visitor: BinaryModuleVisitor(ctx), -) -> Result(#(ctx, Option(ShineTree(CustomSection))), String) { - case shine_tree.shift(custom_sections) { - Ok(#(custom_section, custom_sections)) -> { - use #(ctx, custom_section) <- try(do_visit_custom_section( +) -> 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 custom_section { + + case optional_custom_section { Some(custom_section) -> do_visit_custom_sections_filter( ctx, custom_sections, - shine_tree.push(acc, custom_section), + [custom_section, ..acc], visitor, ) None -> do_visit_custom_sections_filter(ctx, custom_sections, acc, visitor) } } - _ -> Ok(#(ctx, Some(acc))) } } diff --git a/test/decode_test.gleam b/test/decode_test.gleam index 53ffbe8..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 @@ -16,10 +17,9 @@ import internal/structure/numbers import internal/structure/types.{ type FuncIDX, Expr, FuncImport, GlobalImport, MemImport, RefFunc, TableImport, } as structure_types -import shine_tree pub fn func_idx_to_expr(expr: FuncIDX) { - Expr([RefFunc(expr)] |> shine_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(shine_tree.to_list) |> should.equal(#([], <<>>)) <<4, 0x7F, 0x7E, 0x7D, 0x7C>> |> types.decode_result_type |> should.be_ok - |> pair.map_first(shine_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(shine_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 |> shine_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 - |> shine_tree.to_list - |> should.equal(b.parameters |> shine_tree.to_list) - a.results - |> shine_tree.to_list - |> should.equal(b.results |> shine_tree.to_list) + a |> should.equal(b) } fn struct_type_equals( a: structure_types.StructType, b: structure_types.StructType, ) { - a.ft - |> shine_tree.to_list - |> should.equal(b.ft |> shine_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( - shine_tree.empty, - shine_tree.empty, - )), + 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( - shine_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: shine_tree.ShineTree(structure_types.TypeIDX), - b: shine_tree.ShineTree(structure_types.TypeIDX), + a: List(structure_types.TypeIDX), + b: List(structure_types.TypeIDX), ) { - case shine_tree.shift(a), shine_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == shine_tree.empty && rest_b == shine_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: shine_tree.ShineTree(structure_types.FuncIDX), - b: shine_tree.ShineTree(structure_types.FuncIDX), + a: List(structure_types.FuncIDX), + b: List(structure_types.FuncIDX), ) { - case shine_tree.shift(a), shine_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == shine_tree.empty && rest_b == shine_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: shine_tree.ShineTree(structure_types.SubType), - b: shine_tree.ShineTree(structure_types.SubType), + a: List(structure_types.SubType), + b: List(structure_types.SubType), ) { - case shine_tree.shift(a), shine_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == shine_tree.empty && rest_b == shine_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, - shine_tree.empty, + [], 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(shine_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, - shine_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( - shine_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(shine_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(shine_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: shine_tree.ShineTree(structure_types.RecType), - b: shine_tree.ShineTree(structure_types.RecType), + a: List(structure_types.RecType), + b: List(structure_types.RecType), ) { - case shine_tree.shift(a), shine_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == shine_tree.empty && rest_b == shine_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(shine_tree.empty) + 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( - shine_tree.from_list([ - structure_types.SubType( - True, - shine_tree.empty, - 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(shine_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: shine_tree.ShineTree(structure_types.Import), - b: shine_tree.ShineTree(structure_types.Import), + a: List(structure_types.Import), + b: List(structure_types.Import), ) { - case shine_tree.shift(a), shine_tree.shift(b) { - Ok(#(a, rest_a)), Ok(#(b, rest_b)) - if rest_a == shine_tree.empty && rest_b == shine_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(shine_tree.empty) + let empty_import_section = structure_modules.ImportSection([]) <<0x02, 0x01, 0x00>> |> decode_type_equals_helper( @@ -794,7 +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(shine_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), @@ -814,10 +759,8 @@ fn function_section_equals( } } -// 3 function section pub fn decode_function_section_test() { - let empty_function_section = - structure_modules.FunctionSection(shine_tree.empty) + let empty_function_section = structure_modules.FunctionSection([]) <<0x03, 0x01, 0x00>> |> decode_type_equals_helper( @@ -826,12 +769,9 @@ pub fn decode_function_section_test() { function_section_equals, ) - let assert Ok(indexes) = - [1, 2, 3, 4] - |> shine_tree.from_list - |> shine_tree.try_map(numbers.u32) + let assert Ok(indexes) = [1, 2, 3, 4] |> list.try_map(numbers.u32) - let indexes = indexes |> shine_tree.map(structure_types.TypeIDX) + let indexes = indexes |> list.map(structure_types.TypeIDX) let function_section = structure_modules.FunctionSection(indexes) @@ -855,15 +795,16 @@ fn table_section_equals( } fn do_tables_equal( - a: shine_tree.ShineTree(structure_types.Table), - b: shine_tree.ShineTree(structure_types.Table), + a: List(structure_types.Table), + b: List(structure_types.Table), ) { - case shine_tree.shift(a), shine_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" } } @@ -915,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(shine_tree.empty) + let empty_table_section = structure_modules.TableSection([]) <<0x04, 0x01, 0x00>> |> decode_type_equals_helper( @@ -949,7 +890,7 @@ pub fn decode_table_section_test() { second_table_bits |> decode_type_equals_helper( - Some(structure_modules.TableSection(shine_tree.from_list([second_table]))), + Some(structure_modules.TableSection([second_table])), modules.decode_table_section, table_section_equals, ) @@ -972,9 +913,7 @@ pub fn decode_table_section_test() { <<0x04, 0x09, 0x01, table_bytes_three:bits>> |> decode_type_equals_helper( - Some( - structure_modules.TableSection(shine_tree.from_list([table_init_three])), - ), + Some(structure_modules.TableSection([table_init_three])), modules.decode_table_section, table_section_equals, ) @@ -988,15 +927,16 @@ fn mem_types_equals(a: structure_types.MemType, b: structure_types.MemType) { } fn do_mem_types_equal( - a: shine_tree.ShineTree(structure_types.MemType), - b: shine_tree.ShineTree(structure_types.MemType), + a: List(structure_types.MemType), + b: List(structure_types.MemType), ) { - case shine_tree.shift(a), shine_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" } } @@ -1022,7 +962,7 @@ fn memory_section_equals( // 5 memory section pub fn decode_memory_section_test() { - let empty_memory_section = structure_modules.MemorySection(shine_tree.empty) + let empty_memory_section = structure_modules.MemorySection([]) <<0x05, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1042,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(shine_tree.from_list([example_memory])), - ), + Some(structure_modules.MemorySection([example_memory])), modules.decode_memory_section, memory_section_equals, ) @@ -1064,15 +1002,16 @@ fn globals_equals(a: structure_types.Global, b: structure_types.Global) { } fn do_globals_equal( - a: shine_tree.ShineTree(structure_types.Global), - b: shine_tree.ShineTree(structure_types.Global), + a: List(structure_types.Global), + b: List(structure_types.Global), ) { - case shine_tree.shift(a), shine_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" } } @@ -1091,7 +1030,7 @@ fn global_section_equals( // 6 global section pub fn decode_global_section_test() { - let empty_global_section = structure_modules.GlobalSection(shine_tree.empty) + let empty_global_section = structure_modules.GlobalSection([]) <<0x06, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1115,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(shine_tree.from_list([example_global])), - ), + Some(structure_modules.GlobalSection([example_global])), modules.decode_global_section, global_section_equals, ) @@ -1154,15 +1091,16 @@ fn exports_equals(a: structure_types.Export, b: structure_types.Export) { } fn do_exports_equal( - a: shine_tree.ShineTree(structure_types.Export), - b: shine_tree.ShineTree(structure_types.Export), + a: List(structure_types.Export), + b: List(structure_types.Export), ) { - case shine_tree.shift(a), shine_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" } } @@ -1180,7 +1118,7 @@ fn export_section_equals( } pub fn decode_export_section_test() { - let empty_export_section = structure_modules.ExportSection(shine_tree.empty) + let empty_export_section = structure_modules.ExportSection([]) <<0x07, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1204,14 +1142,12 @@ pub fn decode_export_section_test() { structure_types.GlobalExport("global", structure_types.GlobalIDX(four)) let export_section = - structure_modules.ExportSection( - shine_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 @@ -1272,16 +1208,17 @@ pub fn decode_start_section_test() { // 9 element section fn do_expressions_equals( - a: shine_tree.ShineTree(structure_types.Expr), - b: shine_tree.ShineTree(structure_types.Expr), + a: List(structure_types.Expr), + b: List(structure_types.Expr), ) { - case shine_tree.shift(a), shine_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" } } @@ -1310,15 +1247,16 @@ fn elements_equals(a: structure_types.Elem, b: structure_types.Elem) { } fn do_elements_equal( - a: shine_tree.ShineTree(structure_types.Elem), - b: shine_tree.ShineTree(structure_types.Elem), + a: List(structure_types.Elem), + b: List(structure_types.Elem), ) { - case shine_tree.shift(a), shine_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" } } @@ -1336,7 +1274,7 @@ fn element_section_equals( } pub fn decode_element_section_test() { - let empty_element_section = structure_modules.ElementSection(shine_tree.empty) + let empty_element_section = structure_modules.ElementSection([]) <<0x09, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1360,7 +1298,7 @@ pub fn decode_element_section_test() { let ref_func = structure_types.HeapTypeRefType(structure_types.FuncHeapType, False) - // Elem(type_: RefType, init: ShineTree(Expr), mode: ElemMode) + // Elem(type_: RefType, init: List(Expr), mode: ElemMode) let ref_null_i31 = structure_types.I31RefType let null_i31 = @@ -1368,17 +1306,15 @@ pub fn decode_element_section_test() { |> ref.null(structure_types.I31HeapType) |> expression.end_unwrap() - let three_null_i31 = shine_tree.from_list([null_i31, null_i31, null_i31]) + let three_null_i31 = [null_i31, null_i31, null_i31] - let three_func_idx = - shine_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 |> shine_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 = @@ -1580,18 +1516,16 @@ pub fn decode_element_section_test() { ) let element_section = - structure_modules.ElementSection( - shine_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 @@ -1643,15 +1577,16 @@ fn locals_equals(a: structure_types.Locals, b: structure_types.Locals) { } fn do_locals_equals( - a: shine_tree.ShineTree(structure_types.Locals), - b: shine_tree.ShineTree(structure_types.Locals), + a: List(structure_types.Locals), + b: List(structure_types.Locals), ) { - case shine_tree.shift(a), shine_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" } } @@ -1662,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: shine_tree.ShineTree(structure_types.Code), - b: shine_tree.ShineTree(structure_types.Code), -) { - case shine_tree.shift(a), shine_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" } } @@ -1690,27 +1623,22 @@ fn code_section_equals( pub fn code_section_test() { let assert Ok(two) = numbers.u32(2) - let add_locals = - shine_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( - shine_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, @@ -1726,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, @@ -1758,17 +1686,15 @@ fn data_equals(a: structure_types.Data, b: structure_types.Data) { } } -fn do_data_equals( - a: shine_tree.ShineTree(structure_types.Data), - b: shine_tree.ShineTree(structure_types.Data), -) { - case shine_tree.shift(a), shine_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" } } @@ -1813,7 +1739,7 @@ pub fn data_section_test() { 0x07, 0x08, 0x09, >>) - let empty_data_section = structure_modules.DataSection(shine_tree.empty) + let empty_data_section = structure_modules.DataSection([]) <<0x0B, 0x01, 0x00>> |> decode_type_equals_helper( @@ -1823,9 +1749,11 @@ pub fn data_section_test() { ) let data_section = - structure_modules.DataSection( - shine_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 188d8eb..d45c8cb 100644 --- a/test/encode_test.gleam +++ b/test/encode_test.gleam @@ -4,6 +4,7 @@ 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 @@ -13,10 +14,9 @@ import internal/binary/values import internal/structure/modules as structure_modules import internal/structure/numbers import internal/structure/types.{type FuncIDX, Expr, RefFunc} as structure_types -import shine_tree pub fn func_idx_to_expr(expr: FuncIDX) { - Expr([RefFunc(expr)] |> shine_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 = shine_tree.empty - let four = - shine_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(shine_tree.empty)) + |> types.encode_struct_type(structure_types.StructType([])) |> should_equal_helper(<<0>>) bytes_builder.new() |> types.encode_struct_type( - structure_types.StructType( - shine_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( - shine_tree.empty, - shine_tree.empty, - )), - ) - |> should_equal_helper(<<0x60, 0x00, 0x00>>) - - bytes_builder.new() - |> types.encode_composite_type( - structure_types.StructCompositeType( - structure_types.StructType( - shine_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, - shine_tree.empty, + [], 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(shine_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, - shine_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( - shine_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(shine_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(shine_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(shine_tree.empty) + 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( - shine_tree.from_list([ - structure_types.SubType( - True, - shine_tree.empty, - 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(shine_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(shine_tree.empty) + let empty_import_section = structure_modules.ImportSection([]) bytes_builder.new() |> modules.encode_import_section(empty_import_section) @@ -511,7 +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(shine_tree.from_list([func_import_example])) + structure_modules.ImportSection([func_import_example]) bytes_builder.new() |> modules.encode_import_section(example_import_section) @@ -523,19 +501,15 @@ pub fn import_section_test() { } pub fn function_section_test() { - let empty_function_section = - structure_modules.FunctionSection(shine_tree.empty) + 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] - |> shine_tree.from_list - |> shine_tree.try_map(numbers.u32) + let assert Ok(indexes) = [1, 2, 3, 4] |> list.try_map(numbers.u32) - let indexes = indexes |> shine_tree.map(structure_types.TypeIDX) + let indexes = indexes |> list.map(structure_types.TypeIDX) let function_section = structure_modules.FunctionSection(indexes) @@ -545,7 +519,7 @@ pub fn function_section_test() { } pub fn table_section_test() { - let empty_table_section = structure_modules.TableSection(shine_tree.empty) + let empty_table_section = structure_modules.TableSection([]) bytes_builder.new() |> modules.encode_table_section(empty_table_section) @@ -566,7 +540,7 @@ pub fn table_section_test() { bytes_builder.new() |> modules.encode_table_section( - structure_modules.TableSection(shine_tree.from_list([example_table])), + structure_modules.TableSection([example_table]), ) |> should_equal_helper(<< 0x04, @@ -578,7 +552,7 @@ pub fn table_section_test() { let expr = expression.new() |> ref.null(structure_types.ArrayHeapType) - // + // |> expression.end_unwrap() let example_table_init = @@ -593,13 +567,13 @@ pub fn table_section_test() { bytes_builder.new() |> modules.encode_table_section( - structure_modules.TableSection(shine_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(shine_tree.empty) + let empty_memory_section = structure_modules.MemorySection([]) bytes_builder.new() |> modules.encode_memory_section(empty_memory_section) @@ -616,7 +590,7 @@ pub fn memory_section_test() { bytes_builder.new() |> modules.encode_memory_section( - structure_modules.MemorySection(shine_tree.from_list([example_memory])), + structure_modules.MemorySection([example_memory]), ) |> should_equal_helper(<< 0x05, @@ -627,7 +601,7 @@ pub fn memory_section_test() { } pub fn global_section_test() { - let empty_global_section = structure_modules.GlobalSection(shine_tree.empty) + let empty_global_section = structure_modules.GlobalSection([]) bytes_builder.new() |> modules.encode_global_section(empty_global_section) @@ -646,8 +620,7 @@ pub fn global_section_test() { |> expression.end_unwrap(), ) - let global_section = - structure_modules.GlobalSection(shine_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, >> @@ -657,7 +630,7 @@ pub fn global_section_test() { } pub fn export_section_test() { - let empty_export_section = structure_modules.ExportSection(shine_tree.empty) + let empty_export_section = structure_modules.ExportSection([]) bytes_builder.new() |> modules.encode_export_section(empty_export_section) @@ -678,14 +651,12 @@ pub fn export_section_test() { structure_types.GlobalExport("global", structure_types.GlobalIDX(four)) let export_section = - structure_modules.ExportSection( - shine_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 @@ -728,7 +699,7 @@ pub fn start_section_test() { } pub fn element_section_test() { - let empty_element_section = structure_modules.ElementSection(shine_tree.empty) + let empty_element_section = structure_modules.ElementSection([]) bytes_builder.new() |> modules.encode_element_section(empty_element_section) @@ -749,7 +720,7 @@ pub fn element_section_test() { let ref_func = structure_types.HeapTypeRefType(structure_types.FuncHeapType, False) - // Elem(type_: RefType, init: ShineTree(Expr), mode: ElemMode) + // Elem(type_: RefType, init: List(Expr), mode: ElemMode) let ref_null_i31 = structure_types.HeapTypeRefType(structure_types.I31HeapType, True) @@ -758,17 +729,15 @@ pub fn element_section_test() { |> ref.null(structure_types.I31HeapType) |> expression.end_unwrap() - let three_null_i31 = shine_tree.from_list([null_i31, null_i31, null_i31]) + let three_null_i31 = [null_i31, null_i31, null_i31] - let three_func_idx = - shine_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 |> shine_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 = @@ -941,18 +910,16 @@ pub fn element_section_test() { |> should_equal_helper(element_seven_bytes) let element_section = - structure_modules.ElementSection( - shine_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 @@ -997,27 +964,22 @@ pub fn element_section_test() { pub fn code_section_test() { let assert Ok(two) = numbers.u32(2) - let add_locals = - shine_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( - shine_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, @@ -1033,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, @@ -1076,16 +1038,18 @@ pub fn data_section_test() { 0x07, 0x08, 0x09, >>) - let empty_data_section = structure_modules.DataSection(shine_tree.empty) + 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( - shine_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 c581bfc..282b2df 100644 --- a/test/instruction_test.gleam +++ b/test/instruction_test.gleam @@ -9,7 +9,6 @@ import internal/binary/types import internal/structure/numbers import internal/structure/types as structure_types import pprint -import shine_tree fn round_trip( expected_inst: structure_types.Instruction, @@ -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 = shine_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 - |> shine_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(shine_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 - |> shine_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 - |> shine_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 |> shine_tree.from_list), + structure_types.Expr(instruction_list), ), ) @@ -284,7 +277,7 @@ pub fn if_test() { let drop = structure_types.Drop let instruction_list = [local_get1, local_get2, i32_add, drop] - let block_body = shine_tree.from_list(instruction_list) + let block_body = instruction_list let assert Ok(#( structure_types.If(structure_types.VoidBlockType, result_body, None), @@ -292,9 +285,7 @@ pub fn if_test() { )) = types.decode_instruction(<<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>) - result_body - |> shine_tree.to_list - |> should.equal(instruction_list) + result_body |> should.equal(instruction_list) let assert Ok(builder) = types.encode_instruction( @@ -313,7 +304,7 @@ pub fn if_else_test() { let local_get1 = structure_types.LocalGet(local_idx1) let drop = structure_types.Drop - let block_body = shine_tree.from_list([local_get1, drop]) + let block_body = [local_get1, drop] round_trip( structure_types.If( @@ -884,14 +875,12 @@ pub fn select_t_test() { structure_types.F32ValType, structure_types.F64ValType, ] - let val_types = shine_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 - |> shine_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/visitor/heap_type_test.gleam b/test/visitor/heap_type_test.gleam index 8aba80b..12e2dfa 100644 --- a/test/visitor/heap_type_test.gleam +++ b/test/visitor/heap_type_test.gleam @@ -1,4 +1,5 @@ import builder/module +import gleam/option.{None} import internal/structure/types.{ AnyHeapType, ArrayHeapType, ConcreteHeapType, EqHeapType, ExternHeapType, FuncHeapType, I31HeapType, NoExternHeapType, NoFuncHeapType, NoneHeapType, @@ -6,7 +7,6 @@ import internal/structure/types.{ } import visitor import visitor/visit_test_variant -import gleam/option.{None} pub fn visit_func_heap_type_test() { visit_test_variant.run( diff --git a/test/visitor/instruction_test.gleam b/test/visitor/instruction_test.gleam index fb2694d..fa95f23 100644 --- a/test/visitor/instruction_test.gleam +++ b/test/visitor/instruction_test.gleam @@ -3,7 +3,7 @@ import builder/instructions/control import builder/instructions/i32 import builder/module import builder/types/block_type -import gleam/option.{None, Some} +import gleam/option.{None} import internal/structure/types.{ ArrayCopy, ArrayFill, ArrayGet, ArrayGetS, ArrayGetU, ArrayInitData, ArrayInitElem, ArrayNew, ArrayNewData, ArrayNewDefault, ArrayNewElem, @@ -16,7 +16,6 @@ import internal/structure/types.{ StructSet, TableCopy, TableFill, TableGet, TableGrow, TableInit, TableSet, TableSize, } -import shine_tree import values import visitor import visitor/visit_test_variant @@ -331,9 +330,8 @@ pub fn visit_array_init_elem_test() { } pub fn visit_select_t_test() { - let val_types = - [I32ValType, I64ValType, F32ValType, F64ValType] - |> module.to_vector + let val_types = [I32ValType, I64ValType, F32ValType, F64ValType] + visit_test_variant.run( SelectT(val_types), visitor.on_enter_instruction, @@ -341,13 +339,7 @@ pub fn visit_select_t_test() { visitor.on_enter_select_t, visitor.on_exit_select_t, visitor.visit_instruction, - Some(fn(actual, expected) { - case actual, expected { - SelectT(actual_val_types), SelectT(expected_val_types) -> - shine_tree.equals(actual_val_types, expected_val_types) - a, b -> a == b - } - }), + None, ) } @@ -589,10 +581,8 @@ pub fn visit_loop_test() { } pub fn visit_if_test() { - let if_block = shine_tree.from_list([Nop]) - visit_test_variant.run( - If(block_type.void, if_block, None), + If(block_type.void, [Nop], None), visitor.on_enter_instruction, visitor.on_exit_instruction, visitor.on_enter_if, @@ -635,14 +625,7 @@ pub fn visit_br_table_test() { 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 = - shine_tree.from_list([ - label_idx1, - label_idx2, - label_idx3, - label_idx4, - label_idx5, - ]) + let labels = [label_idx1, label_idx2, label_idx3, label_idx4, label_idx5] visit_test_variant.run( BrTable(labels, default_label), visitor.on_enter_instruction, @@ -650,17 +633,7 @@ pub fn visit_br_table_test() { visitor.on_enter_br_table, visitor.on_exit_br_table, visitor.visit_instruction, - Some(fn(actual, expected) { - case actual, expected { - BrTable(actual_labels, actual_default), - BrTable(expected_labels, expected_default) - -> { - shine_tree.equals(actual_labels, expected_labels) - && actual_default == expected_default - } - a, b -> a == b - } - }), + None, ) } diff --git a/test/visitor/val_type.gleam b/test/visitor/val_type.gleam index a52767d..9bef1c2 100644 --- a/test/visitor/val_type.gleam +++ b/test/visitor/val_type.gleam @@ -1,8 +1,8 @@ +import gleam/option.{None} import internal/structure/types.{ F32ValType, F64ValType, I31RefType, I32ValType, I64ValType, RefTypeValType, V128ValType, } -import gleam/option.{None} import visitor import visitor/visit_test_variant diff --git a/test/visitor/visit_test_variant.gleam b/test/visitor/visit_test_variant.gleam index e5b8636..df2a078 100644 --- a/test/visitor/visit_test_variant.gleam +++ b/test/visitor/visit_test_variant.gleam @@ -1,6 +1,5 @@ import gleam/option.{type Option, None, Some} import gleeunit/should -import shine_tree import visitor.{type BinaryModuleVisitor} type VisitCallback(u) = From 0ef9c4db484be88468f532e2e00edf4f4c5087d9 Mon Sep 17 00:00:00 2001 From: jtenner Date: Tue, 17 Sep 2024 14:27:24 -0400 Subject: [PATCH 13/16] Create memory builder module, some work on validators. Co-authored-by: Rishit Chaudhary --- CODE_OF_CONDUCT.md | 73 -------- gleam.toml | 1 + manifest.toml | 2 + src/builder/mem_builder.gleam | 278 ++++++++++++++++++++++++++++ src/internal/validation/types.gleam | 94 +++++++++- src/internal/visitor.gleam | 1 - 6 files changed, 373 insertions(+), 76 deletions(-) delete mode 100644 CODE_OF_CONDUCT.md create mode 100644 src/builder/mem_builder.gleam diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 3296375..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,73 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at louis at lpil.uk. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org diff --git a/gleam.toml b/gleam.toml index d853e41..2ea6a76 100644 --- a/gleam.toml +++ b/gleam.toml @@ -18,6 +18,7 @@ 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 51e75e4..2557177 100644 --- a/manifest.toml +++ b/manifest.toml @@ -6,6 +6,7 @@ packages = [ { 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.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.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" }, @@ -15,6 +16,7 @@ packages = [ [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" } 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/internal/validation/types.gleam b/src/internal/validation/types.gleam index c0acfa7..c884c01 100644 --- a/src/internal/validation/types.gleam +++ b/src/internal/validation/types.gleam @@ -1,6 +1,96 @@ -import internal/structure/types.{type RecType} +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} -pub fn validate_rec_type(ctx: Context, rec_type: RecType) -> Result(Nil, String) { +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 } diff --git a/src/internal/visitor.gleam b/src/internal/visitor.gleam index 907985d..48d68bc 100644 --- a/src/internal/visitor.gleam +++ b/src/internal/visitor.gleam @@ -41,7 +41,6 @@ import internal/structure/types.{ TableGrow, TableImport, TableInit, TableSet, TableSize, TableType, TypeIDX, V128ValType, ValTypeBlockType, ValTypeStorageType, VoidBlockType, } -import pprint pub type VisitorCallback(ctx, element) = fn(ctx, element) -> Result(#(ctx, element), String) From febf9e08006731eb08f5f8142d6bd610ffd2f015 Mon Sep 17 00:00:00 2001 From: jtenner Date: Wed, 18 Sep 2024 07:20:33 -0400 Subject: [PATCH 14/16] remove code of conduct --- src/builder/module.gleam | 58 +++ src/internal/finger_tree.gleam | 625 +++++++++++++++++++++++++++++++++ test/instruction_test.gleam | 6 + 3 files changed, 689 insertions(+) create mode 100644 src/internal/finger_tree.gleam diff --git a/src/builder/module.gleam b/src/builder/module.gleam index 6ed0dd4..75fdc0f 100644 --- a/src/builder/module.gleam +++ b/src/builder/module.gleam @@ -17,10 +17,17 @@ import internal/structure/types.{ 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, } @@ -475,30 +482,74 @@ pub fn add_func_type( 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 @@ -775,7 +826,11 @@ pub fn export_table(module: BinaryModule, name: String, table: TableIDX) { /// 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) { @@ -1220,6 +1275,7 @@ 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) { @@ -1229,6 +1285,8 @@ pub fn field_idx(idx: Int) { } } +======= +>>>>>>> 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. diff --git a/src/internal/finger_tree.gleam b/src/internal/finger_tree.gleam new file mode 100644 index 0000000..9a9517a --- /dev/null +++ b/src/internal/finger_tree.gleam @@ -0,0 +1,625 @@ +//// Link to FingerTree description: https://www.staff.city.ac.uk/~ross/papers/FingerTree.html + +import gleam/option.{type Option, None, Some} +import gleam/result + +/// Finger tree implementation +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 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 map(tree: FingerTree(u), f: fn(u) -> v) -> FingerTree(v) { + use tree, a <- reducel(tree, Empty) + tree |> push(f(a)) +} + +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/test/instruction_test.gleam b/test/instruction_test.gleam index 282b2df..5441cac 100644 --- a/test/instruction_test.gleam +++ b/test/instruction_test.gleam @@ -285,7 +285,13 @@ pub fn if_test() { )) = types.decode_instruction(<<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>) +<<<<<<< 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( From 638a16c79eb4292adce5c60c3e59a79b673b5122 Mon Sep 17 00:00:00 2001 From: jtenner Date: Wed, 18 Sep 2024 07:18:58 -0400 Subject: [PATCH 15/16] More --- src/internal/validation/module.gleam | 4 ++-- src/internal/validation/types.gleam | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/internal/validation/module.gleam b/src/internal/validation/module.gleam index 7f4d29e..56de6c0 100644 --- a/src/internal/validation/module.gleam +++ b/src/internal/validation/module.gleam @@ -6,12 +6,12 @@ import internal/structure/types.{type RecType} import internal/validation/common.{ type Context, Context, empty_context, roll_rec_types, } -import internal/validation/types.{validate_rec_type} as _validation_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(validate_rec_type(ctx, rec_type)) + use _ <- result.map(rec_type_is_valid(ctx, rec_type)) ctx } diff --git a/src/internal/validation/types.gleam b/src/internal/validation/types.gleam index c884c01..9e98400 100644 --- a/src/internal/validation/types.gleam +++ b/src/internal/validation/types.gleam @@ -94,3 +94,7 @@ pub fn def_type_is_valid(ctx: Context, def_type: DefType) { pub fn ref_type_is_valid(ctx: Context, ref_type: RefType) { todo } + +pub fn rec_type_is_valid(ctx: Context, rec_type: RecType) { + todo +} From 6dfd4024f1e63778a2f67ec57a55f886ed2c9a74 Mon Sep 17 00:00:00 2001 From: Rishit Chaudhary <12199011+rishitc@users.noreply.github.com> Date: Fri, 20 Sep 2024 21:36:23 +0530 Subject: [PATCH 16/16] remove finger_tree implementation --- src/internal/finger_tree.gleam | 625 --------------------------------- 1 file changed, 625 deletions(-) delete mode 100644 src/internal/finger_tree.gleam diff --git a/src/internal/finger_tree.gleam b/src/internal/finger_tree.gleam deleted file mode 100644 index 9a9517a..0000000 --- a/src/internal/finger_tree.gleam +++ /dev/null @@ -1,625 +0,0 @@ -//// Link to FingerTree description: https://www.staff.city.ac.uk/~ross/papers/FingerTree.html - -import gleam/option.{type Option, None, Some} -import gleam/result - -/// Finger tree implementation -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 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 map(tree: FingerTree(u), f: fn(u) -> v) -> FingerTree(v) { - use tree, a <- reducel(tree, Empty) - tree |> push(f(a)) -} - -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) - } -}