From 55e8b51228d5da41dc888e10d936e78b3d293b52 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Tue, 19 Mar 2019 18:42:50 +0200 Subject: [PATCH] Add exponentiation operator + Add hat token + Add exponentiation operator + Document exponentiation operator + Test exponentiation operator Implements #3 --- README.md | 2 +- src/lib.rs | 11 ++++++++++- src/operator/display.rs | 6 ++++++ src/operator/mod.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6df1aac..35bd3a6 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ Supported binary operators: | / | 100 | Division | | \>= | 80 | Greater than or equal | | % | 100 | Modulo | | == | 80 | Equal | | && | 75 | Logical and | | != | 80 | Not equal | -| || | 70 | Logical or | ^ | 120 | Exponentation | +| || | 70 | Logical or | ^ | 120 | Exponentiation | Supported unary operators: diff --git a/src/lib.rs b/src/lib.rs index c02cb4b..896779e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ //! | / | 100 | Division | | \>= | 80 | Greater than or equal | //! | % | 100 | Modulo | | == | 80 | Equal | //! | && | 75 | Logical and | | != | 80 | Not equal | -//! | || | 70 | Logical or | ^ | 120 | Exponentation | +//! | || | 70 | Logical or | ^ | 120 | Exponentiation | //! //! Supported unary operators: //! @@ -120,6 +120,7 @@ //! Operators that take numbers as arguments can either take integers or floating point numbers. //! If one of the arguments is a floating point number, all others are converted to floating point numbers as well, and the resulting value is a floating point number as well. //! Otherwise, the result is an integer. +//! An exception to this is the exponentiation operator that always returns a floating point number. //! //! Values have a precedence of 200. //! @@ -290,6 +291,14 @@ mod test { assert_eq!(eval("1 % 4 + 2"), Ok(Value::Int(3))); } + #[test] + fn test_pow_examples() { + assert_eq!(eval("1 ^ 4"), Ok(Value::Float(1.0))); + assert_eq!(eval("6 ^ 4"), Ok(Value::Float(6.0f64.powf(4.0)))); + assert_eq!(eval("1 ^ 4 + 2"), Ok(Value::Float(3.0))); + assert_eq!(eval("2 ^ (4 + 2)"), Ok(Value::Float(64.0))); + } + #[test] fn test_boolean_examples() { assert_eq!(eval("true && false"), Ok(Value::Boolean(false))); diff --git a/src/operator/display.rs b/src/operator/display.rs index 8b81a31..7c3f613 100644 --- a/src/operator/display.rs +++ b/src/operator/display.rs @@ -43,6 +43,12 @@ impl Display for Mod { } } +impl Display for Exp { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "^") + } +} + impl Display for Eq { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "==") diff --git a/src/operator/mod.rs b/src/operator/mod.rs index dffc0ae..63cc174 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -45,7 +45,9 @@ pub struct Div; #[derive(Debug)] pub struct Mod; #[derive(Debug)] +pub struct Exp; +#[derive(Debug)] pub struct Eq; #[derive(Debug)] pub struct Neq; @@ -294,6 +296,33 @@ impl Operator for Mod { } } +impl Operator for Exp { + fn precedence(&self) -> i32 { + 120 + } + + fn is_left_to_right(&self) -> bool { + true + } + + fn argument_amount(&self) -> usize { + 2 + } + + fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number(&arguments[0])?; + expect_number(&arguments[1])?; + + Ok(Value::Float( + arguments[0] + .as_float() + .unwrap() + .powf(arguments[1].as_float().unwrap()), + )) + } +} + impl Operator for Eq { fn precedence(&self) -> i32 { 80