diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index da7701a..e34e50f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -14,8 +14,8 @@ jobs:
       - uses: actions/checkout@v4
       - uses: erlef/setup-beam@v1
         with:
-          otp-version: "26.0.2"
-          gleam-version: "1.3.2"
+          otp-version: "27.0.1"
+          gleam-version: "1.4.1"
           rebar3-version: "3"
           # elixir-version: "1.15.4"
       - run: gleam deps download
diff --git a/README.md b/README.md
index 75c8c20..74d70e3 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,74 @@
 # shinecoder
 
-[![Package Version](https://img.shields.io/hexpm/v/shinecoder)](https://hex.pm/packages/shinecoder)
-[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/shinecoder/)
+[![Package Version](https://img.shields.io/hexpm/v/shine_coder)](https://hex.pm/packages/shine_coder)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/shine_coder/)
 
-```sh
-gleam add shinecoder@1
+Parse, encode, build, and analyze WebAssembly modules using `shine_coder`! This library was born out of
+a need to conquer and understand the new WebAssembly GC specification, so all the functions in this library
+are designed to follow the specification as closely as possible.
+
+Currently this project is in an Alpha state and the developer consuming this library is required to understand
+the structure of WASM modules in order to build them. For instance, creating a module with a simple `add`
+function requires the following steps:
+
+```rs
+// 1. Make all the indexes up front. These return a result because all indexes
+//    must be valid unsigned 32 bit integers.
+let assert Ok(type_idx_0) = module.type_idx(0)
+let assert Ok(local_idx_0) = module.local_idx(0)
+let assert Ok(local_idx_1) = module.local_idx(1)
+let assert Ok(func_idx_0) = module.func_idx(0)
+
+let assert Ok(add_module) =
+  // 2. Create the module
+  module.new()
+  // 3. Define the function type, store it at index 0
+  |> module.add_type(
+    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)
+  // 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]
+    [val_type.i32, val_type.i32],
+    // 5.b Create an expression for the function body
+    expression.new()
+      |> local.get(local_idx_0)
+      |> local.get(local_idx_1)
+      |> i32.add
+      // 5.c Validate the expression nesting, and return an `Expr`
+      |> expression.end_unwrap(),
+  )
+  // 6. Finally, export the function at "function index 0" calling it "add"
+  |> module.export_func("add", func_idx_0)
+  |> module.encode
+
+let assert Ok(Nil) = simplifile.write_bits("shinecoder.wasm", add_module)
 ```
-```gleam
-import shinecoder
 
-pub fn main() {
-  // TODO: An example of the project in use
-}
+Visualizing the output using the text format looks like this:
+
+```wat
+(module
+  (type (;0;) (func (param i32 i32) (result i32)))
+  (func (;0;) (type 0) (param i32 i32) (result i32)
+    (local i32 i32)
+    local.get 0
+    local.get 1
+    i32.add)
+  (export "add" (func 0)))
 ```
 
-Further documentation can be found at <https://hexdocs.pm/shinecoder>.
+In the future, this will become more developer friendly with a nice high level api which handles the
+intricacies of building WASM modules.
 
-## Development
+## Goals
 
-```sh
-gleam run   # Run the project
-gleam test  # Run the tests
-```
+Some of these goals are personal, 
+
+1. Create a library that makes WebAssembly accessible to the Gleam package ecosystem
+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
diff --git a/gleam.toml b/gleam.toml
index 67956d1..6e3b1a7 100644
--- a/gleam.toml
+++ b/gleam.toml
@@ -16,6 +16,7 @@ licences = ["MIT"]
 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"
 
 [dev-dependencies]
 gleeunit = ">= 1.0.0 and < 2.0.0"
diff --git a/manifest.toml b/manifest.toml
index 211a0f3..c378ccb 100644
--- a/manifest.toml
+++ b/manifest.toml
@@ -2,12 +2,14 @@
 # You typically do not need to edit this file
 
 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 = "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 = "pprint", version = "1.0.3", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "76BBB92E23D12D954BD452686543F29EDE8EBEBB7FC0ACCBCA66EEF276EC3A06" },
+  { name = "simplifile", version = "2.1.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "BDD04F5D31D6D34E2EDFAEF0B68A6297AEC939888C3BFCE61133DE13857F6DA2" },
 ]
 
 [requirements]
@@ -15,3 +17,4 @@ 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" }
+simplifile = { version = ">= 2.1.0 and < 3.0.0" }
diff --git a/src/builder/expression_builder.gleam b/src/builder/expression.gleam
similarity index 100%
rename from src/builder/expression_builder.gleam
rename to src/builder/expression.gleam
diff --git a/src/builder/instructions/any.gleam b/src/builder/instructions/any.gleam
index 0b44c9f..5b3c6bf 100644
--- a/src/builder/instructions/any.gleam
+++ b/src/builder/instructions/any.gleam
@@ -1,7 +1,7 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{AnyConvertExtern}
 
 pub fn convert_extern(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(AnyConvertExtern)
+  |> expression.push(AnyConvertExtern)
 }
diff --git a/src/builder/instructions/array.gleam b/src/builder/instructions/array.gleam
index 162ef9f..dfa11c1 100644
--- a/src/builder/instructions/array.gleam
+++ b/src/builder/instructions/array.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/numbers.{type U32}
 import internal/structure/types.{
   type DataIDX, type ElemIDX, type TypeIDX, ArrayCopy, ArrayFill, ArrayGet,
@@ -8,70 +8,70 @@ import internal/structure/types.{
 
 pub fn array_new(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayNew(idx))
+  |> expression.push(ArrayNew(idx))
 }
 
 pub fn array_new_default(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayNewDefault(idx))
+  |> expression.push(ArrayNewDefault(idx))
 }
 
 pub fn array_new_data(builder: ExpressionBuilder, idx: TypeIDX, data: DataIDX) {
   builder
-  |> expression_builder.push(ArrayNewData(idx, data))
+  |> expression.push(ArrayNewData(idx, data))
 }
 
 pub fn array_new_elem(builder: ExpressionBuilder, idx: TypeIDX, elem: ElemIDX) {
   builder
-  |> expression_builder.push(ArrayNewElem(idx, elem))
+  |> expression.push(ArrayNewElem(idx, elem))
 }
 
 pub fn array_new_fixed(builder: ExpressionBuilder, idx: TypeIDX, size: U32) {
   builder
-  |> expression_builder.push(ArrayNewFixed(idx, size))
+  |> expression.push(ArrayNewFixed(idx, size))
 }
 
 pub fn array_get(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayGet(idx))
+  |> expression.push(ArrayGet(idx))
 }
 
 pub fn array_get_s(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayGetS(idx))
+  |> expression.push(ArrayGetS(idx))
 }
 
 pub fn array_get_u(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayGetU(idx))
+  |> expression.push(ArrayGetU(idx))
 }
 
 pub fn array_set(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArraySet(idx))
+  |> expression.push(ArraySet(idx))
 }
 
 pub fn array_len(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(ArrayLen)
+  |> expression.push(ArrayLen)
 }
 
 pub fn array_fill(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayFill(idx))
+  |> expression.push(ArrayFill(idx))
 }
 
 pub fn array_copy(builder: ExpressionBuilder, idx1: TypeIDX, idx2: TypeIDX) {
   builder
-  |> expression_builder.push(ArrayCopy(idx1, idx2))
+  |> expression.push(ArrayCopy(idx1, idx2))
 }
 
 pub fn array_init_data(builder: ExpressionBuilder, idx: TypeIDX, data: DataIDX) {
   builder
-  |> expression_builder.push(ArrayInitData(idx, data))
+  |> expression.push(ArrayInitData(idx, data))
 }
 
 pub fn array_init_elem(builder: ExpressionBuilder, idx: TypeIDX, elem: ElemIDX) {
   builder
-  |> expression_builder.push(ArrayInitElem(idx, elem))
+  |> expression.push(ArrayInitElem(idx, elem))
 }
diff --git a/src/builder/instructions/control.gleam b/src/builder/instructions/control.gleam
index 57f5549..8fc240e 100644
--- a/src/builder/instructions/control.gleam
+++ b/src/builder/instructions/control.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+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,
@@ -9,12 +9,12 @@ import internal/structure/types.{
 
 pub fn return(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(Return)
+  |> expression.push(Return)
 }
 
 pub fn return_call(builder: ExpressionBuilder, func_idx: FuncIDX) {
   builder
-  |> expression_builder.push(ReturnCall(func_idx))
+  |> expression.push(ReturnCall(func_idx))
 }
 
 pub fn return_call_indirect(
@@ -23,32 +23,32 @@ pub fn return_call_indirect(
   type_idx: TypeIDX,
 ) {
   builder
-  |> expression_builder.push(ReturnCallIndirect(table_idx, type_idx))
+  |> expression.push(ReturnCallIndirect(table_idx, type_idx))
 }
 
 pub fn return_call_ref(builder: ExpressionBuilder, type_idx: TypeIDX) {
   builder
-  |> expression_builder.push(ReturnCallRef(type_idx))
+  |> expression.push(ReturnCallRef(type_idx))
 }
 
 pub fn select(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(Select)
+  |> expression.push(Select)
 }
 
 pub fn select_t(builder: ExpressionBuilder, val_type: FingerTree(ValType)) {
   builder
-  |> expression_builder.push(SelectT(val_type))
+  |> expression.push(SelectT(val_type))
 }
 
 pub fn unreachable(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(Unreachable)
+  |> expression.push(Unreachable)
 }
 
 pub fn nop(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(Nop)
+  |> expression.push(Nop)
 }
 
 pub fn loop(
@@ -57,9 +57,9 @@ pub fn loop(
   callback: fn(ExpressionBuilder) -> ExpressionBuilder,
 ) {
   builder
-  |> expression_builder.begin_loop(block_type)
+  |> expression.begin_loop(block_type)
   |> callback
-  |> expression_builder.end
+  |> expression.end
 }
 
 pub fn if_(
@@ -73,13 +73,13 @@ pub fn if_(
     ExpressionBuilder,
 ) {
   builder
-  |> expression_builder.begin_if(block_type)
+  |> expression.begin_if(block_type)
   |> callback(fn(builder, callback) {
     builder
-    |> expression_builder.begin_else
+    |> expression.begin_else
     |> callback
   })
-  |> expression_builder.end
+  |> expression.end
 }
 
 pub fn block(
@@ -88,19 +88,19 @@ pub fn block(
   callback: fn(ExpressionBuilder) -> ExpressionBuilder,
 ) {
   builder
-  |> expression_builder.begin_block(block_type)
+  |> expression.begin_block(block_type)
   |> callback
-  |> expression_builder.end
+  |> expression.end
 }
 
 pub fn br(builder: ExpressionBuilder, label_idx: LabelIDX) {
   builder
-  |> expression_builder.push(Br(label_idx))
+  |> expression.push(Br(label_idx))
 }
 
 pub fn br_if(builder: ExpressionBuilder, label_idx: LabelIDX) {
   builder
-  |> expression_builder.push(BrIf(label_idx))
+  |> expression.push(BrIf(label_idx))
 }
 
 pub fn br_on_cast(
@@ -110,7 +110,7 @@ pub fn br_on_cast(
   rt2: RefType,
 ) {
   builder
-  |> expression_builder.push(BrOnCast(label_idx, rt1, rt2))
+  |> expression.push(BrOnCast(label_idx, rt1, rt2))
 }
 
 pub fn br_on_cast_fail(
@@ -120,17 +120,17 @@ pub fn br_on_cast_fail(
   rt2: RefType,
 ) {
   builder
-  |> expression_builder.push(BrOnCastFail(label_idx, rt1, rt2))
+  |> expression.push(BrOnCastFail(label_idx, rt1, rt2))
 }
 
 pub fn br_on_non_null(builder: ExpressionBuilder, label_idx: LabelIDX) {
   builder
-  |> expression_builder.push(BrOnNonNull(label_idx))
+  |> expression.push(BrOnNonNull(label_idx))
 }
 
 pub fn br_on_null(builder: ExpressionBuilder, label_idx: LabelIDX) {
   builder
-  |> expression_builder.push(BrOnNull(label_idx))
+  |> expression.push(BrOnNull(label_idx))
 }
 
 pub fn br_table(
@@ -139,12 +139,12 @@ pub fn br_table(
   default: LabelIDX,
 ) {
   builder
-  |> expression_builder.push(BrTable(labels, default))
+  |> expression.push(BrTable(labels, default))
 }
 
 pub fn call(builder: ExpressionBuilder, func_idx: FuncIDX) {
   builder
-  |> expression_builder.push(Call(func_idx))
+  |> expression.push(Call(func_idx))
 }
 
 pub fn call_indirect(
@@ -153,20 +153,20 @@ pub fn call_indirect(
   type_idx: TypeIDX,
 ) {
   builder
-  |> expression_builder.push(CallIndirect(table_idx, type_idx))
+  |> expression.push(CallIndirect(table_idx, type_idx))
 }
 
 pub fn call_ref(builder: ExpressionBuilder, type_idx: TypeIDX) {
   builder
-  |> expression_builder.push(CallRef(type_idx))
+  |> expression.push(CallRef(type_idx))
 }
 
 pub fn drop(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(Drop)
+  |> expression.push(Drop)
 }
 
 pub fn end_expression(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.end_unwrap
+  |> expression.end_unwrap
 }
diff --git a/src/builder/instructions/data.gleam b/src/builder/instructions/data.gleam
index c2f929f..b2a111b 100644
--- a/src/builder/instructions/data.gleam
+++ b/src/builder/instructions/data.gleam
@@ -1,7 +1,7 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{type DataIDX, DataDrop}
 
 pub fn drop(builder: ExpressionBuilder, data_idx: DataIDX) {
   builder
-  |> expression_builder.push(DataDrop(data_idx))
+  |> expression.push(DataDrop(data_idx))
 }
diff --git a/src/builder/instructions/elem.gleam b/src/builder/instructions/elem.gleam
index cfb022b..e17d4de 100644
--- a/src/builder/instructions/elem.gleam
+++ b/src/builder/instructions/elem.gleam
@@ -1,7 +1,7 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{type ElemIDX, ElemDrop}
 
 pub fn drop(builder: ExpressionBuilder, elem_idx: ElemIDX) {
   builder
-  |> expression_builder.push(ElemDrop(elem_idx))
+  |> expression.push(ElemDrop(elem_idx))
 }
diff --git a/src/builder/instructions/extern.gleam b/src/builder/instructions/extern.gleam
index e790d47..6529644 100644
--- a/src/builder/instructions/extern.gleam
+++ b/src/builder/instructions/extern.gleam
@@ -1,7 +1,7 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{ExternConvertAny}
 
 pub fn convert_any(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(ExternConvertAny)
+  |> expression.push(ExternConvertAny)
 }
diff --git a/src/builder/instructions/f32.gleam b/src/builder/instructions/f32.gleam
index 07c98cf..cadb389 100644
--- a/src/builder/instructions/f32.gleam
+++ b/src/builder/instructions/f32.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/numbers.{type F32}
 import internal/structure/types.{
   type MemArg, F32Abs, F32Add, F32Ceil, F32Const, F32ConvertI32S, F32ConvertI32U,
@@ -9,145 +9,145 @@ import internal/structure/types.{
 
 pub fn const_(builder: ExpressionBuilder, val: F32) {
   builder
-  |> expression_builder.push(F32Const(val))
+  |> expression.push(F32Const(val))
 }
 
 pub fn nearest(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Nearest)
+  |> expression.push(F32Nearest)
 }
 
 pub fn trunc(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Trunc)
+  |> expression.push(F32Trunc)
 }
 
 pub fn floor(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Floor)
+  |> expression.push(F32Floor)
 }
 
 pub fn ceil(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Ceil)
+  |> expression.push(F32Ceil)
 }
 
 pub fn sqrt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Sqrt)
+  |> expression.push(F32Sqrt)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Neg)
+  |> expression.push(F32Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Abs)
+  |> expression.push(F32Abs)
 }
 
 pub fn copysign(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Copysign)
+  |> expression.push(F32Copysign)
 }
 
 pub fn max(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Max)
+  |> expression.push(F32Max)
 }
 
 pub fn min(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Min)
+  |> expression.push(F32Min)
 }
 
 pub fn div(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Div)
+  |> expression.push(F32Div)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Mul)
+  |> expression.push(F32Mul)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Sub)
+  |> expression.push(F32Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Add)
+  |> expression.push(F32Add)
 }
 
 pub fn ge(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Ge)
