feat(joinir): Phase 224-D - ConditionAlias for promoted variable resolution
- Add ConditionAlias type to CarrierInfo (old_name → carrier_name) - Record aliases in DigitPosPromoter and TrimPatternInfo - Resolve aliases in Pattern2 ConditionEnv building - digit_pos now correctly resolves to is_digit_pos carrier Fixes "Variable 'digit_pos' not bound in ConditionEnv" error. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -69,6 +69,13 @@
|
|||||||
- **Root Cause**: Break condition AST が元の変数名(digit_pos)を保持したまま lowerer に渡される
|
- **Root Cause**: Break condition AST が元の変数名(digit_pos)を保持したまま lowerer に渡される
|
||||||
- **Next Steps**: Option B(promoted variable tracking)で lowerer に昇格済み変数を通知する仕組みを追加(1-2h)
|
- **Next Steps**: Option B(promoted variable tracking)で lowerer に昇格済み変数を通知する仕組みを追加(1-2h)
|
||||||
- **詳細**: [PHASE_224_SUMMARY.md](docs/development/current/main/PHASE_224_SUMMARY.md)
|
- **詳細**: [PHASE_224_SUMMARY.md](docs/development/current/main/PHASE_224_SUMMARY.md)
|
||||||
|
- **Phase 224-D 完了** ✅: ConditionAlias 導入(昇格変数の条件参照解決)
|
||||||
|
- **ConditionAlias 型追加**: `CarrierInfo` に `condition_aliases: Vec<ConditionAlias>` フィールド追加
|
||||||
|
- **Promoter 側記録**: DigitPosPromoter / TrimPatternInfo が昇格時に alias を記録(`digit_pos` → `is_digit_pos`)
|
||||||
|
- **Pattern2 統合**: 昇格・merge 後に join_id 割り当て、ConditionEnv に alias を追加(`digit_pos` → ValueId(104))
|
||||||
|
- **CarrierInfo 構造修正**: DigitPosPromoter が carriers list に追加する形に変更(loop_var_name 置換ではなく)
|
||||||
|
- **検証**: `phase2235_p2_digit_pos_min.hako` で alias 解決成功、エラーが次段階(substring init)に進展
|
||||||
|
- **残課題**: substring method in body-local init(Phase 193 limitation)
|
||||||
|
|
||||||
### 2. JsonParser / Trim / selfhost への適用状況
|
### 2. JsonParser / Trim / selfhost への適用状況
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Phase 224: A-4 DigitPos Promoter - Implementation Summary
|
# Phase 224: A-4 DigitPos Promoter - Implementation Summary
|
||||||
|
|
||||||
**Date**: 2025-12-10
|
**Date**: 2025-12-10
|
||||||
**Status**: Core Implementation Complete, Integration Requires Additional Work
|
**Status**: Core Implementation Complete(Phase 224-D まで反映済み、init MethodCall は別 Phase)
|
||||||
**Branch**: main
|
**Branch**: main
|
||||||
**Commits**: TBD
|
**Commits**: TBD
|
||||||
|
|
||||||
@ -14,8 +14,9 @@ Phase 224 successfully implemented the **DigitPosPromoter** Box for A-4 pattern
|
|||||||
✅ **Complete**: DigitPosPromoter implementation with full unit test coverage (6/6 tests passing)
|
✅ **Complete**: DigitPosPromoter implementation with full unit test coverage (6/6 tests passing)
|
||||||
✅ **Complete**: Integration into LoopBodyCondPromoter orchestrator
|
✅ **Complete**: Integration into LoopBodyCondPromoter orchestrator
|
||||||
✅ **Complete**: Two-tier promotion strategy (A-3 Trim → A-4 DigitPos fallback)
|
✅ **Complete**: Two-tier promotion strategy (A-3 Trim → A-4 DigitPos fallback)
|
||||||
✅ **Verified**: Promotion detection working correctly in Pattern2 pipeline
|
✅ **Verified**: Promotion detection working correctly in Pattern2/4 pipeline
|
||||||
⚠️ **Partial**: Full E2E flow blocked by lowerer integration issue
|
✅ **Complete** (Phase 224-D): ConditionEnv alias bridge(`digit_pos` → `is_digit_pos`)実装
|
||||||
|
⚠️ **Partial**: Full E2E flowは body-local init の MethodCall 制約で一部ブロック中
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ Step 2: Try A-4 DigitPos promotion (DigitPosPromoter)
|
|||||||
Step 3: Fail-Fast with clear error message
|
Step 3: Fail-Fast with clear error message
|
||||||
```
|
```
|
||||||
|
|
||||||
**Logs Verify Success**:
|
**Logs Verify Success(昇格フェーズ)**:
|
||||||
```
|
```
|
||||||
[cond_promoter] A-3 Trim promotion failed: No promotable Trim pattern detected
|
[cond_promoter] A-3 Trim promotion failed: No promotable Trim pattern detected
|
||||||
[cond_promoter] Trying A-4 DigitPos promotion...
|
[cond_promoter] Trying A-4 DigitPos promotion...
|
||||||
@ -74,9 +75,9 @@ Step 3: Fail-Fast with clear error message
|
|||||||
|
|
||||||
## Current Limitation: Lowerer Integration Gap
|
## Current Limitation: Lowerer Integration Gap
|
||||||
|
|
||||||
### Problem Statement
|
### Problem Statement(当初) / Phase 224-D での一部解消
|
||||||
|
|
||||||
**Symptom**: E2E test fails despite successful promotion
|
**Symptom(224 実装直後)**: E2E test fails despite successful promotion
|
||||||
**Root Cause**: `lower_loop_with_break_minimal` performs independent LoopBodyLocal check
|
**Root Cause**: `lower_loop_with_break_minimal` performs independent LoopBodyLocal check
|
||||||
**Result**: Promoted variables are detected as "unsupported" by the lowerer
|
**Result**: Promoted variables are detected as "unsupported" by the lowerer
|
||||||
|
|
||||||
@ -108,29 +109,32 @@ But for A-4 DigitPos (Phase 223.5), we:
|
|||||||
- Merge carrier into CarrierInfo ✅
|
- Merge carrier into CarrierInfo ✅
|
||||||
- **BUT**: Break condition AST still contains `digit_pos` ❌
|
- **BUT**: Break condition AST still contains `digit_pos` ❌
|
||||||
|
|
||||||
### Root Cause Analysis
|
### Root Cause Analysis(Phase 224 時点)
|
||||||
|
|
||||||
The break condition is an **AST node** containing:
|
The break condition is an **AST node** containing:
|
||||||
```nyash
|
```nyash
|
||||||
if digit_pos < 0 { break }
|
if digit_pos < 0 { break }
|
||||||
```
|
```
|
||||||
|
|
||||||
After promotion:
|
After promotion(224 時点):
|
||||||
- CarrierInfo knows about `is_digit_pos` carrier ✅
|
- CarrierInfo knows about `is_digit_pos` carrier ✅
|
||||||
- LoopBodyCondPromoter recorded the promotion ✅
|
- LoopBodyCondPromoter recorded the promotion ✅
|
||||||
- **But**: AST node still says `digit_pos`, not `is_digit_pos` ❌
|
- **But**: AST node still says `digit_pos`, not `is_digit_pos` → ConditionEnv から `digit_pos` が見えない ❌
|
||||||
|
|
||||||
When lower_loop_with_break_minimal analyzes the condition:
|
Phase 224-D では AST を直接書き換えるのではなく、
|
||||||
```rust
|
**ConditionAlias(old_name → carrier_name)を CarrierInfo/ConditionEnv に導入する**ことで
|
||||||
let cond_scope = LoopConditionScopeBox::analyze(&conditions);
|
「`digit_pos` という名前で条件式から参照された場合も、内部的には `is_digit_pos` carrier を読む」
|
||||||
if cond_scope.has_loop_body_local() {
|
というブリッジを追加している。
|
||||||
// ERROR: Still sees "digit_pos" in AST!
|
|
||||||
}
|
これにより:
|
||||||
```
|
- LoopBodyLocal 昇格後に `digit_pos < 0` のような条件があっても、
|
||||||
|
ConditionEnvBuilder が ConditionAlias を介して `is_digit_pos` の ValueId に解決できるようになった。
|
||||||
|
- 「LoopBodyLocal が条件にあることによる not‑bound エラー」は解消され、
|
||||||
|
**現時点の Blocker は body‑local init MethodCall(substring など)の lowering 制約だけ**になった。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Solution Options (Phase 224-continuation)
|
## Solution Options (Phase 224-continuation 時点の整理)
|
||||||
|
|
||||||
### Option A: AST Rewriting (Comprehensive)
|
### Option A: AST Rewriting (Comprehensive)
|
||||||
|
|
||||||
@ -146,30 +150,26 @@ if cond_scope.has_loop_body_local() {
|
|||||||
**Cons**: AST rewriting is complex, error-prone
|
**Cons**: AST rewriting is complex, error-prone
|
||||||
**Effort**: ~2-3 hours
|
**Effort**: ~2-3 hours
|
||||||
|
|
||||||
### Option B: Promoted Variable Tracking (Surgical)
|
### Option B: Promoted Variable Tracking + ConditionAlias(採用済み)
|
||||||
|
|
||||||
**Approach**: Add metadata to track promoted variables, exclude from LoopBodyLocal check
|
**Approach(決定案)**:
|
||||||
|
LoopBodyLocal を carrier に昇格した事実を **CarrierInfo(promoted_loopbodylocals + ConditionAlias)** に
|
||||||
|
メタデータとして記録し、ConditionEnvBuilder 側で「元の変数名 → carrier 名」のエイリアスを解決する。
|
||||||
|
|
||||||
**Implementation**:
|
実装(Phase 224-cont / 224-D):
|
||||||
1. Add `promoted_loopbodylocals: Vec<String>` to CarrierInfo
|
1. `CarrierInfo` に `promoted_loopbodylocals: Vec<String>` と `condition_aliases: Vec<ConditionAlias>` を追加。
|
||||||
2. In Phase 223.5, record `promoted_var` in CarrierInfo
|
2. LoopBodyCondPromoter(Trim/DigitPos の両方)で昇格成功時に
|
||||||
3. Modify lower_loop_with_break_minimal signature:
|
`promoted_loopbodylocals.push("digit_pos")` と
|
||||||
```rust
|
`condition_aliases.push(ConditionAlias { old_name: "digit_pos", carrier_name: "is_digit_pos" })` を記録。
|
||||||
fn lower_loop_with_break_minimal(
|
3. Pattern2/4 lowerer は ConditionEnvBuilder v2 を呼ぶ際に `&carrier_info.condition_aliases` を渡す。
|
||||||
...,
|
4. ConditionEnvBuilder は `var_name == "digit_pos"` のような未解決変数を見つけた場合、
|
||||||
promoted_vars: &[String], // NEW
|
ConditionAlias を使って `carrier_name == "is_digit_pos"` に解決し、その ValueId を Condition 役の Param としてバインド。
|
||||||
) -> Result<...>
|
|
||||||
```
|
|
||||||
4. In LoopConditionScopeBox::analyze(), filter out promoted_vars:
|
|
||||||
```rust
|
|
||||||
if cond_scope.has_loop_body_local_except(promoted_vars) {
|
|
||||||
// Only error if non-promoted LoopBodyLocal exists
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Pros**: Minimal changes, surgical fix
|
効果:
|
||||||
**Cons**: Adds parameter to lowerer API
|
- LoopBodyLocal 条件パターン(A-3 Trim/A-4 DigitPos)は、
|
||||||
**Effort**: ~1-2 hours
|
**AST 書き換えなしで「条件式から見える名前」と「carrier 実体」を橋渡しできる**。
|
||||||
|
- Pattern2/4 や LoopConditionScopeBox は「昇格済み LoopBodyLocal」とそれ以外を区別できるようになり、
|
||||||
|
不要な Fail‑Fast を避けつつ、未昇格の LoopBodyLocal には引き続き厳格に対応できる。
|
||||||
|
|
||||||
### Option C: DigitPosLoopHelper Metadata (Consistent)
|
### Option C: DigitPosLoopHelper Metadata (Consistent)
|
||||||
|
|
||||||
|
|||||||
@ -341,7 +341,8 @@ Local Region (1000+):
|
|||||||
- **Two-tier promotion**: Step1 で A-3 Trim 試行 → 失敗なら Step2 で A-4 DigitPos 試行 → 両方失敗で Fail-Fast。
|
- **Two-tier promotion**: Step1 で A-3 Trim 試行 → 失敗なら Step2 で A-4 DigitPos 試行 → 両方失敗で Fail-Fast。
|
||||||
- **DigitPosPromoter 統合**: cascading indexOf パターン(substring → indexOf → comparison)の昇格をサポート。
|
- **DigitPosPromoter 統合**: cascading indexOf パターン(substring → indexOf → comparison)の昇格をサポート。
|
||||||
- **Unit test 完全成功**: 6/6 PASS(promoter 自体は完璧動作)。
|
- **Unit test 完全成功**: 6/6 PASS(promoter 自体は完璧動作)。
|
||||||
- **Lowerer Integration Gap**: lower_loop_with_break_minimal が昇格済み変数を認識せず、独立チェックでエラー検出(Phase 224-continuation で対応予定)。
|
- **Phase 224-D**: ConditionAlias/CarrierInfo との連携により、昇格済み LoopBodyLocal 名(`digit_pos` 等)を ConditionEnv から見えるようにブリッジ。
|
||||||
|
- **残りの制約**: body-local init の MethodCall(`substring` 等)の lowering は Phase 193/224-B/C のスコープ外で、今後の Phase で対応。
|
||||||
- 設計原則:
|
- 設計原則:
|
||||||
- **Thin coordinator**: 専門 Promoter(LoopBodyCarrierPromoter / DigitPosPromoter)に昇格ロジックを委譲。
|
- **Thin coordinator**: 専門 Promoter(LoopBodyCarrierPromoter / DigitPosPromoter)に昇格ロジックを委譲。
|
||||||
- **Pattern-agnostic**: Pattern2 (break) / Pattern4 (continue) の統一入口として機能。
|
- **Pattern-agnostic**: Pattern2 (break) / Pattern4 (continue) の統一入口として機能。
|
||||||
|
|||||||
@ -210,16 +210,6 @@ impl MirBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 201: Allocate carrier ValueIds from Param region and SET join_id
|
|
||||||
// This ensures carriers are also in the safe Param region
|
|
||||||
// CRITICAL: We must set join_id so the lowerer can access it
|
|
||||||
for carrier in &mut carrier_info.carriers {
|
|
||||||
let carrier_join_id = join_value_space.alloc_param();
|
|
||||||
carrier.join_id = Some(carrier_join_id);
|
|
||||||
eprintln!("[pattern2/phase201] Allocated carrier '{}' param ID: {:?}",
|
|
||||||
carrier.name, carrier_join_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 191: Create empty body-local environment
|
// Phase 191: Create empty body-local environment
|
||||||
// LoopBodyLocalInitLowerer will populate it during init lowering
|
// LoopBodyLocalInitLowerer will populate it during init lowering
|
||||||
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
||||||
@ -228,10 +218,6 @@ impl MirBuilder {
|
|||||||
eprintln!("[pattern2/body-local] Phase 201: Created empty body-local environment (param_count={})",
|
eprintln!("[pattern2/body-local] Phase 201: Created empty body-local environment (param_count={})",
|
||||||
join_value_space.param_count());
|
join_value_space.param_count());
|
||||||
|
|
||||||
// Phase 201: Create alloc_join_value closure using JoinValueSpace
|
|
||||||
// This ensures all param allocations go through the unified space
|
|
||||||
let mut alloc_join_value = || join_value_space.alloc_param();
|
|
||||||
|
|
||||||
// Debug: Log condition bindings
|
// Debug: Log condition bindings
|
||||||
eprintln!("[cf_loop/pattern2] Phase 201: ConditionEnv contains {} variables:", env.len());
|
eprintln!("[cf_loop/pattern2] Phase 201: ConditionEnv contains {} variables:", env.len());
|
||||||
eprintln!(" Loop param '{}' → JoinIR {:?}", loop_var_name, env.get(&loop_var_name));
|
eprintln!(" Loop param '{}' → JoinIR {:?}", loop_var_name, env.get(&loop_var_name));
|
||||||
@ -352,6 +338,62 @@ impl MirBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 224-D: Allocate join_ids for ALL carriers (including newly merged ones)
|
||||||
|
// This must happen AFTER promotion/merge to include promoted carriers
|
||||||
|
eprintln!("[pattern2/phase224d] Allocating join_ids for {} carriers", carrier_info.carriers.len());
|
||||||
|
for carrier in &mut carrier_info.carriers {
|
||||||
|
let carrier_join_id = join_value_space.alloc_param();
|
||||||
|
carrier.join_id = Some(carrier_join_id);
|
||||||
|
eprintln!("[pattern2/phase224d] Allocated carrier '{}' param ID: {:?}",
|
||||||
|
carrier.name, carrier_join_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 224-D: Save carriers with join_ids BEFORE filtering
|
||||||
|
let carriers_with_join_ids = carrier_info.carriers.clone();
|
||||||
|
|
||||||
|
// Phase 224-D: Add condition aliases to ConditionEnv
|
||||||
|
// This allows promoted variables to be referenced by their original names in conditions
|
||||||
|
for alias in &carrier_info.condition_aliases {
|
||||||
|
// Check if the carrier_name matches the loop_var_name (promoted as main carrier)
|
||||||
|
if alias.carrier_name == carrier_info.loop_var_name {
|
||||||
|
// Use loop variable's join_id from env
|
||||||
|
if let Some(join_id) = env.get(&carrier_info.loop_var_name) {
|
||||||
|
env.insert(alias.old_name.clone(), join_id);
|
||||||
|
eprintln!(
|
||||||
|
"[pattern2/phase224d] Added condition alias '{}' → loop_var '{}' (join_id={:?})",
|
||||||
|
alias.old_name, carrier_info.loop_var_name, join_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Find the carrier's join_id in the carriers list (BEFORE filtering, with join_ids)
|
||||||
|
if let Some(carrier) = carriers_with_join_ids.iter().find(|c| c.name == alias.carrier_name) {
|
||||||
|
if let Some(join_id) = carrier.join_id {
|
||||||
|
// Add alias mapping: old_name → carrier's join_id
|
||||||
|
env.insert(alias.old_name.clone(), join_id);
|
||||||
|
eprintln!(
|
||||||
|
"[pattern2/phase224d] Added condition alias '{}' → carrier '{}' (join_id={:?})",
|
||||||
|
alias.old_name, alias.carrier_name, join_id
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"[pattern2/phase224d] WARNING: Carrier '{}' has no join_id yet!",
|
||||||
|
alias.carrier_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"[pattern2/phase224d] WARNING: Carrier '{}' not found in carriers list!",
|
||||||
|
alias.carrier_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 201: Create alloc_join_value closure using JoinValueSpace
|
||||||
|
// This ensures all param allocations go through the unified space
|
||||||
|
// NOTE: Must be created AFTER all direct join_value_space.alloc_param() calls
|
||||||
|
let mut alloc_join_value = || join_value_space.alloc_param();
|
||||||
|
|
||||||
// Phase 180-3: Delegate Trim/P5 processing to TrimLoopLowerer
|
// Phase 180-3: Delegate Trim/P5 processing to TrimLoopLowerer
|
||||||
let effective_break_condition = if let Some(trim_result) = super::trim_loop_lowering::TrimLoopLowerer::try_lower_trim_like_loop(
|
let effective_break_condition = if let Some(trim_result) = super::trim_loop_lowering::TrimLoopLowerer::try_lower_trim_like_loop(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@ -73,6 +73,7 @@ impl Pattern4CarrierAnalyzer {
|
|||||||
carriers: updated_carriers,
|
carriers: updated_carriers,
|
||||||
trim_helper: all_carriers.trim_helper.clone(),
|
trim_helper: all_carriers.trim_helper.clone(),
|
||||||
promoted_loopbodylocals: all_carriers.promoted_loopbodylocals.clone(), // Phase 224
|
promoted_loopbodylocals: all_carriers.promoted_loopbodylocals.clone(), // Phase 224
|
||||||
|
condition_aliases: all_carriers.condition_aliases.clone(), // Phase 224-D
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,29 @@
|
|||||||
use crate::mir::ValueId;
|
use crate::mir::ValueId;
|
||||||
use std::collections::BTreeMap; // Phase 222.5-D: HashMap → BTreeMap for determinism
|
use std::collections::BTreeMap; // Phase 222.5-D: HashMap → BTreeMap for determinism
|
||||||
|
|
||||||
|
/// Phase 224-D: Alias for promoted LoopBodyLocal in condition expressions
|
||||||
|
///
|
||||||
|
/// When a LoopBodyLocal variable is promoted to a carrier, the original variable
|
||||||
|
/// name must still be resolvable in condition expressions for backward compatibility.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// // Original variable: "digit_pos"
|
||||||
|
/// // Promoted carrier: "is_digit_pos"
|
||||||
|
/// ConditionAlias {
|
||||||
|
/// old_name: "digit_pos".to_string(),
|
||||||
|
/// carrier_name: "is_digit_pos".to_string(),
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ConditionAlias {
|
||||||
|
/// Original variable name (e.g., "digit_pos")
|
||||||
|
pub old_name: String,
|
||||||
|
/// Promoted carrier name (e.g., "is_digit_pos")
|
||||||
|
pub carrier_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// Information about a single carrier variable
|
/// Information about a single carrier variable
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CarrierVar {
|
pub struct CarrierVar {
|
||||||
@ -52,6 +75,12 @@ pub struct CarrierInfo {
|
|||||||
/// during condition promotion (e.g., DigitPosPromoter). The lowerer should skip
|
/// during condition promotion (e.g., DigitPosPromoter). The lowerer should skip
|
||||||
/// LoopBodyLocal checks for these variables.
|
/// LoopBodyLocal checks for these variables.
|
||||||
pub promoted_loopbodylocals: Vec<String>,
|
pub promoted_loopbodylocals: Vec<String>,
|
||||||
|
/// Phase 224-D: Condition aliases for promoted LoopBodyLocal variables
|
||||||
|
///
|
||||||
|
/// Maps old variable names to their promoted carrier names for condition resolution.
|
||||||
|
/// This allows break/continue conditions to reference promoted variables by their
|
||||||
|
/// original names (e.g., `if digit_pos < 0` still works after promotion to "is_digit_pos").
|
||||||
|
pub condition_aliases: Vec<ConditionAlias>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CarrierInfo {
|
impl CarrierInfo {
|
||||||
@ -113,6 +142,7 @@ impl CarrierInfo {
|
|||||||
carriers,
|
carriers,
|
||||||
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
||||||
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
||||||
|
condition_aliases: Vec::new(), // Phase 224-D: No aliases by default
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +201,7 @@ impl CarrierInfo {
|
|||||||
carriers,
|
carriers,
|
||||||
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
||||||
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
||||||
|
condition_aliases: Vec::new(), // Phase 224-D: No aliases by default
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +229,7 @@ impl CarrierInfo {
|
|||||||
carriers,
|
carriers,
|
||||||
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
||||||
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
||||||
|
condition_aliases: Vec::new(), // Phase 224-D: No aliases by default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +290,13 @@ impl CarrierInfo {
|
|||||||
self.promoted_loopbodylocals.push(promoted_var.clone());
|
self.promoted_loopbodylocals.push(promoted_var.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 224-D: Merge condition_aliases (deduplicate by old_name)
|
||||||
|
for alias in &other.condition_aliases {
|
||||||
|
if !self.condition_aliases.iter().any(|a| a.old_name == alias.old_name) {
|
||||||
|
self.condition_aliases.push(alias.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Phase 171-C-5: Get Trim pattern helper
|
/// Phase 171-C-5: Get Trim pattern helper
|
||||||
|
|||||||
@ -83,6 +83,12 @@ impl TrimPatternInfo {
|
|||||||
// Phase 171-C-5: Attach TrimLoopHelper for pattern-specific lowering logic
|
// Phase 171-C-5: Attach TrimLoopHelper for pattern-specific lowering logic
|
||||||
carrier_info.trim_helper = Some(TrimLoopHelper::from_pattern_info(self));
|
carrier_info.trim_helper = Some(TrimLoopHelper::from_pattern_info(self));
|
||||||
|
|
||||||
|
// Phase 224-D: Record condition alias for promoted variable
|
||||||
|
carrier_info.condition_aliases.push(crate::mir::join_ir::lowering::carrier_info::ConditionAlias {
|
||||||
|
old_name: self.var_name.clone(),
|
||||||
|
carrier_name: self.carrier_name.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
carrier_info
|
carrier_info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -180,17 +180,37 @@ impl DigitPosPromoter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Step 6: Build CarrierInfo
|
// Step 6: Build CarrierInfo
|
||||||
|
// For DigitPos pattern, we add a NEW carrier (not replace loop_var)
|
||||||
let carrier_name = format!("is_{}", var_in_cond);
|
let carrier_name = format!("is_{}", var_in_cond);
|
||||||
let carrier_info = CarrierInfo::with_carriers(
|
|
||||||
carrier_name.clone(),
|
use crate::mir::join_ir::lowering::carrier_info::CarrierVar;
|
||||||
ValueId(0), // Placeholder (will be remapped)
|
let promoted_carrier = CarrierVar {
|
||||||
vec![],
|
name: carrier_name.clone(),
|
||||||
|
host_id: ValueId(0), // Placeholder (will be remapped)
|
||||||
|
join_id: None, // Will be allocated later
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create CarrierInfo with a dummy loop_var_name (will be ignored during merge)
|
||||||
|
let mut carrier_info = CarrierInfo::with_carriers(
|
||||||
|
"__dummy_loop_var__".to_string(), // Placeholder, not used
|
||||||
|
ValueId(0), // Placeholder
|
||||||
|
vec![promoted_carrier],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Phase 224-D: Record condition alias for promoted variable
|
||||||
|
carrier_info.condition_aliases.push(crate::mir::join_ir::lowering::carrier_info::ConditionAlias {
|
||||||
|
old_name: var_in_cond.clone(),
|
||||||
|
carrier_name: carrier_name.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"[digitpos_promoter] A-4 DigitPos pattern promoted: {} → {}",
|
"[digitpos_promoter] A-4 DigitPos pattern promoted: {} → {}",
|
||||||
var_in_cond, carrier_name
|
var_in_cond, carrier_name
|
||||||
);
|
);
|
||||||
|
eprintln!(
|
||||||
|
"[digitpos_promoter] Phase 224-D: Added condition alias '{}' → '{}'",
|
||||||
|
var_in_cond, carrier_name
|
||||||
|
);
|
||||||
|
|
||||||
return DigitPosPromotionResult::Promoted {
|
return DigitPosPromotionResult::Promoted {
|
||||||
carrier_info,
|
carrier_info,
|
||||||
|
|||||||
Reference in New Issue
Block a user