refactor(mir): Extract BindingContext from MirBuilder (Phase 136 follow-up 4/7)

## Summary
Extracted binding management into dedicated BindingContext struct,
completing step 4 of 7 in the Context Box refactoring plan.

## Changes
- NEW: src/mir/builder/binding_context.rs (BindingContext struct + helpers)
- Modified 7 files to use binding_ctx (SSOT pattern with legacy sync)
- Added comprehensive unit tests for BindingContext

## Extracted Fields
- binding_map: BTreeMap<String, BindingId> → binding_ctx.binding_map

## Benefits
- Clear separation: BindingId mapping isolated from MirBuilder
- Better testability: BindingContext can be tested independently
- Consistent pattern: Same SSOT + legacy sync approach as previous steps

## Tests
- cargo test --release --lib: 1008/1008 passed
- phase135_trim_mir_verify.sh: PASS
- Backward compatibility: 100% maintained (deprecated fields synced)

## Progress
Phase 136 Context Extraction: 4/7 complete (57%)
-  Step 1: TypeContext
-  Step 2: CoreContext
-  Step 3: ScopeContext
-  Step 4: BindingContext (this commit)
-  Step 5: VariableContext
-  Step 6: MetadataContext
-  Step 7: RegionContext

🤖 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:40:23 +09:00
parent 3127ebb73d
commit 1adf57ec54
9 changed files with 598 additions and 22 deletions

View File

@ -115,7 +115,8 @@ fn prepare_pattern2_inputs(
// Phase 79-2: Register loop variable BindingId (dev-only)
#[cfg(feature = "normalized_dev")]
if let Some(loop_var_bid) = builder.binding_map.get(&loop_var_name).copied() {
// Phase 136 Step 4/7: Use binding_ctx for lookup
if let Some(loop_var_bid) = builder.binding_ctx.lookup(&loop_var_name) {
env.register_loop_var_binding(loop_var_bid, _loop_var_join_id);
log_pattern2(
verbose,

View File

@ -133,8 +133,9 @@ impl MirBuilder {
#[cfg(feature = "normalized_dev")]
{
// Register loop variable BindingId
if let Some(bid) = self.binding_map.get(&loop_var_name) {
cond_env.register_loop_var_binding(*bid, _loop_var_join_id);
// Phase 136 Step 4/7: Use binding_ctx for lookup
if let Some(bid) = self.binding_ctx.lookup(&loop_var_name) {
cond_env.register_loop_var_binding(bid, _loop_var_join_id);
if debug {
eprintln!(
"[phase80/p3] Registered loop var '{}' BindingId({}) -> ValueId({})",
@ -147,8 +148,9 @@ impl MirBuilder {
// These are variables from the condition expression (e.g., "len" in "i < len")
// May include ConditionOnly carriers if they appear in the condition
for binding in &condition_bindings {
if let Some(bid) = self.binding_map.get(&binding.name) {
cond_env.register_condition_binding(*bid, binding.join_value);
// Phase 136 Step 4/7: Use binding_ctx for lookup
if let Some(bid) = self.binding_ctx.lookup(&binding.name) {
cond_env.register_condition_binding(bid, binding.join_value);
if debug {
eprintln!(
"[phase80/p3] Registered condition binding '{}' BindingId({}) -> ValueId({})",

View File

@ -240,7 +240,8 @@ fn prepare_pattern4_context(
continue_cond,
loop_body: &normalized_body,
#[cfg(feature = "normalized_dev")]
binding_map: Some(&builder.binding_map),
// Phase 136 Step 4/7: Use binding_ctx for binding_map reference
binding_map: Some(builder.binding_ctx.binding_map()),
};
match LoopBodyCondPromoter::try_promote_for_condition(promotion_req) {
@ -339,7 +340,8 @@ fn lower_pattern4_joinir(
let mut join_value_space = JoinValueSpace::new();
#[cfg(feature = "normalized_dev")]
let binding_map_clone = builder.binding_map.clone();
// Phase 136 Step 4/7: Use binding_ctx for binding_map clone
let binding_map_clone = builder.binding_ctx.binding_map().clone();
let (join_module, exit_meta) = match lower_loop_with_continue_minimal(
prepared.loop_scope.clone(),

View File

@ -227,7 +227,8 @@ impl TrimLoopLowerer {
break_cond: Some(break_cond),
loop_body: body,
#[cfg(feature = "normalized_dev")]
binding_map: Some(&builder.binding_map),
// Phase 136 Step 4/7: Use binding_ctx for binding_map reference
binding_map: Some(builder.binding_ctx.binding_map()),
};
match LoopBodyCarrierPromoter::try_promote(&request) {
@ -239,7 +240,8 @@ impl TrimLoopLowerer {
// Step 3: Convert to CarrierInfo and merge
#[cfg(feature = "normalized_dev")]
let promoted_carrier = trim_info.to_carrier_info(Some(&builder.binding_map));
// Phase 136 Step 4/7: Use binding_ctx for binding_map reference
let promoted_carrier = trim_info.to_carrier_info(Some(builder.binding_ctx.binding_map()));
#[cfg(not(feature = "normalized_dev"))]
let promoted_carrier = trim_info.to_carrier_info();
carrier_info.merge_from(&promoted_carrier);