Skip to main content

shape_vm/compiler/
mod.rs

1//! Bytecode compiler - translates AST to bytecode
2
3use shape_ast::error::{Result, ShapeError, SourceLocation};
4use std::collections::{HashMap, HashSet};
5use std::sync::Arc;
6
7use crate::blob_cache_v2::BlobCache;
8/// Borrow mode for reference parameters - Shared (&) or Exclusive (&mut).
9/// Kept for codegen even though the lexical borrow checker has been removed.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum BorrowMode {
12    Shared,
13    Exclusive,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub(crate) enum ExprResultMode {
18    Value,
19    PreserveRef,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
23pub(crate) struct ExprReferenceResult {
24    pub raw_mode: Option<BorrowMode>,
25    pub auto_deref_mode: Option<BorrowMode>,
26}
27
28/// A borrow place key used for encoding borrow targets in codegen.
29pub type BorrowPlace = u32;
30use crate::bytecode::{
31    BuiltinFunction, BytecodeProgram, Constant, FunctionBlob, FunctionHash, Instruction, OpCode,
32    Operand, Program as ContentAddressedProgram,
33};
34use crate::type_tracking::{TypeTracker, VariableTypeInfo};
35use shape_ast::ast::{FunctionDef, Program, Span, TypeAnnotation};
36use shape_runtime::type_schema::SchemaId;
37use shape_runtime::type_system::{
38    Type, TypeAnalysisMode, TypeError, TypeErrorWithLocation, analyze_program_with_mode,
39    checking::MethodTable,
40};
41
42// Sub-modules
43pub(crate) mod comptime;
44pub(crate) mod comptime_builtins;
45pub(crate) mod comptime_concrete;
46pub(crate) mod comptime_target;
47mod control_flow;
48mod expressions;
49mod functions;
50mod functions_annotations;
51mod functions_foreign;
52mod helpers;
53mod helpers_binding;
54mod helpers_reference;
55mod literals;
56mod loops;
57pub(crate) mod mir_schema_threading;
58pub(crate) mod monomorphization;
59mod patterns;
60pub(crate) mod post_inference_verify;
61mod statements;
62pub mod string_interpolation;
63mod trait_object_emission;
64
65/// Loop compilation context
66pub(crate) struct LoopContext {
67    /// Break jump targets
68    pub(crate) break_jumps: Vec<usize>,
69    /// Continue jump target (usize::MAX = deferred, use continue_jumps)
70    pub(crate) continue_target: usize,
71    /// Optional local to store break values for expression loops
72    pub(crate) break_value_local: Option<u16>,
73    /// Whether a for-in iterator is on the stack (break must pop it)
74    pub(crate) iterator_on_stack: bool,
75    /// Drop scope depth when the loop was entered (for break/continue early exit drops)
76    pub(crate) drop_scope_depth: usize,
77    /// Forward-patched continue jumps for range counter loops where the
78    /// increment block is after the body (so continue must forward-jump).
79    pub(crate) continue_jumps: Vec<usize>,
80}
81
82/// Information about an imported symbol (fields used for diagnostics/LSP)
83#[derive(Debug, Clone)]
84#[allow(dead_code)]
85pub(crate) struct ImportedSymbol {
86    /// Original name in the source module
87    pub original_name: String,
88    /// Module path the symbol was imported from
89    pub module_path: String,
90    /// High-level kind of the imported symbol (function, type, etc.)
91    /// `None` for legacy inlining path where kind is not tracked.
92    pub kind: Option<shape_ast::module_utils::ModuleExportKind>,
93}
94
95/// Imported annotation binding routed through a hidden synthetic module.
96#[derive(Debug, Clone)]
97pub(crate) struct ImportedAnnotationSymbol {
98    /// Original annotation name in the source module.
99    pub original_name: String,
100    /// Source module path the annotation was imported from.
101    pub _module_path: String,
102    /// Hidden synthetic module name that owns the compiled annotation scope.
103    pub hidden_module_name: String,
104}
105
106/// Module-scoped builtin function declaration with a runtime source module.
107#[derive(Debug, Clone)]
108pub(crate) struct ModuleBuiltinFunction {
109    /// The callable name as exported by the runtime/native module.
110    pub export_name: String,
111    /// Original source module path that provides the runtime implementation.
112    pub source_module_path: String,
113}
114
115/// Compiler-internal scope taxonomy for name resolution.
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117#[allow(dead_code)]
118pub(crate) enum ResolutionScope {
119    Local,
120    ModuleBinding,
121    NamedImport,
122    NamespaceImport,
123    TypeAssociated,
124    Prelude,
125    SyntaxReserved,
126    InternalIntrinsic,
127}
128
129impl ResolutionScope {
130    pub(crate) const fn label(self) -> &'static str {
131        match self {
132            Self::Local => "local scope",
133            Self::ModuleBinding => "module scope",
134            Self::NamedImport => "named import scope",
135            Self::NamespaceImport => "namespace import scope",
136            Self::TypeAssociated => "type-associated scope",
137            Self::Prelude => "implicit prelude scope",
138            Self::SyntaxReserved => "syntax-reserved scope",
139            Self::InternalIntrinsic => "internal intrinsic scope",
140        }
141    }
142}
143
144/// Builtin lookup result annotated with the scope class it currently belongs to.
145#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub(crate) enum BuiltinNameResolution {
147    Surface {
148        builtin: BuiltinFunction,
149        scope: ResolutionScope,
150    },
151    InternalOnly {
152        builtin: BuiltinFunction,
153        scope: ResolutionScope,
154    },
155}
156
157impl BuiltinNameResolution {
158    pub(crate) const fn scope(self) -> ResolutionScope {
159        match self {
160            Self::Surface { scope, .. } | Self::InternalOnly { scope, .. } => scope,
161        }
162    }
163}
164
165#[derive(Debug, Clone)]
166pub(crate) struct StructGenericInfo {
167    pub type_params: Vec<shape_ast::ast::TypeParam>,
168    pub runtime_field_types: HashMap<String, shape_ast::ast::TypeAnnotation>,
169}
170
171/// Whether a type's Drop impl is sync-only, async-only, or both.
172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub(crate) enum DropKind {
174    SyncOnly,
175    AsyncOnly,
176    Both,
177}
178
179/// Canonical compile-time parameter passing contract.
180///
181/// This is the single source of truth used by compiler lowering and LSP rendering.
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
183pub enum ParamPassMode {
184    ByValue,
185    ByRefShared,
186    ByRefExclusive,
187}
188
189impl ParamPassMode {
190    pub const fn is_reference(self) -> bool {
191        !matches!(self, Self::ByValue)
192    }
193
194    pub const fn is_exclusive(self) -> bool {
195        matches!(self, Self::ByRefExclusive)
196    }
197}
198
199#[derive(Debug, Clone, PartialEq, Eq)]
200pub(crate) struct FunctionReturnReferenceSummary {
201    pub param_index: usize,
202    pub mode: BorrowMode,
203    pub projection: Option<Vec<crate::mir::types::ProjectionStep>>,
204}
205
206impl From<crate::mir::analysis::ReturnReferenceSummary> for FunctionReturnReferenceSummary {
207    fn from(value: crate::mir::analysis::ReturnReferenceSummary) -> Self {
208        Self {
209            param_index: value.param_index,
210            mode: match value.kind {
211                crate::mir::types::BorrowKind::Shared => BorrowMode::Shared,
212                crate::mir::types::BorrowKind::Exclusive => BorrowMode::Exclusive,
213            },
214            projection: value.projection,
215        }
216    }
217}
218
219/// Per-function blob builder for content-addressed compilation.
220///
221/// Uses a **snapshot** strategy: records the global instruction/constant/string
222/// pool sizes at the start of function compilation, then at finalization
223/// extracts the delta and remaps global indices to blob-local indices.
224pub(crate) struct FunctionBlobBuilder {
225    /// Function name.
226    pub name: String,
227    /// Global instruction index where this function's code starts.
228    pub instr_start: usize,
229    /// Global constant pool size when this function started compiling.
230    #[allow(dead_code)]
231    pub const_start: usize,
232    /// Global string pool size when this function started compiling.
233    #[allow(dead_code)]
234    pub string_start: usize,
235    /// Names of functions called by this function (for dependency tracking).
236    pub called_functions: Vec<String>,
237    /// Type schema names this function constructs.
238    pub type_schemas: Vec<String>,
239    /// Accumulated permissions required by this function's direct calls.
240    pub required_permissions: shape_abi_v1::PermissionSet,
241}
242
243impl FunctionBlobBuilder {
244    pub fn new(name: String, instr_start: usize, const_start: usize, string_start: usize) -> Self {
245        Self {
246            name,
247            instr_start,
248            const_start,
249            string_start,
250            called_functions: Vec::new(),
251            type_schemas: Vec::new(),
252            required_permissions: shape_abi_v1::PermissionSet::pure(),
253        }
254    }
255
256    /// Record that this function calls another function by name.
257    pub fn record_call(&mut self, callee_name: &str) {
258        if !self.called_functions.iter().any(|n| n == callee_name) {
259            self.called_functions.push(callee_name.to_owned());
260        }
261    }
262
263    /// Record that this function requires the given permissions
264    /// (e.g., from a stdlib module call identified by capability_tags).
265    pub fn record_permissions(&mut self, perms: &shape_abi_v1::PermissionSet) {
266        self.required_permissions = self.required_permissions.union(perms);
267    }
268
269    /// Finalize this builder into a FunctionBlob by extracting the delta from
270    /// the global program pools and remapping indices to blob-local ones.
271    pub fn finalize(
272        &self,
273        program: &crate::bytecode::BytecodeProgram,
274        func: &crate::bytecode::Function,
275        blob_name_to_hash: &HashMap<String, FunctionHash>,
276        instr_end: usize,
277    ) -> FunctionBlob {
278        use crate::bytecode::Operand;
279
280        // Extract global-indexed instructions for this function.
281        let global_instructions = &program.instructions[self.instr_start..instr_end];
282
283        // Build constant remap: global index -> local index.
284        let mut const_remap: HashMap<u16, u16> = HashMap::new();
285        let mut local_constants: Vec<Constant> = Vec::new();
286        // Build string remap similarly.
287        let mut string_remap: HashMap<u16, u16> = HashMap::new();
288        let mut local_strings: Vec<String> = Vec::new();
289        // Build function operand remap: global function index -> dependency-local index.
290        let mut func_remap: HashMap<u16, u16> = HashMap::new();
291        // Start from explicitly recorded call dependencies, then augment with
292        // function-value references found in constants/operands.
293        let mut called_functions = self.called_functions.clone();
294
295        let mut ensure_called = |callee_name: &str| -> u16 {
296            if let Some(dep_idx) = called_functions.iter().position(|n| n == callee_name) {
297                dep_idx as u16
298            } else {
299                called_functions.push(callee_name.to_owned());
300                (called_functions.len() - 1) as u16
301            }
302        };
303
304        // Scan instructions for all constant/string references and build
305        // blob-local pools with remapped indices.
306        for instr in global_instructions {
307            if let Some(ref operand) = instr.operand {
308                match operand {
309                    Operand::Const(idx) => {
310                        if !const_remap.contains_key(idx) {
311                            let local_idx = local_constants.len() as u16;
312                            const_remap.insert(*idx, local_idx);
313                            let mut constant = program.constants[*idx as usize].clone();
314                            if let Constant::Function(fid) = constant {
315                                let global_idx = fid as usize;
316                                if let Some(callee) = program.functions.get(global_idx) {
317                                    let dep_idx = ensure_called(&callee.name);
318                                    constant = Constant::Function(dep_idx);
319                                }
320                            }
321                            local_constants.push(constant);
322                        }
323                    }
324                    Operand::Property(idx) => {
325                        if !string_remap.contains_key(idx) {
326                            let local_idx = local_strings.len() as u16;
327                            string_remap.insert(*idx, local_idx);
328                            local_strings.push(program.strings[*idx as usize].clone());
329                        }
330                    }
331                    Operand::Name(sid) => {
332                        let gidx = sid.0 as u16;
333                        if !string_remap.contains_key(&gidx) {
334                            let local_idx = local_strings.len() as u16;
335                            string_remap.insert(gidx, local_idx);
336                            local_strings.push(program.strings[gidx as usize].clone());
337                        }
338                    }
339                    Operand::TypedMethodCall { string_id, .. } => {
340                        let gidx = *string_id;
341                        if !string_remap.contains_key(&gidx) {
342                            let local_idx = local_strings.len() as u16;
343                            string_remap.insert(gidx, local_idx);
344                            local_strings.push(program.strings[gidx as usize].clone());
345                        }
346                    }
347                    Operand::Function(fid) => {
348                        let global_idx = fid.0 as usize;
349                        if !func_remap.contains_key(&fid.0) {
350                            // Map global function index -> dependency-local index.
351                            // If this call target was not explicitly recorded (e.g. emitted via
352                            // function-valued constants), add it so content-addressed linking can
353                            // remap stable function IDs correctly.
354                            if let Some(callee) = program.functions.get(global_idx) {
355                                let dep_idx = ensure_called(&callee.name);
356                                func_remap.insert(fid.0, dep_idx);
357                            }
358                        }
359                    }
360                    // Closure spec H5: `MakeClosure` now carries the function id
361                    // (plus the escape flag) in a `ClosureAlloc` operand when the
362                    // closure escapes. Treat it exactly like `Operand::Function`
363                    // for dependency tracking — the content-addressed blob must
364                    // record the closure's compiled body as a dependency.
365                    Operand::ClosureAlloc { fid, .. } => {
366                        let global_idx = fid.0 as usize;
367                        if !func_remap.contains_key(&fid.0) {
368                            if let Some(callee) = program.functions.get(global_idx) {
369                                let dep_idx = ensure_called(&callee.name);
370                                func_remap.insert(fid.0, dep_idx);
371                            }
372                        }
373                    }
374                    _ => {}
375                }
376            }
377        }
378
379        // Remap instructions to use local indices.
380        let local_instructions: Vec<Instruction> = global_instructions
381            .iter()
382            .map(|instr| {
383                let mut remapped = instr.clone();
384                if let Some(operand) = &mut remapped.operand {
385                    match operand {
386                        Operand::Const(idx) => {
387                            if let Some(&local) = const_remap.get(idx) {
388                                *idx = local;
389                            }
390                        }
391                        Operand::Property(idx) => {
392                            if let Some(&local) = string_remap.get(idx) {
393                                *idx = local;
394                            }
395                        }
396                        Operand::Name(sid) => {
397                            if let Some(&local) = string_remap.get(&(sid.0 as u16)) {
398                                sid.0 = local as u32;
399                            }
400                        }
401                        Operand::TypedMethodCall { string_id, .. } => {
402                            if let Some(&local) = string_remap.get(string_id) {
403                                *string_id = local;
404                            }
405                        }
406                        Operand::Function(fid) => {
407                            if let Some(&local) = func_remap.get(&fid.0) {
408                                fid.0 = local;
409                            }
410                        }
411                        // Closure spec H5: parallel remap for `ClosureAlloc`.
412                        Operand::ClosureAlloc { fid, .. } => {
413                            if let Some(&local) = func_remap.get(&fid.0) {
414                                fid.0 = local;
415                            }
416                        }
417                        _ => {}
418                    }
419                }
420                remapped
421            })
422            .collect();
423
424        // Build dependency list from called function names.
425        // Use FunctionHash::ZERO as sentinel for forward references (not yet compiled).
426        let dependencies: Vec<FunctionHash> = called_functions
427            .iter()
428            .map(|callee| {
429                blob_name_to_hash
430                    .get(callee)
431                    .copied()
432                    .unwrap_or(FunctionHash::ZERO)
433            })
434            .collect();
435
436        // Build source map from global debug info.
437        let source_map: Vec<(usize, u32, u32)> = program
438            .debug_info
439            .line_numbers
440            .iter()
441            .filter(|(idx, _, _)| *idx >= self.instr_start && *idx < instr_end)
442            .map(|(idx, fid, line)| (idx - self.instr_start, *fid as u32, *line))
443            .collect();
444
445        // Scan instructions for CallForeign operands and collect content hashes
446        // from the program's foreign_functions table.
447        let mut foreign_deps: Vec<[u8; 32]> = Vec::new();
448        for instr in &local_instructions {
449            if instr.opcode == crate::bytecode::OpCode::CallForeign {
450                if let Some(Operand::ForeignFunction(idx)) = instr.operand {
451                    if let Some(entry) = program.foreign_functions.get(idx as usize) {
452                        if let Some(hash) = entry.content_hash {
453                            foreign_deps.push(hash);
454                        }
455                    }
456                }
457            }
458        }
459        foreign_deps.sort();
460        foreign_deps.dedup();
461
462        let mut blob = FunctionBlob {
463            content_hash: FunctionHash::ZERO,
464            name: self.name.clone(),
465            arity: func.arity,
466            param_names: func.param_names.clone(),
467            locals_count: func.locals_count,
468            is_closure: func.is_closure,
469            captures_count: func.captures_count,
470            is_async: func.is_async,
471            ref_params: func.ref_params.clone(),
472            ref_mutates: func.ref_mutates.clone(),
473            mutable_captures: func.mutable_captures.clone(),
474            frame_descriptor: func.frame_descriptor.clone(),
475            required_permissions: self.required_permissions.clone(),
476            instructions: local_instructions,
477            constants: local_constants,
478            strings: local_strings,
479            dependencies,
480            callee_names: called_functions,
481            type_schemas: self.type_schemas.clone(),
482            foreign_dependencies: foreign_deps,
483            source_map,
484        };
485        blob.finalize();
486        blob
487    }
488}
489
490#[derive(Debug, Clone, Copy, PartialEq, Eq)]
491pub enum TypeDiagnosticMode {
492    ReliableOnly,
493    Strict,
494    RecoverAll,
495}
496
497#[derive(Debug, Clone, Copy, PartialEq, Eq)]
498pub enum CompileDiagnosticMode {
499    FailFast,
500    RecoverAll,
501}
502
503/// cluster-2-cw-IB-class-b (2026-05-16, supervisor R3 binding-ratified):
504/// retained closure-literal peek used to re-run body return-type
505/// inference at the value-call site with caller-context arg type hints.
506/// Stored per-local-slot in `BytecodeCompiler.local_callable_closure_bodies`
507/// at let-binding time (`update_callable_binding_from_expr` /
508/// `FunctionExpr` arm). The body is the AST `Vec<Statement>` clone — no
509/// bytecode-lowering happens at lookup time; the inference walker only
510/// inspects AST shape.
511#[derive(Debug, Clone)]
512pub struct ClosureBodyPeek {
513    /// Formal parameters of the closure literal (`|inner|` →
514    /// `[FunctionParameter { pattern: Identifier("inner"), .. }]`).
515    pub params: Vec<shape_ast::ast::FunctionParameter>,
516    /// Closure literal body statements.
517    pub body: Vec<shape_ast::ast::Statement>,
518    /// Explicit `-> T` return annotation, if any.
519    pub return_type: Option<shape_ast::ast::TypeAnnotation>,
520    /// Compiled-function index assigned to the closure body by
521    /// `compile_expr_closure`. `None` until the closure literal is
522    /// actually lowered (the peek is built from the AST; the function
523    /// index is assigned at compile-emission time). Used by the value-
524    /// call propagation path to retroactively patch
525    /// `mir.local_typed_array_element_types` for the closure body's
526    /// MIR-side typed-array param seed.
527    pub function_index: Option<usize>,
528}
529
530/// Phase 4b Round 6 WS-1b W16.2-C residual (2026-05-21) — identifies the
531/// binding slot that holds a bare empty-array accumulator awaiting a
532/// downstream-`.push()`-resolved element kind.
533///
534/// A `let mut out = []` either lands in a function-body local slot or a
535/// top-level module binding; both are keyed by their `u16` index. The push
536/// site (`compile_expr_method_call`) resolves the receiver to the same key,
537/// patches the placeholder allocator, and promotes the binding.
538#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
539pub(crate) enum EmptyArrayAccumulatorKey {
540    /// Function-body local slot index.
541    Local(u16),
542    /// Top-level module-binding index.
543    ModuleBinding(u16),
544}
545
546/// Phase 4b Round 6 WS-1b W16.2-C residual — a pending bare empty-array
547/// accumulator. Carries the placeholder `NewArray(0)` instruction index so
548/// the first `.push()` (or the end-of-compilation finalizer) can patch it.
549#[derive(Debug, Clone)]
550pub(crate) struct EmptyArrayAccumulator {
551    /// Instruction index of the placeholder `OpCode::NewArray` emitted at the
552    /// empty-array literal site. Patched in-place to `kind.new_opcode()` once
553    /// the element kind is proven.
554    pub alloc_instr_idx: usize,
555    /// Source location of the empty-array literal — used for the clean
556    /// "element type un-resolvable" diagnostic if no push ever resolves it.
557    pub literal_loc: Option<SourceLocation>,
558    /// The accumulator variable's source name (for diagnostics).
559    pub var_name: String,
560}
561
562/// Compiler state
563pub struct BytecodeCompiler {
564    /// The program being built
565    pub(crate) program: BytecodeProgram,
566
567    /// Current function being compiled
568    pub(crate) current_function: Option<usize>,
569
570    /// Local variable mappings (name -> index)
571    pub(crate) locals: Vec<HashMap<String, u16>>,
572
573    /// ModuleBinding variable mappings (name -> index)
574    pub(crate) module_bindings: HashMap<String, u16>,
575
576    /// Next local variable index
577    pub(crate) next_local: u16,
578
579    /// Next module_binding variable index
580    pub(crate) next_global: u16,
581
582    /// Loop context stack for break/continue
583    pub(crate) loop_stack: Vec<LoopContext>,
584
585    /// Counter for synthetic closure function names
586    pub(crate) closure_counter: u64,
587
588    /// Closure function indices discovered during bytecode compilation of the
589    /// current function. Each entry is (closure_function_name, function_index).
590    /// Used to back-patch MIR ClosurePlaceholder/ClosureCapture after compilation.
591    pub(crate) closure_function_ids: Vec<(String, u16)>,
592
593    /// Registry of closure capture layouts (v2 closure specialization Phase A).
594    ///
595    /// Keyed on capture signature (`Vec<ConcreteType>`): two closures with
596    /// identical capture signatures share a `ClosureTypeId`. Phase C will
597    /// consume this to extend the monomorphization cache key.
598    pub(crate) closure_registry: shape_value::v2::closure_layout::ClosureRegistry,
599
600    /// Mapping from closure function index to its `ClosureTypeId`.
601    /// Populated alongside `closure_function_ids` as each closure literal is
602    /// lowered. Phase C reads this to key monomorphization on the closure type.
603    pub(crate) closure_type_ids: Vec<(u16, shape_value::v2::concrete_type::ClosureTypeId)>,
604
605    /// Track A.1C — per-closure `CaptureKind` vector, one entry per capture
606    /// in declaration order. Populated alongside `closure_type_ids` so that
607    /// `compiler_impl_reference_model::build_closure_function_layouts` can
608    /// construct the per-function `ClosureLayout` with the correct
609    /// `CaptureKind` per capture (rather than defaulting to the
610    /// `ClosureRegistry::intern`'d all-`Immutable` shape). A missing entry
611    /// (closure registered via the legacy path, e.g. test helpers) falls
612    /// back to all-`Immutable`, matching the pre-A.1C layout.
613    pub(crate) closure_capture_kinds: Vec<(u16, Vec<shape_value::v2::closure_layout::CaptureKind>)>,
614
615    /// Registry of `Function<A, R>` signatures (v2 closure specialization
616    /// Phase F). `FunctionTypeId`s assigned here are written into
617    /// `TypedClosureHeader.type_id` in the JIT path and consumed by
618    /// `CallFunctionIndirect` to pick a Cranelift `call_indirect` signature.
619    pub(crate) function_type_registry:
620        shape_value::v2::function_type_registry::FunctionTypeRegistry,
621
622    /// Mapping from closure function index to the `FunctionTypeId` of its
623    /// callable signature (params + return). Populated alongside
624    /// `closure_type_ids` when a closure literal is lowered. The JIT reads
625    /// this to emit the per-`ClosureTypeId` direct-call signature and the
626    /// polymorphic `CallFunctionIndirect` signature.
627    pub(crate) function_type_ids: Vec<(u16, shape_value::v2::concrete_type::FunctionTypeId)>,
628
629    /// Phase F one-shot: if set, the next closure-literal emission uses
630    /// `MakeClosureHeap` instead of the legacy `MakeClosure`. The flag is
631    /// consumed (reset to false) as soon as `compile_expr_closure`
632    /// finishes emitting the opcode. Callers that want to force the heap
633    /// ABI (e.g. the return-statement compiler when the returned value is
634    /// a closure literal) set this right before lowering the closure.
635    pub(crate) emit_make_closure_heap_next: bool,
636
637    /// Wave E+5-cleanup task #108 side-channel: native-kind hint for
638    /// `GetProp` emit sites where the producer-flip in `op_get_prop`
639    /// pushes raw native bits (I64 / Timestamp / F64 / Bool field tags
640    /// against non-heap slots). Keyed by emitted-instruction index;
641    /// consumed by `last_emitted_native_kind`'s `GetProp` arm so the
642    /// host-boundary synthesizer re-tags raw bits per the recorded
643    /// kind. `GetProp` is `Instruction::simple` (no operand) so neither
644    /// operand-decode nor walk-back recovers the field tag — the
645    /// compiler must record the resolved kind at the emit site
646    /// (`compile_expr_property_access`).
647    pub(crate) get_prop_native_kinds: HashMap<usize, crate::type_tracking::StorageHint>,
648
649    /// When compiling a DataTable closure method (e.g. dt.filter(row => ...)),
650    /// this holds the (schema_id, type_name) to tag the closure's row parameter as RowView.
651    pub(crate) closure_row_schema: Option<(u32, String)>,
652
653    /// Strict-typing-sweep (Cluster 3): bidirectional closure inference for
654    /// HOF method calls. When the next compiled closure literal is the
655    /// argument to `arr.map(|x| …)` / `.filter` / `.reduce` / etc., the
656    /// outer `compile_expr_method_call` resolves the receiver's element
657    /// type and stashes per-user-param `TypeAnnotation` hints here. The
658    /// closure compile reads these hints and attaches them to params with
659    /// no explicit annotation, then clears the field. The vector indexes
660    /// USER params only (excludes synthesized capture-params).
661    pub(crate) pending_closure_param_types: Option<Vec<Option<shape_ast::ast::TypeAnnotation>>>,
662
663    /// Unified type metadata for the last compiled expression.
664    ///
665    /// This is the single source for relational/value kind propagation
666    /// (Table<T>, Indexed<T>, known object schema, etc.).
667    pub(crate) last_expr_type_info: Option<VariableTypeInfo>,
668
669    /// Type tracker for optimized field access
670    pub(crate) type_tracker: TypeTracker,
671
672    /// Schema ID of the last compiled expression (if it's a TypedObject).
673    /// Used for compile-time typed merge optimization.
674    pub(crate) last_expr_schema: Option<SchemaId>,
675
676    /// Numeric type of the last compiled expression (for typed opcode emission).
677    /// Set by literal compilation, variable loads, and other expression compilers.
678    /// Read by binary op compilation to emit typed opcodes (e.g., MulInt).
679    pub(crate) last_expr_numeric_type: Option<crate::type_tracking::NumericType>,
680
681    /// E+5.5 Unit C step 2: captured top-level program return-kind, snapshotted
682    /// right after the last item compiles (before drop-scope emission and
683    /// Halt overwrite `last_expr_*`). Consumed by
684    /// `populate_program_storage_hints` to populate
685    /// `top_level_frame.return_kind` so the host boundary reads the kind
686    /// off the parallel-kind track (per ADR-006 §2.7.7 — the deleted
687    /// ValueWord-tagged synthesis is gone).
688    ///
689    /// Per ADR-006 §2.7.5.1 (compiler-tier intermediate state policy),
690    /// "kind not yet stamped" is carried as `Option<StorageHint>` —
691    /// `None` is the post-bulldozer replacement for the deleted
692    /// `StorageHint::Unknown` sentinel.
693    pub(crate) top_level_program_return_kind: Option<crate::type_tracking::StorageHint>,
694
695    /// Result mode for the expression currently being compiled.
696    pub(crate) current_expr_result_mode: ExprResultMode,
697
698    /// Whether the last compiled expression left a raw reference on the stack.
699    ///
700    /// `auto_deref_mode` is only set for propagated ref results (identifier loads,
701    /// ref-returning calls) that should implicitly dereference in value contexts.
702    /// Explicit `&expr` results keep `raw_mode` without enabling auto-deref.
703    pub(crate) last_expr_reference_result: ExprReferenceResult,
704
705    /// Known pass modes for local callable bindings (closures / function aliases).
706    pub(crate) local_callable_pass_modes: HashMap<u16, Vec<ParamPassMode>>,
707
708    /// Known safe return-reference summaries for local callable bindings.
709    pub(crate) local_callable_return_reference_summaries:
710        HashMap<u16, FunctionReturnReferenceSummary>,
711
712    /// Known pass modes for module-binding callable values.
713    pub(crate) module_binding_callable_pass_modes: HashMap<u16, Vec<ParamPassMode>>,
714
715    /// Known safe return-reference summaries for module-binding callable values.
716    pub(crate) module_binding_callable_return_reference_summaries:
717        HashMap<u16, FunctionReturnReferenceSummary>,
718
719    /// Sweep phase 3c.1: inferred return-type names for closures stored in
720    /// local slots. Populated when `update_callable_binding_from_expr`
721    /// observes a `FunctionExpr` initializer; consumed by `infer_expr_type`
722    /// so a `FunctionCall { name: f, .. }` against `let f = |…| body` can
723    /// recover the body's return type for strict-typing binop dispatch.
724    pub(crate) local_callable_return_types: HashMap<u16, String>,
725
726    /// Sweep phase 3c.1: inferred return-type names for closures stored in
727    /// module-binding slots (top-level / REPL `let f = |…|` style).
728    pub(crate) module_binding_callable_return_types: HashMap<u16, String>,
729
730    /// Sweep phase 3c.x: inferred return-type names for arrays whose elements
731    /// are closure literals with a homogeneous return type. Keyed by the
732    /// local slot holding the array. Consumed by `infer_expr_type` for the
733    /// `arr[i](args...)` callsite (which the parser models as
734    /// `MethodCall { method: "__call__", receiver: IndexAccess { .. } }`).
735    /// Without this lookup, `arr[0](1) + arr[1](1)` fails strict-typing as
736    /// `unknown + unknown`.
737    pub(crate) local_array_callable_return_types: HashMap<u16, String>,
738
739    /// Sweep phase 3c.x: inferred return-type names for arrays of closures
740    /// stored in module-binding slots (top-level `let arr = [|x| ..., ...]`).
741    pub(crate) module_binding_array_callable_return_types: HashMap<u16, String>,
742
743    /// cluster-2-cw-IB-class-b (2026-05-16, supervisor R3 binding-
744    /// ratified): retained closure-literal body for local `let f = |..|
745    /// ..` bindings. Populated at let-binding time by
746    /// `update_callable_binding_from_expr`'s `FunctionExpr` arm;
747    /// consumed at `compile_expr_function_call`'s value-call branch when
748    /// re-running closure-body return-type inference with caller-context
749    /// arg types.
750    ///
751    /// The retained body is the AST `Vec<Statement>` clone (no lowering
752    /// occurs at lookup time — the inference walker only inspects AST
753    /// shape, never emits bytecode for the body). Released on
754    /// `clear_callable_binding` and on per-function compilation
755    /// snapshot/restore alongside the existing `local_callable_*`
756    /// maps (`functions.rs:1148-1151` / `:1496-1499` / `:1607-1608`).
757    ///
758    /// Memory cost: bounded by the number of local closure bindings in
759    /// the active function frame; the body is the same AST already held
760    /// by the parent `Statement::VariableDecl` initializer, just held
761    /// for the lifetime of the enclosing function-compile pass to avoid
762    /// re-walking the AST at every value-call site. Released when the
763    /// enclosing function compile completes.
764    pub(crate) local_callable_closure_bodies:
765        HashMap<u16, ClosureBodyPeek>,
766
767    /// cluster-2-cw-IB-class-b: module-binding variant of the closure
768    /// body peek. Covers top-level / REPL `let f = |..|` bindings whose
769    /// slots live in the module-binding space (not the local-slot
770    /// space). Populated/cleared alongside the existing
771    /// `module_binding_callable_return_types` map at the
772    /// `update_callable_binding_from_expr` `FunctionExpr` arm.
773    pub(crate) module_binding_callable_closure_bodies:
774        HashMap<u16, ClosureBodyPeek>,
775
776    /// ADR-006 §2.7.24 Q25.C trait-object emission (Wave 2.6 round-2):
777    /// per-local-slot trait name for `let a: dyn Animal = ...` bindings.
778    /// Consumed by `compile_expr_method_call` (`expressions/function_calls.rs`)
779    /// to route method dispatch through `OpCode::DynMethodCall` instead
780    /// of the standard `OpCode::CallMethod` path. Empty for non-dyn
781    /// locals.
782    pub(crate) dyn_locals: HashMap<u16, String>,
783
784    /// ADR-006 §2.7.24 Q25.C trait-object emission: per-module-binding
785    /// trait name for top-level `let a: dyn Animal = ...` declarations.
786    /// Same role as `dyn_locals` but for the module-binding slot space.
787    pub(crate) dyn_module_bindings: HashMap<u16, String>,
788
789    /// Named functions that safely return one reference parameter unchanged.
790    pub(crate) function_return_reference_summaries: HashMap<String, FunctionReturnReferenceSummary>,
791
792    /// The return-reference summary of the function currently being compiled, if any.
793    pub(crate) current_function_return_reference_summary: Option<FunctionReturnReferenceSummary>,
794
795    /// Type inference engine for match exhaustiveness and type checking
796    pub(crate) type_inference: shape_runtime::type_system::inference::TypeInferenceEngine,
797
798    /// Track type aliases defined in the program
799    /// Maps alias name -> target type (for type validation)
800    pub(crate) type_aliases: HashMap<String, String>,
801
802    /// Current source line being compiled (for debug info)
803    pub(crate) current_line: u32,
804
805    /// Current source file ID (for multi-file debug info)
806    pub(crate) current_file_id: u16,
807
808    /// Source text (for error messages)
809    pub(crate) source_text: Option<String>,
810
811    /// Source lines (split from source_text for quick access)
812    pub(crate) source_lines: Vec<String>,
813
814    /// Imported symbols: local_name -> ImportedSymbol
815    pub(crate) imported_names: HashMap<String, ImportedSymbol>,
816    /// Imported annotations: local_name -> ImportedAnnotationSymbol
817    pub(crate) imported_annotations: HashMap<String, ImportedAnnotationSymbol>,
818    /// R8 W8 Cluster A (2026-05-24): imported `pub const NAME = expr`
819    /// initializers, keyed by the local binding name (alias-respecting).
820    /// At identifier-load time, references to these names compile to an
821    /// inlined `PushConst(<comptime-value>)` rather than a
822    /// `LoadModuleBinding` — the dispatch's "use the existing
823    /// comptime-evaluated-constant mechanism (the `Constant` pool); NOT a
824    /// new opcode, NOT a deferred init runtime computation" binding.
825    /// ADR-006 §2.7.5 stamp-at-compile-time invariant preserved: the
826    /// constant's kind is stamped from the literal's shape at compile time.
827    pub(crate) imported_consts: HashMap<String, shape_ast::ast::Expr>,
828    /// Qualified builtin function declarations available as module-scoped callables.
829    pub(crate) module_builtin_functions: HashMap<String, ModuleBuiltinFunction>,
830    /// Module namespace bindings introduced by `use module.path`.
831    /// Used to avoid UFCS rewrites for module calls like `duckdb.connect(...)`.
832    pub(crate) module_namespace_bindings: HashSet<String>,
833    /// Imported synthetic/local module path -> original source module path.
834    /// Used when code inside a wrapper module needs to dispatch to native exports
835    /// from the underlying source module.
836    pub(crate) module_scope_sources: HashMap<String, String>,
837    /// Active lexical module scope stack while compiling `mod Name { ... }`.
838    pub(crate) module_scope_stack: Vec<String>,
839
840    /// Known exports for import suggestions: function_name -> module_path
841    /// Used to provide helpful error messages like "Did you mean to import from...?"
842    pub(crate) known_exports: HashMap<String, String>,
843    /// Function arity bounds keyed by function name: (required_params, total_params).
844    /// Required params are non-default parameters. Defaults are only allowed
845    /// in trailing positions.
846    pub(crate) function_arity_bounds: HashMap<String, (usize, usize)>,
847    /// Function const parameter indices keyed by function name.
848    /// Const parameters must receive compile-time constant arguments at call sites.
849    pub(crate) function_const_params: HashMap<String, Vec<usize>>,
850    /// Original function definitions keyed by function name.
851    /// Used for const-template specialization at call sites.
852    pub(crate) function_defs: HashMap<String, FunctionDef>,
853    /// Foreign function definitions keyed by function name.
854    /// Used to resolve the effective (Result-wrapped) return type at call sites.
855    pub(crate) foreign_function_defs: HashMap<String, shape_ast::ast::ForeignFunctionDef>,
856    /// Sweep phase 3c.x: per-(enum, variant) struct-variant field
857    /// annotations. The schema-level `EnumVariantInfo` only carries field
858    /// counts (`payload_fields`) and uses `__payload_N` field names with
859    /// `FieldType::Any`, so the named-field types of `enum E { V { x: int,
860    /// y: int } }` are otherwise lost at pattern compile time. Populated
861    /// by `register_enum`; consumed by `compile_typed_enum_binding` (struct
862    /// arm) so `match m::E::V { x, y } => x + y` propagates int onto x and
863    /// y.
864    pub(crate) enum_struct_variant_fields:
865        HashMap<(String, String), Vec<(String, shape_ast::ast::TypeAnnotation)>>,
866    /// R8 W7: per-(enum, variant) tuple-payload positional type
867    /// annotations. Symmetric to `enum_struct_variant_fields` for
868    /// tuple variants. The runtime schema collapses tuple payloads
869    /// into `__payload_N: Any`, so per-position types of
870    /// `enum E { V(string) }` are otherwise lost at pattern-compile
871    /// time. Populated by `register_enum`; consumed by
872    /// `compile_typed_enum_binding` (tuple arm) so `match E::V(id) =>
873    /// id + "!"` propagates `string` onto `id`.
874    pub(crate) enum_tuple_variant_fields:
875        HashMap<(String, String), Vec<shape_ast::ast::TypeAnnotation>>,
876    /// Cached const specializations keyed by `(base_name + const-arg fingerprint)`.
877    pub(crate) const_specializations: HashMap<String, usize>,
878    /// Monotonic counter for unique specialization symbol names.
879    pub(crate) next_const_specialization_id: u64,
880    /// Const-parameter bindings for specialized function symbols.
881    /// These bindings are exposed to comptime handlers as typed module_bindings.
882    /// Kinded carrier per ADR-006 §2.7 / Q7 (`KindedSlot`); the prior
883    /// `shape_value::ValueWord` shape was deleted by the strict-typing
884    /// bulldozer and the comptime ABI in
885    /// `compiler/comptime.rs:execute_comptime_with_annotation_handler`
886    /// already migrated to `(String, KindedSlot)` pairs.
887    pub(crate) specialization_const_bindings:
888        HashMap<String, Vec<(String, shape_value::KindedSlot)>>,
889
890    /// Struct type definitions: type_name -> (field_names in order, definition span)
891    pub(crate) struct_types: HashMap<String, (Vec<String>, shape_ast::ast::Span)>,
892    /// Generic metadata for struct types used to instantiate runtime type names
893    /// (e.g. `MyType<number>`) at struct-literal construction sites.
894    pub(crate) struct_generic_info: HashMap<String, StructGenericInfo>,
895    /// Names of `type C` declarations with native layout metadata.
896    pub(crate) native_layout_types: HashSet<String>,
897    /// Generated conversion pair cache keys: `c_type::object_type`.
898    pub(crate) generated_native_conversion_pairs: HashSet<String>,
899
900    /// Whether the current function being compiled is async
901    pub(crate) current_function_is_async: bool,
902
903    /// Directory of the source file being compiled (for resolving relative source paths)
904    pub(crate) source_dir: Option<std::path::PathBuf>,
905
906    /// Collected compilation errors (for multi-error reporting)
907    pub(crate) errors: Vec<shape_ast::error::ShapeError>,
908
909    /// Hoisted fields from optimistic hoisting pre-pass.
910    /// Maps variable name → list of property names assigned later (e.g., a.y = 2 → "a" → ["y"]).
911    /// Used to include future property assignments in inline object schemas at compile time.
912    pub(crate) hoisted_fields: HashMap<String, Vec<String>>,
913
914    /// Phase 3e: inferred FieldType for hoisted fields, when the assigned
915    /// RHS is a simple literal whose primitive type is statically known.
916    /// Maps variable name → property name → inferred FieldType.
917    ///
918    /// Used by `compile_typed_object_literal` to register the schema with
919    /// concrete primitive types (I64, F64, Bool, String) instead of falling
920    /// back to FieldType::Any. Without this, `let mut a = { x: 10 }; a.y =
921    /// 20; a.x + a.y` types `a.y` as Any in the schema, so the binary-op
922    /// numeric path declines and trait dispatch fires (which has no runtime
923    /// handler for `int.add`).
924    pub(crate) hoisted_field_types:
925        HashMap<String, HashMap<String, shape_runtime::type_schema::FieldType>>,
926
927    /// When compiling a variable initializer, the name of the variable being assigned to.
928    /// Used by compile_typed_object_literal to include hoisted fields in the schema.
929    pub(crate) pending_variable_name: Option<String>,
930
931    /// v2 Phase 3.1: when the enclosing `let arr: Array<T> = [...]` declares
932    /// an explicit `Array<T>` annotation whose element type maps to a
933    /// [`v2_typed_emission::TypedArrayKind`], stash the kind here so
934    /// `compile_expr_array` can lower the literal to a v2 typed-array
935    /// allocation. The statement-binding code path resets this to `None`
936    /// before each new initializer.
937    pub(crate) pending_variable_typed_array_kind:
938        Option<crate::compiler::v2_typed_emission::TypedArrayKind>,
939
940    /// R5.4B: nested-array-literal depth.
941    ///
942    /// Incremented while `compile_expr_array` compiles the elements of an
943    /// array literal, decremented after. When `> 0`, the compiler is inside
944    /// a nested array-literal context (e.g. the inner `[1.0, 2.0]` of
945    /// `[[1.0, 2.0], [3.0, 4.0]]`) and MUST refuse the typed-array fast
946    /// path (`NewTypedArrayF64`/etc.) regardless of annotation or
947    /// inference.
948    ///
949    /// Why: the v2 typed-array opcodes store the allocation as a raw
950    /// native pointer on the kinded VM stack with
951    /// `NativeKind::Ptr(HeapKind::TypedArray)` declared on the parallel-
952    /// kind track (ADR-006 §2.7.7), not as a generic heap-tagged value.
953    /// Downstream consumers that expect a generic `Array` via
954    /// `slot.as_heap_value()` cannot decode a typed-array native pointer
955    /// back into a generic Array (the deleted `as_heap_ref()` /
956    /// `as_any_array()` carrier accessors are gone), so e.g.
957    /// `intrinsic_matmul_mat` fails with "row 0 must be an array of
958    /// numeric values". Refusing typed emission for inner rows forces
959    /// them onto the legacy `NewArray` path, which produces a generic
960    /// `HeapValue::Array` that round-trips correctly through a generic
961    /// outer `Array`.
962    pub(crate) nested_array_literal_depth: u32,
963
964    /// v2 Phase 3.1: per-local-slot record of which locals hold a v2
965    /// typed array (allocated via `NewTypedArrayF64/I64/I32/Bool` rather
966    /// than the legacy v1 `NewTypedArray`/`NewArray`). Populated by the
967    /// statement-binding code path when an `Array<T>` annotation
968    /// successfully picks a typed kind. Consumed by
969    /// `resolve_receiver_typed_array_kind` so the typed Get/Set/Push/Len
970    /// opcodes are only emitted for receivers that were ALSO allocated
971    /// as v2 typed arrays — never for legacy NaN-boxed arrays.
972    pub(crate) v2_typed_array_locals:
973        HashMap<u16, crate::compiler::v2_typed_emission::TypedArrayKind>,
974    /// v2 Phase 3.1: per-module-binding record of v2 typed arrays.
975    /// Mirrors [`v2_typed_array_locals`] for top-level bindings.
976    pub(crate) v2_typed_array_module_bindings:
977        HashMap<u16, crate::compiler::v2_typed_emission::TypedArrayKind>,
978
979    /// Phase 4b Round 6 WS-1 W16.2-C (2026-05-21) — list-comprehension
980    /// element-kind capture.
981    ///
982    /// `compile_list_comprehension` emits the result accumulator's
983    /// `NewTypedArray*` allocator BEFORE the comprehension body is compiled,
984    /// but the element-expression's proven scalar kind is only known AFTER
985    /// the body compiles. `compile_comprehension_clauses` writes the proven
986    /// [`TypedArrayKind`] here at the innermost (clause-empty) base case,
987    /// reading the bytecode compiler's `last_expr_numeric_type` /
988    /// `last_expr_type_info` right after the element expression compiles —
989    /// per ADR-006 §2.7.5 the kind is proven at the producer site, never
990    /// fabricated. `compile_list_comprehension` then patches the recorded
991    /// allocator instruction with the matching typed opcode. `None` means
992    /// the element kind was not statically provable — a clean compile error.
993    pub(crate) comprehension_element_kind:
994        Option<crate::compiler::v2_typed_emission::TypedArrayKind>,
995
996    /// Phase 4b Round 6 WS-1 W16.2-C (2026-05-21) — instruction indices of
997    /// the placeholder `ArrayPush` opcodes emitted at list-comprehension
998    /// element-push sites. `compile_comprehension_clauses` records each
999    /// base-case push here; `compile_list_comprehension` patches them all
1000    /// to the resolved `TypedArrayPush*` opcode once the element kind is
1001    /// known — so the typed accumulator receives a typed push that the JIT
1002    /// and VM both dispatch unambiguously (no generic-carrier path).
1003    pub(crate) comprehension_push_sites: Vec<usize>,
1004
1005    /// Phase 4b Round 6 WS-1b W16.2-C residual (2026-05-21) — bare
1006    /// empty-array accumulator deferred-kind capture.
1007    ///
1008    /// A bare `let mut out = []` (empty array literal, no `Array<T>`
1009    /// annotation, no elements) cannot resolve its `TypedArrayKind` at the
1010    /// literal site — the element type is determined only by downstream
1011    /// `out.push(x)` calls. `compile_expr_array` emits a placeholder
1012    /// `NewArray(0)` and records its instruction index here against the
1013    /// binding (local slot or module binding). The FIRST `arr.push(v)` on
1014    /// that binding resolves the element kind from the compiled argument's
1015    /// proven type (ADR-006 §2.7.5 producer-side stamp — read from the
1016    /// type-tracker at the push site, never decoded from runtime bits, never
1017    /// Bool-defaulted), patches the placeholder to the matching typed
1018    /// `NewTypedArray*` allocator, and promotes the binding into
1019    /// `v2_typed_array_locals` / `v2_typed_array_module_bindings` so every
1020    /// subsequent push is a typed `TypedArrayPush*`. A bare empty array that
1021    /// is never pushed to and never annotated has a genuinely un-resolvable
1022    /// element type — `finalize_unresolved_empty_array_accumulators`
1023    /// surface-and-stops with a clean structured compile error.
1024    pub(crate) empty_array_accumulators: HashMap<EmptyArrayAccumulatorKey, EmptyArrayAccumulator>,
1025
1026    /// Phase 4b Round 6 WS-1b — instruction index of the placeholder
1027    /// `NewArray(0)` emitted by the most recent `compile_expr_array` call for
1028    /// a bare empty array literal. The enclosing `Statement::VariableDecl` /
1029    /// `Item::VariableDecl` reads this immediately after the initializer
1030    /// compiles and re-keys it into [`empty_array_accumulators`] against the
1031    /// resolved binding. `None` when the last array literal was non-empty,
1032    /// annotated, or otherwise resolved a kind directly.
1033    pub(crate) pending_empty_array_alloc_idx: Option<usize>,
1034
1035    /// v2 Phase 3.2: when the enclosing `let m: HashMap<K, V> = HashMap()`
1036    /// declares an explicit `HashMap<K, V>` annotation whose key/value pair
1037    /// maps to a [`v2_typed_map_emission::TypedMapKind`], stash the kind here
1038    /// so `compile_expr_function_call` (HashMap ctor path) can lower the
1039    /// allocation to a v2 typed-map opcode. The statement-binding code path
1040    /// resets this to `None` before each new initializer.
1041    pub(crate) pending_variable_typed_map_kind:
1042        Option<crate::compiler::v2_typed_map_emission::TypedMapKind>,
1043
1044    /// v2 Phase 3.2: per-local-slot record of which locals hold a v2 typed
1045    /// HashMap (allocated via `NewTypedMap*` rather than the legacy
1046    /// `BuiltinCall(HashMapCtor)`). Populated by the statement-binding code
1047    /// path. Consumed by HashMap method dispatch (`m.set/.get/.has/.delete`)
1048    /// so the typed Set/Get/Has/Delete opcodes are only emitted for receivers
1049    /// that were ALSO allocated as v2 typed maps — never for legacy NaN-boxed
1050    /// HashMapData.
1051    pub(crate) v2_typed_map_locals:
1052        HashMap<u16, crate::compiler::v2_typed_map_emission::TypedMapKind>,
1053
1054    /// v2 Phase 3.2: per-module-binding record of v2 typed maps. Mirrors
1055    /// [`v2_typed_map_locals`] for top-level bindings.
1056    pub(crate) v2_typed_map_module_bindings:
1057        HashMap<u16, crate::compiler::v2_typed_map_emission::TypedMapKind>,
1058
1059    /// ADR-006 §2.7.27 / Item 4 ruling (W17-mutation-writeback, 2026-05-12):
1060    /// per-local-slot record of locals known to hold a Copy-on-Write
1061    /// collection (HashSet / HashMap / Deque / PriorityQueue / Array of
1062    /// generic carrier). Populated at let-binding time when the initializer
1063    /// is one of `Set()` / `HashMap()` / `Deque()` / `PriorityQueue()` /
1064    /// `[…]`, or when the binding has an explicit type annotation that
1065    /// names the container kind.
1066    ///
1067    /// Consumed by `compile_expr_method_call`'s `&mut self` writeback
1068    /// emission gate: for an identifier-receiver method call where
1069    /// `(container_kind, method_name)` matches a `MUT_SELF_*` entry, the
1070    /// compiler emits `Dup; StoreLocal recv` after `CallMethod` so the
1071    /// new (possibly Arc-cloned) receiver Arc updates the binding slot.
1072    pub(crate) mut_self_container_locals:
1073        HashMap<u16, crate::compiler::mutation_writeback::ContainerKind>,
1074
1075    /// ADR-006 §2.7.27 / Item 4 ruling: per-module-binding record of
1076    /// mutating-container module bindings. Mirrors
1077    /// [`mut_self_container_locals`] for top-level bindings.
1078    pub(crate) mut_self_container_bindings:
1079        HashMap<u16, crate::compiler::mutation_writeback::ContainerKind>,
1080
1081    /// ADR-006 §2.7.27 / Item 4 ruling: signal raised by container-ctor
1082    /// builtin call emitters (`SetCtor`, `DequeCtor`,
1083    /// `PriorityQueueCtor`, `HashMapCtor`) so the surrounding statement-
1084    /// binding code path can transfer the kind onto the target local
1085    /// / module binding. Mirrors the existing
1086    /// [`pending_variable_typed_array_kind`] convention.
1087    pub(crate) pending_variable_container_kind:
1088        Option<crate::compiler::mutation_writeback::ContainerKind>,
1089
1090    /// v2 Phase 3.2: per-AST-node side table mapping a HashMap-shaped
1091    /// expression to its key/value `ConcreteType` pair. Populated by the
1092    /// `let m: HashMap<K, V> = ...` annotation path AND by inference helpers
1093    /// (`infer_hashmap_kv_from_context`).
1094    pub(crate) map_key_value_types: HashMap<
1095        shape_ast::ast::Span,
1096        (shape_value::v2::ConcreteType, shape_value::v2::ConcreteType),
1097    >,
1098
1099    /// v2 Phase 3.2: per-local-slot side table for HashMap key/value pairs.
1100    pub(crate) local_map_key_value_types:
1101        HashMap<u16, (shape_value::v2::ConcreteType, shape_value::v2::ConcreteType)>,
1102
1103    /// v2 Phase 3.2: per-module-binding side table for HashMap key/value pairs.
1104    pub(crate) module_binding_map_key_value_types:
1105        HashMap<u16, (shape_value::v2::ConcreteType, shape_value::v2::ConcreteType)>,
1106
1107    /// v2 Phase 3.2: per-AST-span array element type table — used by
1108    /// monomorphization helpers and methods that produce arrays from maps.
1109    pub(crate) array_element_types: HashMap<shape_ast::ast::Span, shape_value::v2::ConcreteType>,
1110
1111    /// v2 Phase 3.2: per-local-slot array element type table.
1112    pub(crate) local_array_element_types: HashMap<u16, shape_value::v2::ConcreteType>,
1113
1114    /// v2 Phase 3.2: per-module-binding array element type table.
1115    pub(crate) module_binding_array_element_types: HashMap<u16, shape_value::v2::ConcreteType>,
1116    /// Lexical names that will later need their binding value to remain a raw reference.
1117    /// This is only used to choose `Value` vs `PreserveRef` lowering for bindings; MIR
1118    /// remains the sole authority for borrow legality.
1119    pub(crate) future_reference_use_name_scopes: Vec<HashSet<String>>,
1120
1121    /// Known trait names (populated in the first pass so meta definitions can reference traits)
1122    pub(crate) known_traits: std::collections::HashSet<String>,
1123
1124    /// Full trait definitions keyed by trait name.
1125    /// Used to install default method implementations for impl blocks that omit them.
1126    pub(crate) trait_defs: HashMap<String, shape_ast::ast::types::TraitDef>,
1127
1128    /// J-CT.2 (2026-05-23) — comptime impl blocks deferred for in-mini-VM
1129    /// registration. The outer compiler does NOT desugar/register/compile
1130    /// methods of `comptime impl Trait for Type { ... }` blocks into the
1131    /// runtime program; they are skipped from runtime processing and stored
1132    /// here so the comptime-evaluator mini-VM (`execute_comptime` in
1133    /// `compiler/comptime.rs`) can prepend them as `Item::Impl` items, where
1134    /// the in-comptime-mode compiler then desugars + compiles them normally.
1135    /// Method dispatch from `instance.method()` inside a `comptime { }` block
1136    /// then routes through the standard UFCS / `Type::method` resolution
1137    /// path without a new dispatch shape (audit §2.D carve-out).
1138    pub(crate) comptime_impl_blocks: Vec<shape_ast::ast::types::ImplBlock>,
1139
1140    /// J-CT.2 (2026-05-23) — original struct definitions captured during
1141    /// the first pass. The outer compiler only retains field NAMES in
1142    /// `struct_types`; the comptime-evaluator mini-VM needs full AST
1143    /// (typed annotations, generic info, annotations) to compile
1144    /// struct-literal constructions and field accesses inside `comptime { }`
1145    /// blocks that interact with `comptime_impl_blocks`. Populated in the
1146    /// first-pass `Item::StructType` arm.
1147    pub(crate) comptime_context_struct_defs:
1148        HashMap<String, shape_ast::ast::types::StructTypeDef>,
1149
1150    /// Extension registry for comptime execution
1151    pub(crate) extension_registry: Option<Arc<Vec<shape_runtime::module_exports::ModuleExports>>>,
1152
1153    /// Comptime field values per type: type_name -> (field_name -> bake-time
1154    /// constant). These are type-level constants baked at compile time
1155    /// with zero runtime cost. Inner map releases heap-backed comptime
1156    /// values (strings via `Arc<String>`, etc.) when a type's entry is
1157    /// removed or the compiler is dropped.
1158    ///
1159    /// Kinded carrier per ADR-006 §2.7 / Q7 (`KindedSlot`); the prior
1160    /// `shape_value::ValueMap` shape was deleted by the strict-typing
1161    /// bulldozer along with `ValueWord`. Mirrors the
1162    /// `comptime_builtins::ComptimeDirective::SetParamValue { value:
1163    /// KindedSlot }` migration already landed in
1164    /// `compiler/comptime_builtins.rs`.
1165    pub(crate) comptime_fields:
1166        HashMap<String, HashMap<String, shape_value::KindedSlot>>,
1167    /// Type diagnostic mode for shared analyzer diagnostics.
1168    pub(crate) type_diagnostic_mode: TypeDiagnosticMode,
1169    /// Expression compilation diagnostic mode.
1170    pub(crate) compile_diagnostic_mode: CompileDiagnosticMode,
1171    /// Whether this compiler instance is compiling code for comptime execution.
1172    /// Enables comptime-only builtins and comptime-specific statement semantics.
1173    pub(crate) comptime_mode: bool,
1174    /// Functions removed by comptime annotation handlers (`remove target`).
1175    /// These are still present in `program.functions` (registered in the first pass)
1176    /// but must produce a clear compile-time error when called instead of jumping
1177    /// to an invalid entry point.
1178    pub(crate) removed_functions: HashSet<String>,
1179    /// Internal guard for compiler-synthesized `__comptime__` helper calls.
1180    /// User source must never access `__comptime__` directly.
1181    pub(crate) allow_internal_comptime_namespace: bool,
1182    /// Method table for data-driven method signature queries.
1183    /// Used to replace hardcoded heuristics (e.g., is_type_preserving_table_method)
1184    /// with MethodTable lookups (is_self_returning, takes_closure_with_receiver_param).
1185    pub(crate) method_table: MethodTable,
1186    /// Locals that are reference-typed in the current function.
1187    pub(crate) ref_locals: HashSet<u16>,
1188    /// Subset of ref_locals that hold exclusive (`&mut`) borrows.
1189    /// Used to enforce the three concurrency rules at task boundaries.
1190    pub(crate) exclusive_ref_locals: HashSet<u16>,
1191    /// Subset of ref_locals that were INFERRED as by-reference (not explicitly declared `&`).
1192    /// Inferred-ref params are owned values passed by reference for performance;
1193    /// closures may capture them (the value is dereferenced at capture time).
1194    pub(crate) inferred_ref_locals: HashSet<u16>,
1195    /// Locals whose binding value is itself a first-class reference (`let r = &x`).
1196    /// Reads auto-deref; writes still rebind the local.
1197    pub(crate) reference_value_locals: HashSet<u16>,
1198    /// Subset of reference_value_locals that hold exclusive (`&mut`) references.
1199    pub(crate) exclusive_reference_value_locals: HashSet<u16>,
1200    /// Local variable indices declared as `const` (immutable binding).
1201    pub(crate) const_locals: HashSet<u16>,
1202    /// Module binding indices declared as `const` (immutable binding).
1203    pub(crate) const_module_bindings: HashSet<u16>,
1204    /// Local variable indices declared as immutable `let` (not `let mut` or `var`).
1205    pub(crate) immutable_locals: HashSet<u16>,
1206    /// Local variable indices that are function parameters (first N locals in a function).
1207    /// Used to avoid trusting inferred type hints for params with no explicit annotation.
1208    pub(crate) param_locals: HashSet<u16>,
1209    /// Module binding indices declared as immutable `let`.
1210    pub(crate) immutable_module_bindings: HashSet<u16>,
1211    /// Module bindings whose value is itself a first-class reference.
1212    pub(crate) reference_value_module_bindings: HashSet<u16>,
1213    /// Subset of reference_value_module_bindings that hold exclusive (`&mut`) references.
1214    pub(crate) exclusive_reference_value_module_bindings: HashSet<u16>,
1215    /// ModuleBinding-ref writebacks collected while compiling current call args.
1216    pub(crate) call_arg_module_binding_ref_writebacks: Vec<Vec<(u16, u16)>>,
1217    /// Inferred reference parameters for untyped params: function -> per-param flag.
1218    pub(crate) inferred_ref_params: HashMap<String, Vec<bool>>,
1219    /// Inferred mutating-reference params: function -> per-param flag.
1220    pub(crate) inferred_ref_mutates: HashMap<String, Vec<bool>>,
1221    /// Effective per-parameter pass mode (explicit + inferred), by function name.
1222    pub(crate) inferred_param_pass_modes: HashMap<String, Vec<ParamPassMode>>,
1223    /// Inferred parameter type hints for unannotated params.
1224    /// Keyed by function name; each entry is a per-param optional type string.
1225    pub(crate) inferred_param_type_hints: HashMap<String, Vec<Option<String>>>,
1226    /// v0.3 WS-7: inference-resolved per-parameter `ConcreteType` for
1227    /// UNANNOTATED params. Keyed by function name; each entry is a per-param
1228    /// optional `ConcreteType` projected from the program-wide type-inference
1229    /// engine's result. Annotated params keep `None` here (their
1230    /// `ConcreteType` is stamped directly from the annotation in the
1231    /// `function_local_concrete_types` per-fn seeding pass). This is the
1232    /// proof source that lets the JIT take the v2 typed-array fast path for
1233    /// `fn get(xs, i) { xs[i] }`-style unannotated array parameters — without
1234    /// it the slot stays `ConcreteType::Void`, the JIT mis-classifies the v2
1235    /// `TypedArray` pointer as a NaN-boxed v1 array, and the inline index
1236    /// load reads garbage / SIGSEGVs.
1237    pub(crate) inferred_param_concrete_types:
1238        HashMap<String, Vec<Option<shape_value::v2::ConcreteType>>>,
1239    /// WS-9b: inference-resolved per-parameter ANONYMOUS-OBJECT field
1240    /// definitions for UNANNOTATED params. Keyed by function name; each
1241    /// entry is a per-param optional `Vec<(field_name, FieldType)>`.
1242    ///
1243    /// A *named* struct parameter (`type Box`) resolves through the schema
1244    /// registry — `set_local_type_info` already stamps its `schema_id` from
1245    /// the `"Box"` hint name. But an *anonymous* object parameter (the shape
1246    /// `fn aabb(...) { { min_x: ..., ... } }` produces) has no named schema:
1247    /// its inference hint is the structural string `"{min_x: number, ...}"`,
1248    /// which matches no registered schema. `compile_function_body` consumes
1249    /// this map to register an inline `__inline_obj_*` schema for such a
1250    /// parameter and stamp the slot's `schema_id`, so `param.field` resolves
1251    /// to the proven field type the same way a named-struct field does. The
1252    /// field types are projected from inference's resolved param `Type` —
1253    /// proven, never fabricated; an unresolved field yields `None`.
1254    pub(crate) inferred_param_object_fields: HashMap<
1255        String,
1256        Vec<Option<Vec<(String, shape_runtime::type_schema::FieldType)>>>,
1257    >,
1258    /// WS-9c: per-function inferred RETURN type projected to a
1259    /// `Vec<(field_name, FieldType)>` when that return type is an anonymous
1260    /// structural object (an unannotated object-literal factory such as
1261    /// `fn aabb(lo, hi) { {min: lo, max: hi} }`). `compile_expr_function_call`
1262    /// consumes this to register an inline anonymous schema for the call's
1263    /// result so `aabb(...).field` / `let a = aabb(...); a.field` resolves to
1264    /// the proven field type — the same resolution a named-struct return type
1265    /// already receives. Only unannotated functions appear here (annotated
1266    /// returns resolve through the annotation path). Field types are projected
1267    /// from inference's resolved return `Type` — proven, never fabricated.
1268    pub(crate) inferred_return_object_fields:
1269        HashMap<String, Vec<(String, shape_runtime::type_schema::FieldType)>>,
1270    /// WS-9c: function name → registered inline anonymous schema id for an
1271    /// unannotated function whose inferred return type is an anonymous
1272    /// object. Populated once, up-front, by
1273    /// `register_inferred_return_object_schemas`. Consulted by
1274    /// `compile_expr_function_call` (to stamp `last_expr_schema`) and by the
1275    /// read-only `infer_expr_type` property-access path (to resolve
1276    /// `f(...).field` directly, with no `let` binding).
1277    pub(crate) function_return_schema_ids: HashMap<String, u32>,
1278    /// Stack of scopes, each containing locals that need Drop calls at scope exit.
1279    /// Each entry is (local_index, is_async).
1280    pub(crate) drop_locals: Vec<Vec<(u16, bool)>>,
1281    /// Phase V1.1C: parallel scope stack tracking locals whose storage class
1282    /// is `UniqueHeap` and therefore (when the ownership-moves flag is on)
1283    /// need an ownership-aware `DropLocal` opcode emitted at scope exit to
1284    /// release the owned heap allocation. Orthogonal to `drop_locals` (which
1285    /// drives user-facing `Drop` trait calls via `DropCall`). Populated and
1286    /// consumed only when `ownership_moves_enabled()` is true; otherwise the
1287    /// scope stack is pushed/popped in lockstep with `drop_locals` but kept
1288    /// empty, so the compiler's emission path is byte-identical to
1289    /// pre-V1.1C.
1290    pub(crate) ownership_drop_locals: Vec<Vec<u16>>,
1291    /// Per-type drop kind: tracks whether each type has sync, async, or both drop impls.
1292    /// Populated during the first-pass registration of impl blocks.
1293    pub(crate) drop_type_info: HashMap<String, DropKind>,
1294    /// Module bindings that need Drop calls at program exit.
1295    /// Each entry is (binding_index, is_async).
1296    pub(crate) drop_module_bindings: Vec<(u16, bool)>,
1297    /// Mutable closure captures in the current function being compiled.
1298    /// Maps captured variable name -> upvalue index (for LoadClosure/StoreClosure).
1299    /// Only populated while compiling a closure body that has mutable captures.
1300    pub(crate) mutable_closure_captures: HashMap<String, u16>,
1301
1302    /// Track A.1C.2: subset of `mutable_closure_captures` whose source
1303    /// binding classifies as `CaptureKind::Shared` (a `var` binding
1304    /// mutably captured through a closure). Maps captured variable name
1305    /// → capture index. When the identifier lookup finds a name in this
1306    /// map, the closure body emits `LoadSharedCapture` /
1307    /// `StoreSharedCapture` (A.1B) instead of the legacy `LoadClosure`
1308    /// / `StoreClosure`. Populated while compiling a closure body.
1309    pub(crate) shared_closure_captures: HashMap<String, u16>,
1310
1311    /// Track A.1C.2b: subset of `mutable_closure_captures` whose source
1312    /// binding classifies as `CaptureKind::OwnedMutable` (a `let mut`
1313    /// binding captured by move into a single closure). Maps captured
1314    /// variable name → capture index. When the identifier lookup finds
1315    /// a name in this map, the closure body emits
1316    /// `LoadOwnedMutableCapture` / `StoreOwnedMutableCapture` (A.1B)
1317    /// instead of the legacy `LoadClosure` / `StoreClosure`. Populated
1318    /// while compiling a closure body.
1319    pub(crate) owned_mutable_closure_captures: HashMap<String, u16>,
1320
1321    /// Wave E: parallel to `owned_mutable_closure_captures`, records
1322    /// the interior `FieldKind` of each OwnedMutable capture cell. The
1323    /// inner kind is derived from the captured binding's resolved
1324    /// `ConcreteType` (`concrete_type_for_expr → ConcreteType::to_field_kind`)
1325    /// at the point of closure construction. The closure body uses
1326    /// this map to dispatch to the typed Wave D.1 opcodes
1327    /// (`LoadOwnedMutableCapture<Kind>` / `StoreOwnedMutableCapture<Kind>`,
1328    /// codes 0x140-0x155) instead of the legacy untyped `0x132`/`0x133`
1329    /// opcodes (kind-erased pre-strict-typing — ADR-006 §2.7.7).
1330    /// Populated alongside `owned_mutable_closure_captures`,
1331    /// saved/restored across nested closure-body compilations.
1332    pub(crate) owned_mutable_capture_inner_kinds:
1333        HashMap<String, shape_value::v2::struct_layout::FieldKind>,
1334
1335    /// A2-refined / task #17: parallel to `shared_closure_captures`,
1336    /// records the interior `FieldKind` of each Shared (`var`) capture
1337    /// cell. Derived from the captured binding's resolved `ConcreteType`
1338    /// at closure-construction time, mirroring
1339    /// `owned_mutable_capture_inner_kinds`. The closure body uses this
1340    /// map to dispatch to the typed Wave D.2 opcodes
1341    /// (`LoadSharedCapture<Kind>` / `StoreSharedCapture<Kind>`, codes
1342    /// 0x156-0x16B) instead of the legacy untyped `0x134`/`0x135`
1343    /// opcodes (kind-erased pre-strict-typing — ADR-006 §2.7.7).
1344    /// Saved/restored across nested closure-body compilations.
1345    pub(crate) shared_capture_inner_kinds:
1346        HashMap<String, shape_value::v2::struct_layout::FieldKind>,
1347
1348    /// Variables in the current scope that have been boxed into SharedCells
1349    /// by a mutable closure capture. When a subsequent closure captures one
1350    /// of these variables (even immutably), it must use the SharedCell path
1351    /// so it shares the same mutable cell.
1352    pub(crate) boxed_locals: HashSet<String>,
1353
1354    /// Track A.1C.2: local slots that have been promoted to
1355    /// `Arc<parking_lot::Mutex<u64>>` via the `AllocSharedLocal`
1356    /// opcode (with the matching `NativeKind` declared on the cell's
1357    /// parallel-kind track per ADR-006 §2.7.8). After promotion, every
1358    /// outer-scope read/write of the slot
1359    /// must go through `LoadSharedLocal` / `StoreSharedLocal` (never plain
1360    /// `LoadLocal` / `StoreLocal`), and scope exit must emit
1361    /// `DropSharedLocal` so the Arc strong count is released exactly once
1362    /// per owning frame.
1363    ///
1364    /// Keyed by the binding *name* (mirroring `boxed_locals`). Populated
1365    /// by `compile_expr_closure` when a `var` capture escapes into a
1366    /// closure and gets classified as `CaptureKind::Shared`.
1367    pub(crate) shared_locals: HashSet<String>,
1368
1369    /// Track A.1C.3: local names that have been classified as
1370    /// `CaptureKind::OwnedMutable` by at least one closure in the
1371    /// current function scope. Needed because `binding_semantics_for_name`
1372    /// can return `None` after an inner closure's `compile_function`
1373    /// wipes the type-tracker local semantics, and we need the
1374    /// classification to be stable across sibling closures (otherwise
1375    /// a second closure capturing a different `let mut` local could
1376    /// fall back to `Immutable`, nulling the layout's OwnedMutable mask
1377    /// bit and triggering a layout mismatch in `op_make_closure`).
1378    pub(crate) owned_mutable_locals: HashSet<String>,
1379
1380    /// Session 1 (Rust-move semantics for `let mut`): names of `let mut`
1381    /// local bindings that have been **moved by value into a closure
1382    /// capture** (i.e. classified as `CaptureKind::OwnedMutable` and
1383    /// emitted at `op_make_closure` time as `Box::into_raw(Box::new(bits))`).
1384    /// After the move, the outer slot holds only a stale snapshot of the
1385    /// initial value — every subsequent outer-scope read or write of the
1386    /// same binding is a compile error ("use-after-move").
1387    ///
1388    /// Stored as `name → span-of-the-capturing-closure` so the diagnostic
1389    /// can point the user at the exact capture site that consumed the
1390    /// binding. Populated in `compile_expr_closure`, consulted in
1391    /// `compile_expr_identifier` and `compile_expr_assign`. Saved /
1392    /// restored across nested `compile_function` calls, mirroring the
1393    /// `shared_locals` / `owned_mutable_locals` discipline.
1394    pub(crate) captured_let_mut_moved: HashMap<String, Span>,
1395
1396    /// Track A.1C.3: module-binding slots that have been promoted to
1397    /// `Arc<parking_lot::Mutex<u64>>` via `AllocSharedModuleBinding`
1398    /// (with the matching `NativeKind` declared on the cell's
1399    /// parallel-kind track per ADR-006 §2.7.8).
1400    /// After promotion, every outer-scope read/write of the binding must
1401    /// go through `LoadSharedModuleBinding` / `StoreSharedModuleBinding`
1402    /// (never plain `LoadModuleBinding` / `StoreModuleBinding`). Keyed
1403    /// by the binding's **scoped name** — the same key used by
1404    /// `resolve_scoped_module_binding_name` and the `module_bindings`
1405    /// index map. Populated by `compile_expr_closure` when a
1406    /// module-scope `var` is captured mutably.
1407    pub(crate) shared_module_bindings: HashSet<String>,
1408
1409    /// Track A.1C.2: per-scope stack of slot indices that need a
1410    /// `DropSharedLocal` opcode at scope exit, mirroring the
1411    /// `ownership_drop_locals` discipline. Push in lockstep with
1412    /// `push_drop_scope`; pop and emit in lockstep with `pop_drop_scope`.
1413    pub(crate) shared_drop_locals: Vec<Vec<u16>>,
1414
1415    /// Active permission set for capability checking.
1416    ///
1417    /// When set, imported stdlib functions are checked against capability_tags.
1418    /// If a function requires a permission not in this set, a compile error is
1419    /// emitted and the function never enters bytecode.
1420    ///
1421    /// `None` means no checking (backwards-compatible default).
1422    pub(crate) permission_set: Option<shape_abi_v1::PermissionSet>,
1423
1424    // -- Content-addressed blob tracking --
1425    /// Active blob builder (set while compiling a function body).
1426    pub(crate) current_blob_builder: Option<FunctionBlobBuilder>,
1427    /// Completed function blobs (finalized with content hash).
1428    pub(crate) completed_blobs: Vec<FunctionBlob>,
1429    /// Map from function name to content hash (populated after finalization).
1430    pub(crate) blob_name_to_hash: HashMap<String, FunctionHash>,
1431    /// The content-addressed program produced alongside BytecodeProgram.
1432    pub(crate) content_addressed_program: Option<ContentAddressedProgram>,
1433    /// Content hash per compiled function index (function_id -> blob hash).
1434    /// This is the stable identity bridge for the flat runtime format.
1435    pub(crate) function_hashes_by_id: Vec<Option<FunctionHash>>,
1436
1437    /// Optional blob-level cache for incremental compilation.
1438    /// When set, compiled blobs are stored after finalization and looked up
1439    /// by content hash to avoid redundant work across compilations.
1440    pub(crate) blob_cache: Option<BlobCache>,
1441
1442    /// Temporary function name aliases for comptime replace body.
1443    /// Maps alias (e.g., `__original__`) to actual function name (e.g., `__original__myFunc`).
1444    /// Set before compiling a replacement body and cleared after.
1445    pub(crate) function_aliases: HashMap<String, String>,
1446
1447    /// Parameters of the function currently being compiled.
1448    /// Used by match exhaustiveness checking to fall back to type annotations
1449    /// when the type inference engine cannot resolve a parameter's type.
1450    pub(crate) current_function_params: Vec<shape_ast::ast::FunctionParameter>,
1451
1452    /// Legacy cache of function names collected from stdlib-loaded modules.
1453    ///
1454    /// Internal builtin access is now gated by per-definition declaring-module
1455    /// provenance, not by membership in this set.
1456    pub stdlib_function_names: HashSet<String>,
1457
1458    /// Per-function flag: when true, `get_builtin_function` resolves `__*` names.
1459    /// Toggled during compilation for definitions originating from `std::*`.
1460    pub(crate) allow_internal_builtins: bool,
1461
1462    /// Package-scoped native library resolutions for the current host.
1463    pub(crate) native_resolution_context:
1464        Option<shape_runtime::native_resolution::NativeResolutionSet>,
1465
1466    /// Active synthetic MIR context while compiling non-function code.
1467    pub(crate) non_function_mir_context_stack: Vec<String>,
1468
1469    /// MIR lowered for compiled functions and synthetic non-function contexts.
1470    pub(crate) mir_functions: HashMap<String, crate::mir::types::MirFunction>,
1471
1472    /// Borrow analyses produced from lowered MIR for compiled functions and
1473    /// synthetic non-function contexts.
1474    pub(crate) mir_borrow_analyses: HashMap<String, crate::mir::BorrowAnalysis>,
1475
1476    /// Storage plans produced by the storage planning pass for each function.
1477    /// Maps function name to the plan mapping each MIR slot to a `BindingStorageClass`.
1478    pub(crate) mir_storage_plans: HashMap<String, crate::mir::StoragePlan>,
1479
1480    /// Per-function borrow summaries for interprocedural alias checking.
1481    /// Describes which parameters conflict and must not alias at call sites.
1482    pub(crate) function_borrow_summaries: HashMap<String, crate::mir::FunctionBorrowSummary>,
1483
1484    /// Per-function mapping from AST spans to MIR program points.
1485    /// Used to bridge the bytecode compiler (which knows AST spans) to
1486    /// MIR ownership decisions (which are keyed by `Point`).
1487    pub(crate) mir_span_to_point:
1488        HashMap<String, HashMap<shape_ast::ast::Span, crate::mir::types::Point>>,
1489
1490    /// Field-level definite-initialization and liveness analyses for compiled functions.
1491    pub(crate) mir_field_analyses: HashMap<String, crate::mir::FieldAnalysis>,
1492
1493    /// Graph-compiled namespace map: local namespace name -> canonical module path.
1494    /// Populated during graph-driven compilation to resolve qualified names.
1495    pub(crate) graph_namespace_map: HashMap<String, String>,
1496
1497    /// Module dependency graph (set during graph-driven compilation).
1498    pub(crate) module_graph: Option<std::sync::Arc<crate::module_graph::ModuleGraph>>,
1499
1500    /// Per-local-slot concrete type table for the function currently being compiled.
1501    pub(crate) current_function_local_concrete_types: HashMap<u16, shape_value::v2::ConcreteType>,
1502
1503    /// v0.3 WS-6 — per-module-binding concrete type table, populated at
1504    /// let-binding time from the binding's explicit `TypeAnnotation`.
1505    ///
1506    /// Consumed by the monomorphization call-site resolver
1507    /// (`identifier_concrete_type`) so a generic free-function call whose
1508    /// argument is a variable with an explicit struct / enum / `Option<T>` /
1509    /// `Result<T, E>` / `HashMap<K, V>` annotation can bind its type
1510    /// parameter — `let n: Option<int> = ...; id(n)`. The array / map
1511    /// element side-tables (`module_binding_array_element_types`,
1512    /// `module_binding_map_key_value_types`) already cover the
1513    /// container-element cases; this table covers the remaining
1514    /// fully-annotated shapes.
1515    pub(crate) module_binding_concrete_types: HashMap<u16, shape_value::v2::ConcreteType>,
1516
1517    /// Monomorphization cache for generic function specialization.
1518    pub(crate) monomorphization_cache: monomorphization::cache::MonomorphizationCache,
1519
1520    /// BUG3 — cycle detector for generic method / free-function monomorphization.
1521    ///
1522    /// Holds the set of `mono_key`s whose specialization is currently being
1523    /// compiled further down the call stack. If `ensure_monomorphic_function`
1524    /// is (re-)entered for a key that is already in-progress, it means the
1525    /// specialized body is transitively trying to resolve itself before its
1526    /// own `compile_function` has finished — without the guard this would
1527    /// overflow the compiler stack or cache the wrong index. The entry is
1528    /// inserted BEFORE the inner `compile_function` call and removed right
1529    /// after, whether compilation succeeded or failed.
1530    ///
1531    /// Note: direct self-recursion in the body is already handled by the
1532    /// cache-insert-before-compile behaviour; this guard only fires on the
1533    /// pathological transitive-resolution cycle.
1534    pub(crate) monomorphization_in_progress: std::collections::HashSet<String>,
1535
1536    /// Monotonic counter for monomorphization specialization IDs.
1537    pub(crate) next_monomorphization_id: u64,
1538
1539    /// Phase C — running count of closure-aware specializations emitted in
1540    /// the current module. When this exceeds
1541    /// [`monomorphization::cache::DEFAULT_CLOSURE_SPECIALIZATION_BUDGET`],
1542    /// further closure-aware specializations bail back to the generic
1543    /// (non-inlined) dispatch path.
1544    pub(crate) closure_specialization_count: u32,
1545}
1546
1547impl Default for BytecodeCompiler {
1548    fn default() -> Self {
1549        Self::new()
1550    }
1551}
1552
1553mod compiler_impl_initialization;
1554mod compiler_impl_reference_model;
1555
1556/// Infer effective reference parameters and mutation behavior without compiling bytecode.
1557///
1558/// Returns `(inferred_ref_params, inferred_ref_mutates)` keyed by function name.
1559/// - `inferred_ref_params[f][i] == true` means parameter `i` of `f` is inferred/treated as ref.
1560/// - `inferred_ref_mutates[f][i] == true` means that reference parameter is mutating (`&mut`).
1561pub fn infer_reference_model(
1562    program: &Program,
1563) -> (HashMap<String, Vec<bool>>, HashMap<String, Vec<bool>>) {
1564    let (inferred_ref_params, inferred_ref_mutates, _, _, _, _, _) =
1565        BytecodeCompiler::infer_reference_model(program);
1566    (inferred_ref_params, inferred_ref_mutates)
1567}
1568
1569/// Infer effective parameter pass modes (`ByValue` / `ByRefShared` / `ByRefExclusive`)
1570/// keyed by function name.
1571pub fn infer_param_pass_modes(program: &Program) -> HashMap<String, Vec<ParamPassMode>> {
1572    let (inferred_ref_params, inferred_ref_mutates, _, _, _, _, _) =
1573        BytecodeCompiler::infer_reference_model(program);
1574    BytecodeCompiler::build_param_pass_mode_map(
1575        program,
1576        &inferred_ref_params,
1577        &inferred_ref_mutates,
1578    )
1579}
1580
1581// ADR-006 §2.7.4 / §2.7.7 — Phase 2c deferral.
1582//
1583// `compiler_tests.rs` is a deep test harness that uses `eval()`-style
1584// helpers returning the deleted `shape_value::ValueWord`. Per playbook
1585// §7 REVISED #4, the correct surface for a non-migratable test site is
1586// `cfg(any())`-gating rather than reintroducing the §2.7.7 forbidden
1587// carrier. Re-enabling is Phase 2c work tracked in playbook §10's
1588// Wave-β B12 deferral pattern.
1589#[cfg(any())]
1590#[path = "compiler_tests.rs"]
1591mod compiler_deep;
1592pub(crate) mod v2_array_emission;
1593pub(crate) mod v2_map_emission;
1594pub(crate) mod v2_typed_emission;
1595pub(crate) mod v2_typed_map_emission;
1596
1597// ADR-006 §2.7.27 / Item 4 ruling (W17-mutation-writeback, 2026-05-12):
1598// compile-time write-back emission for `&mut self` opt-in methods on
1599// COW container receivers (HashSet / HashMap / Array / Deque /
1600// PriorityQueue / TypedArray).
1601pub(crate) mod mutation_writeback;