feat(joinir): add Pattern2 post-loop early return step

This commit is contained in:
nyash-codex
2025-12-17 22:32:55 +09:00
parent aa29dc8085
commit 9ec2e28b6a
3 changed files with 57 additions and 2 deletions

View File

@ -11,6 +11,7 @@ use super::pattern2_steps::apply_policy_step_box::ApplyPolicyStepBox;
use super::pattern2_steps::emit_joinir_step_box::EmitJoinIRStepBox; use super::pattern2_steps::emit_joinir_step_box::EmitJoinIRStepBox;
use super::pattern2_steps::gather_facts_step_box::GatherFactsStepBox; use super::pattern2_steps::gather_facts_step_box::GatherFactsStepBox;
use super::pattern2_steps::merge_step_box::MergeStepBox; use super::pattern2_steps::merge_step_box::MergeStepBox;
use super::pattern2_steps::post_loop_early_return_step_box::PostLoopEarlyReturnStepBox;
use super::pattern2_steps::promote_step_box::PromoteStepBox; use super::pattern2_steps::promote_step_box::PromoteStepBox;
pub(crate) struct Pattern2LoweringOrchestrator; pub(crate) struct Pattern2LoweringOrchestrator;
@ -54,6 +55,8 @@ impl Pattern2LoweringOrchestrator {
skeleton, skeleton,
)?; )?;
MergeStepBox::merge(builder, emitted.join_module, emitted.boundary, debug) let out = MergeStepBox::merge(builder, emitted.join_module, emitted.boundary, debug)?;
PostLoopEarlyReturnStepBox::maybe_emit(builder, promoted.inputs.post_loop_early_return.as_ref())?;
Ok(out)
} }
} }

View File

@ -10,5 +10,5 @@ pub(crate) mod apply_policy_step_box;
pub(crate) mod emit_joinir_step_box; pub(crate) mod emit_joinir_step_box;
pub(crate) mod gather_facts_step_box; pub(crate) mod gather_facts_step_box;
pub(crate) mod merge_step_box; pub(crate) mod merge_step_box;
pub(crate) mod post_loop_early_return_step_box;
pub(crate) mod promote_step_box; pub(crate) mod promote_step_box;

View File

@ -0,0 +1,52 @@
//! PostLoopEarlyReturnStepBox (Phase 107)
//!
//! Responsibility: emulate `return i` inside the loop by emitting a post-loop
//! early-return guard. This keeps JoinIR lowering "break-only" while preserving
//! source semantics for the recognized family.
use crate::ast::{ASTNode, BinaryOperator, Span};
use crate::mir::builder::MirBuilder;
pub(crate) struct PostLoopEarlyReturnStepBox;
impl PostLoopEarlyReturnStepBox {
pub(crate) fn maybe_emit(
builder: &mut MirBuilder,
plan: Option<
&crate::mir::builder::control_flow::joinir::patterns::policies::balanced_depth_scan_policy::PostLoopEarlyReturnPlan,
>,
) -> Result<(), String> {
let Some(plan) = plan else { return Ok(()); };
// if i < n { return i }
let cond = ASTNode::BinaryOp {
operator: BinaryOperator::Less,
left: Box::new(ASTNode::Variable {
name: plan.loop_counter_name.clone(),
span: Span::unknown(),
}),
right: Box::new(ASTNode::Variable {
name: plan.bound_name.clone(),
span: Span::unknown(),
}),
span: Span::unknown(),
};
let ret_stmt = ASTNode::Return {
value: Some(Box::new(ASTNode::Variable {
name: plan.loop_counter_name.clone(),
span: Span::unknown(),
})),
span: Span::unknown(),
};
builder.build_statement(ASTNode::If {
condition: Box::new(cond),
then_body: vec![ret_stmt],
else_body: None,
span: Span::unknown(),
})?;
Ok(())
}
}