+  |> expression.push(F32Ge)
 }
 
 pub fn le(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Le)
+  |> expression.push(F32Le)
 }
 
 pub fn gt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Gt)
+  |> expression.push(F32Gt)
 }
 
 pub fn lt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Lt)
+  |> expression.push(F32Lt)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Ne)
+  |> expression.push(F32Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32Eq)
+  |> expression.push(F32Eq)
 }
 
 pub fn demote_f64(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32DemoteF64)
+  |> expression.push(F32DemoteF64)
 }
 
 pub fn convert_i64s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32ConvertI64S)
+  |> expression.push(F32ConvertI64S)
 }
 
 pub fn convert_i64u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32ConvertI64U)
+  |> expression.push(F32ConvertI64U)
 }
 
 pub fn convert_i32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32ConvertI32S)
+  |> expression.push(F32ConvertI32S)
 }
 
 pub fn convert_i32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32ConvertI32U)
+  |> expression.push(F32ConvertI32U)
 }
 
 pub fn reinterpret_i32(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32ReinterpretI32)
+  |> expression.push(F32ReinterpretI32)
 }
 
 pub fn load(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(F32Load(mem_arg))
+  |> expression.push(F32Load(mem_arg))
 }
 
 pub fn store(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(F32Store(mem_arg))
+  |> expression.push(F32Store(mem_arg))
 }
diff --git a/src/builder/instructions/f32x4.gleam b/src/builder/instructions/f32x4.gleam
index b87ff8e..95ac939 100644
--- a/src/builder/instructions/f32x4.gleam
+++ b/src/builder/instructions/f32x4.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type LaneIDX4, F32x4Abs, F32x4Add, F32x4Ceil, F32x4ConvertI32x4S,
   F32x4ConvertI32x4U, F32x4DemoteF64x2Zero, F32x4Div, F32x4Eq, F32x4ExtractLane,
@@ -9,135 +9,135 @@ import internal/structure/types.{
 
 pub fn splat(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Splat)
+  |> expression.push(F32x4Splat)
 }
 
 pub fn extract_lane(builder: ExpressionBuilder, lane_idx: LaneIDX4) {
   builder
-  |> expression_builder.push(F32x4ExtractLane(lane_idx))
+  |> expression.push(F32x4ExtractLane(lane_idx))
 }
 
 pub fn replace_lane(builder: ExpressionBuilder, lane_idx: LaneIDX4) {
   builder
-  |> expression_builder.push(F32x4ReplaceLane(lane_idx))
+  |> expression.push(F32x4ReplaceLane(lane_idx))
 }
 
 pub fn ge(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Ge)
+  |> expression.push(F32x4Ge)
 }
 
 pub fn le(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Le)
+  |> expression.push(F32x4Le)
 }
 
 pub fn gt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Gt)
+  |> expression.push(F32x4Gt)
 }
 
 pub fn lt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Lt)
+  |> expression.push(F32x4Lt)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Ne)
+  |> expression.push(F32x4Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Eq)
+  |> expression.push(F32x4Eq)
 }
 
 pub fn nearest(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Nearest)
+  |> expression.push(F32x4Nearest)
 }
 
 pub fn trunc(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Trunc)
+  |> expression.push(F32x4Trunc)
 }
 
 pub fn floor(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Floor)
+  |> expression.push(F32x4Floor)
 }
 
 pub fn ceil(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Ceil)
+  |> expression.push(F32x4Ceil)
 }
 
 pub fn sqrt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Sqrt)
+  |> expression.push(F32x4Sqrt)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Neg)
+  |> expression.push(F32x4Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Abs)
+  |> expression.push(F32x4Abs)
 }
 
 pub fn pmax(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Pmax)
+  |> expression.push(F32x4Pmax)
 }
 
 pub fn pmin(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Pmin)
+  |> expression.push(F32x4Pmin)
 }
 
 pub fn max(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Max)
+  |> expression.push(F32x4Max)
 }
 
 pub fn min(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Min)
+  |> expression.push(F32x4Min)
 }
 
 pub fn div(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Div)
+  |> expression.push(F32x4Div)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Mul)
+  |> expression.push(F32x4Mul)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Sub)
+  |> expression.push(F32x4Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4Add)
+  |> expression.push(F32x4Add)
 }
 
 pub fn convert_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4ConvertI32x4S)
+  |> expression.push(F32x4ConvertI32x4S)
 }
 
 pub fn convert_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4ConvertI32x4U)
+  |> expression.push(F32x4ConvertI32x4U)
 }
 
 pub fn demote_f64x2_zero(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F32x4DemoteF64x2Zero)
+  |> expression.push(F32x4DemoteF64x2Zero)
 }
diff --git a/src/builder/instructions/f64.gleam b/src/builder/instructions/f64.gleam
index e37a2b4..b5666e4 100644
--- a/src/builder/instructions/f64.gleam
+++ b/src/builder/instructions/f64.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/numbers.{type F64}
 import internal/structure/types.{
   type MemArg, F64Abs, F64Add, F64Ceil, F64Const, F64ConvertI32S, F64ConvertI32U,
@@ -9,145 +9,145 @@ import internal/structure/types.{
 
 pub fn const_(builder: ExpressionBuilder, val: F64) {
   builder
-  |> expression_builder.push(F64Const(val))
+  |> expression.push(F64Const(val))
 }
 
 pub fn nearest(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Nearest)
+  |> expression.push(F64Nearest)
 }
 
 pub fn trunc(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Trunc)
+  |> expression.push(F64Trunc)
 }
 
 pub fn floor(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Floor)
+  |> expression.push(F64Floor)
 }
 
 pub fn ceil(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Ceil)
+  |> expression.push(F64Ceil)
 }
 
 pub fn sqrt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Sqrt)
+  |> expression.push(F64Sqrt)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Neg)
+  |> expression.push(F64Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Abs)
+  |> expression.push(F64Abs)
 }
 
 pub fn copysign(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Copysign)
+  |> expression.push(F64Copysign)
 }
 
 pub fn max(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Max)
+  |> expression.push(F64Max)
 }
 
 pub fn min(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Min)
+  |> expression.push(F64Min)
 }
 
 pub fn div(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Div)
+  |> expression.push(F64Div)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Mul)
+  |> expression.push(F64Mul)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Sub)
+  |> expression.push(F64Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Add)
+  |> expression.push(F64Add)
 }
 
 pub fn ge(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Ge)
+  |> expression.push(F64Ge)
 }
 
 pub fn le(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Le)
+  |> expression.push(F64Le)
 }
 
 pub fn gt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Gt)
+  |> expression.push(F64Gt)
 }
 
 pub fn lt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Lt)
+  |> expression.push(F64Lt)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Ne)
+  |> expression.push(F64Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64Eq)
+  |> expression.push(F64Eq)
 }
 
 pub fn promote_f32(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64PromoteF32)
+  |> expression.push(F64PromoteF32)
 }
 
 pub fn convert_i64s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64ConvertI64S)
+  |> expression.push(F64ConvertI64S)
 }
 
 pub fn convert_i64u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64ConvertI64U)
+  |> expression.push(F64ConvertI64U)
 }
 
 pub fn convert_i32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64ConvertI32S)
+  |> expression.push(F64ConvertI32S)
 }
 
 pub fn convert_i32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64ConvertI32U)
+  |> expression.push(F64ConvertI32U)
 }
 
 pub fn reinterpret_i64(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64ReinterpretI64)
+  |> expression.push(F64ReinterpretI64)
 }
 
 pub fn load(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(F64Load(mem_arg))
+  |> expression.push(F64Load(mem_arg))
 }
 
 pub fn store(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(F64Store(mem_arg))
+  |> expression.push(F64Store(mem_arg))
 }
diff --git a/src/builder/instructions/f64x2.gleam b/src/builder/instructions/f64x2.gleam
index 35b5a3e..9417c09 100644
--- a/src/builder/instructions/f64x2.gleam
+++ b/src/builder/instructions/f64x2.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type LaneIDX2, F64x2Abs, F64x2Add, F64x2Ceil, F64x2ConvertLowI32x4S,
   F64x2ConvertLowI32x4U, F64x2Div, F64x2Eq, F64x2ExtractLane, F64x2Floor,
@@ -9,135 +9,135 @@ import internal/structure/types.{
 
 pub fn splat(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Splat)
+  |> expression.push(F64x2Splat)
 }
 
 pub fn extract_lane(builder: ExpressionBuilder, lane_idx: LaneIDX2) {
   builder
-  |> expression_builder.push(F64x2ExtractLane(lane_idx))
+  |> expression.push(F64x2ExtractLane(lane_idx))
 }
 
 pub fn replace_lane(builder: ExpressionBuilder, lane_idx: LaneIDX2) {
   builder
-  |> expression_builder.push(F64x2ReplaceLane(lane_idx))
+  |> expression.push(F64x2ReplaceLane(lane_idx))
 }
 
 pub fn ge(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Ge)
