refactor: unify string helpers and pattern2 derived slot
This commit is contained in:
@ -122,7 +122,9 @@ pub enum PlanKind {
|
||||
|
||||
### Phase 142 P0: Statement-Level Normalization **CURRENT**
|
||||
- **Change**: Normalization unit changed from "block suffix" to "statement (loop only)"
|
||||
- **Pattern**: `loop(true) { ... break }` - always returns `LoopOnly`, regardless of subsequent statements
|
||||
- **Pattern**: `loop(true)` with **Normalized-supported body shapes** only
|
||||
- Body ends with `break` and prior statements are `assignment`/`local` only
|
||||
- Body is a single `if` with `break`/`continue` branches (optional else)
|
||||
- **Consumed**: Always 1 statement (the loop itself)
|
||||
- **Kind**: `PlanKind::LoopOnly`
|
||||
- **Subsequent statements**: Handled by normal MIR lowering (not normalized)
|
||||
|
||||
@ -99,9 +99,21 @@ impl NormalizationPlanBox {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 142 P0: Always return loop_only for loop(true), regardless of what follows
|
||||
// Phase 142 P0: Only return loop_only when loop body is in Normalized scope
|
||||
// Normalization unit is now "statement (loop 1個)" not "block suffix"
|
||||
// Subsequent statements (return, assignments, etc.) handled by normal MIR lowering
|
||||
if let Some(body) = loop_body {
|
||||
if !loop_true_body_supported_for_normalized(body) {
|
||||
if debug {
|
||||
trace.routing(
|
||||
"normalization/plan",
|
||||
func_name,
|
||||
"Loop(true) body is out of scope for Normalized (returning None)",
|
||||
);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
if debug {
|
||||
trace.routing(
|
||||
"normalization/plan",
|
||||
@ -113,6 +125,44 @@ impl NormalizationPlanBox {
|
||||
}
|
||||
}
|
||||
|
||||
fn loop_true_body_supported_for_normalized(body: &[ASTNode]) -> bool {
|
||||
if body.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if body.len() == 1 {
|
||||
if let ASTNode::If {
|
||||
then_body,
|
||||
else_body,
|
||||
..
|
||||
} = &body[0]
|
||||
{
|
||||
if is_break_or_continue_only(then_body)
|
||||
&& else_body
|
||||
.as_ref()
|
||||
.map_or(true, |branch| is_break_or_continue_only(branch))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !matches!(body.last(), Some(ASTNode::Break { .. })) {
|
||||
return false;
|
||||
}
|
||||
|
||||
body[..body.len() - 1].iter().all(|stmt| {
|
||||
matches!(stmt, ASTNode::Assignment { .. } | ASTNode::Local { .. })
|
||||
})
|
||||
}
|
||||
|
||||
fn is_break_or_continue_only(stmts: &[ASTNode]) -> bool {
|
||||
if stmts.len() != 1 {
|
||||
return false;
|
||||
}
|
||||
matches!(stmts[0], ASTNode::Break { .. } | ASTNode::Continue { .. })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user