From 1721e163b0431ee87a495ab8793a3e8cb7c5835d Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sat, 13 Apr 2019 19:11:09 +0200 Subject: [PATCH 1/3] Make `Operator::max_argument_amount` optional Relates to #44 --- src/operator/mod.rs | 96 ++++++++++++++++++++++----------------------- src/tree/mod.rs | 2 +- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/operator/mod.rs b/src/operator/mod.rs index e367546..e0ff92d 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -23,12 +23,12 @@ pub trait Operator: Debug + Display { /// True if this operator is a leaf, meaning it accepts no arguments. // Make this a const fn once #57563 is resolved fn is_leaf(&self) -> bool { - self.max_argument_amount() == 0 + self.max_argument_amount() == Some(0) } /// Returns the maximum amount of arguments required by this operator. // Make this a const fn once #57563 is resolved - fn max_argument_amount(&self) -> usize; + fn max_argument_amount(&self) -> Option; /// Evaluates the operator with the given arguments and context. fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult; @@ -127,8 +127,8 @@ impl Operator for RootNode { 200 } - fn max_argument_amount(&self) -> usize { - 1 + fn max_argument_amount(&self) -> Option { + Some(1) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -145,8 +145,8 @@ impl Operator for Add { 95 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -182,8 +182,8 @@ impl Operator for Sub { 95 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -214,8 +214,8 @@ impl Operator for Neg { 110 } - fn max_argument_amount(&self) -> usize { - 1 + fn max_argument_amount(&self) -> Option { + Some(1) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -240,8 +240,8 @@ impl Operator for Mul { 100 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -272,8 +272,8 @@ impl Operator for Div { 100 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -304,8 +304,8 @@ impl Operator for Mod { 100 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -336,8 +336,8 @@ impl Operator for Exp { 120 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -359,8 +359,8 @@ impl Operator for Eq { 80 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -379,8 +379,8 @@ impl Operator for Neq { 80 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -399,8 +399,8 @@ impl Operator for Gt { 80 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -435,8 +435,8 @@ impl Operator for Lt { 80 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -471,8 +471,8 @@ impl Operator for Geq { 80 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -507,8 +507,8 @@ impl Operator for Leq { 80 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -543,8 +543,8 @@ impl Operator for And { 75 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -565,8 +565,8 @@ impl Operator for Or { 70 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -587,8 +587,8 @@ impl Operator for Not { 110 } - fn max_argument_amount(&self) -> usize { - 1 + fn max_argument_amount(&self) -> Option { + Some(1) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -608,8 +608,8 @@ impl Operator for Tuple { 40 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -646,8 +646,8 @@ impl Operator for Assign { false } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, _arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -668,8 +668,8 @@ impl Operator for Chain { 0 } - fn max_argument_amount(&self) -> usize { - 2 + fn max_argument_amount(&self) -> Option { + Some(2) } fn eval(&self, arguments: &[Value], _context: &Context) -> Result { @@ -686,8 +686,8 @@ impl Operator for Const { 200 } - fn max_argument_amount(&self) -> usize { - 0 + fn max_argument_amount(&self) -> Option { + Some(0) } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { @@ -702,8 +702,8 @@ impl Operator for VariableIdentifier { 200 } - fn max_argument_amount(&self) -> usize { - 0 + fn max_argument_amount(&self) -> Option { + Some(0) } fn eval(&self, _arguments: &[Value], context: &Context) -> EvalexprResult { @@ -730,8 +730,8 @@ impl Operator for FunctionIdentifier { false } - fn max_argument_amount(&self) -> usize { - 1 + fn max_argument_amount(&self) -> Option { + Some(1) } fn eval(&self, arguments: &[Value], context: &Context) -> EvalexprResult { diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 775fcb6..c6d2956 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -316,7 +316,7 @@ impl Node { } fn has_enough_children(&self) -> bool { - self.children().len() == self.operator().max_argument_amount() + Some(self.children().len()) == self.operator().max_argument_amount() } fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> EvalexprResult<()> { From eb5c6e99bd1331a495475aa6d7ea931861248499 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sat, 13 Apr 2019 20:04:36 +0200 Subject: [PATCH 2/3] Add flattening of operator chains when building operator tree Relates to #44 --- src/operator/mod.rs | 119 +++++++++++++++++++++++++++++++++++++++++-- src/tree/mod.rs | 3 ++ src/value/mod.rs | 4 ++ tests/integration.rs | 14 +++++ 4 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/operator/mod.rs b/src/operator/mod.rs index e0ff92d..84ca661 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -7,6 +7,10 @@ use crate::{context::Context, error::*, value::Value}; mod display; pub trait Operator: Debug + Display { + /// A numeric id to compare operator types. + // Make this a const fn once #57563 is resolved + fn id(&self) -> i32; + /// Returns the precedence of the operator. /// A high precedence means that the operator has priority to be deeper in the tree. // Make this a const fn once #57563 is resolved @@ -20,6 +24,12 @@ pub trait Operator: Debug + Display { true } + /// Returns true if chains of this operator should be flattened into one operator with many arguments. + // Make this a const fn once #57563 is resolved + fn is_flatten_chains(&self) -> bool { + false + } + /// True if this operator is a leaf, meaning it accepts no arguments. // Make this a const fn once #57563 is resolved fn is_leaf(&self) -> bool { @@ -123,6 +133,10 @@ impl FunctionIdentifier { } impl Operator for RootNode { + fn id(&self) -> i32 { + 1 + } + fn precedence(&self) -> i32 { 200 } @@ -141,6 +155,10 @@ impl Operator for RootNode { } impl Operator for Add { + fn id(&self) -> i32 { + 2 + } + fn precedence(&self) -> i32 { 95 } @@ -178,6 +196,10 @@ impl Operator for Add { } impl Operator for Sub { + fn id(&self) -> i32 { + 3 + } + fn precedence(&self) -> i32 { 95 } @@ -210,6 +232,10 @@ impl Operator for Sub { } impl Operator for Neg { + fn id(&self) -> i32 { + 4 + } + fn precedence(&self) -> i32 { 110 } @@ -236,6 +262,10 @@ impl Operator for Neg { } impl Operator for Mul { + fn id(&self) -> i32 { + 5 + } + fn precedence(&self) -> i32 { 100 } @@ -268,6 +298,10 @@ impl Operator for Mul { } impl Operator for Div { + fn id(&self) -> i32 { + 6 + } + fn precedence(&self) -> i32 { 100 } @@ -300,6 +334,10 @@ impl Operator for Div { } impl Operator for Mod { + fn id(&self) -> i32 { + 7 + } + fn precedence(&self) -> i32 { 100 } @@ -332,6 +370,10 @@ impl Operator for Mod { } impl Operator for Exp { + fn id(&self) -> i32 { + 8 + } + fn precedence(&self) -> i32 { 120 } @@ -355,6 +397,10 @@ impl Operator for Exp { } impl Operator for Eq { + fn id(&self) -> i32 { + 9 + } + fn precedence(&self) -> i32 { 80 } @@ -375,6 +421,10 @@ impl Operator for Eq { } impl Operator for Neq { + fn id(&self) -> i32 { + 10 + } + fn precedence(&self) -> i32 { 80 } @@ -395,6 +445,10 @@ impl Operator for Neq { } impl Operator for Gt { + fn id(&self) -> i32 { + 11 + } + fn precedence(&self) -> i32 { 80 } @@ -431,6 +485,10 @@ impl Operator for Gt { } impl Operator for Lt { + fn id(&self) -> i32 { + 12 + } + fn precedence(&self) -> i32 { 80 } @@ -467,6 +525,10 @@ impl Operator for Lt { } impl Operator for Geq { + fn id(&self) -> i32 { + 13 + } + fn precedence(&self) -> i32 { 80 } @@ -503,6 +565,10 @@ impl Operator for Geq { } impl Operator for Leq { + fn id(&self) -> i32 { + 14 + } + fn precedence(&self) -> i32 { 80 } @@ -539,6 +605,10 @@ impl Operator for Leq { } impl Operator for And { + fn id(&self) -> i32 { + 15 + } + fn precedence(&self) -> i32 { 75 } @@ -561,6 +631,10 @@ impl Operator for And { } impl Operator for Or { + fn id(&self) -> i32 { + 16 + } + fn precedence(&self) -> i32 { 70 } @@ -583,6 +657,10 @@ impl Operator for Or { } impl Operator for Not { + fn id(&self) -> i32 { + 17 + } + fn precedence(&self) -> i32 { 110 } @@ -604,17 +682,26 @@ impl Operator for Not { } impl Operator for Tuple { + fn id(&self) -> i32 { + 18 + } + fn precedence(&self) -> i32 { 40 } fn max_argument_amount(&self) -> Option { - Some(2) + None } fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - if let Value::Tuple(tuple) = &arguments[0] { + if arguments.len() < 2 { + return Err(EvalexprError::wrong_operator_argument_amount(arguments.len(), 2)); + } + + Ok(Value::Tuple(arguments.iter().cloned().collect())) + + /*if let Value::Tuple(tuple) = &arguments[0] { let mut tuple = tuple.clone(); if let Value::Tuple(tuple2) = &arguments[1] { tuple.extend(tuple2.iter().cloned()); @@ -633,11 +720,15 @@ impl Operator for Tuple { arguments[1].clone(), ])) } - } + }*/ } } impl Operator for Assign { + fn id(&self) -> i32 { + 19 + } + fn precedence(&self) -> i32 { 50 } @@ -664,10 +755,18 @@ impl Operator for Assign { } impl Operator for Chain { + fn id(&self) -> i32 { + 20 + } + fn precedence(&self) -> i32 { 0 } + fn is_flatten_chains(&self) -> bool { + true + } + fn max_argument_amount(&self) -> Option { Some(2) } @@ -682,6 +781,10 @@ impl Operator for Chain { } impl Operator for Const { + fn id(&self) -> i32 { + 21 + } + fn precedence(&self) -> i32 { 200 } @@ -698,6 +801,10 @@ impl Operator for Const { } impl Operator for VariableIdentifier { + fn id(&self) -> i32 { + 22 + } + fn precedence(&self) -> i32 { 200 } @@ -722,6 +829,10 @@ impl Operator for VariableIdentifier { } impl Operator for FunctionIdentifier { + fn id(&self) -> i32 { + 23 + } + fn precedence(&self) -> i32 { 190 } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index c6d2956..6aff4ed 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -337,6 +337,9 @@ impl Node { .last_mut() .unwrap() .insert_back_prioritized(node, false) + } else if self.children.last().unwrap().operator().id() == node.operator().id() && node.operator().is_flatten_chains() && !self.children.last().unwrap().has_enough_children() { + // The operators will be chained together, and the next value will be added to this nodes last child. + Ok(()) } else { if node.operator().is_leaf() { return Err(EvalexprError::AppendedToLeafNode); diff --git a/src/value/mod.rs b/src/value/mod.rs index b2e8cee..17aafe2 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -194,6 +194,10 @@ impl From for EvalexprResult { } } +impl From<()> for Value { + fn from(_: ()) -> Self { Value::Empty } +} + #[cfg(test)] mod tests { use value::{TupleType, Value}; diff --git a/tests/integration.rs b/tests/integration.rs index 2c90c9f..5fbd5a2 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -614,3 +614,17 @@ fn test_serde() { assert_eq!(manual_tree.eval(), serde_tree.eval()); } } + +#[test] +fn test_tuple_definitions() { + assert_eq!(eval_empty("()"), Ok(())); + assert_eq!(eval_int("(3)"), Ok(3)); + assert_eq!(eval_tuple("(3, 4)"), Ok(vec![Value::from(3), Value::from(4)])); + assert_eq!(eval_tuple("2, (5, 6)"), Ok(vec![Value::from(2), Value::from(vec![Value::from(5), Value::from(6)])])); + assert_eq!(eval_tuple("1, 2"), Ok(vec![Value::from(1), Value::from(2)])); + assert_eq!(eval_tuple("1, 2, 3, 4"), Ok(vec![Value::from(1), Value::from(2), Value::from(3), Value::from(4)])); + assert_eq!(eval_tuple("(1, 2, 3), 5, 6, (true, false, 0)"), Ok(vec![Value::from(vec![Value::from(1), Value::from(2), Value::from(3)]), Value::from(5), Value::from(6), Value::from(vec![Value::from(true), Value::from(false), Value::from(0)])])); + assert_eq!(eval_tuple("1, (2)"), Ok(vec![Value::from(1), Value::from(2)])); + assert_eq!(eval_tuple("1, ()"), Ok(vec![Value::from(1), Value::from(())])); + assert_eq!(eval_tuple("1, ((2))"), Ok(vec![Value::from(1), Value::from(2)])); +} From 2af40309f6b1431d3f687ae35b23e9bd928bf353 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sat, 13 Apr 2019 20:31:47 +0200 Subject: [PATCH 3/3] Replace manual `type_id` with builtin function of trait `Any` Relates to #44 --- src/operator/mod.rs | 96 --------------------------------------------- src/tree/mod.rs | 4 +- 2 files changed, 3 insertions(+), 97 deletions(-) diff --git a/src/operator/mod.rs b/src/operator/mod.rs index 84ca661..59dd3e6 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -7,10 +7,6 @@ use crate::{context::Context, error::*, value::Value}; mod display; pub trait Operator: Debug + Display { - /// A numeric id to compare operator types. - // Make this a const fn once #57563 is resolved - fn id(&self) -> i32; - /// Returns the precedence of the operator. /// A high precedence means that the operator has priority to be deeper in the tree. // Make this a const fn once #57563 is resolved @@ -133,10 +129,6 @@ impl FunctionIdentifier { } impl Operator for RootNode { - fn id(&self) -> i32 { - 1 - } - fn precedence(&self) -> i32 { 200 } @@ -155,10 +147,6 @@ impl Operator for RootNode { } impl Operator for Add { - fn id(&self) -> i32 { - 2 - } - fn precedence(&self) -> i32 { 95 } @@ -196,10 +184,6 @@ impl Operator for Add { } impl Operator for Sub { - fn id(&self) -> i32 { - 3 - } - fn precedence(&self) -> i32 { 95 } @@ -232,10 +216,6 @@ impl Operator for Sub { } impl Operator for Neg { - fn id(&self) -> i32 { - 4 - } - fn precedence(&self) -> i32 { 110 } @@ -262,10 +242,6 @@ impl Operator for Neg { } impl Operator for Mul { - fn id(&self) -> i32 { - 5 - } - fn precedence(&self) -> i32 { 100 } @@ -298,10 +274,6 @@ impl Operator for Mul { } impl Operator for Div { - fn id(&self) -> i32 { - 6 - } - fn precedence(&self) -> i32 { 100 } @@ -334,10 +306,6 @@ impl Operator for Div { } impl Operator for Mod { - fn id(&self) -> i32 { - 7 - } - fn precedence(&self) -> i32 { 100 } @@ -370,10 +338,6 @@ impl Operator for Mod { } impl Operator for Exp { - fn id(&self) -> i32 { - 8 - } - fn precedence(&self) -> i32 { 120 } @@ -397,10 +361,6 @@ impl Operator for Exp { } impl Operator for Eq { - fn id(&self) -> i32 { - 9 - } - fn precedence(&self) -> i32 { 80 } @@ -421,10 +381,6 @@ impl Operator for Eq { } impl Operator for Neq { - fn id(&self) -> i32 { - 10 - } - fn precedence(&self) -> i32 { 80 } @@ -445,10 +401,6 @@ impl Operator for Neq { } impl Operator for Gt { - fn id(&self) -> i32 { - 11 - } - fn precedence(&self) -> i32 { 80 } @@ -485,10 +437,6 @@ impl Operator for Gt { } impl Operator for Lt { - fn id(&self) -> i32 { - 12 - } - fn precedence(&self) -> i32 { 80 } @@ -525,10 +473,6 @@ impl Operator for Lt { } impl Operator for Geq { - fn id(&self) -> i32 { - 13 - } - fn precedence(&self) -> i32 { 80 } @@ -565,10 +509,6 @@ impl Operator for Geq { } impl Operator for Leq { - fn id(&self) -> i32 { - 14 - } - fn precedence(&self) -> i32 { 80 } @@ -605,10 +545,6 @@ impl Operator for Leq { } impl Operator for And { - fn id(&self) -> i32 { - 15 - } - fn precedence(&self) -> i32 { 75 } @@ -631,10 +567,6 @@ impl Operator for And { } impl Operator for Or { - fn id(&self) -> i32 { - 16 - } - fn precedence(&self) -> i32 { 70 } @@ -657,10 +589,6 @@ impl Operator for Or { } impl Operator for Not { - fn id(&self) -> i32 { - 17 - } - fn precedence(&self) -> i32 { 110 } @@ -682,10 +610,6 @@ impl Operator for Not { } impl Operator for Tuple { - fn id(&self) -> i32 { - 18 - } - fn precedence(&self) -> i32 { 40 } @@ -725,10 +649,6 @@ impl Operator for Tuple { } impl Operator for Assign { - fn id(&self) -> i32 { - 19 - } - fn precedence(&self) -> i32 { 50 } @@ -755,10 +675,6 @@ impl Operator for Assign { } impl Operator for Chain { - fn id(&self) -> i32 { - 20 - } - fn precedence(&self) -> i32 { 0 } @@ -781,10 +697,6 @@ impl Operator for Chain { } impl Operator for Const { - fn id(&self) -> i32 { - 21 - } - fn precedence(&self) -> i32 { 200 } @@ -801,10 +713,6 @@ impl Operator for Const { } impl Operator for VariableIdentifier { - fn id(&self) -> i32 { - 22 - } - fn precedence(&self) -> i32 { 200 } @@ -829,10 +737,6 @@ impl Operator for VariableIdentifier { } impl Operator for FunctionIdentifier { - fn id(&self) -> i32 { - 23 - } - fn precedence(&self) -> i32 { 190 } diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 6aff4ed..88136de 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -11,6 +11,8 @@ use crate::{ operator::*, value::Value, }; +use std::error::Error; +use std::any::Any; mod display; mod iter; @@ -337,7 +339,7 @@ impl Node { .last_mut() .unwrap() .insert_back_prioritized(node, false) - } else if self.children.last().unwrap().operator().id() == node.operator().id() && node.operator().is_flatten_chains() && !self.children.last().unwrap().has_enough_children() { + } else if self.children.last().unwrap().operator().type_id() == node.operator().type_id() && node.operator().is_flatten_chains() && !self.children.last().unwrap().has_enough_children() { // The operators will be chained together, and the next value will be added to this nodes last child. Ok(()) } else {