mirror of https://github.com/rm-dr/daisy
Added tuples
parent
bc3bd3d1fc
commit
999f24ce52
|
@ -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
|
||||||
|
|
|
@ -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!()};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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"},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!() };
|
||||||
|
|
|
@ -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 },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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]));
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
'^'|'!'|'%'|'\\'|
|
'^'|'!'|'%'|'\\'|
|
||||||
'*'|'×'|'/'|'÷'|
|
'*'|'×'|'/'|'÷'|
|
||||||
|
|
Loading…
Reference in New Issue