use std::rc::Rc; use rug::{Float, ops::Pow}; use super::{Environment, Node, NodeEnum, Precedence, constant::Constant}; #[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct Exponent { left: Rc, right: Rc, } impl Node for Exponent { fn evaluate(&self, env: &mut super::Environment) -> Result, String> { let evaluated_left = self.left.evaluate(env)?; let evaluated_right = self.right.evaluate(env)?; match (evaluated_left.as_ref(), evaluated_right.as_ref()) { (NodeEnum::Constant(a), NodeEnum::Constant(b)) => Ok(Rc::new( Constant::new(Float::with_val_64( env.get_float_precision(), a.get_value().pow(b.get_value()), )) .into(), )), _ => Ok(Self::new(evaluated_left, evaluated_right)), } } fn as_string(&self, env: Option<&Environment>) -> String { let left_string = if self.left.precedence() <= self.precedence() { format!("({})", self.left.as_string(env)) } else { self.left.as_string(env) }; let right_string = if self.right.precedence() <= self.precedence() { format!("({})", self.right.as_string(env)) } else { self.right.as_string(env) }; format!("{}^{}", left_string, right_string) } fn precedence(&self) -> Precedence { Precedence::Exponent } } impl Exponent { pub fn new(left: Rc, right: Rc) -> Rc { Rc::new(Self { left, right }.into()) } pub fn get_left(&self) -> &Rc { &self.left } pub fn get_right(&self) -> &Rc { &self.right } }