diff --git a/src/tree/display.rs b/src/tree/display.rs index fbfff95..031a439 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -1,12 +1,129 @@ -use crate::Node; +use crate::{Node, Operator}; use std::fmt::{Display, Error, Formatter}; +fn write_binary(f: &mut Formatter, node: &Node, op: &str) -> Result<(), Error> { + write!( + f, + "({} {} {})", + node.children.get(0).ok_or(Error)?, + op, + node.children.get(1).ok_or(Error)? + ) +} + +fn write_unary(f: &mut Formatter, node: &Node, op: &str) -> Result<(), Error> { + write!(f, "{}{}", op, node.children.get(0).ok_or(Error)?,) +} + +fn write_sequence(f: &mut Formatter, node: &Node, sep: &str) -> Result<(), Error> { + write!(f, "(")?; + for (i, c) in node.children.iter().enumerate() { + write!(f, "{}", c)?; + if i + 1 < node.children.len() { + write!(f, "{} ", sep)?; + } + } + write!(f, ")") +} + impl Display for Node { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - self.operator.fmt(f)?; - for child in self.children() { - write!(f, " {}", child)?; + match &self.operator { + Operator::RootNode => { + for (i, c) in self.children.iter().enumerate() { + write!(f, "{}", c)?; + if i + 1 < self.children.len() { + write!(f, " ")?; + } + } + Ok(()) + }, + Operator::Add => write_binary(f, self, "+"), + Operator::Sub => write_binary(f, self, "-"), + Operator::Neg => write_unary(f, self, "-"), + Operator::Mul => write_binary(f, self, "*"), + Operator::Div => write_binary(f, self, "/"), + Operator::Mod => write_binary(f, self, "%"), + Operator::Exp => write_binary(f, self, "^"), + Operator::Eq => write_binary(f, self, "=="), + Operator::Neq => write_binary(f, self, "!="), + Operator::Gt => write_binary(f, self, ">"), + Operator::Lt => write_binary(f, self, "<"), + Operator::Geq => write_binary(f, self, ">="), + Operator::Leq => write_binary(f, self, "<="), + Operator::And => write_binary(f, self, "&&"), + Operator::Or => write_binary(f, self, "||"), + Operator::Not => write_unary(f, self, "!"), + Operator::Assign => write_binary(f, self, "="), + Operator::AddAssign => write_binary(f, self, "+="), + Operator::SubAssign => write_binary(f, self, "-="), + Operator::MulAssign => write_binary(f, self, "*="), + Operator::DivAssign => write_binary(f, self, "/="), + Operator::ModAssign => write_binary(f, self, "%="), + Operator::ExpAssign => write_binary(f, self, "^="), + Operator::AndAssign => write_binary(f, self, "&&="), + Operator::OrAssign => write_binary(f, self, "||="), + Operator::Tuple => write_sequence(f, self, ","), + Operator::Chain => write_sequence(f, self, ";"), + Operator::Const { value } => write!(f, "{}", value), + Operator::VariableIdentifierWrite { identifier } => { + write!(f, "{}", identifier) + }, + Operator::VariableIdentifierRead { identifier } => { + write!(f, "{}", identifier) + }, + Operator::FunctionIdentifier { identifier } => { + write!(f, "{} ", identifier)?; + for (i, c) in self.children.iter().enumerate() { + write!(f, "{}", c)?; + if i + 1 < self.children.len() { + write!(f, " ")?; + } + } + Ok(()) + }, + } + } +} + +#[cfg(test)] +mod tests { + use crate::build_operator_tree; + + #[test] + fn test_display() { + let pairs = [ + ("", ""), + ("0", "0"), + ("0.1", "0.1"), + ("f (1, 2)", "f (1, 2)"), + ("()", ""), + ("a; b", "(a; b)"), + ("a = b", "(a = b)"), + ("5 + 3", "(5 + 3)"), + ("5 + 3 * 2", "(5 + (3 * 2))"), + ("f (g 4)", "f g 4"), + ("f (g 4; 5)", "f (g 4; 5)"), + ]; + for (i, o) in pairs.iter() { + assert_eq!( + &&format!( + "{}", + build_operator_tree(i).expect("Could not build operator tree"), + ), + o, + ); } - Ok(()) + } + + #[test] + fn test_display_with_float_precision() { + assert_eq!( + &format!( + "{:.1}", + build_operator_tree("0.111").expect("Could not build operator tree"), + ), + "0.1", + ); } } diff --git a/src/value/display.rs b/src/value/display.rs index 599baa4..b7e8e35 100644 --- a/src/value/display.rs +++ b/src/value/display.rs @@ -6,7 +6,13 @@ impl Display for Value { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { match self { Value::String(string) => write!(f, "\"{}\"", string), - Value::Float(float) => write!(f, "{}", float), + Value::Float(float) => { + if let Some(precision) = f.precision() { + write!(f, "{1:.*}", precision, float) + } else { + write!(f, "{}", float) + } + }, Value::Int(int) => write!(f, "{}", int), Value::Boolean(boolean) => write!(f, "{}", boolean), Value::Tuple(tuple) => {