+  |> expression.push(F64x2Ge)
 }
 
 pub fn le(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Le)
+  |> expression.push(F64x2Le)
 }
 
 pub fn gt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Gt)
+  |> expression.push(F64x2Gt)
 }
 
 pub fn lt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Lt)
+  |> expression.push(F64x2Lt)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Ne)
+  |> expression.push(F64x2Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Eq)
+  |> expression.push(F64x2Eq)
 }
 
 pub fn nearest(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Nearest)
+  |> expression.push(F64x2Nearest)
 }
 
 pub fn trunc(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Trunc)
+  |> expression.push(F64x2Trunc)
 }
 
 pub fn floor(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Floor)
+  |> expression.push(F64x2Floor)
 }
 
 pub fn ceil(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Ceil)
+  |> expression.push(F64x2Ceil)
 }
 
 pub fn sqrt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Sqrt)
+  |> expression.push(F64x2Sqrt)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Neg)
+  |> expression.push(F64x2Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Abs)
+  |> expression.push(F64x2Abs)
 }
 
 pub fn pmax(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Pmax)
+  |> expression.push(F64x2Pmax)
 }
 
 pub fn pmin(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Pmin)
+  |> expression.push(F64x2Pmin)
 }
 
 pub fn max(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Max)
+  |> expression.push(F64x2Max)
 }
 
 pub fn min(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Min)
+  |> expression.push(F64x2Min)
 }
 
 pub fn div(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Div)
+  |> expression.push(F64x2Div)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Mul)
+  |> expression.push(F64x2Mul)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Sub)
+  |> expression.push(F64x2Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2Add)
+  |> expression.push(F64x2Add)
 }
 
 pub fn convert_low_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2ConvertLowI32x4S)
+  |> expression.push(F64x2ConvertLowI32x4S)
 }
 
 pub fn convert_low_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2ConvertLowI32x4U)
+  |> expression.push(F64x2ConvertLowI32x4U)
 }
 
 pub fn promote_low_f32x4(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(F64x2PromoteLowF32x4)
+  |> expression.push(F64x2PromoteLowF32x4)
 }
diff --git a/src/builder/instructions/global.gleam b/src/builder/instructions/global.gleam
index 66e2347..5db22c4 100644
--- a/src/builder/instructions/global.gleam
+++ b/src/builder/instructions/global.gleam
@@ -1,12 +1,12 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{type GlobalIDX, GlobalGet, GlobalSet}
 
 pub fn get(builder: ExpressionBuilder, global_idx: GlobalIDX) {
   builder
-  |> expression_builder.push(GlobalGet(global_idx))
+  |> expression.push(GlobalGet(global_idx))
 }
 
 pub fn set(builder: ExpressionBuilder, global_idx: GlobalIDX) {
   builder
-  |> expression_builder.push(GlobalSet(global_idx))
+  |> expression.push(GlobalSet(global_idx))
 }
diff --git a/src/builder/instructions/i16x8.gleam b/src/builder/instructions/i16x8.gleam
index f324497..54daf05 100644
--- a/src/builder/instructions/i16x8.gleam
+++ b/src/builder/instructions/i16x8.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type LaneIDX8, I16x8Abs, I16x8Add, I16x8AddSatS, I16x8AddSatU, I16x8AllTrue,
   I16x8AvgrU, I16x8Bitmask, I16x8Eq, I16x8ExtaddPairwiseI8x16S,
@@ -14,230 +14,230 @@ import internal/structure/types.{
 
 pub fn splat(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Splat)
+  |> expression.push(I16x8Splat)
 }
 
 pub fn extract_lane_s(builder: ExpressionBuilder, lane_idx: LaneIDX8) {
   builder
-  |> expression_builder.push(I16x8ExtractLaneS(lane_idx))
+  |> expression.push(I16x8ExtractLaneS(lane_idx))
 }
 
 pub fn extract_lane_u(builder: ExpressionBuilder, lane_idx: LaneIDX8) {
   builder
-  |> expression_builder.push(I16x8ExtractLaneU(lane_idx))
+  |> expression.push(I16x8ExtractLaneU(lane_idx))
 }
 
 pub fn replace_lane(builder: ExpressionBuilder, lane_idx: LaneIDX8) {
   builder
-  |> expression_builder.push(I16x8ReplaceLane(lane_idx))
+  |> expression.push(I16x8ReplaceLane(lane_idx))
 }
 
 pub fn ge_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8GeS)
+  |> expression.push(I16x8GeS)
 }
 
 pub fn ge_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8GeU)
+  |> expression.push(I16x8GeU)
 }
 
 pub fn le_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8LeS)
+  |> expression.push(I16x8LeS)
 }
 
 pub fn le_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8LeU)
+  |> expression.push(I16x8LeU)
 }
 
 pub fn gt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8GtS)
+  |> expression.push(I16x8GtS)
 }
 
 pub fn gt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8GtU)
+  |> expression.push(I16x8GtU)
 }
 
 pub fn lt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8LtS)
+  |> expression.push(I16x8LtS)
 }
 
 pub fn lt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8LtU)
+  |> expression.push(I16x8LtU)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Ne)
+  |> expression.push(I16x8Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Eq)
+  |> expression.push(I16x8Eq)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Neg)
+  |> expression.push(I16x8Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Abs)
+  |> expression.push(I16x8Abs)
 }
 
 pub fn i16x8q15mulr_sat_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Q15mulrSatS)
+  |> expression.push(I16x8Q15mulrSatS)
 }
 
 pub fn all_true(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8AllTrue)
+  |> expression.push(I16x8AllTrue)
 }
 
 pub fn bitmask(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Bitmask)
+  |> expression.push(I16x8Bitmask)
 }
 
 pub fn narrow_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8NarrowI32x4S)
+  |> expression.push(I16x8NarrowI32x4S)
 }
 
 pub fn narrow_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8NarrowI32x4U)
+  |> expression.push(I16x8NarrowI32x4U)
 }
 
 pub fn extend_high_i8x16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtendHighI8x16S)
+  |> expression.push(I16x8ExtendHighI8x16S)
 }
 
 pub fn extend_high_i8x16u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtendHighI8x16U)
+  |> expression.push(I16x8ExtendHighI8x16U)
 }
 
 pub fn extend_low_i8x16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtendLowI8x16S)
+  |> expression.push(I16x8ExtendLowI8x16S)
 }
 
 pub fn extend_low_i8x16u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtendLowI8x16U)
+  |> expression.push(I16x8ExtendLowI8x16U)
 }
 
 pub fn shr_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ShrS)
+  |> expression.push(I16x8ShrS)
 }
 
 pub fn shr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ShrU)
+  |> expression.push(I16x8ShrU)
 }
 
 pub fn shl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Shl)
+  |> expression.push(I16x8Shl)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Sub)
+  |> expression.push(I16x8Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Add)
+  |> expression.push(I16x8Add)
 }
 
 pub fn max_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8MaxS)
+  |> expression.push(I16x8MaxS)
 }
 
 pub fn max_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8MaxU)
+  |> expression.push(I16x8MaxU)
 }
 
 pub fn min_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8MinS)
+  |> expression.push(I16x8MinS)
 }
 
 pub fn min_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8MinU)
+  |> expression.push(I16x8MinU)
 }
 
 pub fn sub_sat_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8SubSatS)
+  |> expression.push(I16x8SubSatS)
 }
 
 pub fn sub_sat_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8SubSatU)
+  |> expression.push(I16x8SubSatU)
 }
 
 pub fn add_sat_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8AddSatS)
+  |> expression.push(I16x8AddSatS)
 }
 
 pub fn add_sat_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8AddSatU)
+  |> expression.push(I16x8AddSatU)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8Mul)
+  |> expression.push(I16x8Mul)
 }
 
 pub fn avgr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8AvgrU)
+  |> expression.push(I16x8AvgrU)
 }
 
 pub fn extmul_high_i8x16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtmulHighI8x16S)
+  |> expression.push(I16x8ExtmulHighI8x16S)
 }
 
 pub fn extmul_high_i8x16u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtmulHighI8x16U)
+  |> expression.push(I16x8ExtmulHighI8x16U)
 }
 
 pub fn extmul_low_i8x16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtmulLowI8x16S)
+  |> expression.push(I16x8ExtmulLowI8x16S)
 }
 
 pub fn extmul_low_i8x16u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtmulLowI8x16U)
+  |> expression.push(I16x8ExtmulLowI8x16U)
 }
 
 pub fn extadd_pairwise_i8x16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtaddPairwiseI8x16S)
+  |> expression.push(I16x8ExtaddPairwiseI8x16S)
 }
 
 pub fn extadd_pairwise_i8x16u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I16x8ExtaddPairwiseI8x16U)
+  |> expression.push(I16x8ExtaddPairwiseI8x16U)
 }
diff --git a/src/builder/instructions/i32.gleam b/src/builder/instructions/i32.gleam
index 10b8584..fa62193 100644
--- a/src/builder/instructions/i32.gleam
+++ b/src/builder/instructions/i32.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/numbers.{type I32}
 import internal/structure/types.{
   type MemArg, I32Add, I32And, I32Clz, I32Const, I32Ctz, I32DivS, I32DivU, I32Eq,
@@ -12,245 +12,245 @@ import internal/structure/types.{
 
 pub fn const_(builder: ExpressionBuilder, value: I32) {
   builder
-  |> expression_builder.push(I32Const(value))
+  |> expression.push(I32Const(value))
 }
 
 pub fn popcnt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Popcnt)
+  |> expression.push(I32Popcnt)
 }
 
 pub fn ctz(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Ctz)
+  |> expression.push(I32Ctz)
 }
 
 pub fn clz(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Clz)
+  |> expression.push(I32Clz)
 }
 
 pub fn rotr(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Rotr)
+  |> expression.push(I32Rotr)
 }
 
 pub fn rotl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Rotl)
+  |> expression.push(I32Rotl)
 }
 
 pub fn shr_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32ShrS)
+  |> expression.push(I32ShrS)
 }
 
 pub fn shr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32ShrU)
+  |> expression.push(I32ShrU)
 }
 
 pub fn shl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Shl)
+  |> expression.push(I32Shl)
 }
 
 pub fn or(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Or)
+  |> expression.push(I32Or)
 }
 
 pub fn and(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32And)
+  |> expression.push(I32And)
 }
 
 pub fn rem_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32RemS)
+  |> expression.push(I32RemS)
 }
 
 pub fn rem_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32RemU)
+  |> expression.push(I32RemU)
 }
 
 pub fn div_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32DivS)
+  |> expression.push(I32DivS)
 }
 
 pub fn div_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32DivU)
+  |> expression.push(I32DivU)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Mul)
+  |> expression.push(I32Mul)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Sub)
+  |> expression.push(I32Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Add)
+  |> expression.push(I32Add)
 }
 
 pub fn eqz(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Eqz)
+  |> expression.push(I32Eqz)
 }
 
 pub fn ge_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32GeS)
+  |> expression.push(I32GeS)
 }
 
 pub fn ge_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32GeU)
+  |> expression.push(I32GeU)
 }
 
 pub fn le_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32LeS)
+  |> expression.push(I32LeS)
 }
 
 pub fn le_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32LeU)
+  |> expression.push(I32LeU)
 }
 
 pub fn gt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32GtS)
+  |> expression.push(I32GtS)
 }
 
 pub fn gt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32GtU)
+  |> expression.push(I32GtU)
 }
 
 pub fn lt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32LtS)
+  |> expression.push(I32LtS)
 }
 
 pub fn lt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32LtU)
+  |> expression.push(I32LtU)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Ne)
+  |> expression.push(I32Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Eq)
+  |> expression.push(I32Eq)
 }
 
 pub fn extend16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Extend16S)
+  |> expression.push(I32Extend16S)
 }
 
 pub fn extend8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32Extend8S)
+  |> expression.push(I32Extend8S)
 }
 
 pub fn wrap_i64(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32WrapI64)
+  |> expression.push(I32WrapI64)
 }
 
 pub fn trunc_f64s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncF64S)
+  |> expression.push(I32TruncF64S)
 }
 
 pub fn trunc_f64u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncF64U)
+  |> expression.push(I32TruncF64U)
 }
 
 pub fn trunc_f32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncF32S)
+  |> expression.push(I32TruncF32S)
 }
 
 pub fn trunc_f32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncF32U)
+  |> expression.push(I32TruncF32U)
 }
 
 pub fn trunc_sat_f64s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncSatF64S)
+  |> expression.push(I32TruncSatF64S)
 }
 
 pub fn trunc_sat_f64u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncSatF64U)
