Added tuples

pull/2/head
Mark 2023-08-03 14:39:53 -07:00
parent bc3bd3d1fc
commit 999f24ce52
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
7 changed files with 85 additions and 4 deletions

View File

@ -43,7 +43,7 @@ pub fn evaluate(t: &Expression, context: &mut Context, allow_incomplete: bool) -
let new = match g { let new = match g {
Expression::Quantity(_, _) => None, Expression::Quantity(_, _) => None,
Expression::Tuple(_, _) => None,
Expression::Constant(_, c) => { Some(evaluate(&c.value(), context, false).unwrap()) }, Expression::Constant(_, c) => { Some(evaluate(&c.value(), context, false).unwrap()) },
Expression::Variable(l, s) => { Expression::Variable(l, s) => {
// Don't move up, re-evaluate // Don't move up, re-evaluate

View File

@ -32,6 +32,15 @@ pub fn eval_function(g: &Expression) -> Result<Expression, (LineLocation, EvalEr
if args.len() != 1 {panic!()}; if args.len() != 1 {panic!()};
let a = &args[0]; let a = &args[0];
// All the functions below take only one argument
if let Expression::Tuple(l, v) = a {
return Err((
*l + *loc,
EvalError::BadArguments(f.to_string(), 1, v.len())
))
};
let Expression::Quantity(l, q) = a else {panic!()}; let Expression::Quantity(l, q) = a else {panic!()};

View File

@ -13,6 +13,7 @@ pub enum EvalError {
IncompatibleUnits(String, String), IncompatibleUnits(String, String),
Undefined(String), Undefined(String),
EvaluationError, EvaluationError,
BadArguments(String, usize, usize)
} }
@ -39,6 +40,11 @@ impl ToString for EvalError {
}, },
EvalError::EvaluationError => { EvalError::EvaluationError => {
String::from("Could not evaluate") String::from("Could not evaluate")
},
EvalError::BadArguments(s, want, got) => {
format!("{s} takes {want} argument{}, got {got}",
if *want == 1 {""} else {"s"},
)
} }
} }
} }

View File

@ -1,3 +1,4 @@
use std::collections::VecDeque;
use crate::parser::LineLocation; use crate::parser::LineLocation;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use crate::parser::Operator; use crate::parser::Operator;
@ -12,6 +13,31 @@ pub fn eval_operator(g: &Expression, _context: &mut Context) -> Result<Option<Ex
match op { match op {
Operator::Function(_) => unreachable!("Functions are handled seperately."), Operator::Function(_) => 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<Expression> = 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 => { Operator::Negative => {
if args.len() != 1 { panic!() }; if args.len() != 1 { panic!() };

View File

@ -14,6 +14,7 @@ pub enum Expression {
Quantity(LineLocation, Quantity), Quantity(LineLocation, Quantity),
Constant(LineLocation, Constant), Constant(LineLocation, Constant),
Operator(LineLocation, Operator, VecDeque<Expression>), Operator(LineLocation, Operator, VecDeque<Expression>),
Tuple(LineLocation, VecDeque<Expression>),
} }
impl ToString for Expression { impl ToString for Expression {
@ -22,7 +23,15 @@ impl ToString for Expression {
Expression::Quantity(_, v) => v.to_string(), Expression::Quantity(_, v) => v.to_string(),
Expression::Constant(_, c) => c.to_string(), Expression::Constant(_, c) => c.to_string(),
Expression::Variable(_, s) => s.clone(), 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::<Vec<String>>()
.join(", ")
)
}
} }
} }
} }
@ -35,7 +44,15 @@ impl Expression {
Expression::Quantity(_, v) => v.to_string_outer(), Expression::Quantity(_, v) => v.to_string_outer(),
Expression::Constant(_, c) => c.to_string(), Expression::Constant(_, c) => c.to_string(),
Expression::Variable(_, s) => s.clone(), 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::<Vec<String>>()
.join(", ")
)
}
} }
} }
@ -92,6 +109,7 @@ impl Expression {
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Expression>> { pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Expression>> {
match self { match self {
Expression::Operator(_, _, ref mut a) => Some(a), Expression::Operator(_, _, ref mut a) => Some(a),
Expression::Tuple(_, ref mut a) => Some(a),
_ => None _ => None
} }
} }
@ -100,6 +118,7 @@ impl Expression {
pub fn get_args(&self) -> Option<&VecDeque<Expression>> { pub fn get_args(&self) -> Option<&VecDeque<Expression>> {
match self { match self {
Expression::Operator(_, _, ref a) => Some(a), Expression::Operator(_, _, ref a) => Some(a),
Expression::Tuple(_, ref a) => Some(a),
_ => None _ => None
} }
} }
@ -134,6 +153,7 @@ impl Expression {
| Expression::Constant(l, _) | Expression::Constant(l, _)
| Expression::Variable(l, _) | Expression::Variable(l, _)
| Expression::Operator(l, _,_) | Expression::Operator(l, _,_)
| Expression::Tuple(l, _)
=> { *l } => { *l }
} }
} }
@ -144,6 +164,7 @@ impl Expression {
Expression::Constant(l, _) => { *l = *loc }, Expression::Constant(l, _) => { *l = *loc },
Expression::Variable(l, _) => { *l = *loc }, Expression::Variable(l, _) => { *l = *loc },
Expression::Operator(l, _,_) => { *l = *loc }, Expression::Operator(l, _,_) => { *l = *loc },
Expression::Tuple(l, _) => { *l = *loc },
} }
} }
} }

View File

@ -13,7 +13,9 @@ use super::Function;
pub enum Operator { pub enum Operator {
// When adding operators, don't forget to update help command text. // When adding operators, don't forget to update help command text.
// It isn't automatically generated. // It isn't automatically generated.
ModuloLong = 0, // Mod invoked with "mod" Tuple = 0,
ModuloLong, // Mod invoked with "mod"
DivideLong, // Division invoked with "per" DivideLong, // Division invoked with "per"
UnitConvert, UnitConvert,
Subtract, Subtract,
@ -67,6 +69,7 @@ impl Operator {
} }
return match s { return match s {
"," => {Some( Operator::Tuple )},
"+" => {Some( Operator::Add )}, "+" => {Some( Operator::Add )},
"-" => {Some( Operator::Subtract )}, "-" => {Some( Operator::Subtract )},
"neg" => {Some( Operator::Negative )}, "neg" => {Some( Operator::Negative )},
@ -143,6 +146,14 @@ impl Operator {
pub fn print(&self, args: &VecDeque<Expression>) -> String { pub fn print(&self, args: &VecDeque<Expression>) -> String {
match self { match self {
Operator::Tuple => {
return format!(
"{}, {}",
self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(&args[1])
);
},
Operator::Negative => { Operator::Negative => {
return format!("-{}", self.add_parens_to_arg(&args[0])); return format!("-{}", self.add_parens_to_arg(&args[0]));
}, },

View File

@ -135,6 +135,14 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
}; };
}, },
',' => {
push_token(&mut g, t, i);
t = Some(Token::Operator(
LineLocation{pos: i, len: 1},
String::from(c)
));
},
// Operator // Operator
'^'|'!'|'%'|'\\'| '^'|'!'|'%'|'\\'|
'*'|'×'|'/'|'÷'| '*'|'×'|'/'|'÷'|