diff --git a/src/entry/unix/unix.rs b/src/entry/unix/unix.rs index c2ea378..94ab461 100644 --- a/src/entry/unix/unix.rs +++ b/src/entry/unix/unix.rs @@ -12,9 +12,7 @@ use termion::{ }; use super::promptbuffer::PromptBuffer; - use crate::parser; -use crate::evaluate; #[inline(always)] fn draw_greeter(stdout: &mut RawTerminal) -> Result<(), std::io::Error> { @@ -82,7 +80,7 @@ pub fn main() -> Result<(), std::io::Error> { #[cfg(debug_assertions)] RawTerminal::suspend_raw_mode(&stdout)?; let out_str = g.to_string(); - let g = evaluate::evaluate(g); + let g = g.evaluate(); #[cfg(debug_assertions)] RawTerminal::activate_raw_mode(&stdout)?; diff --git a/src/evaluate.rs b/src/evaluate.rs deleted file mode 100644 index 4d7b0c0..0000000 --- a/src/evaluate.rs +++ /dev/null @@ -1,62 +0,0 @@ -use crate::tokens::Token; - -#[inline(always)] -fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec) -> &'a mut Token { - let mut h = &mut *g; - - for t in coords.iter() { - let inner = h.get_args_mut().unwrap(); - h = &mut inner[*t]; - } - - return h; -} - - -pub fn evaluate( - mut g: Token, -) -> Result { - let mut coords: Vec = Vec::with_capacity(16); - coords.push(0); - - 'outer: loop { - - let mut h = &mut g; - for t in coords.iter() { - let inner = h.get_args_mut(); - - if inner.is_none() || *t >= inner.as_ref().unwrap().len() { - coords.pop(); - - - let p = get_at_coords(&mut g, &coords); - let e = p.eval()?; - *p = e; - - if coords.len() == 0 { break 'outer; } - let l = coords.pop().unwrap(); - coords.push(l + 1); - continue 'outer; - } - - h = &mut inner.unwrap()[*t]; - } - - match h { - Token::Operator(_,_) - => { - coords.push(0); - continue 'outer; - }, - - Token::Constant(_,_) | - Token::Number(_) => { - let l = coords.pop().unwrap(); - coords.push(l + 1); - continue 'outer; - } - }; - } - - return Ok(g); -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9f95eae..19b4b5c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ pub mod tokens; pub mod parser; -pub mod evaluate; pub mod quantity; //use crate::tokens::Token; diff --git a/src/tests.rs b/src/tests.rs index 36d91cb..dbca87b 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,6 +1,5 @@ // Many of these have been borrowed from insect. use crate::parser; -use crate::evaluate; fn eval_to_str(s: &str) -> Result { let g = match parser::parse(&String::from(s)) { @@ -9,7 +8,7 @@ fn eval_to_str(s: &str) -> Result { }; //let out_str = g.print(); - return match evaluate::evaluate(g) { + return match g.evaluate() { Ok(x) => Ok(x.to_string_outer()), Err(_) => Err(()) }; diff --git a/src/tokens/mod.rs b/src/tokens/mod.rs index baad63f..82ac2d1 100644 --- a/src/tokens/mod.rs +++ b/src/tokens/mod.rs @@ -1,87 +1,7 @@ -use std::collections::VecDeque; - mod function; mod operator; +mod token; +pub use crate::tokens::token::Token; pub use crate::tokens::function::Function; -pub use crate::tokens::operator::Operator; - - -use crate::quantity::Quantity; - -/// Tokens represent logical objects in an expession. -/// -/// Tokens starting with `Pre*` are intermediate tokens, and -/// will never show up in a fully-parsed expression tree. -#[derive(Debug)] -#[derive(Clone)] -pub enum Token { - Number(Quantity), - - Constant(Quantity, String), - - Operator( - Operator, - VecDeque - ), -} - -impl ToString for Token { - fn to_string(&self) -> String { - match self { - Token::Number(v) => v.to_string(), - Token::Constant(_, s) => s.clone(), - Token::Operator(o,a) => o.print(a) - } - } -} - -impl Token { - - // This is called only when this is the outermost token. - // This sometimes leads to different--usually more verbose--behavior. - pub fn to_string_outer(&self) -> String { - match self { - Token::Number(v) => v.to_string_outer(), - Token::Constant(_, s) => s.clone(), - Token::Operator(o,a) => o.print(a) - } - } - - - #[inline(always)] - pub fn get_args(&self) -> Option<&VecDeque> { - match self { - Token::Operator(_, ref a) => Some(a), - _ => None - } - } - - #[inline(always)] - pub fn get_args_mut(&mut self) -> Option<&mut VecDeque> { - match self { - Token::Operator(_, ref mut a) => Some(a), - _ => None - } - } - - #[inline(always)] - pub fn eval(&self) -> Result { - Ok(match self { - Token::Number(_) => { self.clone() }, - Token::Constant(v,_) => { Token::Number(v.clone()) }, - Token::Operator(o,v) => { o.apply(&v)? } - }) - } - - // Temporary solution - #[inline(always)] - pub fn as_number(&self) -> Token { - match self { - Token::Number(v) => { Token::Number(v.clone()) }, - Token::Constant(v,_) => { Token::Number(v.clone()) }, - _ => panic!() - } - } - -} \ No newline at end of file +pub use crate::tokens::operator::Operator; \ No newline at end of file diff --git a/src/tokens/token.rs b/src/tokens/token.rs new file mode 100644 index 0000000..ff498ed --- /dev/null +++ b/src/tokens/token.rs @@ -0,0 +1,145 @@ +use std::collections::VecDeque; + +use crate::tokens::Operator; +use crate::quantity::Quantity; + +/// Tokens represent logical objects in an expession. +/// +/// Tokens starting with `Pre*` are intermediate tokens, and +/// will never show up in a fully-parsed expression tree. +#[derive(Debug)] +#[derive(Clone)] +pub enum Token { + Number(Quantity), + + Constant(Quantity, String), + + Operator( + Operator, + VecDeque + ), +} + +impl ToString for Token { + fn to_string(&self) -> String { + match self { + Token::Number(v) => v.to_string(), + Token::Constant(_, s) => s.clone(), + Token::Operator(o,a) => o.print(a) + } + } +} + +impl Token { + + // This is called only when this is the outermost token. + // This sometimes leads to different--usually more verbose--behavior. + pub fn to_string_outer(&self) -> String { + match self { + Token::Number(v) => v.to_string_outer(), + Token::Constant(_, s) => s.clone(), + Token::Operator(o,a) => o.print(a) + } + } + + + #[inline(always)] + pub fn get_args(&self) -> Option<&VecDeque> { + match self { + Token::Operator(_, ref a) => Some(a), + _ => None + } + } + + #[inline(always)] + pub fn get_args_mut(&mut self) -> Option<&mut VecDeque> { + match self { + Token::Operator(_, ref mut a) => Some(a), + _ => None + } + } + + #[inline(always)] + pub fn eval(&self) -> Result { + Ok(match self { + Token::Number(_) => { self.clone() }, + Token::Constant(v,_) => { Token::Number(v.clone()) }, + Token::Operator(o,v) => { o.apply(&v)? } + }) + } + + // Temporary solution + #[inline(always)] + pub fn as_number(&self) -> Token { + match self { + Token::Number(v) => { Token::Number(v.clone()) }, + Token::Constant(v,_) => { Token::Number(v.clone()) }, + _ => panic!() + } + } + +} + + +// Evaluate +impl Token { + #[inline(always)] + fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec) -> &'a mut Token { + let mut h = &mut *g; + + for t in coords.iter() { + let inner = h.get_args_mut().unwrap(); + h = &mut inner[*t]; + } + + return h; + } + + + pub fn evaluate(&self) -> Result { + let mut g = self.clone(); + let mut coords: Vec = Vec::with_capacity(16); + coords.push(0); + + 'outer: loop { + + let mut h = &mut g; + for t in coords.iter() { + let inner = h.get_args_mut(); + + if inner.is_none() || *t >= inner.as_ref().unwrap().len() { + coords.pop(); + + + let p = Token::get_at_coords(&mut g, &coords); + let e = p.eval()?; + *p = e; + + if coords.len() == 0 { break 'outer; } + let l = coords.pop().unwrap(); + coords.push(l + 1); + continue 'outer; + } + + h = &mut inner.unwrap()[*t]; + } + + match h { + Token::Operator(_,_) + => { + coords.push(0); + continue 'outer; + }, + + Token::Constant(_,_) | + Token::Number(_) => { + let l = coords.pop().unwrap(); + coords.push(l + 1); + continue 'outer; + } + }; + } + + return Ok(g); + } +} \ No newline at end of file