feat(mir): Phase 136 Step 3/7 - ScopeContext extraction

## Summary
Extract scope and control flow management into ScopeContext for better organization.

## Changes
- **New file**: src/mir/builder/scope_context.rs (264 lines)
  - Lexical scope stack management
  - Control flow stacks (loop/if)
  - Function context tracking
  - Debug scope helpers
- **Updated**: src/mir/builder.rs
  - Add scope_ctx field
  - Mark legacy fields as deprecated
  - Add sync helpers (sync_scope_ctx_to_legacy, sync_legacy_to_scope_ctx)
- **Updated**: src/mir/builder/vars/lexical_scope.rs
  - Use scope_ctx as SSOT
  - Sync to legacy fields for backward compat
- **Updated**: src/mir/builder/lifecycle.rs
  - Sync current_function via scope_ctx
- **Updated**: src/mir/builder/calls/lowering.rs
  - Sync function context in lowering flow

## Extracted Fields (7)
1. lexical_scope_stack - Block-scoped locals
2. loop_header_stack - Loop headers for break/continue
3. loop_exit_stack - Loop exit blocks
4. if_merge_stack - If merge blocks
5. current_function - Currently building function
6. function_param_names - Function parameters (for LoopForm)
7. debug_scope_stack - Debug region identifiers

## Test Results
-  cargo build --release (291 warnings - deprecated usage)
-  cargo test --release --lib - 1005/1009 PASS
-  phase135_trim_mir_verify.sh - PASS
- ⚠️ phase132_exit_phi_parity.sh - Error (pre-existing issue)

## Progress
Phase 136: 3/7 Contexts complete (TypeContext, CoreContext, ScopeContext)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-15 20:28:21 +09:00
parent 89edf11699
commit 3127ebb73d
6 changed files with 463 additions and 57 deletions

View File

