use downcast::Any;
use std::rc::Rc;
use rand::Rng;
pub trait AstNode: Any+Mutatable+Copyable+Sync {
fn node_type(&self) -> usize;
fn children(&self) -> Vec<&AstNode>;
fn replace_child(&self, old_child: &AstNode, new_child: &mut Option<Box<AstNode>>) -> Box<AstNode>;
}
impl_downcast!(AstNode);
downcast_methods!(AstNode);
pub trait Mutatable {
fn mutate(&self, max_height: i32, rng: &mut Rng) -> Box<AstNode>;
}
pub trait Copyable {
fn copy(&self) -> Box<AstNode>;
}
impl <T: Clone+AstNode> Copyable for T {
fn copy(&self) -> Box<AstNode> { Box::new(self.clone()) }
}
pub fn depth(node: &AstNode) -> usize {
1 + node.children().into_iter().map(|c| depth(c)).max().unwrap_or(0)
}
#[derive(Clone)]
pub struct NodeInTree<'a> {
pub node: &'a AstNode,
pub root_path: Option<Rc<NodeInTree<'a>>>
}
pub fn find_nodes_and_parents<'a>(root: &'a AstNode) -> Vec<Rc<NodeInTree<'a>>> {
let mut result: Vec<Rc<NodeInTree<'a>>> = vec![];
result.reserve(100); let current_root_path = Rc::new(NodeInTree { node: root, root_path: None });
result.push(current_root_path.clone());
find_nodes_and_parents_into(root, ¤t_root_path, &mut result);
result
}
fn find_nodes_and_parents_into<'a>(parent: &'a AstNode,
parent_root_path: &Rc<NodeInTree<'a>>,
acc: &mut Vec<Rc<NodeInTree<'a>>>) {
for node in parent.children() {
let current_root_path = Rc::new(NodeInTree { node: node.clone(), root_path: Some(parent_root_path.clone()) });
acc.push(current_root_path.clone());
find_nodes_and_parents_into(node, ¤t_root_path, acc);
}
}
struct TraitObject {
pub data: *mut (),
pub vtable: *mut (),
}
fn same_node<T: AstNode>(node1: &T, node2: &AstNode) -> bool {
use std::mem;
unsafe {
let address: *mut() = mem::transmute(node1);
let obj: TraitObject = mem::transmute(node2);
address == obj.data
}
}
pub fn clone_or_replace<T: AstNode+Clone>(child: &T, old_child: &AstNode, new_child: &mut Option<Box<AstNode>>) -> Box<T> {
if same_node(child, old_child) {
new_child.take().unwrap().downcast::<T>().ok().unwrap()
} else {
Box::new(child.clone())
}
}
pub fn replace_to_root<T: AstNode>(nap: &Rc<NodeInTree>, new_child: Box<AstNode>) -> Box<T> {
let mut new_child_opt = Some(new_child);
do_replace_to_root(nap, &mut new_child_opt)
}
fn do_replace_to_root<T: AstNode>(nap: &Rc<NodeInTree>, new_child: &mut Option<Box<AstNode>>) -> Box<T> {
match nap.root_path {
None => new_child.take().unwrap().downcast().ok().unwrap(),
Some(ref parent) => {
let mut new_node = Some(parent.node.replace_child(nap.node, new_child));
do_replace_to_root(parent, &mut new_node)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rand::Rng;
#[derive(Clone,PartialEq,Eq,Debug)]
enum TestNode {
Leaf(u32),
Node(u32, Box<TestNode>),
Two(u32, Box<TestNode>, Box<TestNode>)
}
impl AstNode for TestNode {
fn node_type(&self) -> usize { 0 }
fn children(&self) -> Vec<&AstNode> {
match *self {
TestNode::Leaf(_) => vec![],
TestNode::Node(_, ref x) => vec![x.as_ref()],
TestNode::Two(_, ref x, ref y) => vec![x.as_ref(), y.as_ref()],
}
}
fn replace_child(&self, old_child: &AstNode, new_child: &mut Option<Box<AstNode>>) -> Box<AstNode> {
Box::new(match *self {
TestNode::Leaf(_) => self.clone(),
TestNode::Node(n, ref x) => TestNode::Node(n,
clone_or_replace(x, old_child, new_child)),
TestNode::Two(n, ref x, ref y) => TestNode::Two(n,
clone_or_replace(x, old_child, new_child),
clone_or_replace(y, old_child, new_child)),
})
}
}
impl Mutatable for TestNode {
fn mutate(&self, _: i32, _: &mut Rng) -> Box<AstNode> {
Box::new(self.clone())
}
}
fn expect_node(value: u32, ast: &AstNode) {
let x = ast.downcast_ref::<TestNode>().unwrap();
if let TestNode::Node(v, _) = *x {
assert!(v == value);
} else {
assert!(false);
}
}
#[test]
fn test_find_parents() {
let tree = Box::new(TestNode::Node(0,
Box::new(TestNode::Node(1,
Box::new(TestNode::Node(2,
Box::new(TestNode::Leaf(3))))))));
let results = find_nodes_and_parents(tree.as_ref());
expect_node(0, results[0].node);
assert!(results[0].root_path.is_none());
expect_node(1, results[1].node);
expect_node(0, results[1].root_path.as_ref().unwrap().node);
expect_node(2, results[2].node);
expect_node(1, results[2].root_path.as_ref().unwrap().node);
expect_node(0, results[2].root_path.as_ref().unwrap().root_path.as_ref().unwrap().node);
}
#[test]
fn test_replace_child() {
let tree = TestNode::Two(0,
Box::new(TestNode::Leaf(1)),
Box::new(TestNode::Leaf(2)));
let old_child = tree.children()[1];
let mut new_child = Some(Box::new(TestNode::Leaf(3)) as Box<AstNode>);
let new_tree = tree.replace_child(old_child, &mut new_child);
assert_eq!(&TestNode::Two(0,
Box::new(TestNode::Leaf(1)),
Box::new(TestNode::Leaf(3))), new_tree.downcast_ref::<TestNode>().unwrap());
}
#[test]
fn test_depth() {
let tree = TestNode::Two(0,
Box::new(TestNode::Leaf(1)),
Box::new(TestNode::Leaf(2)));
assert_eq!(2, depth(&tree));
}
}