1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use crateassign_indices;
use crateencode_internal;
use crateget_topological_events;
use crateVisitCtx;
use cratetypes;
use crateComponent;
pub
/// Encode this component into its binary WebAssembly representation.
///
/// # Overview
///
/// Encoding proceeds in **three distinct phases**:
///
/// 1. **Collect**
/// 2. **Assign**
/// 3. **Encode**
///
/// These phases exist to decouple *traversal*, *index computation*, and
/// *binary emission*, which is required because instrumentation may insert,
/// reorder, or otherwise affect items that participate in index spaces.
///
/// At a high level:
///
/// - **Collect** walks the IR and records *what* needs to be encoded and
/// *where* indices are referenced.
/// - **Assign** resolves all logical references to their final concrete
/// indices after instrumentation.
/// - **Encode** emits the final binary using the resolved indices.
///
/// ---
///
/// # Phase 1: Collect
///
/// The collect phase performs a structured traversal of the component IR.
/// During this traversal:
///
/// - All items that participate in encoding are recorded into an internal
/// "plan" that determines section order and contents.
/// - Any IR node that *references indices* (e.g. types, instances, modules,
/// exports) is recorded along with enough context to later rewrite those
/// references.
///
/// No indices are rewritten during this phase.
///
/// ## Component ID Stack
///
/// Components may be arbitrarily nested. To correctly associate items with
/// their owning component, the encoder maintains a **stack of component IDs**
/// during traversal.
///
/// - When entering a component, its `ComponentId` is pushed onto the stack.
/// - When exiting, it is popped.
/// - The top of the stack always represents the *current component context*.
///
/// A **component registry** maps `ComponentId` → `&Component`, allowing the
/// encoder to recover the owning component at any point without relying on
/// pointer identity for components themselves.
///
/// ---
///
/// # Phase 2: Assign
///
/// The assign phase resolves all *logical* references recorded during collect
/// into *concrete* indices suitable for encoding.
///
/// This includes:
///
/// - Mapping original indices to their post-instrumentation positions
/// - Resolving cross-item references (e.g. type references inside signatures)
/// - Ensuring index spaces are internally consistent
///
/// ## Scope Stack
///
/// Many IR nodes are scoped (for example, nested types, instances, or
/// component-local definitions). During traversal, the encoder maintains a
/// **stack of scopes** representing the current lexical and component nesting.
///
/// - Entering a scoped node pushes a new scope.
/// - Exiting the node pops the scope.
/// - At any point, the scope stack represents the active lookup context.
///
/// ## Scope Registry
///
/// Because scoped nodes may be deeply nested and arbitrarily structured,
/// scopes are not looked up via traversal position alone.
///
/// Instead, the encoder uses a **scope registry**, which maps the *identity*
/// of an IR node to its associated scope.
///
/// - Scoped IR nodes are stored behind stable pointers (e.g. `Box<T>`).
/// - These pointers are registered exactly once when the IR is built.
/// - During assign, any IR node can query the registry to recover its scope
/// in O(1) time.
///
/// This allows index resolution to be:
///
/// - Independent of traversal order
/// - Robust to instrumentation
/// - Safe against reordering or insertion of unrelated nodes
///
/// ---
///
/// # Phase 3: Encode
///
/// Once all indices have been assigned, the encode phase performs a final
/// traversal and emits the binary representation.
///
/// At this point:
///
/// - No structural mutations occur
/// - All index values are final
/// - Encoding is a pure, deterministic process
///
/// The encoder follows the previously constructed plan to emit sections
/// in the correct order and format.
///
/// ---
///
/// # Design Notes
///
/// This three-phase architecture ensures that:
///
/// - Instrumentation can freely insert or modify IR before encoding
/// - Index correctness is guaranteed before any bytes are emitted
/// - Encoding logic remains simple and local
///
/// The use of component IDs, scope stacks, and a scope registry allows the
/// encoder to handle arbitrarily nested components and scoped definitions
/// without relying on fragile positional assumptions.
///
/// # Panics
///
/// This method may panic if:
///
/// - The component registry is inconsistent
/// - A scoped IR node is missing from the scope registry
/// - Index resolution encounters an unresolved reference
///
/// These conditions indicate an internal bug or invalid IR construction.