diff --git a/src/evaluate/evaluate.rs b/src/evaluate/evaluate.rs index 6199654..df50812 100644 --- a/src/evaluate/evaluate.rs +++ b/src/evaluate/evaluate.rs @@ -43,7 +43,7 @@ pub fn evaluate(t: &Expression, context: &mut Context, allow_incomplete: bool) - let new = match g { Expression::Quantity(_, _) => None, - + Expression::Tuple(_, _) => None, Expression::Constant(_, c) => { Some(evaluate(&c.value(), context, false).unwrap()) }, Expression::Variable(l, s) => { // Don't move up, re-evaluate diff --git a/src/evaluate/function.rs b/src/evaluate/function.rs index 8aacd9d..1255b4a 100644 --- a/src/evaluate/function.rs +++ b/src/evaluate/function.rs @@ -32,6 +32,15 @@ pub fn eval_function(g: &Expression) -> Result { String::from("Could not evaluate") + }, + EvalError::BadArguments(s, want, got) => { + format!("{s} takes {want} argument{}, got {got}", + if *want == 1 {""} else {"s"}, + ) } } } diff --git a/src/evaluate/operator.rs b/src/evaluate/operator.rs index 702df7d..d127a0a 100644 --- a/src/evaluate/operator.rs +++ b/src/evaluate/operator.rs @@ -1,3 +1,4 @@ +use std::collections::VecDeque; use crate::parser::LineLocation; use crate::quantity::Quantity; use crate::parser::Operator; @@ -12,6 +13,31 @@ pub fn eval_operator(g: &Expression, _context: &mut Context) -> Result unreachable!("Functions are handled seperately."), + Operator::Tuple => { + if args.len() != 2 { panic!() }; + let a = &args[0]; + let b = &args[1]; + + let mut loc = *op_loc; + let mut vec: VecDeque = VecDeque::new(); + if let Expression::Tuple(l, v) = a { + loc += *l; + for i in v { vec.push_back(i.clone()) } + } else { + loc += a.get_linelocation(); + vec.push_back(a.clone()) + } + + if let Expression::Tuple(l, v) = b { + loc += *l; + for i in v { vec.push_back(i.clone()) } + } else { + loc += b.get_linelocation(); + vec.push_back(b.clone()) + } + + return Ok(Some(Expression::Tuple(loc, vec))) + } Operator::Negative => { if args.len() != 1 { panic!() }; diff --git a/src/parser/expression/expression.rs b/src/parser/expression/expression.rs index fa1d5d6..74f9a61 100644 --- a/src/parser/expression/expression.rs +++ b/src/parser/expression/expression.rs @@ -14,6 +14,7 @@ pub enum Expression { Quantity(LineLocation, Quantity), Constant(LineLocation, Constant), Operator(LineLocation, Operator, VecDeque), + Tuple(LineLocation, VecDeque), } impl ToString for Expression { @@ -22,7 +23,15 @@ impl ToString for Expression { Expression::Quantity(_, v) => v.to_string(), Expression::Constant(_, c) => c.to_string(), Expression::Variable(_, s) => s.clone(), - Expression::Operator(_, o,a) => o.print(a) + Expression::Operator(_, o,a) => o.print(a), + Expression::Tuple(_, v) => { + format!("({})", + v.iter() + .map(|x| x.to_string()) + .collect::>() + .join(", ") + ) + } } } } @@ -35,7 +44,15 @@ impl Expression { Expression::Quantity(_, v) => v.to_string_outer(), Expression::Constant(_, c) => c.to_string(), Expression::Variable(_, s) => s.clone(), - Expression::Operator(_, o,a) => o.print(a) + Expression::Operator(_, o,a) => o.print(a), + Expression::Tuple(_, v) => { + format!("({})", + v.iter() + .map(|x| x.to_string()) + .collect::>() + .join(", ") + ) + } } } @@ -92,6 +109,7 @@ impl Expression { pub fn get_args_mut(&mut self) -> Option<&mut VecDeque> { match self { Expression::Operator(_, _, ref mut a) => Some(a), + Expression::Tuple(_, ref mut a) => Some(a), _ => None } } @@ -100,6 +118,7 @@ impl Expression { pub fn get_args(&self) -> Option<&VecDeque> { match self { Expression::Operator(_, _, ref a) => Some(a), + Expression::Tuple(_, ref a) => Some(a), _ => None } } @@ -134,6 +153,7 @@ impl Expression { | Expression::Constant(l, _) | Expression::Variable(l, _) | Expression::Operator(l, _,_) + | Expression::Tuple(l, _) => { *l } } } @@ -144,6 +164,7 @@ impl Expression { Expression::Constant(l, _) => { *l = *loc }, Expression::Variable(l, _) => { *l = *loc }, Expression::Operator(l, _,_) => { *l = *loc }, + Expression::Tuple(l, _) => { *l = *loc }, } } } \ No newline at end of file diff --git a/src/parser/expression/operator.rs b/src/parser/expression/operator.rs index a53d006..a6d16b6 100644 --- a/src/parser/expression/operator.rs +++ b/src/parser/expression/operator.rs @@ -13,7 +13,9 @@ use super::Function; pub enum Operator { // When adding operators, don't forget to update help command text. // It isn't automatically generated. - ModuloLong = 0, // Mod invoked with "mod" + Tuple = 0, + + ModuloLong, // Mod invoked with "mod" DivideLong, // Division invoked with "per" UnitConvert, Subtract, @@ -67,6 +69,7 @@ impl Operator { } return match s { + "," => {Some( Operator::Tuple )}, "+" => {Some( Operator::Add )}, "-" => {Some( Operator::Subtract )}, "neg" => {Some( Operator::Negative )}, @@ -143,6 +146,14 @@ impl Operator { pub fn print(&self, args: &VecDeque) -> String { match self { + Operator::Tuple => { + return format!( + "{}, {}", + self.add_parens_to_arg(&args[0]), + self.add_parens_to_arg(&args[1]) + ); + }, + Operator::Negative => { return format!("-{}", self.add_parens_to_arg(&args[0])); }, diff --git a/src/parser/stage/tokenize.rs b/src/parser/stage/tokenize.rs index aeccfed..47b81b8 100644 --- a/src/parser/stage/tokenize.rs +++ b/src/parser/stage/tokenize.rs @@ -135,6 +135,14 @@ pub fn tokenize(input: &String) -> VecDeque { }; }, + ',' => { + push_token(&mut g, t, i); + t = Some(Token::Operator( + LineLocation{pos: i, len: 1}, + String::from(c) + )); + }, + // Operator '^'|'!'|'%'|'\\'| '*'|'×'|'/'|'÷'|