feat(control_tree): add StepTreeContract and signature (dev-only)
This commit is contained in:
@ -70,6 +70,18 @@ pub(crate) fn detect_break_in_body(body: &[ASTNode]) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Detect if a loop body contains return statements
|
||||
///
|
||||
/// This is used for dev-only parity checks with structure SSOT (StepTree).
|
||||
pub(crate) fn detect_return_in_body(body: &[ASTNode]) -> bool {
|
||||
for stmt in body {
|
||||
if has_return_node(stmt) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Extract full feature set from loop body AST
|
||||
///
|
||||
/// This is the main entry point for feature extraction. It analyzes the loop body
|
||||
@ -273,6 +285,26 @@ fn has_break_node(node: &ASTNode) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursive helper to check if AST node contains return
|
||||
fn has_return_node(node: &ASTNode) -> bool {
|
||||
match node {
|
||||
ASTNode::Return { .. } => true,
|
||||
ASTNode::If {
|
||||
then_body,
|
||||
else_body,
|
||||
..
|
||||
} => {
|
||||
then_body.iter().any(has_return_node)
|
||||
|| else_body
|
||||
.as_ref()
|
||||
.map_or(false, |e| e.iter().any(has_return_node))
|
||||
}
|
||||
ASTNode::Loop { body, .. } => body.iter().any(has_return_node),
|
||||
ASTNode::ScopeBox { body, .. } => body.iter().any(has_return_node),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@ -41,6 +41,7 @@ pub(in crate::mir::builder) fn choose_pattern_kind(
|
||||
// Phase 193: Use AST Feature Extractor Box for break/continue detection
|
||||
let has_continue = ast_features::detect_continue_in_body(body);
|
||||
let has_break = ast_features::detect_break_in_body(body);
|
||||
let has_return = ast_features::detect_return_in_body(body);
|
||||
|
||||
// Phase 110: StepTree parity check (structure-only SSOT).
|
||||
//
|
||||
@ -56,10 +57,18 @@ pub(in crate::mir::builder) fn choose_pattern_kind(
|
||||
};
|
||||
|
||||
let tree = StepTreeBuilderBox::build_from_ast(&loop_ast);
|
||||
if tree.features.has_break != has_break || tree.features.has_continue != has_continue {
|
||||
if tree.features.has_break != has_break
|
||||
|| tree.features.has_continue != has_continue
|
||||
|| tree.features.has_return != has_return
|
||||
{
|
||||
let msg = format!(
|
||||
"[choose_pattern_kind/STEPTREE_PARITY] step_tree(break={}, cont={}) != extractor(break={}, cont={})",
|
||||
tree.features.has_break, tree.features.has_continue, has_break, has_continue
|
||||
"[choose_pattern_kind/STEPTREE_PARITY] step_tree(break={}, cont={}, ret={}) != extractor(break={}, cont={}, ret={})",
|
||||
tree.features.has_break,
|
||||
tree.features.has_continue,
|
||||
tree.features.has_return,
|
||||
has_break,
|
||||
has_continue,
|
||||
has_return
|
||||
);
|
||||
|
||||
if crate::config::env::joinir_dev::strict_enabled() {
|
||||
|
||||
Reference in New Issue
Block a user