feat(mir): Phase 92 P2-2 - Body-local variable support for ConditionalStep
Phase 92 P2-2完了:ConditionalStepのcondition(ch == '\\'など)でbody-local変数をサポート ## 主要変更 ### 1. condition_lowerer.rs拡張 - `lower_condition_to_joinir`に`body_local_env`パラメータ追加 - 変数解決優先度:ConditionEnv → LoopBodyLocalEnv - すべての再帰ヘルパー(comparison, logical_and, logical_or, not, value_expression)対応 ### 2. conditional_step_emitter.rs修正 - `emit_conditional_step_update`に`body_local_env`パラメータ追加 - condition loweringにbody-local環境を渡す ### 3. loop_with_break_minimal.rs修正 - break condition loweringをbody-local init の**後**に移動(line 411) - header_break_lowering::lower_break_conditionにbody_local_env渡す - emit_conditional_step_updateにbody_local_env渡す(line 620) ### 4. header_break_lowering.rs修正 - `lower_break_condition`に`body_local_env`パラメータ追加 - scope_managerにbody-local環境を渡す ### 5. 全呼び出し箇所修正 - expr_lowerer.rs (2箇所) - method_call_lowerer.rs (2箇所) - loop_with_if_phi_if_sum.rs (3箇所) - loop_with_continue_minimal.rs (1箇所) - carrier_update_emitter.rs (1箇所・legacy) ## アーキテクチャ改善 ### Break Condition Lowering順序修正 旧: Header → **Break Cond** → Body-local Init 新: Header → **Body-local Init** → Break Cond 理由:break conditionが`ch == '\"'`のようにbody-local変数を参照する場合、body-local initが先に必要 ### 変数解決優先度(Phase 92 P2-2) 1. ConditionEnv(ループパラメータ、captured変数) 2. LoopBodyLocalEnv(body-local変数like `ch`) ## テスト ### ビルド ✅ cargo build --release成功(30 warnings、0 errors) ### E2E ⚠️ body-local promotion問題でブロック(Phase 92範囲外) - Pattern2はbody-local変数をcarrier promotionする必要あり - 既存パターン(A-3 Trim, A-4 DigitPos)に`ch = get_char(i)`が該当しない - **Phase 92 P2-2目標(condition loweringでbody-local変数サポート)は達成** ## 次タスク(Phase 92 P3以降) - body-local variable promotion拡張(Pattern2で`ch`のような変数を扱う) - P5b E2Eテスト完全動作確認 ## Phase 92 P2-2完了 ✅ Body-local変数のcondition lowering対応完了 ✅ ConditionalStepでbody-local変数参照可能 ✅ Break condition lowering順序修正
This commit is contained in:
@ -408,7 +408,8 @@ pub fn emit_conditional_step_update(
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
// Step 1: Lower the condition expression
|
||||
let (cond_id, cond_insts) = lower_condition_to_joinir(cond_ast, alloc_value, env)?;
|
||||
// Phase 92 P2-2: No body-local support in legacy emitter (use common/conditional_step_emitter instead)
|
||||
let (cond_id, cond_insts) = lower_condition_to_joinir(cond_ast, alloc_value, env, None)?;
|
||||
instructions.extend(cond_insts);
|
||||
|
||||
// Step 2: Get carrier parameter ValueId from env
|
||||
|
||||
@ -18,6 +18,7 @@ use crate::ast::ASTNode;
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierVar;
|
||||
use crate::mir::join_ir::lowering::condition_env::ConditionEnv;
|
||||
use crate::mir::join_ir::lowering::condition_lowerer::lower_condition_to_joinir;
|
||||
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv; // Phase 92 P2-2
|
||||
use crate::mir::join_ir::{BinOpKind, ConstValue, JoinInst, MirLikeInst, VarId};
|
||||
use crate::mir::{MirType, ValueId};
|
||||
|
||||
@ -44,8 +45,14 @@ use crate::mir::{MirType, ValueId};
|
||||
/// * `else_delta` - Delta to add when condition is false
|
||||
/// * `alloc_value` - ValueId allocator closure
|
||||
/// * `env` - ConditionEnv for variable resolution
|
||||
/// * `body_local_env` - Phase 92 P2-2: Optional body-local variable environment
|
||||
/// * `instructions` - Output vector to append instructions to
|
||||
///
|
||||
/// # Phase 92 P2-2: Body-Local Variable Support
|
||||
///
|
||||
/// When the condition references body-local variables (e.g., `ch == '\\'` in escape patterns),
|
||||
/// the `body_local_env` provides name → ValueId mappings for variables defined in the loop body.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// ValueId of the computed update result (the dst of Select)
|
||||
@ -63,6 +70,7 @@ pub fn emit_conditional_step_update(
|
||||
else_delta: i64,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
// Phase 92 P1-1: Fail-Fast check - then_delta must differ from else_delta
|
||||
@ -73,8 +81,8 @@ pub fn emit_conditional_step_update(
|
||||
));
|
||||
}
|
||||
|
||||
// Step 1: Lower the condition expression
|
||||
let (cond_id, cond_insts) = lower_condition_to_joinir(cond_ast, alloc_value, env).map_err(|e| {
|
||||
// Phase 92 P2-2: Lower the condition expression with body-local support
|
||||
let (cond_id, cond_insts) = lower_condition_to_joinir(cond_ast, alloc_value, env, body_local_env).map_err(|e| {
|
||||
format!(
|
||||
"ConditionalStep invariant violated: condition must be pure expression for carrier '{}': {}",
|
||||
carrier_name, e
|
||||
|
||||
@ -17,6 +17,7 @@ use crate::mir::join_ir::{BinOpKind, CompareOp, ConstValue, JoinInst, MirLikeIns
|
||||
use crate::mir::ValueId;
|
||||
|
||||
use super::condition_env::ConditionEnv;
|
||||
use super::loop_body_local_env::LoopBodyLocalEnv; // Phase 92 P2-2: Body-local support
|
||||
use super::method_call_lowerer::MethodCallLowerer;
|
||||
|
||||
/// Lower an AST condition to JoinIR instructions
|
||||
@ -26,6 +27,7 @@ use super::method_call_lowerer::MethodCallLowerer;
|
||||
/// * `cond_ast` - AST node representing the boolean condition
|
||||
/// * `alloc_value` - ValueId allocator function
|
||||
/// * `env` - ConditionEnv for variable resolution (JoinIR-local ValueIds)
|
||||
/// * `body_local_env` - Phase 92 P2-2: Optional body-local variable environment
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
@ -38,6 +40,16 @@ use super::method_call_lowerer::MethodCallLowerer;
|
||||
/// - Logical: `a && b`, `a || b`, `!cond`
|
||||
/// - Variables and literals
|
||||
///
|
||||
/// # Phase 92 P2-2: Body-Local Variable Support
|
||||
///
|
||||
/// When lowering conditions that reference body-local variables (e.g., `ch == '\\'`
|
||||
/// in escape patterns), the `body_local_env` parameter provides name → ValueId
|
||||
/// mappings for variables defined in the loop body.
|
||||
///
|
||||
/// Variable resolution priority:
|
||||
/// 1. ConditionEnv (loop parameters, captured variables)
|
||||
/// 2. LoopBodyLocalEnv (body-local variables like `ch`)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
@ -45,6 +57,9 @@ use super::method_call_lowerer::MethodCallLowerer;
|
||||
/// env.insert("i".to_string(), ValueId(0));
|
||||
/// env.insert("end".to_string(), ValueId(1));
|
||||
///
|
||||
/// let mut body_env = LoopBodyLocalEnv::new();
|
||||
/// body_env.insert("ch".to_string(), ValueId(5)); // Phase 92 P2-2
|
||||
///
|
||||
/// let mut value_counter = 2u32;
|
||||
/// let mut alloc_value = || {
|
||||
/// let id = ValueId(value_counter);
|
||||
@ -52,30 +67,37 @@ use super::method_call_lowerer::MethodCallLowerer;
|
||||
/// id
|
||||
/// };
|
||||
///
|
||||
/// // Lower condition: i < end
|
||||
/// // Lower condition: ch == '\\'
|
||||
/// let (cond_value, cond_insts) = lower_condition_to_joinir(
|
||||
/// condition_ast,
|
||||
/// &mut alloc_value,
|
||||
/// &env,
|
||||
/// Some(&body_env), // Phase 92 P2-2: Body-local support
|
||||
/// )?;
|
||||
/// ```
|
||||
pub fn lower_condition_to_joinir(
|
||||
cond_ast: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
) -> Result<(ValueId, Vec<JoinInst>), String> {
|
||||
let mut instructions = Vec::new();
|
||||
let result_value = lower_condition_recursive(cond_ast, alloc_value, env, &mut instructions)?;
|
||||
let result_value = lower_condition_recursive(cond_ast, alloc_value, env, body_local_env, &mut instructions)?;
|
||||
Ok((result_value, instructions))
|
||||
}
|
||||
|
||||
/// Recursive helper for condition lowering
|
||||
///
|
||||
/// Handles all supported AST node types and emits appropriate JoinIR instructions.
|
||||
///
|
||||
/// # Phase 92 P2-2
|
||||
///
|
||||
/// Added `body_local_env` parameter to support body-local variable resolution.
|
||||
fn lower_condition_recursive(
|
||||
cond_ast: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
match cond_ast {
|
||||
@ -92,10 +114,10 @@ fn lower_condition_recursive(
|
||||
| BinaryOperator::LessEqual
|
||||
| BinaryOperator::GreaterEqual
|
||||
| BinaryOperator::Greater => {
|
||||
lower_comparison(operator, left, right, alloc_value, env, instructions)
|
||||
lower_comparison(operator, left, right, alloc_value, env, body_local_env, instructions)
|
||||
}
|
||||
BinaryOperator::And => lower_logical_and(left, right, alloc_value, env, instructions),
|
||||
BinaryOperator::Or => lower_logical_or(left, right, alloc_value, env, instructions),
|
||||
BinaryOperator::And => lower_logical_and(left, right, alloc_value, env, body_local_env, instructions),
|
||||
BinaryOperator::Or => lower_logical_or(left, right, alloc_value, env, body_local_env, instructions),
|
||||
_ => Err(format!(
|
||||
"Unsupported binary operator in condition: {:?}",
|
||||
operator
|
||||
@ -107,12 +129,22 @@ fn lower_condition_recursive(
|
||||
operator: UnaryOperator::Not,
|
||||
operand,
|
||||
..
|
||||
} => lower_not_operator(operand, alloc_value, env, instructions),
|
||||
} => lower_not_operator(operand, alloc_value, env, body_local_env, instructions),
|
||||
|
||||
// Variables - resolve from ConditionEnv
|
||||
ASTNode::Variable { name, .. } => env
|
||||
.get(name)
|
||||
.ok_or_else(|| format!("Variable '{}' not bound in ConditionEnv", name)),
|
||||
// Phase 92 P2-2: Variables - resolve from ConditionEnv or LoopBodyLocalEnv
|
||||
ASTNode::Variable { name, .. } => {
|
||||
// Priority 1: ConditionEnv (loop parameters, captured variables)
|
||||
if let Some(value_id) = env.get(name) {
|
||||
return Ok(value_id);
|
||||
}
|
||||
// Priority 2: LoopBodyLocalEnv (body-local variables like `ch`)
|
||||
if let Some(body_env) = body_local_env {
|
||||
if let Some(value_id) = body_env.get(name) {
|
||||
return Ok(value_id);
|
||||
}
|
||||
}
|
||||
Err(format!("Variable '{}' not found in ConditionEnv or LoopBodyLocalEnv", name))
|
||||
}
|
||||
|
||||
// Literals - emit as constants
|
||||
ASTNode::Literal { value, .. } => lower_literal(value, alloc_value, instructions),
|
||||
@ -128,11 +160,12 @@ fn lower_comparison(
|
||||
right: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
// Lower left and right sides
|
||||
let lhs = lower_value_expression(left, alloc_value, env, instructions)?;
|
||||
let rhs = lower_value_expression(right, alloc_value, env, instructions)?;
|
||||
let lhs = lower_value_expression(left, alloc_value, env, body_local_env, instructions)?;
|
||||
let rhs = lower_value_expression(right, alloc_value, env, body_local_env, instructions)?;
|
||||
let dst = alloc_value();
|
||||
|
||||
let cmp_op = match operator {
|
||||
@ -162,11 +195,12 @@ fn lower_logical_and(
|
||||
right: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
// Logical AND: evaluate both sides and combine
|
||||
let lhs = lower_condition_recursive(left, alloc_value, env, instructions)?;
|
||||
let rhs = lower_condition_recursive(right, alloc_value, env, instructions)?;
|
||||
let lhs = lower_condition_recursive(left, alloc_value, env, body_local_env, instructions)?;
|
||||
let rhs = lower_condition_recursive(right, alloc_value, env, body_local_env, instructions)?;
|
||||
let dst = alloc_value();
|
||||
|
||||
// Emit BinOp And instruction
|
||||
@ -186,11 +220,12 @@ fn lower_logical_or(
|
||||
right: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
// Logical OR: evaluate both sides and combine
|
||||
let lhs = lower_condition_recursive(left, alloc_value, env, instructions)?;
|
||||
let rhs = lower_condition_recursive(right, alloc_value, env, instructions)?;
|
||||
let lhs = lower_condition_recursive(left, alloc_value, env, body_local_env, instructions)?;
|
||||
let rhs = lower_condition_recursive(right, alloc_value, env, body_local_env, instructions)?;
|
||||
let dst = alloc_value();
|
||||
|
||||
// Emit BinOp Or instruction
|
||||
@ -209,9 +244,10 @@ fn lower_not_operator(
|
||||
operand: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
let operand_val = lower_condition_recursive(operand, alloc_value, env, instructions)?;
|
||||
let operand_val = lower_condition_recursive(operand, alloc_value, env, body_local_env, instructions)?;
|
||||
let dst = alloc_value();
|
||||
|
||||
// Emit UnaryOp Not instruction
|
||||
@ -258,17 +294,33 @@ fn lower_literal(
|
||||
///
|
||||
/// This handles the common case where we need to evaluate a simple value
|
||||
/// (variable or literal) as part of a comparison.
|
||||
///
|
||||
/// # Phase 92 P2-2
|
||||
///
|
||||
/// Added `body_local_env` parameter to support body-local variable resolution
|
||||
/// (e.g., `ch` in `ch == '\\'`).
|
||||
pub fn lower_value_expression(
|
||||
expr: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
match expr {
|
||||
// Variables - look up in ConditionEnv
|
||||
ASTNode::Variable { name, .. } => env
|
||||
.get(name)
|
||||
.ok_or_else(|| format!("Variable '{}' not bound in ConditionEnv", name)),
|
||||
// Phase 92 P2-2: Variables - resolve from ConditionEnv or LoopBodyLocalEnv
|
||||
ASTNode::Variable { name, .. } => {
|
||||
// Priority 1: ConditionEnv (loop parameters, captured variables)
|
||||
if let Some(value_id) = env.get(name) {
|
||||
return Ok(value_id);
|
||||
}
|
||||
// Priority 2: LoopBodyLocalEnv (body-local variables like `ch`)
|
||||
if let Some(body_env) = body_local_env {
|
||||
if let Some(value_id) = body_env.get(name) {
|
||||
return Ok(value_id);
|
||||
}
|
||||
}
|
||||
Err(format!("Variable '{}' not found in ConditionEnv or LoopBodyLocalEnv", name))
|
||||
}
|
||||
|
||||
// Literals - emit as constants
|
||||
ASTNode::Literal { value, .. } => lower_literal(value, alloc_value, instructions),
|
||||
@ -279,7 +331,7 @@ pub fn lower_value_expression(
|
||||
left,
|
||||
right,
|
||||
..
|
||||
} => lower_arithmetic_binop(operator, left, right, alloc_value, env, instructions),
|
||||
} => lower_arithmetic_binop(operator, left, right, alloc_value, env, body_local_env, instructions),
|
||||
|
||||
// Phase 224-C: MethodCall support with arguments (e.g., s.length(), s.indexOf(ch))
|
||||
ASTNode::MethodCall {
|
||||
@ -289,7 +341,7 @@ pub fn lower_value_expression(
|
||||
..
|
||||
} => {
|
||||
// 1. Lower receiver (object) to ValueId
|
||||
let recv_val = lower_value_expression(object, alloc_value, env, instructions)?;
|
||||
let recv_val = lower_value_expression(object, alloc_value, env, body_local_env, instructions)?;
|
||||
|
||||
// 2. Lower method call using MethodCallLowerer (will lower arguments internally)
|
||||
MethodCallLowerer::lower_for_condition(
|
||||
@ -316,10 +368,11 @@ fn lower_arithmetic_binop(
|
||||
right: &ASTNode,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
env: &ConditionEnv,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
instructions: &mut Vec<JoinInst>,
|
||||
) -> Result<ValueId, String> {
|
||||
let lhs = lower_value_expression(left, alloc_value, env, instructions)?;
|
||||
let rhs = lower_value_expression(right, alloc_value, env, instructions)?;
|
||||
let lhs = lower_value_expression(left, alloc_value, env, body_local_env, instructions)?;
|
||||
let rhs = lower_value_expression(right, alloc_value, env, body_local_env, instructions)?;
|
||||
let dst = alloc_value();
|
||||
|
||||
let bin_op = match operator {
|
||||
|
||||
@ -211,7 +211,7 @@ impl<'env, 'builder, S: ScopeManager> ExprLowerer<'env, 'builder, S> {
|
||||
};
|
||||
|
||||
let (result_value, instructions) =
|
||||
lower_condition_to_joinir(ast, &mut alloc_value, &condition_env)
|
||||
lower_condition_to_joinir(ast, &mut alloc_value, &condition_env, None) // Phase 92 P2-2
|
||||
.map_err(|e| ExprLoweringError::LoweringError(e))?;
|
||||
|
||||
// Phase 235: 保存しておき、テストから観察できるようにする
|
||||
@ -297,7 +297,7 @@ impl<'env, 'builder, S: ScopeManager> ConditionLoweringBox<S> for ExprLowerer<'e
|
||||
|
||||
// Delegate to the well-tested lowerer, but use the caller-provided allocator (SSOT).
|
||||
let (result_value, instructions) =
|
||||
lower_condition_to_joinir(condition, &mut *context.alloc_value, &condition_env)
|
||||
lower_condition_to_joinir(condition, &mut *context.alloc_value, &condition_env, None) // Phase 92 P2-2
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
self.last_instructions = instructions;
|
||||
|
||||
@ -63,8 +63,10 @@ mod tests;
|
||||
|
||||
use crate::mir::join_ir::lowering::carrier_info::{CarrierInfo, JoinFragmentMeta};
|
||||
use crate::mir::join_ir::lowering::carrier_update_emitter::{
|
||||
emit_carrier_update, emit_carrier_update_with_env, emit_conditional_step_update,
|
||||
emit_carrier_update, emit_carrier_update_with_env,
|
||||
};
|
||||
// Phase 92 P2-1: Import ConditionalStep emitter from dedicated module
|
||||
use crate::mir::join_ir::lowering::common::conditional_step_emitter::emit_conditional_step_update;
|
||||
use crate::mir::join_ir::lowering::condition_to_joinir::ConditionEnv;
|
||||
use crate::mir::loop_canonicalizer::UpdateKind;
|
||||
use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace;
|
||||
@ -290,15 +292,8 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
// After condition lowering, allocate remaining ValueIds
|
||||
let exit_cond = alloc_value(); // Exit condition (negated loop condition)
|
||||
|
||||
// Phase 170-B / Phase 236-EX / Phase 244: Lower break condition
|
||||
let (break_cond_value, break_cond_instructions) = lower_break_condition(
|
||||
break_condition,
|
||||
env,
|
||||
carrier_info,
|
||||
loop_var_name,
|
||||
i_param,
|
||||
&mut alloc_value,
|
||||
)?;
|
||||
// Phase 92 P2-2: Break condition lowering moved after body-local init
|
||||
// (will be called later after body_local_env is populated)
|
||||
|
||||
let _const_1 = alloc_value(); // Increment constant
|
||||
let _i_next = alloc_value(); // i + 1
|
||||
@ -409,6 +404,20 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Phase 170-B / Phase 244 / Phase 92 P2-2: Lower break condition
|
||||
// ------------------------------------------------------------------
|
||||
// Phase 92 P2-2: Moved after body-local init to support body-local variable references
|
||||
let (break_cond_value, break_cond_instructions) = lower_break_condition(
|
||||
break_condition,
|
||||
env,
|
||||
carrier_info,
|
||||
loop_var_name,
|
||||
i_param,
|
||||
&mut alloc_value,
|
||||
body_local_env.as_ref().map(|e| &**e), // Phase 92 P2-2: Pass body_local_env
|
||||
)?;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Phase 170-B: Break Condition Check (delegated to condition_to_joinir)
|
||||
// ------------------------------------------------------------------
|
||||
@ -588,27 +597,39 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Phase 92 P0-3: Check if skeleton has ConditionalStep for this carrier
|
||||
// Phase 92 P2-1: Check if skeleton has ConditionalStep for this carrier
|
||||
if let Some(skel) = skeleton {
|
||||
if let Some(carrier_slot) = skel.carriers.iter().find(|c| c.name == *carrier_name) {
|
||||
if let UpdateKind::ConditionalStep { cond, then_delta, else_delta } = &carrier_slot.update_kind {
|
||||
// Use emit_conditional_step_update instead of emit_carrier_update
|
||||
// Phase 92 P2-1: Use ConditionalStepEmitter (dedicated module)
|
||||
eprintln!(
|
||||
"[joinir/pattern2] Phase 92 P0-3: ConditionalStep detected for carrier '{}': then={}, else={}",
|
||||
"[joinir/pattern2] Phase 92 P2-1: ConditionalStep detected for carrier '{}': then={}, else={}",
|
||||
carrier_name, then_delta, else_delta
|
||||
);
|
||||
|
||||
// Phase 92 P2-1: Get carrier parameter ValueId (must be set by header PHI)
|
||||
let carrier_param = carrier.join_id.ok_or_else(|| {
|
||||
format!(
|
||||
"[pattern2/conditional_step] Carrier '{}' join_id not set (header PHI not generated?)",
|
||||
carrier_name
|
||||
)
|
||||
})?;
|
||||
|
||||
// Phase 92 P2-2: Pass body_local_env for condition lowering
|
||||
let updated_value = emit_conditional_step_update(
|
||||
carrier,
|
||||
carrier_name,
|
||||
carrier_param,
|
||||
&*cond,
|
||||
*then_delta,
|
||||
*else_delta,
|
||||
&mut alloc_value,
|
||||
env,
|
||||
body_local_env.as_ref().map(|e| &**e), // Phase 92 P2-2
|
||||
&mut carrier_update_block,
|
||||
)?;
|
||||
).map_err(|e| format!("[pattern2/conditional_step] {}", e))?;
|
||||
updated_carrier_values.push(updated_value);
|
||||
eprintln!(
|
||||
"[joinir/pattern2] Phase 92 P0-3: ConditionalStep carrier '{}' updated → {:?}",
|
||||
"[joinir/pattern2] Phase 92 P2-1: ConditionalStep carrier '{}' updated → {:?}",
|
||||
carrier_name, updated_value
|
||||
);
|
||||
continue; // Skip normal carrier update
|
||||
|
||||
@ -77,11 +77,16 @@ pub(crate) fn lower_header_condition(
|
||||
"[joinir/pattern2/phase244] Header condition via legacy path (not yet supported by ConditionLoweringBox)"
|
||||
);
|
||||
let mut shim = || alloc_value();
|
||||
lower_condition_to_joinir(condition, &mut shim, env)
|
||||
lower_condition_to_joinir(condition, &mut shim, env, None) // Phase 92 P2-2: No body-local for header
|
||||
}
|
||||
}
|
||||
|
||||
/// Lower the break condition via ExprLowerer (no legacy fallback).
|
||||
///
|
||||
/// # Phase 92 P2-2: Body-Local Variable Support
|
||||
///
|
||||
/// Added `body_local_env` parameter to support break conditions that reference
|
||||
/// body-local variables (e.g., `ch == '"'` in escape patterns).
|
||||
pub(crate) fn lower_break_condition(
|
||||
break_condition: &ASTNode,
|
||||
env: &ConditionEnv,
|
||||
@ -89,14 +94,18 @@ pub(crate) fn lower_break_condition(
|
||||
loop_var_name: &str,
|
||||
loop_var_id: ValueId,
|
||||
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>, // Phase 92 P2-2
|
||||
) -> Result<(ValueId, Vec<JoinInst>), String> {
|
||||
use crate::mir::join_ir::lowering::condition_lowering_box::ConditionLoweringBox;
|
||||
|
||||
// Phase 92 P2-2: Use provided body_local_env or empty if None
|
||||
let empty_body_env = LoopBodyLocalEnv::new();
|
||||
let body_env_ref = body_local_env.unwrap_or(&empty_body_env);
|
||||
|
||||
let empty_captured_env = CapturedEnv::new();
|
||||
let scope_manager = make_scope_manager(
|
||||
env,
|
||||
Some(&empty_body_env),
|
||||
Some(body_env_ref), // Phase 92 P2-2: Pass body_local_env to scope
|
||||
Some(&empty_captured_env),
|
||||
carrier_info,
|
||||
);
|
||||
|
||||
@ -284,7 +284,7 @@ pub(crate) fn lower_loop_with_continue_minimal(
|
||||
} else {
|
||||
// Legacy path: condition_to_joinir (for complex conditions not yet supported)
|
||||
eprintln!("[joinir/pattern4/phase244] Header condition via legacy path (not yet supported by ConditionLoweringBox)");
|
||||
lower_condition_to_joinir(condition, &mut alloc_value, &env)?
|
||||
lower_condition_to_joinir(condition, &mut alloc_value, &env, None)? // Phase 92 P2-2: No body-local for header
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -464,7 +464,7 @@ where
|
||||
column: 1,
|
||||
},
|
||||
};
|
||||
lower_value_expression(&var_node, alloc_value, cond_env, &mut limit_instructions)?
|
||||
lower_value_expression(&var_node, alloc_value, cond_env, None, &mut limit_instructions)? // Phase 92 P2-2
|
||||
}
|
||||
};
|
||||
|
||||
@ -500,10 +500,10 @@ where
|
||||
|
||||
// Lower left-hand side (complex expression)
|
||||
let mut instructions = Vec::new();
|
||||
let lhs_val = lower_value_expression(left, alloc_value, cond_env, &mut instructions)?;
|
||||
let lhs_val = lower_value_expression(left, alloc_value, cond_env, None, &mut instructions)?; // Phase 92 P2-2
|
||||
|
||||
// Lower right-hand side
|
||||
let rhs_val = lower_value_expression(right, alloc_value, cond_env, &mut instructions)?;
|
||||
let rhs_val = lower_value_expression(right, alloc_value, cond_env, None, &mut instructions)?; // Phase 92 P2-2
|
||||
|
||||
// Extract base variable name from LHS if possible
|
||||
let var_name = extract_base_variable(left);
|
||||
|
||||
@ -127,6 +127,7 @@ impl MethodCallLowerer {
|
||||
arg_ast,
|
||||
alloc_value,
|
||||
env,
|
||||
None, // Phase 92 P2-2: No body-local for method call args
|
||||
instructions,
|
||||
)?;
|
||||
lowered_args.push(arg_val);
|
||||
@ -305,6 +306,7 @@ impl MethodCallLowerer {
|
||||
expr,
|
||||
alloc_value,
|
||||
cond_env,
|
||||
None, // Phase 92 P2-2: No body-local for method call expressions
|
||||
instructions,
|
||||
),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user