phase29ai(p14): add pattern2 promotion hint
This commit is contained in:
@ -264,6 +264,7 @@ pub(crate) fn extract_pattern2_plan(
|
||||
carrier_update_in_break,
|
||||
carrier_update_in_body,
|
||||
loop_increment,
|
||||
promotion: None,
|
||||
})))
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
//! This prevents "second language processor" from growing inside Lowerer.
|
||||
|
||||
use crate::ast::ASTNode;
|
||||
use crate::mir::builder::control_flow::plan::facts::pattern2_loopbodylocal_facts::Pattern2LoopBodyLocalFacts;
|
||||
use crate::mir::{BasicBlockId, BinaryOp, CompareOp, ConstValue, EffectMask, ValueId};
|
||||
use crate::mir::builder::control_flow::edgecfg::api::Frag;
|
||||
|
||||
@ -279,6 +280,16 @@ pub(in crate::mir::builder) struct Pattern2BreakPlan {
|
||||
pub carrier_update_in_body: ASTNode,
|
||||
/// Loop increment expression AST (e.g., `i + 1`)
|
||||
pub loop_increment: ASTNode,
|
||||
/// Optional promotion hint for LoopBodyLocal handling (planner-only metadata)
|
||||
#[allow(dead_code)]
|
||||
pub promotion: Option<Pattern2PromotionHint>,
|
||||
}
|
||||
|
||||
/// Phase 29ai P14: Promotion hint metadata for Pattern2BreakPlan
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(in crate::mir::builder) enum Pattern2PromotionHint {
|
||||
LoopBodyLocal(Pattern2LoopBodyLocalFacts),
|
||||
}
|
||||
|
||||
/// Phase 286 P3.2: Exit kind for Pattern5 infinite loop
|
||||
|
||||
@ -10,7 +10,8 @@ use crate::mir::builder::control_flow::plan::normalize::{canonicalize_loop_facts
|
||||
use super::candidates::{CandidateSet, PlanCandidate};
|
||||
use super::Freeze;
|
||||
use crate::mir::builder::control_flow::plan::{
|
||||
DomainPlan, Pattern2BreakPlan, ScanDirection, ScanWithInitPlan, SplitScanPlan,
|
||||
DomainPlan, Pattern2BreakPlan, Pattern2PromotionHint, ScanDirection, ScanWithInitPlan,
|
||||
SplitScanPlan,
|
||||
};
|
||||
|
||||
/// Phase 29ai P0: External-ish SSOT entrypoint (skeleton)
|
||||
@ -71,6 +72,11 @@ pub(in crate::mir::builder) fn build_plan_from_facts(
|
||||
}
|
||||
|
||||
if let Some(pattern2) = &facts.facts.pattern2_break {
|
||||
let promotion = facts
|
||||
.facts
|
||||
.pattern2_loopbodylocal
|
||||
.as_ref()
|
||||
.map(|facts| Pattern2PromotionHint::LoopBodyLocal(facts.clone()));
|
||||
candidates.push(PlanCandidate {
|
||||
plan: DomainPlan::Pattern2Break(Pattern2BreakPlan {
|
||||
loop_var: pattern2.loop_var.clone(),
|
||||
@ -80,6 +86,7 @@ pub(in crate::mir::builder) fn build_plan_from_facts(
|
||||
carrier_update_in_break: pattern2.carrier_update_in_break.clone(),
|
||||
carrier_update_in_body: pattern2.carrier_update_in_body.clone(),
|
||||
loop_increment: pattern2.loop_increment.clone(),
|
||||
promotion,
|
||||
}),
|
||||
rule: "loop/pattern2_break",
|
||||
});
|
||||
@ -97,7 +104,27 @@ mod tests {
|
||||
use crate::mir::builder::control_flow::plan::facts::loop_facts::{
|
||||
LoopFacts, ScanWithInitFacts, SplitScanFacts,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::facts::pattern2_break_facts::Pattern2BreakFacts;
|
||||
use crate::mir::builder::control_flow::plan::facts::pattern2_loopbodylocal_facts::{
|
||||
LoopBodyLocalShape, Pattern2LoopBodyLocalFacts,
|
||||
};
|
||||
use crate::mir::builder::control_flow::plan::normalize::canonicalize_loop_facts;
|
||||
use crate::mir::builder::control_flow::plan::Pattern2PromotionHint;
|
||||
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
|
||||
|
||||
fn v(name: &str) -> ASTNode {
|
||||
ASTNode::Variable {
|
||||
name: name.to_string(),
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_int(value: i64) -> ASTNode {
|
||||
ASTNode::Literal {
|
||||
value: LiteralValue::Integer(value),
|
||||
span: Span::unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn planner_builds_split_scan_plan_from_facts() {
|
||||
@ -169,4 +196,74 @@ mod tests {
|
||||
other => panic!("expected scan_with_init plan, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn planner_sets_promotion_hint_for_pattern2_loopbodylocal() {
|
||||
let loop_condition = ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Less,
|
||||
left: Box::new(v("i")),
|
||||
right: Box::new(lit_int(3)),
|
||||
span: Span::unknown(),
|
||||
};
|
||||
let break_condition = ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Equal,
|
||||
left: Box::new(v("seg")),
|
||||
right: Box::new(ASTNode::Literal {
|
||||
value: LiteralValue::String(" ".to_string()),
|
||||
span: Span::unknown(),
|
||||
}),
|
||||
span: Span::unknown(),
|
||||
};
|
||||
let carrier_update = ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Add,
|
||||
left: Box::new(v("sum")),
|
||||
right: Box::new(lit_int(1)),
|
||||
span: Span::unknown(),
|
||||
};
|
||||
let loop_increment = ASTNode::BinaryOp {
|
||||
operator: BinaryOperator::Add,
|
||||
left: Box::new(v("i")),
|
||||
right: Box::new(lit_int(1)),
|
||||
span: Span::unknown(),
|
||||
};
|
||||
|
||||
let facts = LoopFacts {
|
||||
condition_shape: ConditionShape::Unknown,
|
||||
step_shape: StepShape::Unknown,
|
||||
scan_with_init: None,
|
||||
split_scan: None,
|
||||
pattern2_break: Some(Pattern2BreakFacts {
|
||||
loop_var: "i".to_string(),
|
||||
carrier_var: "sum".to_string(),
|
||||
loop_condition,
|
||||
break_condition,
|
||||
carrier_update_in_break: None,
|
||||
carrier_update_in_body: carrier_update,
|
||||
loop_increment,
|
||||
}),
|
||||
pattern2_loopbodylocal: Some(Pattern2LoopBodyLocalFacts {
|
||||
loop_var: "i".to_string(),
|
||||
loopbodylocal_var: "seg".to_string(),
|
||||
break_uses_loopbodylocal: true,
|
||||
shape: LoopBodyLocalShape::TrimSeg {
|
||||
s_var: "s".to_string(),
|
||||
i_var: "i".to_string(),
|
||||
},
|
||||
}),
|
||||
};
|
||||
let canonical = canonicalize_loop_facts(facts);
|
||||
let plan = build_plan_from_facts(canonical).expect("Ok");
|
||||
|
||||
match plan {
|
||||
Some(DomainPlan::Pattern2Break(plan)) => {
|
||||
let promotion = plan.promotion.expect("promotion hint");
|
||||
match promotion {
|
||||
Pattern2PromotionHint::LoopBodyLocal(facts) => {
|
||||
assert_eq!(facts.loopbodylocal_var, "seg");
|
||||
}
|
||||
}
|
||||
}
|
||||
other => panic!("expected pattern2 break plan, got {:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user