123 lines
3.2 KiB
Rust
123 lines
3.2 KiB
Rust
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<NodeEnum>,
|
|
to: Rc<NodeEnum>,
|
|
}
|
|
|
|
impl Node for Range {
|
|
fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, 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<NodeEnum>, to: Rc<NodeEnum>) -> Rc<NodeEnum> {
|
|
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<Self::Item> {
|
|
// 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<Self::Item> {
|
|
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,
|
|
}
|
|
}
|
|
}
|