+  |> expression.push(I32TruncSatF64U)
 }
 
 pub fn trunc_sat_f32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncSatF32S)
+  |> expression.push(I32TruncSatF32S)
 }
 
 pub fn trunc_sat_f32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32TruncSatF32U)
+  |> expression.push(I32TruncSatF32U)
 }
 
 pub fn reinterpret_f32(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32ReinterpretF32)
+  |> expression.push(I32ReinterpretF32)
 }
 
 pub fn load(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Load(arg))
+  |> expression.push(I32Load(arg))
 }
 
 pub fn store(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Store(arg))
+  |> expression.push(I32Store(arg))
 }
 
 pub fn store8(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Store8(arg))
+  |> expression.push(I32Store8(arg))
 }
 
 pub fn store16(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Store16(arg))
+  |> expression.push(I32Store16(arg))
 }
 
 pub fn load16s(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Load16S(arg))
+  |> expression.push(I32Load16S(arg))
 }
 
 pub fn load16u(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Load16U(arg))
+  |> expression.push(I32Load16U(arg))
 }
 
 pub fn load8s(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Load8S(arg))
+  |> expression.push(I32Load8S(arg))
 }
 
 pub fn load8u(builder: ExpressionBuilder, arg: MemArg) {
   builder
-  |> expression_builder.push(I32Load8U(arg))
+  |> expression.push(I32Load8U(arg))
 }
diff --git a/src/builder/instructions/i32x4.gleam b/src/builder/instructions/i32x4.gleam
index f08c7d9..c326de1 100644
--- a/src/builder/instructions/i32x4.gleam
+++ b/src/builder/instructions/i32x4.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type LaneIDX4, I32x4Abs, I32x4Add, I32x4AllTrue, I32x4Bitmask, I32x4DotI16x8S,
   I32x4Eq, I32x4ExtaddPairwiseI16x8S, I32x4ExtaddPairwiseI16x8U,
@@ -14,210 +14,210 @@ import internal/structure/types.{
 
 pub fn splat(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Splat)
+  |> expression.push(I32x4Splat)
 }
 
 pub fn extract_lane(builder: ExpressionBuilder, lane_idx: LaneIDX4) {
   builder
-  |> expression_builder.push(I32x4ExtractLane(lane_idx))
+  |> expression.push(I32x4ExtractLane(lane_idx))
 }
 
 pub fn replace_lane(builder: ExpressionBuilder, lane_idx: LaneIDX4) {
   builder
-  |> expression_builder.push(I32x4ReplaceLane(lane_idx))
+  |> expression.push(I32x4ReplaceLane(lane_idx))
 }
 
 pub fn ge_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4GeS)
+  |> expression.push(I32x4GeS)
 }
 
 pub fn ge_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4GeU)
+  |> expression.push(I32x4GeU)
 }
 
 pub fn le_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4LeS)
+  |> expression.push(I32x4LeS)
 }
 
 pub fn le_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4LeU)
+  |> expression.push(I32x4LeU)
 }
 
 pub fn gt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4GtS)
+  |> expression.push(I32x4GtS)
 }
 
 pub fn gt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4GtU)
+  |> expression.push(I32x4GtU)
 }
 
 pub fn lt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4LtS)
+  |> expression.push(I32x4LtS)
 }
 
 pub fn lt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4LtU)
+  |> expression.push(I32x4LtU)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Ne)
+  |> expression.push(I32x4Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Eq)
+  |> expression.push(I32x4Eq)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Neg)
+  |> expression.push(I32x4Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Abs)
+  |> expression.push(I32x4Abs)
 }
 
 pub fn dot_i16x8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4DotI16x8S)
+  |> expression.push(I32x4DotI16x8S)
 }
 
 pub fn all_true(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4AllTrue)
+  |> expression.push(I32x4AllTrue)
 }
 
 pub fn bitmask(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Bitmask)
+  |> expression.push(I32x4Bitmask)
 }
 
 pub fn extend_high_i16x8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtendHighI16x8S)
+  |> expression.push(I32x4ExtendHighI16x8S)
 }
 
 pub fn extend_high_i16x8u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtendHighI16x8U)
+  |> expression.push(I32x4ExtendHighI16x8U)
 }
 
 pub fn extend_low_i16x8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtendLowI16x8S)
+  |> expression.push(I32x4ExtendLowI16x8S)
 }
 
 pub fn extend_low_i16x8u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtendLowI16x8U)
+  |> expression.push(I32x4ExtendLowI16x8U)
 }
 
 pub fn shr_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ShrS)
+  |> expression.push(I32x4ShrS)
 }
 
 pub fn shr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ShrU)
+  |> expression.push(I32x4ShrU)
 }
 
 pub fn shl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Shl)
+  |> expression.push(I32x4Shl)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Sub)
+  |> expression.push(I32x4Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Add)
+  |> expression.push(I32x4Add)
 }
 
 pub fn max_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4MaxS)
+  |> expression.push(I32x4MaxS)
 }
 
 pub fn max_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4MaxU)
+  |> expression.push(I32x4MaxU)
 }
 
 pub fn min_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4MinS)
+  |> expression.push(I32x4MinS)
 }
 
 pub fn min_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4MinU)
+  |> expression.push(I32x4MinU)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4Mul)
+  |> expression.push(I32x4Mul)
 }
 
 pub fn extmul_high_i16x8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtmulHighI16x8S)
+  |> expression.push(I32x4ExtmulHighI16x8S)
 }
 
 pub fn extmul_high_i16x8u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtmulHighI16x8U)
+  |> expression.push(I32x4ExtmulHighI16x8U)
 }
 
 pub fn extmul_low_i16x8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtmulLowI16x8S)
+  |> expression.push(I32x4ExtmulLowI16x8S)
 }
 
 pub fn extmul_low_i16x8u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtmulLowI16x8U)
+  |> expression.push(I32x4ExtmulLowI16x8U)
 }
 
 pub fn extadd_pairwise_i16x8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtaddPairwiseI16x8S)
+  |> expression.push(I32x4ExtaddPairwiseI16x8S)
 }
 
 pub fn extadd_pairwise_i16x8u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4ExtaddPairwiseI16x8U)
+  |> expression.push(I32x4ExtaddPairwiseI16x8U)
 }
 
 pub fn trunc_sat_f32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4TruncSatF32x4S)
+  |> expression.push(I32x4TruncSatF32x4S)
 }
 
 pub fn trunc_sat_f32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4TruncSatF32x4U)
+  |> expression.push(I32x4TruncSatF32x4U)
 }
 
 pub fn trunc_sat_f64x2s_zero(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4TruncSatF64x2SZero)
+  |> expression.push(I32x4TruncSatF64x2SZero)
 }
 
 pub fn trunc_sat_f64x2u_zero(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I32x4TruncSatF64x2UZero)
+  |> expression.push(I32x4TruncSatF64x2UZero)
 }
diff --git a/src/builder/instructions/i64.gleam b/src/builder/instructions/i64.gleam
index 6cbaf17..9ab59bd 100644
--- a/src/builder/instructions/i64.gleam
+++ b/src/builder/instructions/i64.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/numbers.{type I64}
 import internal/structure/types.{
   type MemArg, I64Add, I64And, I64Clz, I64Const, I64Ctz, I64DivS, I64DivU, I64Eq,
@@ -13,270 +13,270 @@ import internal/structure/types.{
 
 pub fn const_(builder: ExpressionBuilder, val: I64) {
   builder
-  |> expression_builder.push(I64Const(val))
+  |> expression.push(I64Const(val))
 }
 
 pub fn popcnt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Popcnt)
+  |> expression.push(I64Popcnt)
 }
 
 pub fn ctz(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Ctz)
+  |> expression.push(I64Ctz)
 }
 
 pub fn clz(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Clz)
+  |> expression.push(I64Clz)
 }
 
 pub fn rotr(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Rotr)
+  |> expression.push(I64Rotr)
 }
 
 pub fn rotl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Rotl)
+  |> expression.push(I64Rotl)
 }
 
 pub fn shr_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64ShrS)
+  |> expression.push(I64ShrS)
 }
 
 pub fn shr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64ShrU)
+  |> expression.push(I64ShrU)
 }
 
 pub fn shl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Shl)
+  |> expression.push(I64Shl)
 }
 
 pub fn or(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Or)
+  |> expression.push(I64Or)
 }
 
 pub fn and(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64And)
+  |> expression.push(I64And)
 }
 
 pub fn rem_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64RemS)
+  |> expression.push(I64RemS)
 }
 
 pub fn rem_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64RemU)
+  |> expression.push(I64RemU)
 }
 
 pub fn div_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64DivS)
+  |> expression.push(I64DivS)
 }
 
 pub fn div_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64DivU)
+  |> expression.push(I64DivU)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Mul)
+  |> expression.push(I64Mul)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Sub)
+  |> expression.push(I64Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Add)
+  |> expression.push(I64Add)
 }
 
 pub fn eqz(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Eqz)
+  |> expression.push(I64Eqz)
 }
 
 pub fn ge_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64GeS)
+  |> expression.push(I64GeS)
 }
 
 pub fn ge_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64GeU)
+  |> expression.push(I64GeU)
 }
 
 pub fn le_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64LeS)
+  |> expression.push(I64LeS)
 }
 
 pub fn le_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64LeU)
+  |> expression.push(I64LeU)
 }
 
 pub fn gt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64GtS)
+  |> expression.push(I64GtS)
 }
 
 pub fn gt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64GtU)
+  |> expression.push(I64GtU)
 }
 
 pub fn lt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64LtS)
+  |> expression.push(I64LtS)
 }
 
 pub fn lt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64LtU)
+  |> expression.push(I64LtU)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Ne)
+  |> expression.push(I64Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Eq)
+  |> expression.push(I64Eq)
 }
 
 pub fn extend32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Extend32S)
+  |> expression.push(I64Extend32S)
 }
 
 pub fn extend16s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Extend16S)
+  |> expression.push(I64Extend16S)
 }
 
 pub fn extend8s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64Extend8S)
+  |> expression.push(I64Extend8S)
 }
 
 pub fn extend_i32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64ExtendI32S)
+  |> expression.push(I64ExtendI32S)
 }
 
 pub fn extend_i32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64ExtendI32U)
+  |> expression.push(I64ExtendI32U)
 }
 
 pub fn trunc_f64s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncF64S)
+  |> expression.push(I64TruncF64S)
 }
 
 pub fn trunc_f64u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncF64U)
+  |> expression.push(I64TruncF64U)
 }
 
 pub fn trunc_f32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncF32S)
+  |> expression.push(I64TruncF32S)
 }
 
 pub fn trunc_f32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncF32U)
+  |> expression.push(I64TruncF32U)
 }
 
 pub fn trunc_sat_f64s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncSatF64S)
+  |> expression.push(I64TruncSatF64S)
 }
 
 pub fn trunc_sat_f64u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncSatF64U)
+  |> expression.push(I64TruncSatF64U)
 }
 
 pub fn trunc_sat_f32s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncSatF32S)
+  |> expression.push(I64TruncSatF32S)
 }
 
 pub fn trunc_sat_f32u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64TruncSatF32U)
+  |> expression.push(I64TruncSatF32U)
 }
 
 pub fn reinterpret_f64(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64ReinterpretF64)
+  |> expression.push(I64ReinterpretF64)
 }
 
 pub fn load(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load(mem_arg))
+  |> expression.push(I64Load(mem_arg))
 }
 
 pub fn store(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Store(mem_arg))
+  |> expression.push(I64Store(mem_arg))
 }
 
 pub fn store8(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Store8(mem_arg))
+  |> expression.push(I64Store8(mem_arg))
 }
 
 pub fn store16(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Store16(mem_arg))
+  |> expression.push(I64Store16(mem_arg))
 }
 
 pub fn store32(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Store32(mem_arg))
+  |> expression.push(I64Store32(mem_arg))
 }
 
 pub fn load16s(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load16S(mem_arg))
+  |> expression.push(I64Load16S(mem_arg))
 }
 
 pub fn load16u(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load16U(mem_arg))
+  |> expression.push(I64Load16U(mem_arg))
 }
 
 pub fn load8s(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load8S(mem_arg))
+  |> expression.push(I64Load8S(mem_arg))
 }
 
 pub fn load8u(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load8U(mem_arg))
+  |> expression.push(I64Load8U(mem_arg))
 }
 
 pub fn load32s(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load32S(mem_arg))
+  |> expression.push(I64Load32S(mem_arg))
 }
 
 pub fn load32u(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(I64Load32U(mem_arg))
+  |> expression.push(I64Load32U(mem_arg))
 }
