From f55f6cc653a7bfddcd54e5ac3a61b312afbd43b9 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Fri, 19 Dec 2025 05:58:36 +0900 Subject: [PATCH] feat(phase143): Step 3 - Condition lowering integration with validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 143 P0 Step 3: Integrate NormalizedExprLowererBox for condition validation - Extract If condition AST from loop(true) { if(cond) break } pattern - Validate condition with PureOnly scope (variables, literals, arith, compare only) - Return Ok(None) gracefully if condition is impure or out-of-scope - Maintain skeleton structure: returns Ok(None) overall (full JoinModule in Steps 4-6) - cargo check passes with no errors Key changes: - Updated extract_loop_true_if_break() to return condition AST - Implemented validation using NormalizedExprLowererBox::lower_expr_with_scope() - Proper error handling with fallback to Ok(None) for out-of-scope - Debug logging for dev-only tracing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 --- .../loop_true_if_break_continue.rs | 74 ++++++++++++++++--- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs b/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs index 312d2985..14f05a97 100644 --- a/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs +++ b/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs @@ -21,9 +21,13 @@ //! - Err(msg): In scope but failed (internal error, strict mode freeze) use super::env_layout::EnvLayout; +use super::common::expr_lowerer_box::NormalizedExprLowererBox; +use super::common::expr_lowering_contract::ExprLoweringScope; use crate::mir::control_tree::step_tree::{StepNode, StepStmtKind, StepTree}; use crate::mir::join_ir::lowering::carrier_info::JoinFragmentMeta; -use crate::mir::join_ir::JoinModule; +use crate::mir::join_ir::{JoinFunction, JoinFuncId, JoinInst, JoinModule}; +use crate::mir::ValueId; +use std::collections::BTreeMap; /// Box-First: loop(true) + if + break lowering to Normalized pub struct LoopTrueIfBreakContinueBuilderBox; @@ -42,12 +46,13 @@ impl LoopTrueIfBreakContinueBuilderBox { } // Pattern: loop(true) { if(cond) break } - // Extract must succeed for this phase to proceed - let _extracted = match Self::extract_loop_true_if_break(&step_tree.root) { - Some(_) => { + // Step 1: Extract pattern match + let cond_ast = match Self::extract_loop_true_if_break(&step_tree.root) { + Some(cond) => { if crate::config::env::joinir_dev_enabled() { eprintln!("[phase143/debug] Pattern matched: loop(true) if break"); } + cond } None => { if crate::config::env::joinir_dev_enabled() { @@ -57,16 +62,62 @@ impl LoopTrueIfBreakContinueBuilderBox { } }; - // Phase 143 P0: Skeleton returns Ok(None) for now - // Full implementation in Steps 2-6 + // Step 3 (P0): Validate condition lowering with PureOnly scope + // This step checks if the condition can be lowered as a pure expression. + // We don't emit the actual JoinModule yet (that's Steps 4-6), + // but we verify early that the condition is in scope. + + let env_fields = env_layout.env_fields(); + let mut env_check: BTreeMap = BTreeMap::new(); + + // Build a dummy env for validation (temp ValueIds) + let mut temp_vid = 1u32; + for field in &env_fields { + env_check.insert(field.clone(), ValueId(temp_vid)); + temp_vid += 1; + } + + // Try to lower the condition with PureOnly scope + let mut dummy_body: Vec = Vec::new(); + let mut temp_next_vid = temp_vid; + + match NormalizedExprLowererBox::lower_expr_with_scope( + ExprLoweringScope::PureOnly, + &cond_ast, + &env_check, + &mut dummy_body, + &mut temp_next_vid, + ) { + Ok(Some(_vid)) => { + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Condition is pure and lowerable"); + } + } + Ok(None) => { + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Condition is not pure (impure/out-of-scope), falling back to legacy"); + } + return Ok(None); // Condition not pure, fallback to legacy + } + Err(e) => { + return Err(format!("phase143/condition_lowering: {}", e)); + } + } + + // Phase 143 P0: Skeleton continues to return Ok(None) + // Steps 4-6 will build the actual JoinModule with Jump instructions + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Step 3 validation passed, skeleton still returns Ok(None)"); + } Ok(None) } /// Extract loop(true) + single if + break pattern /// - /// Returns Some(()) if pattern matches, None otherwise. + /// Returns Some(cond_ast) if pattern matches, None otherwise. /// Pattern: StepNode::Loop with body containing single If with break - fn extract_loop_true_if_break(root: &StepNode) -> Option<()> { + /// Also returns the If condition AST for lowering. + fn extract_loop_true_if_break(root: &StepNode) -> Option { match root { StepNode::Loop { cond_ast, body, .. } => { // Condition must be Bool(true) literal @@ -88,6 +139,7 @@ impl LoopTrueIfBreakContinueBuilderBox { // If statement structure: if(cond_pure) { break } if let StepNode::If { + cond_ast: if_cond, then_branch, else_branch, .. @@ -117,7 +169,7 @@ impl LoopTrueIfBreakContinueBuilderBox { }; if has_break { - Some(()) // Pattern matched + Some((*if_cond.0).clone()) // Return If condition AST } else { None } @@ -148,9 +200,9 @@ mod tests { #[test] fn test_pattern_detection_out_of_scope_no_loop() { // If pattern is not loop, should return None - assert_eq!(LoopTrueIfBreakContinueBuilderBox::extract_loop_true_if_break( + assert!(LoopTrueIfBreakContinueBuilderBox::extract_loop_true_if_break( &StepNode::Block(vec![]) - ), None); + ).is_none()); } #[test]