phase29ak(p0): ssot rule order + planner context plumbing
This commit is contained in:
8
src/mir/builder/control_flow/plan/planner/context.rs
Normal file
8
src/mir/builder/control_flow/plan/planner/context.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use crate::mir::loop_pattern_detection::LoopPatternKind;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(in crate::mir::builder) struct PlannerContext {
|
||||
pub pattern_kind: Option<LoopPatternKind>,
|
||||
pub in_static_box: bool,
|
||||
pub debug: bool,
|
||||
}
|
||||
@ -7,9 +7,13 @@
|
||||
|
||||
pub(in crate::mir::builder) mod build;
|
||||
pub(in crate::mir::builder) mod candidates;
|
||||
pub(in crate::mir::builder) mod context;
|
||||
pub(in crate::mir::builder) mod freeze;
|
||||
pub(in crate::mir::builder) mod outcome;
|
||||
|
||||
pub(in crate::mir::builder) use build::build_plan;
|
||||
pub(in crate::mir::builder) use context::PlannerContext;
|
||||
pub(in crate::mir::builder) use freeze::Freeze;
|
||||
pub(in crate::mir::builder) use outcome::{build_plan_with_facts, PlanBuildOutcome};
|
||||
pub(in crate::mir::builder) use outcome::{
|
||||
build_plan_with_facts, build_plan_with_facts_ctx, PlanBuildOutcome,
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ use crate::mir::builder::control_flow::plan::normalize::{
|
||||
use crate::mir::builder::control_flow::plan::DomainPlan;
|
||||
|
||||
use super::build::build_plan_from_facts;
|
||||
use super::context::PlannerContext;
|
||||
use super::Freeze;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -34,3 +35,11 @@ pub(in crate::mir::builder) fn build_plan_with_facts(
|
||||
plan,
|
||||
})
|
||||
}
|
||||
|
||||
pub(in crate::mir::builder) fn build_plan_with_facts_ctx(
|
||||
_ctx: &PlannerContext,
|
||||
condition: &ASTNode,
|
||||
body: &[ASTNode],
|
||||
) -> Result<PlanBuildOutcome, Freeze> {
|
||||
build_plan_with_facts(condition, body)
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternCont
|
||||
use super::DomainPlan;
|
||||
|
||||
mod rules;
|
||||
mod rule_order;
|
||||
|
||||
pub(in crate::mir::builder) fn try_build_domain_plan(
|
||||
ctx: &LoopPatternContext,
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(super) enum PlanRuleId {
|
||||
Pattern6,
|
||||
Pattern7,
|
||||
Pattern5,
|
||||
Pattern8,
|
||||
Pattern3,
|
||||
Pattern4,
|
||||
Pattern9,
|
||||
Pattern2,
|
||||
Pattern1,
|
||||
}
|
||||
|
||||
pub(super) const PLAN_RULE_ORDER: &[PlanRuleId] = &[
|
||||
PlanRuleId::Pattern6,
|
||||
PlanRuleId::Pattern7,
|
||||
PlanRuleId::Pattern5,
|
||||
PlanRuleId::Pattern8,
|
||||
PlanRuleId::Pattern3,
|
||||
PlanRuleId::Pattern4,
|
||||
PlanRuleId::Pattern9,
|
||||
PlanRuleId::Pattern2,
|
||||
PlanRuleId::Pattern1,
|
||||
];
|
||||
|
||||
pub(super) fn rule_name(id: PlanRuleId) -> &'static str {
|
||||
match id {
|
||||
PlanRuleId::Pattern6 => "Pattern6_ScanWithInit (Phase 273)",
|
||||
PlanRuleId::Pattern7 => "Pattern7_SplitScan (Phase 273)",
|
||||
PlanRuleId::Pattern5 => "Pattern5_InfiniteEarlyExit (Phase 286 P3.2)",
|
||||
PlanRuleId::Pattern8 => "Pattern8_BoolPredicateScan (Phase 286 P2.4)",
|
||||
PlanRuleId::Pattern3 => "Pattern3_IfPhi (Phase 286 P2.6)",
|
||||
PlanRuleId::Pattern4 => "Pattern4_Continue (Phase 286 P2)",
|
||||
PlanRuleId::Pattern9 => "Pattern9_AccumConstLoop (Phase 286 P2.3)",
|
||||
PlanRuleId::Pattern2 => "Pattern2_Break (Phase 286 P3.1)",
|
||||
PlanRuleId::Pattern1 => "Pattern1_SimpleWhile (Phase 286 P2.1)",
|
||||
}
|
||||
}
|
||||
@ -8,13 +8,20 @@ use crate::mir::loop_pattern_detection::LoopPatternKind;
|
||||
|
||||
use crate::mir::builder::control_flow::plan::extractors;
|
||||
use crate::mir::builder::control_flow::plan::facts::pattern2_loopbodylocal_facts::LoopBodyLocalShape;
|
||||
use crate::mir::builder::control_flow::plan::planner;
|
||||
use crate::mir::builder::control_flow::plan::planner::{self, PlannerContext};
|
||||
use crate::mir::builder::control_flow::plan::DomainPlan;
|
||||
|
||||
use super::rule_order::{rule_name, PlanRuleId, PLAN_RULE_ORDER};
|
||||
|
||||
pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result<Option<DomainPlan>, String> {
|
||||
use crate::mir::builder::control_flow::joinir::trace;
|
||||
|
||||
let outcome = planner::build_plan_with_facts(ctx.condition, ctx.body)
|
||||
let planner_ctx = PlannerContext {
|
||||
pattern_kind: Some(ctx.pattern_kind),
|
||||
in_static_box: ctx.in_static_box,
|
||||
debug: ctx.debug,
|
||||
};
|
||||
let outcome = planner::build_plan_with_facts_ctx(&planner_ctx, ctx.condition, ctx.body)
|
||||
.map_err(|freeze| freeze.to_string())?;
|
||||
let planner_opt = outcome.plan.clone();
|
||||
let promotion_facts = outcome
|
||||
@ -22,65 +29,26 @@ pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result<Option<D
|
||||
.as_ref()
|
||||
.and_then(|facts| facts.facts.pattern2_loopbodylocal.as_ref());
|
||||
|
||||
// NOTE: Names must match the previous PLAN_EXTRACTORS entries exactly.
|
||||
// Order must match exactly.
|
||||
let rules: &[RuleEntry] = &[
|
||||
RuleEntry {
|
||||
name: "Pattern6_ScanWithInit (Phase 273)",
|
||||
kind: RuleKind::Pattern6,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern7_SplitScan (Phase 273)",
|
||||
kind: RuleKind::Pattern7,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern5_InfiniteEarlyExit (Phase 286 P3.2)",
|
||||
kind: RuleKind::Pattern5,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern8_BoolPredicateScan (Phase 286 P2.4)",
|
||||
kind: RuleKind::Pattern8,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern3_IfPhi (Phase 286 P2.6)",
|
||||
kind: RuleKind::Pattern3,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern4_Continue (Phase 286 P2)",
|
||||
kind: RuleKind::Pattern4,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern9_AccumConstLoop (Phase 286 P2.3)",
|
||||
kind: RuleKind::Pattern9,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern2_Break (Phase 286 P3.1)",
|
||||
kind: RuleKind::Pattern2,
|
||||
},
|
||||
RuleEntry {
|
||||
name: "Pattern1_SimpleWhile (Phase 286 P2.1)",
|
||||
kind: RuleKind::Pattern1,
|
||||
},
|
||||
];
|
||||
|
||||
for entry in rules {
|
||||
for rule_id in PLAN_RULE_ORDER {
|
||||
let rule_id = *rule_id;
|
||||
let name = rule_name(rule_id);
|
||||
// Phase 286 P2.6: Pattern1 Plan guard (structural Fail-Fast)
|
||||
// Pattern1 should only match Pattern1SimpleWhile pattern_kind
|
||||
// This prevents Pattern1 from incorrectly matching Pattern3 fixtures
|
||||
if matches!(entry.kind, RuleKind::Pattern1)
|
||||
if matches!(rule_id, PlanRuleId::Pattern1)
|
||||
&& ctx.pattern_kind != LoopPatternKind::Pattern1SimpleWhile
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let planner_hit = try_take_planner(&planner_opt, entry.kind);
|
||||
let planner_hit = try_take_planner(&planner_opt, rule_id);
|
||||
let (plan_opt, log_none) = if planner_hit.is_some() {
|
||||
(planner_hit, false)
|
||||
} else {
|
||||
(fallback_extract(ctx, entry.kind)?, true)
|
||||
(fallback_extract(ctx, rule_id)?, true)
|
||||
};
|
||||
|
||||
let promotion_tag = if matches!(entry.kind, RuleKind::Pattern2)
|
||||
let promotion_tag = if matches!(rule_id, PlanRuleId::Pattern2)
|
||||
&& crate::config::env::joinir_dev::strict_enabled()
|
||||
{
|
||||
promotion_facts.map(|facts| match facts.shape {
|
||||
@ -96,28 +64,26 @@ pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result<Option<D
|
||||
}
|
||||
|
||||
if let Some(domain_plan) = plan_opt {
|
||||
|
||||
// Phase 286 P3: Pattern8 static box filtering
|
||||
// Plan extractors are pure (no builder access), so we filter here.
|
||||
if matches!(entry.kind, RuleKind::Pattern8) && ctx.in_static_box {
|
||||
if matches!(rule_id, PlanRuleId::Pattern8) && ctx.in_static_box {
|
||||
if ctx.debug {
|
||||
trace::trace().debug(
|
||||
"route/plan",
|
||||
&format!(
|
||||
"{} extracted but rejected: static box context (fallback to legacy)",
|
||||
entry.name
|
||||
name
|
||||
),
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let log_msg = format!("route=plan strategy=extract pattern={}", entry.name);
|
||||
let log_msg = format!("route=plan strategy=extract pattern={}", name);
|
||||
trace::trace().pattern("route", &log_msg, true);
|
||||
return Ok(Some(domain_plan));
|
||||
} else if log_none && ctx.debug {
|
||||
let debug_msg =
|
||||
format!("{} extraction returned None, trying next pattern", entry.name);
|
||||
let debug_msg = format!("{} extraction returned None, trying next pattern", name);
|
||||
trace::trace().debug("route", &debug_msg);
|
||||
}
|
||||
}
|
||||
@ -125,69 +91,52 @@ pub(super) fn try_build_domain_plan(ctx: &LoopPatternContext) -> Result<Option<D
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct RuleEntry {
|
||||
name: &'static str,
|
||||
kind: RuleKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum RuleKind {
|
||||
Pattern1,
|
||||
Pattern2,
|
||||
Pattern3,
|
||||
Pattern4,
|
||||
Pattern5,
|
||||
Pattern6,
|
||||
Pattern7,
|
||||
Pattern8,
|
||||
Pattern9,
|
||||
}
|
||||
|
||||
fn try_take_planner(planner_opt: &Option<DomainPlan>, kind: RuleKind) -> Option<DomainPlan> {
|
||||
fn try_take_planner(planner_opt: &Option<DomainPlan>, kind: PlanRuleId) -> Option<DomainPlan> {
|
||||
match (kind, planner_opt.as_ref()) {
|
||||
(RuleKind::Pattern1, Some(DomainPlan::Pattern1SimpleWhile(_))) => planner_opt.clone(),
|
||||
(RuleKind::Pattern2, Some(DomainPlan::Pattern2Break(_))) => planner_opt.clone(),
|
||||
(RuleKind::Pattern3, Some(DomainPlan::Pattern3IfPhi(_))) => planner_opt.clone(),
|
||||
(RuleKind::Pattern4, Some(DomainPlan::Pattern4Continue(_))) => planner_opt.clone(),
|
||||
(RuleKind::Pattern5, Some(DomainPlan::Pattern5InfiniteEarlyExit(_))) => {
|
||||
(PlanRuleId::Pattern1, Some(DomainPlan::Pattern1SimpleWhile(_))) => planner_opt.clone(),
|
||||
(PlanRuleId::Pattern2, Some(DomainPlan::Pattern2Break(_))) => planner_opt.clone(),
|
||||
(PlanRuleId::Pattern3, Some(DomainPlan::Pattern3IfPhi(_))) => planner_opt.clone(),
|
||||
(PlanRuleId::Pattern4, Some(DomainPlan::Pattern4Continue(_))) => planner_opt.clone(),
|
||||
(PlanRuleId::Pattern5, Some(DomainPlan::Pattern5InfiniteEarlyExit(_))) => {
|
||||
planner_opt.clone()
|
||||
}
|
||||
(RuleKind::Pattern6, Some(DomainPlan::ScanWithInit(_))) => planner_opt.clone(),
|
||||
(RuleKind::Pattern7, Some(DomainPlan::SplitScan(_))) => planner_opt.clone(),
|
||||
(RuleKind::Pattern8, Some(DomainPlan::Pattern8BoolPredicateScan(_))) => {
|
||||
(PlanRuleId::Pattern6, Some(DomainPlan::ScanWithInit(_))) => planner_opt.clone(),
|
||||
(PlanRuleId::Pattern7, Some(DomainPlan::SplitScan(_))) => planner_opt.clone(),
|
||||
(PlanRuleId::Pattern8, Some(DomainPlan::Pattern8BoolPredicateScan(_))) => {
|
||||
planner_opt.clone()
|
||||
}
|
||||
(PlanRuleId::Pattern9, Some(DomainPlan::Pattern9AccumConstLoop(_))) => {
|
||||
planner_opt.clone()
|
||||
}
|
||||
(RuleKind::Pattern9, Some(DomainPlan::Pattern9AccumConstLoop(_))) => planner_opt.clone(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn fallback_extract(
|
||||
ctx: &LoopPatternContext,
|
||||
kind: RuleKind,
|
||||
kind: PlanRuleId,
|
||||
) -> Result<Option<DomainPlan>, String> {
|
||||
match kind {
|
||||
RuleKind::Pattern1 => extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body),
|
||||
RuleKind::Pattern2 => {
|
||||
PlanRuleId::Pattern1 => extractors::pattern1::extract_pattern1_plan(ctx.condition, ctx.body),
|
||||
PlanRuleId::Pattern2 => {
|
||||
extractors::pattern2_break::extract_pattern2_plan(ctx.condition, ctx.body)
|
||||
}
|
||||
RuleKind::Pattern3 => extractors::pattern3::extract_pattern3_plan(ctx.condition, ctx.body),
|
||||
RuleKind::Pattern4 => extractors::pattern4::extract_pattern4_plan(ctx.condition, ctx.body),
|
||||
RuleKind::Pattern5 => extractors::pattern5::extract_pattern5_plan(ctx.condition, ctx.body),
|
||||
RuleKind::Pattern6 => {
|
||||
PlanRuleId::Pattern3 => extractors::pattern3::extract_pattern3_plan(ctx.condition, ctx.body),
|
||||
PlanRuleId::Pattern4 => extractors::pattern4::extract_pattern4_plan(ctx.condition, ctx.body),
|
||||
PlanRuleId::Pattern5 => extractors::pattern5::extract_pattern5_plan(ctx.condition, ctx.body),
|
||||
PlanRuleId::Pattern6 => {
|
||||
extractors::pattern6_scan_with_init::extract_scan_with_init_plan(
|
||||
ctx.condition,
|
||||
ctx.body,
|
||||
ctx.fn_body,
|
||||
)
|
||||
}
|
||||
RuleKind::Pattern7 => extractors::pattern7_split_scan::extract_split_scan_plan(
|
||||
PlanRuleId::Pattern7 => extractors::pattern7_split_scan::extract_split_scan_plan(
|
||||
ctx.condition,
|
||||
ctx.body,
|
||||
&[],
|
||||
),
|
||||
RuleKind::Pattern8 => extractors::pattern8::extract_pattern8_plan(ctx.condition, ctx.body),
|
||||
RuleKind::Pattern9 => extractors::pattern9::extract_pattern9_plan(ctx.condition, ctx.body),
|
||||
PlanRuleId::Pattern8 => extractors::pattern8::extract_pattern8_plan(ctx.condition, ctx.body),
|
||||
PlanRuleId::Pattern9 => extractors::pattern9::extract_pattern9_plan(ctx.condition, ctx.body),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user