diff --git a/src/builder/instructions/i64x2.gleam b/src/builder/instructions/i64x2.gleam
index 292fbfa..293d67a 100644
--- a/src/builder/instructions/i64x2.gleam
+++ b/src/builder/instructions/i64x2.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type LaneIDX2, I64x2Abs, I64x2Add, I64x2AllTrue, I64x2Bitmask, I64x2Eq,
   I64x2ExtendHighI32x4S, I64x2ExtendHighI32x4U, I64x2ExtendLowI32x4S,
@@ -10,135 +10,135 @@ import internal/structure/types.{
 
 pub fn splat(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Splat)
+  |> expression.push(I64x2Splat)
 }
 
 pub fn extract_lane(builder: ExpressionBuilder, lane_idx: LaneIDX2) {
   builder
-  |> expression_builder.push(I64x2ExtractLane(lane_idx))
+  |> expression.push(I64x2ExtractLane(lane_idx))
 }
 
 pub fn replace_lane(builder: ExpressionBuilder, lane_idx: LaneIDX2) {
   builder
-  |> expression_builder.push(I64x2ReplaceLane(lane_idx))
+  |> expression.push(I64x2ReplaceLane(lane_idx))
 }
 
 pub fn ge_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2GeS)
+  |> expression.push(I64x2GeS)
 }
 
 pub fn le_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2LeS)
+  |> expression.push(I64x2LeS)
 }
 
 pub fn gt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2GtS)
+  |> expression.push(I64x2GtS)
 }
 
 pub fn lt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2LtS)
+  |> expression.push(I64x2LtS)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Ne)
+  |> expression.push(I64x2Ne)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Eq)
+  |> expression.push(I64x2Eq)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Neg)
+  |> expression.push(I64x2Neg)
 }
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Abs)
+  |> expression.push(I64x2Abs)
 }
 
 pub fn all_true(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2AllTrue)
+  |> expression.push(I64x2AllTrue)
 }
 
 pub fn bitmask(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Bitmask)
+  |> expression.push(I64x2Bitmask)
 }
 
 pub fn extend_high_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtendHighI32x4S)
+  |> expression.push(I64x2ExtendHighI32x4S)
 }
 
 pub fn extend_high_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtendHighI32x4U)
+  |> expression.push(I64x2ExtendHighI32x4U)
 }
 
 pub fn extend_low_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtendLowI32x4S)
+  |> expression.push(I64x2ExtendLowI32x4S)
 }
 
 pub fn extend_low_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtendLowI32x4U)
+  |> expression.push(I64x2ExtendLowI32x4U)
 }
 
 pub fn shr_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ShrS)
+  |> expression.push(I64x2ShrS)
 }
 
 pub fn shr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ShrU)
+  |> expression.push(I64x2ShrU)
 }
 
 pub fn shl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Shl)
+  |> expression.push(I64x2Shl)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Sub)
+  |> expression.push(I64x2Sub)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Add)
+  |> expression.push(I64x2Add)
 }
 
 pub fn mul(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2Mul)
+  |> expression.push(I64x2Mul)
 }
 
 pub fn extmul_high_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtmulHighI32x4S)
+  |> expression.push(I64x2ExtmulHighI32x4S)
 }
 
 pub fn extmul_high_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtmulHighI32x4U)
+  |> expression.push(I64x2ExtmulHighI32x4U)
 }
 
 pub fn extmul_low_i32x4s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtmulLowI32x4S)
+  |> expression.push(I64x2ExtmulLowI32x4S)
 }
 
 pub fn extmul_low_i32x4u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I64x2ExtmulLowI32x4U)
+  |> expression.push(I64x2ExtmulLowI32x4U)
 }
diff --git a/src/builder/instructions/i8x16.gleam b/src/builder/instructions/i8x16.gleam
index efd712a..2d3db1b 100644
--- a/src/builder/instructions/i8x16.gleam
+++ b/src/builder/instructions/i8x16.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type LaneIDX16, I8x16Abs, I8x16Add, I8x16AddSatS, I8x16AddSatU, I8x16AllTrue,
   I8x16AvgrU, I8x16Bitmask, I8x16Eq, I8x16ExtractLaneS, I8x16ExtractLaneU,
@@ -11,157 +11,157 @@ import internal/structure/types.{
 
 pub fn abs(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Abs)
+  |> expression.push(I8x16Abs)
 }
 
 pub fn add(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Add)
+  |> expression.push(I8x16Add)
 }
 
 pub fn add_sat_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16AddSatS)
+  |> expression.push(I8x16AddSatS)
 }
 
 pub fn add_sat_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16AddSatU)
+  |> expression.push(I8x16AddSatU)
 }
 
 pub fn all_true(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16AllTrue)
+  |> expression.push(I8x16AllTrue)
 }
 
 pub fn avgr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16AvgrU)
+  |> expression.push(I8x16AvgrU)
 }
 
 pub fn bitmask(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Bitmask)
+  |> expression.push(I8x16Bitmask)
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Eq)
+  |> expression.push(I8x16Eq)
 }
 
 pub fn extract_lane_u(builder: ExpressionBuilder, lane_idx: LaneIDX16) {
   builder
-  |> expression_builder.push(I8x16ExtractLaneU(lane_idx))
+  |> expression.push(I8x16ExtractLaneU(lane_idx))
 }
 
 pub fn extract_lane_s(builder: ExpressionBuilder, lane_idx: LaneIDX16) {
   builder
-  |> expression_builder.push(I8x16ExtractLaneS(lane_idx))
+  |> expression.push(I8x16ExtractLaneS(lane_idx))
 }
 
 pub fn ge_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16GeS)
+  |> expression.push(I8x16GeS)
 }
 
 pub fn ge_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16GeU)
+  |> expression.push(I8x16GeU)
 }
 
 pub fn gt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16GtS)
+  |> expression.push(I8x16GtS)
 }
 
 pub fn gt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16GtU)
+  |> expression.push(I8x16GtU)
 }
 
 pub fn le_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16LeS)
+  |> expression.push(I8x16LeS)
 }
 
 pub fn le_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16LeU)
+  |> expression.push(I8x16LeU)
 }
 
 pub fn lt_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16LtS)
+  |> expression.push(I8x16LtS)
 }
 
 pub fn lt_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16LtU)
+  |> expression.push(I8x16LtU)
 }
 
 pub fn max_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16MaxS)
+  |> expression.push(I8x16MaxS)
 }
 
 pub fn max_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16MaxU)
+  |> expression.push(I8x16MaxU)
 }
 
 pub fn min_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16MinS)
+  |> expression.push(I8x16MinS)
 }
 
 pub fn min_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16MinU)
+  |> expression.push(I8x16MinU)
 }
 
 pub fn narrow_i16x8_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16NarrowI16x8S)
+  |> expression.push(I8x16NarrowI16x8S)
 }
 
 pub fn narrow_i16x8_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16NarrowI16x8U)
+  |> expression.push(I8x16NarrowI16x8U)
 }
 
 pub fn ne(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Ne)
+  |> expression.push(I8x16Ne)
 }
 
 pub fn neg(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Neg)
+  |> expression.push(I8x16Neg)
 }
 
 pub fn popcnt(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Popcnt)
+  |> expression.push(I8x16Popcnt)
 }
 
 pub fn replace_lane(builder: ExpressionBuilder, lane_idx: LaneIDX16) {
   builder
-  |> expression_builder.push(I8x16ReplaceLane(lane_idx))
+  |> expression.push(I8x16ReplaceLane(lane_idx))
 }
 
 pub fn shl(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Shl)
+  |> expression.push(I8x16Shl)
 }
 
 pub fn shr_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16ShrS)
+  |> expression.push(I8x16ShrS)
 }
 
 pub fn shr_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16ShrU)
