Files
hakorune/src/mir/control_tree/step_tree/builder.rs

219 lines
8.1 KiB
Rust

use crate::ast::ASTNode;
use crate::mir::control_tree::step_tree_contract_box::StepTreeContractBox;
use super::fact_extractor::extract_facts_from_tree;
use super::signature::collect_node_kinds;
use super::summary::{ast_kind_name, summarize_ast};
use super::types::{AstNodeHandle, StepNode, StepStmtKind, StepTree, StepTreeFeatures, StepTreeSignature};
pub struct StepTreeBuilderBox;
impl StepTreeBuilderBox {
pub fn build_from_ast(ast: &ASTNode) -> StepTree {
match ast {
ASTNode::Program { statements, .. } => Self::build_from_block(statements),
ASTNode::ScopeBox { body, .. } => Self::build_from_block(body),
_ => {
let (node, features) = Self::build_node(ast, 0, 0);
build_step_tree(node, features)
}
}
}
pub fn build_from_block(stmts: &[ASTNode]) -> StepTree {
let mut nodes = Vec::with_capacity(stmts.len());
let mut features = StepTreeFeatures::default();
for stmt in stmts {
let (node, node_features) = Self::build_node(stmt, 0, 0);
nodes.push(node);
features = merge_features(features, node_features);
}
build_step_tree(StepNode::Block(nodes), features)
}
fn build_node(ast: &ASTNode, if_depth: u32, loop_depth: u32) -> (StepNode, StepTreeFeatures) {
match ast {
ASTNode::If {
condition,
then_body,
else_body,
span,
} => {
let cond = summarize_ast(condition);
let cond_ast = AstNodeHandle(condition.clone());
let (then_node, then_features) =
Self::build_block_node(then_body, if_depth + 1, loop_depth);
let (else_node, else_features) = match else_body {
Some(else_body) => {
let (node, f) =
Self::build_block_node(else_body, if_depth + 1, loop_depth);
(Some(Box::new(node)), f)
}
None => (None, StepTreeFeatures::default()),
};
let mut features = StepTreeFeatures {
has_if: true,
max_if_depth: (if_depth + 1).max(then_features.max_if_depth),
..StepTreeFeatures::default()
};
features = merge_features(features, then_features);
features = merge_features(features, else_features);
(
StepNode::If {
cond,
cond_ast,
then_branch: Box::new(then_node),
else_branch: else_node,
span: span.clone(),
},
features,
)
}
ASTNode::Loop {
condition, body, span, ..
} => {
let cond = summarize_ast(condition);
let cond_ast = AstNodeHandle(condition.clone());
let (body_node, body_features) =
Self::build_block_node(body, if_depth, loop_depth + 1);
let mut features = StepTreeFeatures {
has_loop: true,
max_loop_depth: (loop_depth + 1).max(body_features.max_loop_depth),
..StepTreeFeatures::default()
};
features = merge_features(features, body_features);
(
StepNode::Loop {
cond,
cond_ast,
body: Box::new(body_node),
span: span.clone(),
},
features,
)
}
ASTNode::ScopeBox { body, span } => {
let (node, features) = Self::build_block_node(body, if_depth, loop_depth);
(node.with_span(span.clone()), features)
}
ASTNode::Return { value, span } => (
StepNode::Stmt {
kind: StepStmtKind::Return {
value_ast: value.as_ref().map(|v| AstNodeHandle(v.clone())),
},
span: span.clone(),
},
StepTreeFeatures {
has_return: true,
..StepTreeFeatures::default()
},
),
ASTNode::Break { span } => (
StepNode::Stmt {
kind: StepStmtKind::Break,
span: span.clone(),
},
StepTreeFeatures {
has_break: true,
..StepTreeFeatures::default()
},
),
ASTNode::Continue { span } => (
StepNode::Stmt {
kind: StepStmtKind::Continue,
span: span.clone(),
},
StepTreeFeatures {
has_continue: true,
..StepTreeFeatures::default()
},
),
ASTNode::Local { variables, span, .. } => (
StepNode::Stmt {
kind: StepStmtKind::LocalDecl {
vars: variables.clone(),
},
span: span.clone(),
},
StepTreeFeatures::default(),
),
ASTNode::Assignment { span, value, .. } => (
StepNode::Stmt {
kind: StepStmtKind::Assign {
target: match ast {
ASTNode::Assignment { target, .. } => match target.as_ref() {
ASTNode::Variable { name, .. } => Some(name.clone()),
_ => None,
},
_ => None,
},
// Phase 128: Store value AST for Normalized lowering
value_ast: Some(AstNodeHandle(value.clone())),
},
span: span.clone(),
},
StepTreeFeatures::default(),
),
ASTNode::Print { span, .. } => (
StepNode::Stmt {
kind: StepStmtKind::Print,
span: span.clone(),
},
StepTreeFeatures::default(),
),
other => (
StepNode::Stmt {
kind: StepStmtKind::Other(ast_kind_name(other)),
span: other.span(),
},
StepTreeFeatures::default(),
),
}
}
fn build_block_node(
stmts: &[ASTNode],
if_depth: u32,
loop_depth: u32,
) -> (StepNode, StepTreeFeatures) {
let mut nodes = Vec::with_capacity(stmts.len());
let mut features = StepTreeFeatures::default();
for stmt in stmts {
let (node, node_features) = Self::build_node(stmt, if_depth, loop_depth);
nodes.push(node);
features = merge_features(features, node_features);
}
(StepNode::Block(nodes), features)
}
}
fn build_step_tree(root: StepNode, features: StepTreeFeatures) -> StepTree {
// Phase 120: Facts → Contract → Signature (separated concerns)
let facts = extract_facts_from_tree(&root, &features);
let contract = StepTreeContractBox::from_facts(&facts);
let mut kinds = Vec::new();
collect_node_kinds(&root, &mut kinds);
let kinds = kinds.join(",");
let basis = contract.signature_basis_string(&kinds);
let signature = StepTreeSignature::from_basis_string(&basis);
StepTree {
root,
features,
contract,
signature,
}
}
fn merge_features(mut a: StepTreeFeatures, b: StepTreeFeatures) -> StepTreeFeatures {
a.has_if |= b.has_if;
a.has_loop |= b.has_loop;
a.has_break |= b.has_break;
a.has_continue |= b.has_continue;
a.has_return |= b.has_return;
a.max_if_depth = a.max_if_depth.max(b.max_if_depth);
a.max_loop_depth = a.max_loop_depth.max(b.max_loop_depth);
a
}