2025-08-12 11:33:48 +00:00
|
|
|
|
/*!
|
|
|
|
|
|
* MIR Builder - Converts AST to MIR/SSA form
|
2025-09-17 07:43:07 +09:00
|
|
|
|
*
|
2025-08-12 11:33:48 +00:00
|
|
|
|
* Implements AST → MIR conversion with SSA construction
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
use super::{
|
2025-12-27 16:45:13 +09:00
|
|
|
|
BasicBlock, BasicBlockId, CompareOp, ConstValue, Effect, EffectMask, FunctionSignature,
|
|
|
|
|
|
MirFunction, MirInstruction, MirModule, MirType, ValueId,
|
2025-08-12 11:33:48 +00:00
|
|
|
|
};
|
2025-12-27 16:45:13 +09:00
|
|
|
|
pub(crate) use builder_calls::CallTarget;
|
2025-12-19 08:36:45 +09:00
|
|
|
|
use std::collections::HashMap;
|
2025-12-16 07:02:14 +09:00
|
|
|
|
mod binding_context; // Phase 136 follow-up (Step 4/7): BindingContext extraction
|
2025-12-27 16:45:13 +09:00
|
|
|
|
mod builder_build;
|
|
|
|
|
|
mod builder_debug;
|
|
|
|
|
|
mod builder_emit;
|
|
|
|
|
|
mod builder_init;
|
|
|
|
|
|
mod builder_metadata;
|
|
|
|
|
|
mod builder_method_index;
|
|
|
|
|
|
mod builder_value_kind;
|
2025-12-27 17:41:30 +09:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod builder_test_api;
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod phi_observation_tests;
|
2025-09-03 01:37:38 +09:00
|
|
|
|
mod builder_calls;
|
2025-09-24 01:05:44 +09:00
|
|
|
|
mod call_resolution; // ChatGPT5 Pro: Type-safe call resolution utilities
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod calls; // Call system modules (refactored from builder_calls)
|
2025-12-15 22:12:33 +09:00
|
|
|
|
mod compilation_context; // Phase 136 follow-up (Step 7/7): CompilationContext extraction
|
2025-11-17 11:28:18 +09:00
|
|
|
|
mod context; // BoxCompilationContext - 箱理論による静的Boxコンパイル時のコンテキスト分離
|
2025-12-15 20:10:36 +09:00
|
|
|
|
mod core_context; // Phase 136 follow-up (Step 2/7): CoreContext extraction
|
🎉 Phase 11.8/12.7: MIR Core-13 完全実装 + 糖衣構文ドキュメント更新
主要な変更:
- MIR Core-13命令セット確定(Load/Store削除の革命的設計)
- Const, BinOp, Compare(値・計算)
- Jump, Branch, Return, Phi(制御)
- Call, BoxCall, ExternCall(呼び出し)
- TypeOp, Safepoint, Barrier(メタ)
- Phase 12.7糖衣構文ドキュメント整理(超圧縮重視、可逆変換保証)
- MIRビルダーのモジュール分割完了
- vtableテストスイート拡充
- AI協調開発ツール追加(並列リファクタリング支援)
詳細:
- src/mir/instruction_introspection.rs: core13_instruction_names()追加
- MIRビルダー分割: decls.rs, exprs_*.rs, fields.rs
- plugin_loader_v2: errors.rs, host_bridge.rs分離
- 論文用データ: mir13-final.md作成
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 11:34:15 +09:00
|
|
|
|
mod decls; // declarations lowering split
|
2025-09-17 07:43:07 +09:00
|
|
|
|
mod exprs; // expression lowering split
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod exprs_call;
|
2025-12-16 07:02:14 +09:00
|
|
|
|
mod metadata_context; // Phase 136 follow-up (Step 6/7): MetadataContext extraction
|
|
|
|
|
|
mod method_call_handlers;
|
|
|
|
|
|
mod variable_context; // Phase 136 follow-up (Step 5/7): VariableContext extraction // Method call handler separation (Phase 3) // call(expr)
|
2025-12-16 07:09:22 +09:00
|
|
|
|
// include lowering removed (using is handled in runner)
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod control_flow; // thin wrappers to centralize control-flow entrypoints
|
2025-12-16 07:09:22 +09:00
|
|
|
|
|
|
|
|
|
|
// Phase 140-P4-A: Re-export for loop_canonicalizer SSOT (crate-wide visibility)
|
2025-12-19 08:36:45 +09:00
|
|
|
|
pub(crate) use control_flow::detect_skip_whitespace_pattern;
|
2025-12-17 18:29:27 +09:00
|
|
|
|
// Phase 104: Re-export read_digits(loop(true)) detection for loop_canonicalizer
|
2025-12-19 08:36:45 +09:00
|
|
|
|
pub(crate) use control_flow::detect_read_digits_loop_true_pattern;
|
2025-12-16 09:08:37 +09:00
|
|
|
|
// Phase 142-P1: Re-export continue pattern detection for loop_canonicalizer
|
2025-12-19 08:36:45 +09:00
|
|
|
|
pub(crate) use control_flow::detect_continue_pattern;
|
2025-12-16 09:08:37 +09:00
|
|
|
|
// Phase 143-P0: Re-export parse_number pattern detection for loop_canonicalizer
|
2025-12-19 08:36:45 +09:00
|
|
|
|
pub(crate) use control_flow::detect_parse_number_pattern;
|
|
|
|
|
|
pub(crate) use control_flow::detect_parse_string_pattern;
|
2025-12-16 14:36:32 +09:00
|
|
|
|
// Phase 91 P5b: Re-export escape skip pattern detection for loop_canonicalizer
|
2025-12-19 08:36:45 +09:00
|
|
|
|
pub(crate) use control_flow::detect_escape_skip_pattern;
|
2025-12-18 08:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
/// Phase 129: Public (crate) wrapper for StepTree capability guard.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// `control_flow` is intentionally private to keep control-flow entrypoints centralized.
|
|
|
|
|
|
/// Shadow pipelines outside `mir::builder` must call this wrapper instead of reaching into
|
|
|
|
|
|
/// `control_flow::*` directly.
|
|
|
|
|
|
pub(crate) fn check_step_tree_capabilities(
|
|
|
|
|
|
tree: &crate::mir::control_tree::StepTree,
|
|
|
|
|
|
func_name: &str,
|
|
|
|
|
|
strict: bool,
|
|
|
|
|
|
dev: bool,
|
|
|
|
|
|
) -> Result<(), String> {
|
|
|
|
|
|
control_flow::joinir::control_tree_capability_guard::check(tree, func_name, strict, dev)
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
mod exprs_lambda; // lambda lowering
|
|
|
|
|
|
mod exprs_peek; // peek expression
|
|
|
|
|
|
mod exprs_qmark; // ?-propagate
|
|
|
|
|
|
mod fields; // field access/assignment lowering split
|
refactor(cleanup): Phase 285A1 Post-Implementation Cleanup
Code quality improvements after Phase 285A1 implementation:
**Task 1: Dead Code Cleanup**
- Removed unnecessary #[allow(dead_code)] from emit_weak_load()
- Function is actively used in weak_to_strong() method handler
**Task 2: Unused Import Removal (cargo fix)**
- edgecfg/api/mod.rs: Removed seq, if_, loop_, cleanup, verify_frag_invariants
- pattern3.rs: Removed BinaryOperator
- pattern2/api/mod.rs: Removed PromoteStepResult
- jump.rs: Removed EffectMask, Span
- Result: 6 unused imports eliminated
**Task 3: Deprecated Pattern Removal**
- Fixed 4 PlanKind::LoopWithPost deprecated warnings
- Updated to Phase 142 P0 architecture (statement-level normalization)
- Files: normalized_shadow_suffix_router_box.rs, routing.rs,
execute_box.rs, plan.rs
- Removed 2 deprecated tests: test_loop_with_post_*
**Task 4: WeakFieldValidatorBox Boxification**
- Extracted weak field validation logic into dedicated Box
- New file: src/mir/builder/weak_field_validator.rs (147 lines)
- fields.rs: 277 → 237 lines (-40 lines, -14.4%)
- Added 5 unit tests for validation logic
- Follows Phase 33 boxification principles (single responsibility,
testability, reusability)
**Metrics**:
- Code reduction: -40 lines in fields.rs
- Test coverage: +5 unit tests
- Warnings fixed: 4 deprecated warnings
- Imports cleaned: 6 unused imports
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 03:44:56 +09:00
|
|
|
|
mod weak_field_validator; // Phase 285A1: Weak field contract validator
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod if_form;
|
2025-12-20 06:38:21 +09:00
|
|
|
|
pub mod joinir_id_remapper; // Phase 189: JoinIR ID remapping (ValueId/BlockId translation) - Public for tests
|
2025-12-05 14:11:49 +09:00
|
|
|
|
mod joinir_inline_boundary_injector; // Phase 189: JoinInlineBoundary Copy instruction injector
|
2025-12-11 20:54:33 +09:00
|
|
|
|
mod lifecycle;
|
|
|
|
|
|
mod loop_frontend_binding; // Phase 50: Loop Frontend Binding (JoinIR variable mapping)
|
2025-09-17 07:43:07 +09:00
|
|
|
|
pub(crate) mod loops;
|
|
|
|
|
|
mod ops;
|
|
|
|
|
|
mod phi;
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod phi_merge; // Phase 25.1q: Unified PHI merge helper // prepare/lower_root/finalize split
|
|
|
|
|
|
// legacy large-match remains inline for now (planned extraction)
|
|
|
|
|
|
mod emission; // emission::*(Const/Compare/Branch の薄い発行箱)
|
|
|
|
|
|
mod emit_guard; // EmitGuardBox(emit直前の最終関所)
|
|
|
|
|
|
mod metadata; // MetadataPropagationBox(type/originの伝播)
|
|
|
|
|
|
mod name_const; // NameConstBox(関数名Const生成)
|
2025-09-28 12:19:49 +09:00
|
|
|
|
mod observe; // P0: dev-only observability helpers(ssa/resolve)
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod origin; // P0: origin inference(me/Known)と PHI 伝播(軽量)
|
|
|
|
|
|
mod plugin_sigs; // plugin signature loader
|
|
|
|
|
|
mod receiver; // ReceiverMaterializationBox(Method recv の pin+LocalSSA 集約)
|
2025-09-28 12:19:49 +09:00
|
|
|
|
mod rewrite; // P1: Known rewrite & special consolidation
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod router; // RouterPolicyBox(Unified vs BoxCall)
|
2025-09-28 20:38:09 +09:00
|
|
|
|
mod schedule; // BlockScheduleBox(物理順序: PHI→materialize→body)
|
2025-12-16 07:02:14 +09:00
|
|
|
|
mod scope_context; // Phase 136 follow-up (Step 3/7): ScopeContext extraction
|
2025-11-21 06:25:17 +09:00
|
|
|
|
mod ssa; // LocalSSA helpers (in-block materialization)
|
|
|
|
|
|
mod stmts;
|
2025-12-15 19:59:55 +09:00
|
|
|
|
mod type_context; // Phase 136 follow-up: TypeContext extraction
|
2025-12-15 19:49:41 +09:00
|
|
|
|
mod type_facts; // Phase 136 follow-up: Type inference facts box
|
2025-11-21 06:25:17 +09:00
|
|
|
|
pub(crate) mod type_registry;
|
|
|
|
|
|
mod types; // types::annotation / inference(型注釈/推論の箱: 推論は後段)
|
|
|
|
|
|
mod utils;
|
|
|
|
|
|
mod vars; // variables/scope helpers // small loop helpers (header/exit context) // TypeRegistryBox(型情報管理の一元化)
|
2025-12-25 14:06:22 +09:00
|
|
|
|
// Phase 288 Box化: repl_session moved to src/runner/repl/repl_session.rs
|
2025-08-30 22:52:16 +09:00
|
|
|
|
|
2025-09-19 08:34:29 +09:00
|
|
|
|
// Unified member property kinds for computed/once/birth_once
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
|
|
pub(crate) enum PropertyKind {
|
|
|
|
|
|
Computed,
|
|
|
|
|
|
Once,
|
|
|
|
|
|
BirthOnce,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
|
/// MIR builder for converting AST to SSA form
|
|
|
|
|
|
pub struct MirBuilder {
|
|
|
|
|
|
/// Current module being built
|
2025-08-18 23:36:40 +09:00
|
|
|
|
pub(super) current_module: Option<MirModule>,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
|
/// Current basic block being built
|
2025-08-18 23:36:40 +09:00
|
|
|
|
pub(super) current_block: Option<BasicBlockId>,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-12-15 20:10:36 +09:00
|
|
|
|
/// Phase 136 follow-up (Step 2/7): Core ID generation context
|
|
|
|
|
|
/// Consolidates value_gen, block_gen, next_binding_id, temp_slot_counter, debug_join_counter.
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) core_ctx: core_context::CoreContext,
|
|
|
|
|
|
|
2025-12-15 19:59:55 +09:00
|
|
|
|
/// Phase 136 follow-up: Type information context
|
|
|
|
|
|
/// Consolidates value_types, value_kinds, value_origin_newbox for better organization.
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) type_ctx: type_context::TypeContext,
|
|
|
|
|
|
|
2025-12-15 20:28:21 +09:00
|
|
|
|
/// Phase 136 follow-up (Step 3/7): Scope and control flow context
|
|
|
|
|
|
/// Consolidates lexical_scope_stack, loop stacks, if_merge_stack, current_function,
|
|
|
|
|
|
/// function_param_names, debug_scope_stack for better organization.
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) scope_ctx: scope_context::ScopeContext,
|
|
|
|
|
|
|
2025-12-15 20:40:23 +09:00
|
|
|
|
/// Phase 136 follow-up (Step 4/7): Binding context
|
|
|
|
|
|
/// Consolidates binding_map (String -> BindingId mapping).
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) binding_ctx: binding_context::BindingContext,
|
|
|
|
|
|
|
2025-12-15 21:50:50 +09:00
|
|
|
|
/// Phase 136 follow-up (Step 5/7): Variable context
|
|
|
|
|
|
/// Consolidates variable_map (String -> ValueId mapping for SSA conversion).
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) variable_ctx: variable_context::VariableContext,
|
|
|
|
|
|
|
2025-12-15 22:03:34 +09:00
|
|
|
|
/// Phase 136 follow-up (Step 6/7): Metadata context
|
|
|
|
|
|
/// Consolidates current_span, source_file, hint_sink, current_region_stack.
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) metadata_ctx: metadata_context::MetadataContext,
|
|
|
|
|
|
|
2025-12-15 22:12:33 +09:00
|
|
|
|
/// Phase 136 follow-up (Step 7/7): Compilation context
|
|
|
|
|
|
/// Consolidates compilation_context, current_static_box, user_defined_boxes, reserved_value_ids,
|
|
|
|
|
|
/// fn_body_ast, weak_fields_by_box, property_getters_by_box, field_origin_class, field_origin_by_box,
|
|
|
|
|
|
/// static_method_index, method_tail_index, type_registry, current_slot_registry, plugin_method_sigs.
|
|
|
|
|
|
/// Direct field access for backward compatibility (migration in progress).
|
|
|
|
|
|
pub(super) comp_ctx: compilation_context::CompilationContext,
|
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
|
/// Pending phi functions to be inserted
|
2025-08-16 17:39:04 +09:00
|
|
|
|
#[allow(dead_code)]
|
2025-08-18 23:36:40 +09:00
|
|
|
|
pub(super) pending_phis: Vec<(BasicBlockId, ValueId, String)>,
|
2025-08-20 20:56:08 +09:00
|
|
|
|
|
2025-12-15 23:51:01 +09:00
|
|
|
|
// Phase 2-5: binding_map removed - use binding_ctx.binding_map instead
|
2025-12-13 05:34:56 +09:00
|
|
|
|
|
2025-09-25 00:41:56 +09:00
|
|
|
|
// include guards removed
|
2025-09-23 07:25:58 +09:00
|
|
|
|
// フェーズM: no_phi_modeフィールド削除(常にPHI使用)
|
2025-09-19 02:07:38 +09:00
|
|
|
|
|
|
|
|
|
|
// ---- Try/Catch/Cleanup lowering context ----
|
|
|
|
|
|
/// When true, `return` statements are deferred: they assign to `return_defer_slot`
|
|
|
|
|
|
/// and jump to `return_defer_target` (typically the cleanup/exit block).
|
|
|
|
|
|
pub(super) return_defer_active: bool,
|
|
|
|
|
|
/// Slot value to receive deferred return values (edge-copy mode friendly).
|
|
|
|
|
|
pub(super) return_defer_slot: Option<ValueId>,
|
|
|
|
|
|
/// Target block to jump to on deferred return.
|
|
|
|
|
|
pub(super) return_defer_target: Option<BasicBlockId>,
|
|
|
|
|
|
/// Set to true when a deferred return has been emitted in the current context.
|
|
|
|
|
|
pub(super) return_deferred_emitted: bool,
|
|
|
|
|
|
/// True while lowering the cleanup block.
|
|
|
|
|
|
pub(super) in_cleanup_block: bool,
|
|
|
|
|
|
/// Policy flags (snapshotted at entry of try/catch lowering)
|
|
|
|
|
|
pub(super) cleanup_allow_return: bool,
|
|
|
|
|
|
pub(super) cleanup_allow_throw: bool,
|
2025-09-20 03:37:20 +09:00
|
|
|
|
|
2025-09-26 05:28:20 +09:00
|
|
|
|
/// If true, skip entry materialization of pinned slots on the next start_new_block call.
|
|
|
|
|
|
suppress_pin_entry_copy_next: bool,
|
2025-09-28 01:33:58 +09:00
|
|
|
|
|
|
|
|
|
|
// ----------------------
|
|
|
|
|
|
// Debug scope context (dev only; zero-cost when unused)
|
|
|
|
|
|
// ----------------------
|
2025-09-28 20:38:09 +09:00
|
|
|
|
/// Local SSA cache: ensure per-block materialization for critical operands (e.g., recv)
|
|
|
|
|
|
/// Key: (bb, original ValueId, kind) -> local ValueId
|
|
|
|
|
|
/// kind: 0=recv, 1+ reserved for future (args etc.)
|
|
|
|
|
|
pub(super) local_ssa_map: HashMap<(BasicBlockId, ValueId, u8), ValueId>,
|
|
|
|
|
|
/// BlockSchedule cache: deduplicate materialize copies per (bb, src)
|
|
|
|
|
|
pub(super) schedule_mat_map: HashMap<(BasicBlockId, ValueId), ValueId>,
|
2025-11-19 02:44:40 +09:00
|
|
|
|
/// Mapping from ValueId to its pin slot name (e.g., "__pin$3$@recv")
|
|
|
|
|
|
/// Used by LocalSSA to redirect old pinned values to the latest slot value.
|
|
|
|
|
|
pub(super) pin_slot_names: HashMap<ValueId, String>,
|
2025-11-17 17:31:09 +09:00
|
|
|
|
|
|
|
|
|
|
/// Guard flag to prevent re-entering emit_unified_call from BoxCall fallback.
|
|
|
|
|
|
/// Used when RouterPolicyBox in emit_unified_call has already decided to
|
|
|
|
|
|
/// route a given Method call to BoxCall; emit_box_or_plugin_call must not
|
|
|
|
|
|
/// bounce back into the unified path for the same call, otherwise an
|
|
|
|
|
|
/// infinite recursion (emit_unified_call → emit_box_or_plugin_call →
|
|
|
|
|
|
/// emit_unified_call …) can occur when routing decisions disagree.
|
|
|
|
|
|
pub(super) in_unified_boxcall_fallback: bool,
|
2025-11-17 17:53:40 +09:00
|
|
|
|
|
|
|
|
|
|
/// Recursion depth counter for debugging stack overflow
|
|
|
|
|
|
/// Tracks the depth of build_expression calls to detect infinite loops
|
|
|
|
|
|
pub(super) recursion_depth: usize,
|
2025-11-18 06:39:45 +09:00
|
|
|
|
|
|
|
|
|
|
/// Root lowering mode: how to treat top-level Program
|
|
|
|
|
|
/// - None: not decided yet (lower_root not called)
|
|
|
|
|
|
/// - Some(true): App mode (static box Main.main is entry)
|
|
|
|
|
|
/// - Some(false): Script/Test mode (top-level Program runs sequentially)
|
|
|
|
|
|
pub(super) root_is_app_mode: Option<bool>,
|
2025-11-22 00:00:51 +09:00
|
|
|
|
|
|
|
|
|
|
/// 🎯 Phase 21.7: Static box singleton instances for methodization
|
|
|
|
|
|
/// Maps BoxName → ValueId of singleton instance (created on demand)
|
|
|
|
|
|
/// Used when HAKO_MIR_BUILDER_METHODIZE=1 to convert Global("BoxName.method/arity")
|
|
|
|
|
|
/// to Method{receiver=singleton} calls
|
|
|
|
|
|
pub(super) static_box_singletons: HashMap<String, ValueId>,
|
2025-12-25 13:38:04 +09:00
|
|
|
|
|
|
|
|
|
|
/// Phase 288 P2: REPL mode flag - enables implicit local declarations
|
|
|
|
|
|
/// File mode: false (explicit local required)
|
|
|
|
|
|
/// REPL mode: true (暗黙 local 許可)
|
|
|
|
|
|
pub(crate) repl_mode: bool,
|
2025-08-12 11:33:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Default for MirBuilder {
|
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
|
Self::new()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-13 05:34:56 +09:00
|
|
|
|
|
2025-12-13 07:05:30 +09:00
|
|
|
|
// Phase 79: BindingMapProvider implementation
|
|
|
|
|
|
// Centralizes feature-gated binding_map access for promoters
|
|
|
|
|
|
use crate::mir::loop_pattern_detection::BindingMapProvider;
|
|
|
|
|
|
|
|
|
|
|
|
impl BindingMapProvider for MirBuilder {
|
|
|
|
|
|
#[cfg(feature = "normalized_dev")]
|
2025-12-16 07:02:14 +09:00
|
|
|
|
fn get_binding_map(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
) -> Option<&std::collections::BTreeMap<String, crate::mir::BindingId>> {
|
2025-12-15 20:40:23 +09:00
|
|
|
|
// Phase 136 Step 4/7: Use binding_ctx (SSOT)
|
|
|
|
|
|
Some(self.binding_ctx.binding_map())
|
2025-12-13 07:05:30 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(not(feature = "normalized_dev"))]
|
2025-12-16 07:02:14 +09:00
|
|
|
|
fn get_binding_map(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
) -> Option<&std::collections::BTreeMap<String, crate::mir::BindingId>> {
|
2025-12-13 07:05:30 +09:00
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-13 05:34:56 +09:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod binding_id_tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_binding_map_initialization() {
|
|
|
|
|
|
let builder = MirBuilder::new();
|
2025-12-15 23:05:36 +09:00
|
|
|
|
assert_eq!(builder.core_ctx.next_binding_id, 0);
|
2025-12-16 03:48:44 +09:00
|
|
|
|
// Phase 2-6: binding_ctx is now SSOT (legacy field removed)
|
2025-12-27 17:41:30 +09:00
|
|
|
|
assert!(builder.binding_ctx.binding_map.is_empty());
|
2025-12-13 05:34:56 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_binding_allocation_sequential() {
|
|
|
|
|
|
let mut builder = MirBuilder::new();
|
|
|
|
|
|
let bid0 = builder.allocate_binding_id();
|
|
|
|
|
|
let bid1 = builder.allocate_binding_id();
|
|
|
|
|
|
let bid2 = builder.allocate_binding_id();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(bid0.raw(), 0);
|
|
|
|
|
|
assert_eq!(bid1.raw(), 1);
|
|
|
|
|
|
assert_eq!(bid2.raw(), 2);
|
2025-12-15 23:05:36 +09:00
|
|
|
|
assert_eq!(builder.core_ctx.next_binding_id, 3);
|
2025-12-13 05:34:56 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_shadowing_binding_restore() {
|
|
|
|
|
|
let mut builder = MirBuilder::new();
|
|
|
|
|
|
|
|
|
|
|
|
// Simulate function entry scope
|
|
|
|
|
|
builder.push_lexical_scope();
|
|
|
|
|
|
|
|
|
|
|
|
// Declare outer x
|
2025-12-15 19:37:30 +09:00
|
|
|
|
// Phase 136 P0: Use SSOT allocator for function scope simulation
|
|
|
|
|
|
let outer_vid = builder.next_value_id();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
builder
|
|
|
|
|
|
.declare_local_in_current_scope("x", outer_vid)
|
|
|
|
|
|
.unwrap();
|
2025-12-16 03:48:44 +09:00
|
|
|
|
// Phase 2-6: Check binding_ctx (SSOT)
|
2025-12-15 20:40:23 +09:00
|
|
|
|
let outer_bid = builder.binding_ctx.lookup("x").unwrap();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
assert_eq!(outer_bid.raw(), 0);
|
|
|
|
|
|
|
|
|
|
|
|
// Enter inner scope and shadow x
|
|
|
|
|
|
builder.push_lexical_scope();
|
2025-12-15 19:37:30 +09:00
|
|
|
|
// Phase 136 P0: Use SSOT allocator for function scope simulation
|
|
|
|
|
|
let inner_vid = builder.next_value_id();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
builder
|
|
|
|
|
|
.declare_local_in_current_scope("x", inner_vid)
|
|
|
|
|
|
.unwrap();
|
2025-12-16 03:48:44 +09:00
|
|
|
|
// Phase 2-6: Check binding_ctx (SSOT)
|
2025-12-15 20:40:23 +09:00
|
|
|
|
let inner_bid = builder.binding_ctx.lookup("x").unwrap();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
assert_eq!(inner_bid.raw(), 1);
|
|
|
|
|
|
|
|
|
|
|
|
// Exit inner scope - should restore outer binding
|
|
|
|
|
|
builder.pop_lexical_scope();
|
2025-12-16 03:48:44 +09:00
|
|
|
|
// Phase 2-6: Check binding_ctx (SSOT)
|
2025-12-15 20:40:23 +09:00
|
|
|
|
let restored_bid = builder.binding_ctx.lookup("x").unwrap();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
assert_eq!(restored_bid, outer_bid);
|
|
|
|
|
|
assert_eq!(restored_bid.raw(), 0);
|
|
|
|
|
|
|
|
|
|
|
|
// Cleanup
|
|
|
|
|
|
builder.pop_lexical_scope();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_valueid_binding_parallel_allocation() {
|
|
|
|
|
|
let mut builder = MirBuilder::new();
|
|
|
|
|
|
|
2025-12-15 19:37:30 +09:00
|
|
|
|
// Phase 136 P0: Use SSOT allocator (next_value_id)
|
|
|
|
|
|
// Note: Without current_function, next_value_id() falls back to value_gen.next()
|
|
|
|
|
|
// so this test still validates ValueId/BindingId independence
|
2025-12-13 05:34:56 +09:00
|
|
|
|
// Allocate ValueIds and BindingIds in parallel
|
2025-12-15 19:37:30 +09:00
|
|
|
|
let vid0 = builder.next_value_id();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
let bid0 = builder.allocate_binding_id();
|
2025-12-15 19:37:30 +09:00
|
|
|
|
let vid1 = builder.next_value_id();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
let bid1 = builder.allocate_binding_id();
|
|
|
|
|
|
|
|
|
|
|
|
// ValueId and BindingId should be independent
|
|
|
|
|
|
assert_eq!(vid0.0, 0);
|
|
|
|
|
|
assert_eq!(bid0.raw(), 0);
|
|
|
|
|
|
assert_eq!(vid1.0, 1);
|
|
|
|
|
|
assert_eq!(bid1.raw(), 1);
|
|
|
|
|
|
|
|
|
|
|
|
// Allocating more ValueIds should not affect BindingId counter
|
2025-12-15 19:37:30 +09:00
|
|
|
|
let _ = builder.next_value_id();
|
|
|
|
|
|
let _ = builder.next_value_id();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
let bid2 = builder.allocate_binding_id();
|
|
|
|
|
|
assert_eq!(bid2.raw(), 2); // Still sequential
|
|
|
|
|
|
|
|
|
|
|
|
// Allocating more BindingIds should not affect ValueId counter
|
|
|
|
|
|
let _ = builder.allocate_binding_id();
|
|
|
|
|
|
let _ = builder.allocate_binding_id();
|
2025-12-15 19:37:30 +09:00
|
|
|
|
let vid2 = builder.next_value_id();
|
2025-12-13 05:34:56 +09:00
|
|
|
|
assert_eq!(vid2.0, 4); // Continues from where we left off
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|