feat(phase143): Step 3 - Condition lowering integration with validation
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 <noreply@anthropic.com>
This commit is contained in:
@ -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<String, ValueId> = 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<JoinInst> = 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<crate::ast::ASTNode> {
|
||||
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]
|
||||
|
||||
Reference in New Issue
Block a user