149 lines
3.8 KiB
Rust
149 lines
3.8 KiB
Rust
use std::fmt;
|
|
use termtree;
|
|
|
|
#[non_exhaustive]
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub enum FieldOp {
|
|
Add,
|
|
Sub,
|
|
Mul,
|
|
Div,
|
|
}
|
|
|
|
impl fmt::Display for FieldOp {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let name = match self {
|
|
FieldOp::Add => "+",
|
|
FieldOp::Sub => "-",
|
|
FieldOp::Mul => "*",
|
|
FieldOp::Div => "/",
|
|
};
|
|
|
|
write!(f, "{}", name)
|
|
}
|
|
}
|
|
|
|
pub trait Field: fmt::Debug + Clone {
|
|
fn op(&self, other: Self, op: FieldOp) -> Self;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct FieldNode<T: Field> {
|
|
field: T,
|
|
op: FieldOp,
|
|
children: Vec<FieldNode<T>>,
|
|
}
|
|
|
|
impl<T: Field> FieldNode<T> {
|
|
pub fn evaluate(&self) -> T {
|
|
let mut result = self.field.clone();
|
|
|
|
for child in self.children.iter() {
|
|
let child_result = child.evaluate();
|
|
result = result.op(child_result, child.op);
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
pub fn to_termtree(&self) -> termtree::Tree<String> {
|
|
let desc = format!("{} {:?} ({:?})", self.op, self.field, self.evaluate());
|
|
let mut tree = termtree::Tree::new(desc);
|
|
|
|
for child in self.children.iter() {
|
|
tree.push(child.to_termtree());
|
|
}
|
|
|
|
tree
|
|
}
|
|
}
|
|
|
|
impl<T: Field> fmt::Display for FieldNode<T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "{}", self.to_termtree())
|
|
}
|
|
}
|
|
|
|
impl Field for f32 {
|
|
fn op(&self, other: Self, op: FieldOp) -> Self {
|
|
match op {
|
|
FieldOp::Add => self + other,
|
|
FieldOp::Sub => self - other,
|
|
FieldOp::Mul => self * other,
|
|
FieldOp::Div => self / other,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_nodes() {
|
|
use FieldOp::*;
|
|
|
|
let nodes: FieldNode<f32> = FieldNode {
|
|
field: 10.0,
|
|
op: Add,
|
|
children: vec![
|
|
FieldNode {
|
|
field: 4.0,
|
|
op: Add,
|
|
children: Vec::new(),
|
|
},
|
|
FieldNode {
|
|
field: 2.0,
|
|
op: Sub,
|
|
children: vec![
|
|
FieldNode {
|
|
field: 0.0,
|
|
op: Add,
|
|
children: vec![
|
|
FieldNode {
|
|
field: 0.6,
|
|
op: Add,
|
|
children: Vec::new(),
|
|
},
|
|
FieldNode {
|
|
field: 0.2,
|
|
op: Sub,
|
|
children: Vec::new(),
|
|
},
|
|
],
|
|
},
|
|
FieldNode {
|
|
field: 3.0,
|
|
op: Div,
|
|
children: Vec::new(),
|
|
},
|
|
],
|
|
},
|
|
FieldNode {
|
|
field: 7.0,
|
|
op: Mul,
|
|
children: vec![
|
|
FieldNode {
|
|
field: 0.75,
|
|
op: Add,
|
|
children: Vec::new(),
|
|
},
|
|
FieldNode {
|
|
field: 0.5,
|
|
op: Sub,
|
|
children: Vec::new(),
|
|
},
|
|
FieldNode {
|
|
field: 2.0,
|
|
op: Div,
|
|
children: Vec::new(),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
println!("{}", nodes);
|
|
}
|
|
}
|