File size: 1,546 Bytes
224e773 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | //! AST validation and dangerous pattern detection
use super::nodes::AstNode;
use crate::Result;
use hyperkitty_core::Error;
/// Validate AST structure before construction
pub fn validate(nodes: &[AstNode], edges: &[(usize, usize)]) -> Result<()> {
// Check for dangerous patterns
for &(from_idx, to_idx) in edges {
if from_idx >= nodes.len() || to_idx >= nodes.len() {
return Err(Error::InvalidAST("Edge index out of bounds".to_string()));
}
let from = &nodes[from_idx];
let to = &nodes[to_idx];
if super::weights::has_dangerous_pattern(from, to) {
return Err(Error::InvalidAST(format!(
"Dangerous pattern: {} → {}",
from.label, to.label
)));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use super::super::nodes::NodeType;
#[test]
fn valid_ast() {
let nodes = vec![
AstNode::new(NodeType::Intent, "route"),
AstNode::new(NodeType::Word, "hello"),
];
let edges = vec![(0, 1)]; // structural → payload (OK)
assert!(validate(&nodes, &edges).is_ok());
}
#[test]
fn invalid_ast_dangerous() {
let nodes = vec![
AstNode::new(NodeType::Word, "hello"),
AstNode::new(NodeType::Intent, "route"),
];
let edges = vec![(0, 1)]; // payload → structural (BLOCKED)
assert!(validate(&nodes, &edges).is_err());
}
}
|