@ -53,6 +53,7 @@ mod router; // RouterPolicyBoxUnified vs BoxCall
mod schedule; // BlockScheduleBox物理順序: PHI→materialize→body
mod ssa; // LocalSSA helpers (in-block materialization)
mod stmts;
mod scope_context; // Phase 136 follow-up (Step 3/7): ScopeContext extraction
mod type_context; // Phase 136 follow-up: TypeContext extraction
mod type_facts; // Phase 136 follow-up: Type inference facts box
pub(crate) mod type_registry;
@ -73,7 +74,9 @@ pub struct MirBuilder {
/// Current module being built
pub(super) current_module: Option<MirModule>,
/// Current function being built
/// [DEPRECATED] Current function being built
/// Phase 136: Moved to scope_ctx.current_function (backward compat wrapper)
#[deprecated(note = "Use scope_ctx.current_function instead")]
pub(super) current_function: Option<MirFunction>,
/// Current basic block being built
@ -104,15 +107,20 @@ pub struct MirBuilder {
/// Direct field access for backward compatibility (migration in progress).
pub(super) type_ctx: type_context::TypeContext,
/// 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,
/// Variable name to ValueId mapping (for SSA conversion)
/// 注意: compilation_contextがSomeの場合は使用されません
/// Phase 25.1: HashMap → BTreeMapPHI生成の決定性確保
pub(super) variable_map: BTreeMap<String, ValueId>,
/// Lexical scope stack for block-scoped `local` declarations.
///
/// This tracks per-block shadowing so `local x` inside `{...}` restores the
/// outer binding when the block ends.
/// [DEPRECATED] Lexical scope stack for block-scoped `local` declarations.
/// Phase 136: Moved to scope_ctx.lexical_scope_stack (backward compat wrapper)
#[deprecated(note = "Use scope_ctx.lexical_scope_stack instead")]
lexical_scope_stack: Vec<vars::lexical_scope::LexicalScopeFrame>,
/// Pending phi functions to be inserted
@ -172,8 +180,9 @@ pub struct MirBuilder {
/// Index of static methods seen during lowering: name -> [(BoxName, arity)]
pub(super) static_method_index: std::collections::HashMap<String, Vec<(String, usize)>>,
/// Function parameter names (for LoopForm PHI construction)
/// Tracks the original parameter names at function entry
/// [DEPRECATED] Function parameter names (for LoopForm PHI construction)
/// Phase 136: Moved to scope_ctx.function_param_names (backward compat wrapper)
#[deprecated(note = "Use scope_ctx.function_param_names instead")]
pub(super) function_param_names: HashSet<String>,
/// Fast lookup: method+arity tail → candidate function names (e.g., ".str/0" → ["JsonNode.str/0", ...])
@ -209,14 +218,17 @@ pub struct MirBuilder {
pub binding_map: BTreeMap<String, super::BindingId>,
// include guards removed
/// Loop context stacks for lowering break/continue inside nested control flow
/// Top of stack corresponds to the innermost active loop
/// [DEPRECATED] Loop context stacks for lowering break/continue inside nested control flow
/// Phase 136: Moved to scope_ctx.loop_header_stack (backward compat wrapper)
#[deprecated(note = "Use scope_ctx.loop_header_stack instead")]
pub(super) loop_header_stack: Vec<BasicBlockId>,
#[allow(dead_code)]
#[deprecated(note = "Use scope_ctx.loop_exit_stack instead")]
pub(super) loop_exit_stack: Vec<BasicBlockId>,
/// If/merge context stack (innermost first). Used to make merge targets explicit
/// when lowering nested conditionals and to simplify jump generation.
/// [DEPRECATED] If/merge context stack (innermost first)
/// Phase 136: Moved to scope_ctx.if_merge_stack (backward compat wrapper)
#[deprecated(note = "Use scope_ctx.if_merge_stack instead")]
pub(super) if_merge_stack: Vec<BasicBlockId>,
// フェーズM: no_phi_modeフィールド削除常にPHI使用
@ -250,7 +262,9 @@ pub struct MirBuilder {
// ----------------------
// Debug scope context (dev only; zero-cost when unused)
// ----------------------
/// Stack of region identifiers like "loop#1/header" or "join#3/join".
/// [DEPRECATED] Stack of region identifiers like "loop#1/header" or "join#3/join".
/// Phase 136: Moved to scope_ctx.debug_scope_stack (backward compat wrapper)
#[deprecated(note = "Use scope_ctx.debug_scope_stack instead")]
debug_scope_stack: Vec<String>,
/// [DEPRECATED] Monotonic counter for region IDs (deterministic across a run).
/// Phase 136: Moved to core_ctx.debug_join_counter (backward compat wrapper)
@ -320,6 +334,7 @@ impl MirBuilder {
compilation_context: None, // 箱理論: デフォルトは従来モード
type_ctx: type_context::TypeContext::new(), // Phase 136: Type context
scope_ctx: scope_context::ScopeContext::new(), // Phase 136 Step 3/7: Scope context
variable_map: BTreeMap::new(), // Phase 25.1: 決定性確保
lexical_scope_stack: Vec::new(),
pending_phis: Vec::new(),
@ -396,11 +411,42 @@ impl MirBuilder {
self.type_ctx.value_origin_newbox = self.value_origin_newbox.clone();
}
// ---- Phase 136 Step 3/7: ScopeContext synchronization helpers ----
/// Sync scope_ctx changes back to legacy fields (backward compatibility)
#[allow(deprecated)]
fn sync_scope_ctx_to_legacy(&mut self) {
self.lexical_scope_stack = self.scope_ctx.lexical_scope_stack.clone();
self.loop_header_stack = self.scope_ctx.loop_header_stack.clone();
self.loop_exit_stack = self.scope_ctx.loop_exit_stack.clone();
self.if_merge_stack = self.scope_ctx.if_merge_stack.clone();
self.current_function = self.scope_ctx.current_function.clone();
self.function_param_names = self.scope_ctx.function_param_names.clone();
self.debug_scope_stack = self.scope_ctx.debug_scope_stack.clone();
}
/// Sync legacy field changes to scope_ctx (backward compatibility)
#[allow(deprecated)]
fn sync_legacy_to_scope_ctx(&mut self) {
self.scope_ctx.lexical_scope_stack = self.lexical_scope_stack.clone();
self.scope_ctx.loop_header_stack = self.loop_header_stack.clone();
self.scope_ctx.loop_exit_stack = self.loop_exit_stack.clone();
self.scope_ctx.if_merge_stack = self.if_merge_stack.clone();
self.scope_ctx.current_function = self.current_function.clone();
self.scope_ctx.function_param_names = self.function_param_names.clone();
self.scope_ctx.debug_scope_stack = self.debug_scope_stack.clone();
}
/// Push/pop helpers for If merge context (best-effort; optional usage)
#[allow(deprecated)]
pub(super) fn push_if_merge(&mut self, bb: BasicBlockId) {
// Phase 136 Step 3/7: Update both scope_ctx (SSOT) and legacy field (backward compat)
self.scope_ctx.push_if_merge(bb);
self.if_merge_stack.push(bb);
}
#[allow(deprecated)]
pub(super) fn pop_if_merge(&mut self) {
// Phase 136 Step 3/7: Update both scope_ctx (SSOT) and legacy field (backward compat)
let _ = self.scope_ctx.pop_if_merge();
let _ = self.if_merge_stack.pop();
}
@ -467,18 +513,27 @@ impl MirBuilder {
}
#[inline]
#[allow(deprecated)]
pub(crate) fn debug_push_region<S: Into<String>>(&mut self, region: S) {
self.debug_scope_stack.push(region.into());
// Phase 136 Step 3/7: Update both scope_ctx (SSOT) and legacy field (backward compat)
let region = region.into();
self.scope_ctx.debug_push_region(region.clone());
self.debug_scope_stack.push(region);
}
#[inline]
#[allow(deprecated)]
pub(crate) fn debug_pop_region(&mut self) {
// Phase 136 Step 3/7: Update both scope_ctx (SSOT) and legacy field (backward compat)
self.scope_ctx.debug_pop_region();
let _ = self.debug_scope_stack.pop();
}
#[inline]
#[allow(deprecated)]
pub(crate) fn debug_current_region_id(&self) -> Option<String> {
self.debug_scope_stack.last().cloned()
// Phase 136 Step 3/7: Read from scope_ctx (SSOT)
self.scope_ctx.debug_current_region_id()
}
/// Hint for downstream metadata: set the logical source file name/path for the next build.