phase29ac(p1): normalize pattern6 reverse scan and flip smoke to PASS

This commit is contained in:
2025-12-28 16:54:01 +09:00
parent 209b04d808
commit 1e1679f361
6 changed files with 112 additions and 64 deletions

View File

@ -65,14 +65,6 @@ pub(crate) fn extract_scan_with_init_plan(
"phase29ab/pattern6/contract",
)?;
// Phase 273 P1: Filter out patterns not supported by Plan-based normalizer
if let Some(ref p) = parts {
// P1 scope: Only forward scan (step=1) supported
if p.step_lit != 1 {
return Ok(None);
}
}
// Wrap in DomainPlan if extracted successfully
Ok(parts.map(DomainPlan::ScanWithInit))
}

View File

@ -1,4 +1,5 @@
use super::{CoreEffectPlan, CoreLoopPlan, CorePhiInfo, CorePlan, ScanWithInitPlan};
use crate::mir::builder::control_flow::plan::ScanDirection;
use crate::mir::basic_block::EdgeArgs;
use crate::mir::builder::control_flow::edgecfg::api::{BranchStub, EdgeStub, ExitKind, Frag};
use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternContext;
@ -34,12 +35,21 @@ impl super::PlanNormalizer {
);
}
// P1 Scope: Forward scan (step=1) only
if parts.step_lit != 1 {
return Err(format!(
"[normalizer] P1 scope: only forward scan supported (step={})",
parts.step_lit
));
// P1 Scope: forward (step=1) or reverse (step=-1)
match parts.scan_direction {
ScanDirection::Forward if parts.step_lit != 1 => {
return Err(format!(
"[normalizer] P1 scope: forward scan requires step=1 (step={})",
parts.step_lit
));
}
ScanDirection::Reverse if parts.step_lit != -1 => {
return Err(format!(
"[normalizer] P1 scope: reverse scan requires step=-1 (step={})",
parts.step_lit
));
}
_ => {}
}
// Step 1: Get host ValueIds for variables
@ -169,30 +179,55 @@ impl super::PlanNormalizer {
});
}
// len = s.length()
header_effects.push(CoreEffectPlan::MethodCall {
dst: Some(len_val),
object: s_host,
method: "length".to_string(),
args: vec![],
effects: EffectMask::PURE.add(Effect::Io),
});
match parts.scan_direction {
ScanDirection::Forward => {
// len = s.length()
header_effects.push(CoreEffectPlan::MethodCall {
dst: Some(len_val),
object: s_host,
method: "length".to_string(),
args: vec![],
effects: EffectMask::PURE.add(Effect::Io),
});
// bound = len - needle_len
header_effects.push(CoreEffectPlan::BinOp {
dst: bound_val,
lhs: len_val,
op: BinaryOp::Sub,
rhs: needle_len_val,
});
// bound = len - needle_len
header_effects.push(CoreEffectPlan::BinOp {
dst: bound_val,
lhs: len_val,
op: BinaryOp::Sub,
rhs: needle_len_val,
});
// cond_loop = i <= bound
header_effects.push(CoreEffectPlan::Compare {
dst: cond_loop,
lhs: i_current,
op: CompareOp::Le,
rhs: bound_val,
});
// cond_loop = i <= bound
header_effects.push(CoreEffectPlan::Compare {
dst: cond_loop,
lhs: i_current,
op: CompareOp::Le,
rhs: bound_val,
});
}
ScanDirection::Reverse => {
let zero_val = builder.next_value_id();
builder
.type_ctx
.value_types
.insert(zero_val, MirType::Integer);
// zero = 0
header_effects.push(CoreEffectPlan::Const {
dst: zero_val,
value: ConstValue::Integer(0),
});
// cond_loop = i >= 0
header_effects.push(CoreEffectPlan::Compare {
dst: cond_loop,
lhs: i_current,
op: CompareOp::Ge,
rhs: zero_val,
});
}
}
// Step 6: Build body (emitted in body_bb)
let body = vec![
@ -221,15 +256,22 @@ impl super::PlanNormalizer {
];
// Step 7: Build step_effects (emitted in step_bb)
let step_effects = vec![
// i_next = i + 1
CoreEffectPlan::BinOp {
let step_effects = match parts.scan_direction {
ScanDirection::Forward => vec![CoreEffectPlan::BinOp {
// i_next = i + 1
dst: i_next_val,
lhs: i_current,
op: BinaryOp::Add,
rhs: one_val,
},
];
}],
ScanDirection::Reverse => vec![CoreEffectPlan::BinOp {
// i_next = i - 1
dst: i_next_val,
lhs: i_current,
op: BinaryOp::Sub,
rhs: one_val,
}],
};
// Step 8: Build block_effects (Phase 273 P2)
let block_effects = vec![