+  |> expression.push(I8x16ShrU)
 }
 
 pub fn shuffle(
@@ -184,7 +184,7 @@ pub fn shuffle(
   l15: LaneIDX16,
 ) {
   builder
-  |> expression_builder.push(I8x16Shuffle(
+  |> expression.push(I8x16Shuffle(
     l0,
     l1,
     l2,
@@ -206,25 +206,25 @@ pub fn shuffle(
 
 pub fn splat(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Splat)
+  |> expression.push(I8x16Splat)
 }
 
 pub fn sub(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Sub)
+  |> expression.push(I8x16Sub)
 }
 
 pub fn sub_sat_s(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16SubSatS)
+  |> expression.push(I8x16SubSatS)
 }
 
 pub fn sub_sat_u(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16SubSatU)
+  |> expression.push(I8x16SubSatU)
 }
 
 pub fn swizzle(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(I8x16Swizzle)
+  |> expression.push(I8x16Swizzle)
 }
diff --git a/src/builder/instructions/local.gleam b/src/builder/instructions/local.gleam
index 44da4bd..58af511 100644
--- a/src/builder/instructions/local.gleam
+++ b/src/builder/instructions/local.gleam
@@ -1,17 +1,17 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{type LocalIDX, LocalGet, LocalSet, LocalTee}
 
 pub fn get(builder: ExpressionBuilder, local_idx: LocalIDX) {
   builder
-  |> expression_builder.push(LocalGet(local_idx))
+  |> expression.push(LocalGet(local_idx))
 }
 
 pub fn set(builder: ExpressionBuilder, local_idx: LocalIDX) {
   builder
-  |> expression_builder.push(LocalSet(local_idx))
+  |> expression.push(LocalSet(local_idx))
 }
 
 pub fn tee(builder: ExpressionBuilder, local_idx: LocalIDX) {
   builder
-  |> expression_builder.push(LocalTee(local_idx))
+  |> expression.push(LocalTee(local_idx))
 }
diff --git a/src/builder/instructions/memory.gleam b/src/builder/instructions/memory.gleam
index a001052..b13e15b 100644
--- a/src/builder/instructions/memory.gleam
+++ b/src/builder/instructions/memory.gleam
@@ -1,29 +1,29 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type DataIDX, MemoryCopy, MemoryFill, MemoryGrow, MemoryInit, MemorySize,
 }
 
 pub fn copy(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(MemoryCopy)
+  |> expression.push(MemoryCopy)
 }
 
 pub fn fill(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(MemoryFill)
+  |> expression.push(MemoryFill)
 }
 
 pub fn grow(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(MemoryGrow)
+  |> expression.push(MemoryGrow)
 }
 
 pub fn init(builder: ExpressionBuilder, data_idx: DataIDX) {
   builder
-  |> expression_builder.push(MemoryInit(data_idx))
+  |> expression.push(MemoryInit(data_idx))
 }
 
 pub fn size(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(MemorySize)
+  |> expression.push(MemorySize)
 }
diff --git a/src/builder/instructions/ref.gleam b/src/builder/instructions/ref.gleam
index fd736fc..8129589 100644
--- a/src/builder/instructions/ref.gleam
+++ b/src/builder/instructions/ref.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type FuncIDX, type HeapType, RefAsNonNull, RefCast, RefCastNullable, RefEq,
   RefFunc, RefI31, RefIsNull, RefNull, RefTest, RefTestNullable,
@@ -6,50 +6,50 @@ import internal/structure/types.{
 
 pub fn as_non_null(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(RefAsNonNull)
+  |> expression.push(RefAsNonNull)
 }
 
 pub fn cast(builder: ExpressionBuilder, heap_type: HeapType) {
   builder
-  |> expression_builder.push(RefCast(heap_type))
+  |> expression.push(RefCast(heap_type))
 }
 
 pub fn cast_nullable(builder: ExpressionBuilder, heap_type: HeapType) {
   builder
-  |> expression_builder.push(RefCastNullable(heap_type))
+  |> expression.push(RefCastNullable(heap_type))
 }
 
 pub fn eq(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(RefEq)
+  |> expression.push(RefEq)
 }
 
 pub fn func(builder: ExpressionBuilder, idx: FuncIDX) {
   builder
-  |> expression_builder.push(RefFunc(idx))
+  |> expression.push(RefFunc(idx))
 }
 
 pub fn i31(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(RefI31)
+  |> expression.push(RefI31)
 }
 
 pub fn is_null(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(RefIsNull)
+  |> expression.push(RefIsNull)
 }
 
 pub fn null(builder: ExpressionBuilder, ht: HeapType) {
   builder
-  |> expression_builder.push(RefNull(ht))
+  |> expression.push(RefNull(ht))
 }
 
 pub fn test_(builder: ExpressionBuilder, heap_type: HeapType) {
   builder
-  |> expression_builder.push(RefTest(heap_type))
+  |> expression.push(RefTest(heap_type))
 }
 
 pub fn test_nullable(builder: ExpressionBuilder, heap_type: HeapType) {
   builder
-  |> expression_builder.push(RefTestNullable(heap_type))
+  |> expression.push(RefTestNullable(heap_type))
 }
diff --git a/src/builder/instructions/struct.gleam b/src/builder/instructions/struct.gleam
index f58262c..88b8b52 100644
--- a/src/builder/instructions/struct.gleam
+++ b/src/builder/instructions/struct.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type FieldIDX, type TypeIDX, StructGet, StructGetS, StructGetU, StructNew,
   StructNewDefault, StructSet,
@@ -6,30 +6,30 @@ import internal/structure/types.{
 
 pub fn new(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(StructNew(idx))
+  |> expression.push(StructNew(idx))
 }
 
 pub fn new_default(builder: ExpressionBuilder, idx: TypeIDX) {
   builder
-  |> expression_builder.push(StructNewDefault(idx))
+  |> expression.push(StructNewDefault(idx))
 }
 
 pub fn get(builder: ExpressionBuilder, tidx: TypeIDX, fidx: FieldIDX) {
   builder
-  |> expression_builder.push(StructGet(tidx, fidx))
+  |> expression.push(StructGet(tidx, fidx))
 }
 
 pub fn get_s(builder: ExpressionBuilder, tidx: TypeIDX, fidx: FieldIDX) {
   builder
-  |> expression_builder.push(StructGetS(tidx, fidx))
+  |> expression.push(StructGetS(tidx, fidx))
 }
 
 pub fn get_u(builder: ExpressionBuilder, tidx: TypeIDX, fidx: FieldIDX) {
   builder
-  |> expression_builder.push(StructGetU(tidx, fidx))
+  |> expression.push(StructGetU(tidx, fidx))
 }
 
 pub fn set(builder: ExpressionBuilder, tidx: TypeIDX, fidx: FieldIDX) {
   builder
-  |> expression_builder.push(StructSet(tidx, fidx))
+  |> expression.push(StructSet(tidx, fidx))
 }
diff --git a/src/builder/instructions/table.gleam b/src/builder/instructions/table.gleam
index 8964e6c..fea189b 100644
--- a/src/builder/instructions/table.gleam
+++ b/src/builder/instructions/table.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/types.{
   type ElemIDX, type TableIDX, TableCopy, TableFill, TableGet, TableGrow,
   TableInit, TableSet, TableSize,
@@ -6,35 +6,35 @@ import internal/structure/types.{
 
 pub fn get(builder: ExpressionBuilder, tidx: TableIDX) {
   builder
-  |> expression_builder.push(TableGet(tidx))
+  |> expression.push(TableGet(tidx))
 }
 
 pub fn set(builder: ExpressionBuilder, tidx: TableIDX) {
   builder
-  |> expression_builder.push(TableSet(tidx))
+  |> expression.push(TableSet(tidx))
 }
 
 pub fn size(builder: ExpressionBuilder, tidx: TableIDX) {
   builder
-  |> expression_builder.push(TableSize(tidx))
+  |> expression.push(TableSize(tidx))
 }
 
 pub fn grow(builder: ExpressionBuilder, tidx: TableIDX) {
   builder
-  |> expression_builder.push(TableGrow(tidx))
+  |> expression.push(TableGrow(tidx))
 }
 
 pub fn fill(builder: ExpressionBuilder, tidx: TableIDX) {
   builder
-  |> expression_builder.push(TableFill(tidx))
+  |> expression.push(TableFill(tidx))
 }
 
 pub fn copy(builder: ExpressionBuilder, tidx1: TableIDX, tidx2: TableIDX) {
   builder
-  |> expression_builder.push(TableCopy(tidx1, tidx2))
+  |> expression.push(TableCopy(tidx1, tidx2))
 }
 
 pub fn init(builder: ExpressionBuilder, elem: ElemIDX, tidx: TableIDX) {
   builder
-  |> expression_builder.push(TableInit(elem, tidx))
+  |> expression.push(TableInit(elem, tidx))
 }
diff --git a/src/builder/instructions/v128.gleam b/src/builder/instructions/v128.gleam
index 72cf02b..a4a45cb 100644
--- a/src/builder/instructions/v128.gleam
+++ b/src/builder/instructions/v128.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder.{type ExpressionBuilder}
+import builder/expression.{type ExpressionBuilder}
 import internal/structure/numbers.{type V128Value}
 import internal/structure/types.{
   type LaneIDX16, type LaneIDX2, type LaneIDX4, type LaneIDX8, type MemArg,
@@ -12,112 +12,112 @@ import internal/structure/types.{
 
 pub fn and_not(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128AndNot)
+  |> expression.push(V128AndNot)
 }
 
 pub fn const_(builder: ExpressionBuilder, value: V128Value) {
   builder
-  |> expression_builder.push(V128Const(value))
+  |> expression.push(V128Const(value))
 }
 
 pub fn not(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128Not)
+  |> expression.push(V128Not)
 }
 
 pub fn xor(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128Xor)
+  |> expression.push(V128Xor)
 }
 
 pub fn or(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128Or)
+  |> expression.push(V128Or)
 }
 
 pub fn and(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128And)
+  |> expression.push(V128And)
 }
 
 pub fn bitselect(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128Bitselect)
+  |> expression.push(V128Bitselect)
 }
 
 pub fn any_true(builder: ExpressionBuilder) {
   builder
-  |> expression_builder.push(V128AnyTrue)
+  |> expression.push(V128AnyTrue)
 }
 
 pub fn load(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load(mem_arg))
+  |> expression.push(V128Load(mem_arg))
 }
 
 pub fn store(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Store(mem_arg))
+  |> expression.push(V128Store(mem_arg))
 }
 
 pub fn load8x8s(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load8x8S(mem_arg))
+  |> expression.push(V128Load8x8S(mem_arg))
 }
 
 pub fn load8x8u(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load8x8U(mem_arg))
+  |> expression.push(V128Load8x8U(mem_arg))
 }
 
 pub fn load16x4s(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load16x4S(mem_arg))
+  |> expression.push(V128Load16x4S(mem_arg))
 }
 
 pub fn load16x4u(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load16x4U(mem_arg))
+  |> expression.push(V128Load16x4U(mem_arg))
 }
 
 pub fn load32x2s(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load32x2S(mem_arg))
+  |> expression.push(V128Load32x2S(mem_arg))
 }
 
 pub fn load32x2u(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load32x2U(mem_arg))
+  |> expression.push(V128Load32x2U(mem_arg))
 }
 
 pub fn load32_zero(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load32Zero(mem_arg))
+  |> expression.push(V128Load32Zero(mem_arg))
 }
 
 pub fn load64_zero(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load64Zero(mem_arg))
+  |> expression.push(V128Load64Zero(mem_arg))
 }
 
 pub fn load64_splat(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load64Splat(mem_arg))
+  |> expression.push(V128Load64Splat(mem_arg))
 }
 
 pub fn load32_splat(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load32Splat(mem_arg))
+  |> expression.push(V128Load32Splat(mem_arg))
 }
 
 pub fn load16_splat(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load16Splat(mem_arg))
