use std::rc::Rc; use rug::ops::{AddFrom, CompleteRound}; use crate::environment::Environment; use super::{Error, Node, NodeEnum, Precedence, constant::ConstantValue}; #[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct Range { from: Rc, to: Rc, } impl Node for Range { fn evaluate(&self, env: &mut Environment) -> Result, Error> { let from_evaluated = self.from.evaluate(env)?; let to_evaluated = self.to.evaluate(env)?; Ok(Self::new(from_evaluated, to_evaluated)) } fn as_string(&self, env: Option<&Environment>) -> String { format!("{}..{}", self.from.as_string(env), self.to.as_string(env)) } fn precedence(&self) -> Precedence { Precedence::Primary } } impl Range { pub fn new(from: Rc, to: Rc) -> Rc { Rc::new(Self { from, to }.into()) } pub fn min(&self) -> Result<&ConstantValue, Error> { match self.from.as_ref() { NodeEnum::Constant(c) => Ok(c.get_value()), _ => Err(Error::MismatchedType(format!( "Minimum (from) in range was a {}, but it needs to be a Constant", self.from.type_str() ))), } } pub fn max(&self) -> Result<&ConstantValue, Error> { match self.to.as_ref() { NodeEnum::Constant(c) => Ok(c.get_value()), _ => Err(Error::MismatchedType(format!( "Maximum (to) in range was a {}, but it needs to be a Constant", self.to.type_str() ))), } } } // impl Iterator for &Range { // type Item = ConstantValue; // // fn next(&mut self) -> Option { // if self.it.is_none() { // return None; // } // // let max = match self.to.as_ref() { // NodeEnum::Constant(c) => c.get_value(), // _ => panic!("Max is not a fucking constant dipshit"), // }; // // let result = { // let added = self.it.clone().unwrap() + 1; // let comp = added < max.clone(); // if comp { self.it.clone() } else { None } // }; // self.it.as_mut().unwrap().add_from(1); // result // } // } pub struct RangeIter { it: ConstantValue, start: ConstantValue, end: ConstantValue, } impl<'a> Iterator for RangeIter { type Item = ConstantValue; fn next(&mut self) -> Option { let result = { if self.it < self.end { Some(self.it.clone()) } else { None } }; self.it += 1; result } } impl IntoIterator for &Range { type Item = ConstantValue; type IntoIter = RangeIter; fn into_iter(self) -> Self::IntoIter { let it = match self.from.as_ref() { NodeEnum::Constant(c) => c.get_value().clone(), _ => panic!("This range does not have a defined start"), }; let end = match self.to.as_ref() { NodeEnum::Constant(c) => c.get_value().clone(), _ => panic!("This range does not have a defined end"), }; RangeIter { start: it.clone(), end, it, } } }