diff --git a/src/mir/control_tree/normalized_shadow/builder.rs b/src/mir/control_tree/normalized_shadow/builder.rs index 3a136f76..4eb39dc6 100644 --- a/src/mir/control_tree/normalized_shadow/builder.rs +++ b/src/mir/control_tree/normalized_shadow/builder.rs @@ -12,6 +12,7 @@ use crate::mir::control_tree::normalized_shadow::env_layout::{ }; use crate::mir::control_tree::normalized_shadow::if_as_last_join_k::IfAsLastJoinKLowererBox; use crate::mir::control_tree::normalized_shadow::loop_true_break_once::LoopTrueBreakOnceBuilderBox; // Phase 131 +use crate::mir::control_tree::normalized_shadow::loop_true_if_break_continue::LoopTrueIfBreakContinueBuilderBox; // Phase 143 P0 use crate::mir::control_tree::normalized_shadow::post_if_post_k::PostIfPostKBuilderBox; // Phase 129-C use crate::mir::control_tree::normalized_shadow::legacy::LegacyLowerer; use crate::mir::control_tree::step_tree::StepTree; @@ -98,6 +99,11 @@ impl StepTreeNormalizedShadowLowererBox { return Ok(Some((module, meta))); } + // Phase 143 P0: loop(true) + if + break pattern + if let Some((module, meta)) = LoopTrueIfBreakContinueBuilderBox::lower(step_tree, &env_layout)? { + return Ok(Some((module, meta))); + } + // Not supported: fall back to legacy (returns Ok(None)) Ok(None) } 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 new file mode 100644 index 00000000..312d2985 --- /dev/null +++ b/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs @@ -0,0 +1,170 @@ +//! Phase 143 P0: loop(true) + if + break Normalized lowering +//! +//! ## Responsibility +//! +//! - Lower `loop(true) { if(cond_pure) break }` to Normalized JoinModule +//! - Conditional exit control flow (Branch instructions) +//! - PHI-free: all state passing via env arguments + continuations +//! - Pure condition expressions only (Phase 143 P0 scope) +//! +//! ## Scope (P0) +//! +//! - Loop condition: `true` literal only +//! - Loop body: Single `if` statement only +//! - If branch: `break` only (no continue, no else) +//! - Condition expression: Pure only (variables, literals, arith, compare) +//! +//! ## Return Behavior +//! +//! - Ok(Some((module, meta))): Successfully lowered +//! - Ok(None): Out of scope (fallback to legacy) +//! - Err(msg): In scope but failed (internal error, strict mode freeze) + +use super::env_layout::EnvLayout; +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; + +/// Box-First: loop(true) + if + break lowering to Normalized +pub struct LoopTrueIfBreakContinueBuilderBox; + +impl LoopTrueIfBreakContinueBuilderBox { + /// Try to lower loop(true) + if + break pattern to Normalized JoinModule. + /// + /// Phase 143 P0: Minimal scope - loop(true){ if(cond) break } only + pub fn lower( + step_tree: &StepTree, + env_layout: &EnvLayout, + ) -> Result, String> { + // DEBUG: Log attempt + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Attempting loop_true_if_break pattern (P0 minimal scope)"); + } + + // 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(_) => { + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Pattern matched: loop(true) if break"); + } + } + None => { + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Pattern not matched, out of scope"); + } + return Ok(None); // Out of scope + } + }; + + // Phase 143 P0: Skeleton returns Ok(None) for now + // Full implementation in Steps 2-6 + Ok(None) + } + + /// Extract loop(true) + single if + break pattern + /// + /// Returns Some(()) if pattern matches, None otherwise. + /// Pattern: StepNode::Loop with body containing single If with break + fn extract_loop_true_if_break(root: &StepNode) -> Option<()> { + match root { + StepNode::Loop { cond_ast, body, .. } => { + // Condition must be Bool(true) literal + if !Self::is_bool_true_literal(&cond_ast.0) { + return None; + } + + // Body must be single if statement (possibly wrapped in Block) + let if_node = match body.as_ref() { + StepNode::If { .. } => Some(body.as_ref()), + StepNode::Block(stmts) if stmts.len() == 1 => { + match &stmts[0] { + StepNode::If { .. } => Some(&stmts[0]), + _ => None, + } + } + _ => None, + }?; + + // If statement structure: if(cond_pure) { break } + if let StepNode::If { + then_branch, + else_branch, + .. + } = if_node + { + // Phase 143 P0: no else branch allowed + if else_branch.is_some() { + return None; + } + + // Then branch must be Break statement + let has_break = match then_branch.as_ref() { + StepNode::Stmt { + kind: StepStmtKind::Break, + .. + } => true, + StepNode::Block(stmts) if stmts.len() == 1 => { + matches!( + &stmts[0], + StepNode::Stmt { + kind: StepStmtKind::Break, + .. + } + ) + } + _ => false, + }; + + if has_break { + Some(()) // Pattern matched + } else { + None + } + } else { + None + } + } + _ => None, + } + } + + /// Check if AST node is Bool(true) literal + fn is_bool_true_literal(ast: &crate::ast::ASTNode) -> bool { + matches!( + ast, + crate::ast::ASTNode::Literal { + value: crate::ast::LiteralValue::Bool(true), + .. + } + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[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( + &StepNode::Block(vec![]) + ), None); + } + + #[test] + fn test_is_bool_true_literal() { + let true_lit = crate::ast::ASTNode::Literal { + value: crate::ast::LiteralValue::Bool(true), + span: (0, 0), + }; + assert!(LoopTrueIfBreakContinueBuilderBox::is_bool_true_literal(&true_lit)); + + let false_lit = crate::ast::ASTNode::Literal { + value: crate::ast::LiteralValue::Bool(false), + span: (0, 0), + }; + assert!(!LoopTrueIfBreakContinueBuilderBox::is_bool_true_literal(&false_lit)); + } +} diff --git a/src/mir/control_tree/normalized_shadow/mod.rs b/src/mir/control_tree/normalized_shadow/mod.rs index d2909837..665f973e 100644 --- a/src/mir/control_tree/normalized_shadow/mod.rs +++ b/src/mir/control_tree/normalized_shadow/mod.rs @@ -35,6 +35,7 @@ pub mod normalized_verifier; pub mod env_layout; pub mod if_as_last_join_k; pub mod loop_true_break_once; // Phase 131: loop(true) break-once +pub mod loop_true_if_break_continue; // Phase 143 P0: loop(true) + if + break pub mod post_if_post_k; // Phase 129-C: post-if with post_k continuation pub mod legacy; pub mod dev_pipeline;