+  |> expression.push(V128Load16Splat(mem_arg))
 }
 
 pub fn load8_splat(builder: ExpressionBuilder, mem_arg: MemArg) {
   builder
-  |> expression_builder.push(V128Load8Splat(mem_arg))
+  |> expression.push(V128Load8Splat(mem_arg))
 }
 
 pub fn load8_lane(
@@ -126,7 +126,7 @@ pub fn load8_lane(
   lane_idx: LaneIDX16,
 ) {
   builder
-  |> expression_builder.push(V128Load8Lane(mem_arg, lane_idx))
+  |> expression.push(V128Load8Lane(mem_arg, lane_idx))
 }
 
 pub fn load16_lane(
@@ -135,7 +135,7 @@ pub fn load16_lane(
   lane_idx: LaneIDX8,
 ) {
   builder
-  |> expression_builder.push(V128Load16Lane(mem_arg, lane_idx))
+  |> expression.push(V128Load16Lane(mem_arg, lane_idx))
 }
 
 pub fn load32_lane(
@@ -144,7 +144,7 @@ pub fn load32_lane(
   lane_idx: LaneIDX4,
 ) {
   builder
-  |> expression_builder.push(V128Load32Lane(mem_arg, lane_idx))
+  |> expression.push(V128Load32Lane(mem_arg, lane_idx))
 }
 
 pub fn load64_lane(
@@ -153,7 +153,7 @@ pub fn load64_lane(
   lane_idx: LaneIDX2,
 ) {
   builder
-  |> expression_builder.push(V128Load64Lane(mem_arg, lane_idx))
+  |> expression.push(V128Load64Lane(mem_arg, lane_idx))
 }
 
 pub fn store8_lane(
@@ -162,7 +162,7 @@ pub fn store8_lane(
   lane_idx: LaneIDX16,
 ) {
   builder
-  |> expression_builder.push(V128Store8Lane(mem_arg, lane_idx))
+  |> expression.push(V128Store8Lane(mem_arg, lane_idx))
 }
 
 pub fn store16_lane(
@@ -171,7 +171,7 @@ pub fn store16_lane(
   lane_idx: LaneIDX8,
 ) {
   builder
-  |> expression_builder.push(V128Store16Lane(mem_arg, lane_idx))
+  |> expression.push(V128Store16Lane(mem_arg, lane_idx))
 }
 
 pub fn store32_lane(
@@ -180,7 +180,7 @@ pub fn store32_lane(
   lane_idx: LaneIDX4,
 ) {
   builder
-  |> expression_builder.push(V128Store32Lane(mem_arg, lane_idx))
+  |> expression.push(V128Store32Lane(mem_arg, lane_idx))
 }
 
 pub fn store64_lane(
@@ -189,5 +189,5 @@ pub fn store64_lane(
   lane_idx: LaneIDX2,
 ) {
   builder
-  |> expression_builder.push(V128Store64Lane(mem_arg, lane_idx))
+  |> expression.push(V128Store64Lane(mem_arg, lane_idx))
 }
diff --git a/src/builder/module.gleam b/src/builder/module.gleam
index 86a517b..aec40ff 100644
--- a/src/builder/module.gleam
+++ b/src/builder/module.gleam
@@ -1,22 +1,28 @@
-import gleam/dict
 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,
-  type TableSection, type TypeSection, BinaryModule, CustomSection,
-  ExportSection, FunctionSection, GlobalSection, ImportSection, MemorySection,
-  TableSection, TypeSection,
-}
+  type TableSection, type TypeSection, BinaryModule, CodeSection, CustomSection,
+  DataCountSection, DataSection, ElementSection, ExportSection, FunctionSection,
+  GlobalSection, ImportSection, MemorySection, StartSection, TableSection,
+  TypeSection,
+} as structure_modules
+import internal/structure/numbers.{type U32, u32}
 import internal/structure/types.{
-  type Export, type FuncIDX, type Global, type GlobalIDX, type Import,
-  type MemIDX, type MemType, type RecType, type Table, type TableIDX,
-  type TypeIDX, FuncExport, FuncIDX, GlobalExport, MemExport, TableExport,
-  TypeIDX,
+  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,
 }
 
-pub const new = modules.binary_module_new
+pub const new = structure_modules.binary_module_new
 
 pub fn custom_section(module: BinaryModule, name: String, data: BitArray) {
   case module {
@@ -461,18 +467,158 @@ pub fn add_type(module: BinaryModule, type_: RecType) {
   }
 }
 
-pub fn add_import(module: BinaryModule, import_: Import) {
+/// 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
+/// method panics.
+pub fn import_func(
+  module: BinaryModule,
+  module_name: String,
+  name: String,
+  type_: TypeIDX,
+) {
+  let BinaryModule(imports: imports, ..) = module
+  case imports, type_ {
+    None, TypeIDX(_) ->
+      BinaryModule(
+        ..module,
+        imports: Some(
+          ImportSection(
+            finger_tree.single(FuncImport(module_name, name, type_)),
+          ),
+        ),
+      )
+
+    Some(ImportSection(imports)), TypeIDX(_) ->
+      BinaryModule(
+        ..module,
+        imports: Some(
+          ImportSection(finger_tree.push(
+            imports,
+            FuncImport(module_name, name, type_),
+          )),
+        ),
+      )
+
+    _, _ -> panic as "Invalid type index. Type Index must be absolute."
+  }
+}
+
+/// Import a global from the host. The module_name and name are used to identify the
+/// import as the host specifies it. The type of the global is defined by a ValType and
+/// whether it is mutable or not.
+pub fn import_global(
+  module: BinaryModule,
+  module_name: String,
+  name: String,
+  vt: ValType,
+  mut: Bool,
+) {
+  let BinaryModule(imports: imports, ..) = module
+  let mut = case mut {
+    True -> Var
+    False -> Const
+  }
+  case imports {
+    None ->
+      BinaryModule(
+        ..module,
+        imports: Some(
+          ImportSection(
+            finger_tree.single(GlobalImport(
+              module_name,
+              name,
+              GlobalType(vt, mut),
+            )),
+          ),
+        ),
+      )
+    Some(ImportSection(imports)) ->
+      BinaryModule(
+        ..module,
+        imports: Some(
+          ImportSection(finger_tree.push(
+            imports,
+            GlobalImport(module_name, name, GlobalType(vt, mut)),
+          )),
+        ),
+      )
+  }
+}
+
+/// Import a table from the host. The module_name and name are used to identify the
+/// import as the host specifies it. The type of the table is defined by a TableType
+/// which specifies a refrence type and the size limits of the table.
+pub fn import_table(
+  module: BinaryModule,
+  module_name: String,
+  name: String,
+  ref_type: RefType,
+  limits: Limits,
+) {
   let BinaryModule(imports: imports, ..) = module
   case imports {
     None ->
       BinaryModule(
         ..module,
-        imports: Some(ImportSection(finger_tree.single(import_))),
+        imports: Some(
+          ImportSection(
+            finger_tree.single(TableImport(
+              module_name,
+              name,
+              TableType(ref_type, limits),
+            )),
+          ),
+        ),
       )
     Some(ImportSection(imports)) ->
       BinaryModule(
         ..module,
-        imports: Some(ImportSection(finger_tree.push(imports, import_))),
+        imports: Some(
+          ImportSection(finger_tree.push(
+            imports,
+            TableImport(module_name, name, TableType(ref_type, limits)),
+          )),
+        ),
+      )
+  }
+}
+
+/// 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,
+  module_name: String,
+  name: String,
+  min: U32,
+  max: Option(U32),
+) {
+  let BinaryModule(imports: imports, ..) = module
+  case imports {
+    None ->
+      BinaryModule(
+        ..module,
+        imports: Some(
+          ImportSection(
+            finger_tree.single(MemImport(
+              module_name,
+              name,
+              MemType(Limits(min, max)),
+            )),
+          ),
+        ),
+      )
+    Some(ImportSection(imports)) ->
+      BinaryModule(
+        ..module,
+        imports: Some(
+          ImportSection(finger_tree.push(
+            imports,
+            MemImport(module_name, name, MemType(Limits(min, max))),
+          )),
+        ),
       )
   }
 }
@@ -652,3 +798,397 @@ pub fn export_global(module: BinaryModule, name: String, global: GlobalIDX) {
     }
   }
 }
+
+pub fn set_start(module: BinaryModule, func: FuncIDX) {
+  BinaryModule(..module, start: Some(StartSection(func)))
+}
+
+pub fn active_funcs_element_segment(
+  module: BinaryModule,
+  offset: Expr,
+  table_index: TableIDX,
+  funcs: List(FuncIDX),
+) {
+  let BinaryModule(elements: elements, ..) = module
+  case elements {
+    None ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(
+            finger_tree.single(ElemFuncs(
+              HeapTypeRefType(FuncHeapType, False),
+              finger_tree.from_list(funcs),
+              ActiveElemMode(table_index, offset),
+            )),
+          ),
+        ),
+      )
+    Some(ElementSection(elements)) ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(finger_tree.push(
+            elements,
+            ElemFuncs(
+              HeapTypeRefType(FuncHeapType, False),
+              finger_tree.from_list(funcs),
+              ActiveElemMode(table_index, offset),
+            ),
+          )),
+        ),
+      )
+  }
+}
+
+pub fn passive_funcs_element_segment(module: BinaryModule, funcs: List(FuncIDX)) {
+  let BinaryModule(elements: elements, ..) = module
+  case elements {
+    None ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(
+            finger_tree.single(ElemFuncs(
+              HeapTypeRefType(FuncHeapType, False),
+              finger_tree.from_list(funcs),
+              PassiveElemMode,
+            )),
+          ),
+        ),
+      )
+    Some(ElementSection(elements)) ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(finger_tree.push(
+            elements,
+            ElemFuncs(
+              HeapTypeRefType(FuncHeapType, False),
+              finger_tree.from_list(funcs),
+              PassiveElemMode,
+            ),
+          )),
+        ),
+      )
+  }
+}
+
+pub fn declarative_funcs_element_segment(
+  module: BinaryModule,
+  funcs: List(FuncIDX),
+) {
+  let BinaryModule(elements: elements, ..) = module
+  case elements {
+    None ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(
+            finger_tree.single(ElemFuncs(
+              HeapTypeRefType(FuncHeapType, False),
+              finger_tree.from_list(funcs),
+              DeclarativeElemMode,
+            )),
+          ),
+        ),
+      )
+    Some(ElementSection(elements)) ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(finger_tree.push(
+            elements,
+            ElemFuncs(
+              HeapTypeRefType(FuncHeapType, False),
+              finger_tree.from_list(funcs),
+              DeclarativeElemMode,
+            ),
+          )),
+        ),
+      )
+  }
+}
+
+pub fn active_element_segment(
+  module: BinaryModule,
+  ref_type: RefType,
+  offset: Expr,
+  table_index: TableIDX,
+  exprs: List(Expr),
+) {
+  let BinaryModule(elements: elements, ..) = module
+  case elements {
+    None -> {
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(
+            finger_tree.single(ElemExpressions(
+              ref_type,
+              finger_tree.from_list(exprs),
+              ActiveElemMode(table_index, offset),
+            )),
+          ),
+        ),
+      )
+    }
+    Some(ElementSection(elements)) ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(finger_tree.push(
+            elements,
+            ElemExpressions(
+              ref_type,
+              finger_tree.from_list(exprs),
+              ActiveElemMode(table_index, offset),
+            ),
+          )),
+        ),
+      )
+  }
+}
+
+pub fn passive_element_segment(
+  module: BinaryModule,
+  ref_type: RefType,
+  exprs: List(Expr),
+) {
+  let BinaryModule(elements: elements, ..) = module
+  case elements {
+    None -> {
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(
+            finger_tree.single(ElemExpressions(
+              ref_type,
+              finger_tree.from_list(exprs),
+              PassiveElemMode,
+            )),
+          ),
+        ),
+      )
+    }
+    Some(ElementSection(elements)) ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(finger_tree.push(
+            elements,
+            ElemExpressions(
+              ref_type,
+              finger_tree.from_list(exprs),
+              PassiveElemMode,
+            ),
+          )),
+        ),
+      )
+  }
+}
+
+pub fn declarative_element_segment(
+  module: BinaryModule,
+  ref_type: RefType,
+  exprs: List(Expr),
+) {
+  let BinaryModule(elements: elements, ..) = module
+  case elements {
+    None -> {
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(
+            finger_tree.single(ElemExpressions(
+              ref_type,
+              finger_tree.from_list(exprs),
+              DeclarativeElemMode,
+            )),
+          ),
+        ),
+      )
+    }
+    Some(ElementSection(elements)) ->
+      BinaryModule(
+        ..module,
+        elements: Some(
+          ElementSection(finger_tree.push(
+            elements,
+            ElemExpressions(
+              ref_type,
+              finger_tree.from_list(exprs),
+              DeclarativeElemMode,
+            ),
+          )),
+        ),
+      )
+  }
+}
+
+fn concatenate_locals(locals: List(ValType)) {
+  case locals {
+    [] -> finger_tree.new()
+    [a, ..rest] -> do_concatenate_locals(rest, finger_tree.new(), #(1, a))
+  }
+}
+
+fn do_concatenate_locals(
+  locals: List(ValType),
+  acc: FingerTree(Locals),
+  current: #(Int, ValType),
+) {
+  case locals, current {
+    [val_type, ..rest], #(count, current_type) if val_type == current_type ->
+      do_concatenate_locals(rest, acc, #(count + 1, val_type))
+    [val_type, ..rest], #(count, current_type) -> {
+      let assert Ok(count) = u32(count)
+
+      let locals = Locals(count, current_type)
+      do_concatenate_locals(rest, finger_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)
+    }
+  }
+}
+
+/// Add a code function to the code section.
+pub fn add_code(module: BinaryModule, locals: List(ValType), body: Expr) {
+  let BinaryModule(code: code, ..) = module
+
+  let locals = concatenate_locals(locals)
+
+  case code {
+    None ->
+      BinaryModule(
+        ..module,
+        code: Some(CodeSection(finger_tree.single(Code(locals, body)))),
+      )
+    Some(CodeSection(code)) ->
+      BinaryModule(
+        ..module,
+        code: Some(CodeSection(finger_tree.push(code, Code(locals, body)))),
+      )
+  }
+}
+
+pub fn add_active_data(
+  module: BinaryModule,
+  mem_idx: MemIDX,
+  offset: Expr,
+  data: BitArray,
+) {
+  let BinaryModule(data: data_section, ..) = module
+  case data_section {
+    None ->
+      BinaryModule(
+        ..module,
+        data: Some(
+          DataSection(finger_tree.single(ActiveData(mem_idx, offset, data))),
+        ),
+      )
+    Some(DataSection(data_section)) ->
+      BinaryModule(
+        ..module,
+        data: Some(
+          DataSection(finger_tree.push(
+            data_section,
+            ActiveData(mem_idx, offset, 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(finger_tree.single(PassiveData(data)))),
+      )
+    Some(DataSection(data_section)) ->
+      BinaryModule(
+        ..module,
+        data: Some(
+          DataSection(finger_tree.push(data_section, PassiveData(data))),
+        ),
+      )
+  }
+}
+
+pub fn set_data_count(module: BinaryModule, count: U32) {
+  BinaryModule(..module, data_count: Some(DataCountSection(count)))
+}
+
+pub fn type_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(TypeIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn local_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(LocalIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn global_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(GlobalIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn table_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(TableIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn mem_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(MemIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn elem_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(ElemIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn data_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(DataIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn label_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(LabelIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn func_idx(idx: Int) {
+  case u32(idx) {
+    Ok(idx) -> Ok(FuncIDX(idx))
+    Error(msg) -> Error(msg)
+  }
+}
+
+pub fn encode(module: BinaryModule) {
+  modules.encode_module(module)
+}
diff --git a/src/builder/types/rec_type.gleam b/src/builder/types/rec_type.gleam
index e4cd2b8..43e8c2a 100644
--- a/src/builder/types/rec_type.gleam
+++ b/src/builder/types/rec_type.gleam
@@ -1,6 +1,8 @@
 import internal/finger_tree
 import internal/structure/types.{
-  type SubType, type ValType, FuncCompositeType, FuncType, RecType, SubType,
+  type FieldType, type StructType, type SubType, type ValType,
+  ArrayCompositeType, ArrayType, FuncCompositeType, FuncType, RecType,
+  StructCompositeType, StructType, SubType,
 }
 
 pub fn from_sub_types(sub_types: List(SubType)) {
@@ -21,3 +23,23 @@ 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)),
+    ]),
+  )
+}
+
+pub fn array_type(element_type: FieldType) {
+  RecType(
+    finger_tree.from_list([
+      SubType(
+        True,
+        finger_tree.new(),
+        ArrayCompositeType(ArrayType(element_type)),
+      ),
+    ]),
+  )
+}
diff --git a/src/internal/finger_tree.gleam b/src/internal/finger_tree.gleam
index 7335804..e5d27ae 100644
--- a/src/internal/finger_tree.gleam
+++ b/src/internal/finger_tree.gleam
@@ -125,9 +125,66 @@ pub fn from_list(l: List(e)) {
 }
 
 fn do_from_list(l: List(e), tree: FingerTree(e)) {
-  case l {
-    [] -> tree
-    [x, ..xs] -> do_from_list(xs, tree |> push(x))
+  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?"
   }
 }
 
diff --git a/src/shinecoder.gleam b/src/shinecoder.gleam
index 34ad648..822fde4 100644
--- a/src/shinecoder.gleam
+++ b/src/shinecoder.gleam
@@ -1,5 +1,33 @@
-import gleam/io
+import builder/expression
+import builder/instructions/i32
+import builder/instructions/local
+import builder/module
+import builder/types/rec_type
+import builder/types/val_type
+import simplifile
 
 pub fn main() {
-  io.println("Thank you for using shinecoder! You rock!")
+  let assert Ok(type_idx_0) = module.type_idx(0)
+  let assert Ok(local_idx_0) = module.local_idx(0)
+  let assert Ok(local_idx_1) = module.local_idx(1)
+  let assert Ok(func_idx_0) = module.func_idx(0)
+
+  let assert Ok(add_module) =
+    module.new()
+    |> module.add_type(
+      rec_type.func_type([val_type.i32, val_type.i32], [val_type.i32]),
+    )
+    |> module.add_function_type(type_idx_0)
+    |> module.add_code(
+      [val_type.i32, val_type.i32],
+      expression.new()
+        |> local.get(local_idx_0)
+        |> local.get(local_idx_1)
+        |> i32.add
+        |> expression.end_unwrap(),
+    )
+    |> module.export_func("add", func_idx_0)
+    |> module.encode
+
+  let assert Ok(Nil) = simplifile.write_bits("shinecoder.wasm", add_module)
 }
diff --git a/test/decode_test.gleam b/test/decode_test.gleam
index 6ce1346..3e651d3 100644
--- a/test/decode_test.gleam
+++ b/test/decode_test.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder
+import builder/expression
 import builder/instructions/i32
 import builder/instructions/ref
 import gleam/bit_array
@@ -957,9 +957,9 @@ pub fn decode_table_section_test() {
   )
 
   let expr_three =
-    expression_builder.new()
+    expression.new()
     |> ref.null(structure_types.ArrayHeapType)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
   let table_limits_three = structure_types.Limits(zero, None)
   let table_init_three =
     structure_types.Table(
@@ -1110,9 +1110,9 @@ pub fn decode_global_section_test() {
   let example_global =
     structure_types.Global(
       gt,
-      expression_builder.new()
+      expression.new()
         |> i32.const_(fourty_two)
-        |> expression_builder.end_unwrap(),
+        |> expression.end_unwrap(),
     )
 
   <<0x06, 0x07, 0x01, 0x7F, 0x01, 0x41, 0xC2, 0x00, 0x0B>>
@@ -1354,9 +1354,9 @@ pub fn decode_element_section_test() {
   let assert Ok(fourty_two) = numbers.i32(42)
   let assert Ok(fourty_two_unsigned) = numbers.u32(42)
   let offset_fourty_two =
-    expression_builder.new()
+    expression.new()
     |> i32.const_(fourty_two)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let table_idx_zero = structure_types.TableIDX(zero)
   let table_idx_fourty_two = structure_types.TableIDX(fourty_two_unsigned)
@@ -1367,9 +1367,9 @@ pub fn decode_element_section_test() {
 
   let ref_null_i31 = structure_types.I31RefType
   let null_i31 =
-    expression_builder.new()
+    expression.new()
     |> ref.null(structure_types.I31HeapType)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let three_null_i31 = finger_tree.from_list([null_i31, null_i31, null_i31])
 
@@ -1706,11 +1706,11 @@ pub fn code_section_test() {
       finger_tree.from_list([
         structure_types.Code(
           add_locals,
-          expression_builder.new()
+          expression.new()
             |> i32.const_(forty_one)
             |> i32.const_(one)
             |> i32.add()
-            |> expression_builder.end_unwrap(),
+            |> expression.end_unwrap(),
         ),
       ]),
     )
@@ -1795,14 +1795,14 @@ pub fn data_section_test() {
   let mem_idx_zero = structure_types.MemIDX(mem_idx_zero)
   let mem_idx_one = structure_types.MemIDX(mem_idx_one)
   let offset_zero_expr =
-    expression_builder.new()
+    expression.new()
     |> i32.const_(offset_zero)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let offset_ten_expr =
-    expression_builder.new()
+    expression.new()
     |> i32.const_(offset_ten)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let active_data_zero_idx =
     structure_types.ActiveData(mem_idx_zero, offset_zero_expr, <<
diff --git a/test/encode_test.gleam b/test/encode_test.gleam
index 355a3fc..c003f6e 100644
--- a/test/encode_test.gleam
+++ b/test/encode_test.gleam
@@ -1,4 +1,4 @@
-import builder/expression_builder
+import builder/expression
 import builder/instructions/i32
 import builder/instructions/ref
 import gleam/bit_array
@@ -578,10 +578,10 @@ pub fn table_section_test() {
   >>)
 
   let expr =
-    expression_builder.new()
+    expression.new()
     |> ref.null(structure_types.ArrayHeapType)
     // 
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let example_table_init =
     structure_types.Table(
@@ -643,9 +643,9 @@ pub fn global_section_test() {
   let example_global =
     structure_types.Global(
       gt,
-      expression_builder.new()
+      expression.new()
         |> i32.const_(fourty_two)
-        |> expression_builder.end_unwrap(),
+        |> expression.end_unwrap(),
     )
 
   let global_section =
@@ -743,9 +743,9 @@ pub fn element_section_test() {
   let assert Ok(fourty_two) = numbers.i32(42)
   let assert Ok(fourty_two_unsigned) = numbers.u32(42)
   let offset_fourty_two =
-    expression_builder.new()
+    expression.new()
     |> i32.const_(fourty_two)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let table_idx_zero = structure_types.TableIDX(zero)
   let table_idx_fourty_two = structure_types.TableIDX(fourty_two_unsigned)
@@ -757,9 +757,9 @@ pub fn element_section_test() {
   let ref_null_i31 =
     structure_types.HeapTypeRefType(structure_types.I31HeapType, True)
   let null_i31 =
-    expression_builder.new()
+    expression.new()
     |> ref.null(structure_types.I31HeapType)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let three_null_i31 = finger_tree.from_list([null_i31, null_i31, null_i31])
 
@@ -1013,11 +1013,11 @@ pub fn code_section_test() {
       finger_tree.from_list([
         structure_types.Code(
           add_locals,
-          expression_builder.new()
+          expression.new()
             |> i32.const_(forty_one)
             |> i32.const_(one)
             |> i32.add()
-            |> expression_builder.end_unwrap(),
+            |> expression.end_unwrap(),
         ),
       ]),
     )
@@ -1058,14 +1058,14 @@ pub fn data_section_test() {
   let mem_idx_zero = structure_types.MemIDX(mem_idx_zero)
   let mem_idx_one = structure_types.MemIDX(mem_idx_one)
   let offset_zero_expr =
-    expression_builder.new()
+    expression.new()
     |> i32.const_(offset_zero)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let offset_ten_expr =
-    expression_builder.new()
+    expression.new()
     |> i32.const_(offset_ten)
-    |> expression_builder.end_unwrap()
+    |> expression.end_unwrap()
 
   let active_data_zero_idx =
     structure_types.ActiveData(mem_idx_zero, offset_zero_expr, <<
diff --git a/test/instruction_test.gleam b/test/instruction_test.gleam
index f6b7e95..c2a41e8 100644
--- a/test/instruction_test.gleam
+++ b/test/instruction_test.gleam
@@ -3,6 +3,7 @@ import gleam/bytes_builder
 import gleam/option.{None, Some}
 import gleam/result
 import gleam/string
+import gleeunit/should
 import ieee_float
 import internal/binary/types
 import internal/finger_tree
@@ -114,13 +115,30 @@ pub fn br_table_test() {
   let label_b = structure_types.LabelIDX(label_b)
   let label_c = structure_types.LabelIDX(label_c)
 
-  let labels =
-    [label_a, label_b, label_c]
-    |> finger_tree.from_list
+  let label_list = [label_a, label_b, label_c]
+  let labels = finger_tree.from_list(label_list)
 
-  round_trip(structure_types.BrTable(labels, label_default), <<
-    0x0E, 3, 1, 2, 3, 42,
-  >>)
+  let assert Ok(#(
+    structure_types.BrTable(actual_labels, actual_label_default),
+    <<>>,
+  )) = types.decode_instruction(<<0x0E, 3, 1, 2, 3, 42>>)
+
+  actual_labels
+  |> finger_tree.to_list
+  |> should.equal(label_list)
+
+  actual_label_default
+  |> should.equal(label_default)
+
+  let assert Ok(builder) =
+    types.encode_instruction(
+      bytes_builder.new(),
+      structure_types.BrTable(labels, label_default),
+    )
+
+  builder
+  |> bytes_builder.to_bit_array
+  |> should.equal(<<0x0E, 3, 1, 2, 3, 42>>)
 }
 
 pub fn return_test() {
@@ -185,14 +203,34 @@ pub fn block_test() {
   let i32_add = structure_types.I32Add
   let drop = structure_types.Drop
 
-  let block_body =
-    structure_types.Expr(
-      finger_tree.from_list([local_get1, local_get2, i32_add, drop]),
+  let instruction_list = [local_get1, local_get2, i32_add, drop]
+  let block_body = structure_types.Expr(finger_tree.from_list(instruction_list))
+
+  let assert Ok(#(
+    structure_types.Block(
+      actual_block_type,
+      structure_types.Expr(actual_block_body),
+    ),
+    <<>>,
+  )) =
+    types.decode_instruction(<<0x02, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>)
+
+  actual_block_type
+  |> should.equal(structure_types.VoidBlockType)
+
+  actual_block_body
+  |> finger_tree.to_list
+  |> should.equal(instruction_list)
+
+  let assert Ok(builder) =
+    types.encode_instruction(
+      bytes_builder.new(),
+      structure_types.Block(structure_types.VoidBlockType, block_body),
     )
 
-  round_trip(structure_types.Block(structure_types.VoidBlockType, block_body), <<
-    0x02, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B,
-  >>)
+  builder
+  |> bytes_builder.to_bit_array
+  |> should.equal(<<0x02, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>)
 }
 
 // https://webassembly.github.io/gc/core/binary/instructions.html#control-instructions
@@ -206,14 +244,33 @@ pub fn loop_test() {
   let i32_add = structure_types.I32Add
   let drop = structure_types.Drop
 
-  let block_body =
-    structure_types.Expr(
-      finger_tree.from_list([local_get1, local_get2, i32_add, drop]),
+  let instruction_list = [local_get1, local_get2, i32_add, drop]
+
+  let assert Ok(#(
+    structure_types.Loop(
+      structure_types.VoidBlockType,
+      structure_types.Expr(block_body),
+    ),
+    <<>>,
+  )) =
+    types.decode_instruction(<<0x03, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>)
+
+  block_body
+  |> finger_tree.to_list
+  |> should.equal(instruction_list)
+
+  let assert Ok(builder) =
+    types.encode_instruction(
+      bytes_builder.new(),
+      structure_types.Loop(
+        structure_types.VoidBlockType,
+        structure_types.Expr(instruction_list |> finger_tree.from_list),
+      ),
     )
 
-  round_trip(structure_types.Loop(structure_types.VoidBlockType, block_body), <<
-    0x03, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B,
-  >>)
+  builder
+  |> bytes_builder.to_bit_array
+  |> should.equal(<<0x03, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>)
 }
 
 pub fn if_test() {
@@ -226,13 +283,28 @@ pub fn if_test() {
   let i32_add = structure_types.I32Add
   let drop = structure_types.Drop
 
-  let block_body =
-    finger_tree.from_list([local_get1, local_get2, i32_add, drop])
+  let instruction_list = [local_get1, local_get2, i32_add, drop]
+  let block_body = finger_tree.from_list(instruction_list)
 
-  round_trip(
+  let assert Ok(#(
     structure_types.If(structure_types.VoidBlockType, block_body, None),
-    <<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>,
-  )
+    <<>>,
+  )) =
+    types.decode_instruction(<<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>)
+
+  block_body
+  |> finger_tree.to_list
+  |> should.equal(instruction_list)
+
+  let assert Ok(builder) =
+    types.encode_instruction(
+      bytes_builder.new(),
+      structure_types.If(structure_types.VoidBlockType, block_body, None),
+    )
+
+  builder
+  |> bytes_builder.to_bit_array
+  |> should.equal(<<0x04, 0x40, 0x20, 0, 0x20, 1, 0x6A, 0x1A, 0x0B>>)
 }
 
 pub fn if_else_test() {
@@ -806,17 +878,29 @@ pub fn select_test() {
 }
 
 pub fn select_t_test() {
-  let val_types =
-    finger_tree.from_list([
-      structure_types.I32ValType,
-      structure_types.I64ValType,
-      structure_types.F32ValType,
-      structure_types.F64ValType,
-    ])
-
-  round_trip(structure_types.SelectT(val_types), <<
-    0x1C, 0x04, 0x7F, 0x7E, 0x7D, 0x7C,
-  >>)
+  let val_types_list = [
+    structure_types.I32ValType,
+    structure_types.I64ValType,
+    structure_types.F32ValType,
+    structure_types.F64ValType,
+  ]
+  let val_types = finger_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
+  |> should.equal(val_types_list)
+
+  let assert Ok(builder) =
+    types.encode_instruction(
+      bytes_builder.new(),
+      structure_types.SelectT(val_types),
+    )
+  builder
+  |> bytes_builder.to_bit_array
+  |> should.equal(<<0x1C, 0x04, 0x7F, 0x7E, 0x7D, 0x7C>>)
 }
 
 pub fn local_get_test() {
