From 4fed05c20a094e477d14b89972cb2b9225759c10 Mon Sep 17 00:00:00 2001 From: russ Date: Tue, 31 Oct 2017 15:06:13 -0700 Subject: [PATCH] bugfix for binary and, modulo, binary ops tests --- src/engine.rs | 4 +++- src/parser.rs | 27 ++++++++++++++++++++++++-- src/tests.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index a67ea15e..5428bb29 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -7,7 +7,7 @@ use std::fmt; use parser::{lex, parse, Expr, Stmt, FnDef}; use fn_register::FnRegister; -use std::ops::{Add, Sub, Mul, Div, Neg, BitAnd, BitOr, BitXor, Shl, Shr}; +use std::ops::{Add, Sub, Mul, Div, Neg, BitAnd, BitOr, BitXor, Shl, Shr, Rem}; use std::cmp::{PartialOrd, PartialEq}; #[derive(Debug)] @@ -1417,6 +1417,7 @@ impl Engine { fn binary_xor(x: T, y: T) -> ::Output { x ^ y } fn left_shift>(x: T, y: T) -> >::Output { x.shl(y) } fn right_shift>(x: T, y: T) -> >::Output { x.shr(y) } + fn modulo>(x: T, y: T) -> >::Output { x % y} reg_op!(engine, "+", add, i32, i64, u32, u64, f32, f64); reg_op!(engine, "-", sub, i32, i64, u32, u64, f32, f64); @@ -1439,6 +1440,7 @@ impl Engine { reg_op!(engine, "^", binary_xor, i32, i64, u32, u64); reg_op!(engine, "<<", left_shift, i32, i64, u32, u64); reg_op!(engine, ">>", right_shift, i32, i64, u32, u64); + reg_op!(engine, "%", modulo, i32, i64, u32, u64); reg_un!(engine, "-", neg, i32, i64, f32, f64); reg_un!(engine, "!", not, bool); diff --git a/src/parser.rs b/src/parser.rs index 67096fba..0bc7ccfa 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -168,6 +168,8 @@ pub enum Token { LeftShift, RightShift, XOr, + Modulo, + ModuloEquals, LexErr(LexError), } @@ -626,6 +628,15 @@ impl<'a> TokenIterator<'a> { } _ => return Some(Token::XOr) } + }, + '%' => { + match self.char_stream.peek() { + Some(&'=') => { + self.char_stream.next(); + return Some(Token::ModuloEquals); + } + _ => return Some(Token::Modulo) + } } _x if _x.is_whitespace() => (), _ => return Some(Token::LexErr(LexError::UnexpectedChar)), @@ -664,11 +675,13 @@ fn get_precedence(token: &Token) -> i32 { | Token::RightShiftEquals | Token::AndEquals | Token::OrEquals - | Token::XOrEquals => 10, + | Token::XOrEquals + | Token::ModuloEquals => 10, Token::Or | Token::XOr | Token::Pipe => 11, - Token::And => 12, + Token::And + | Token::Ampersand => 12, Token::LessThan | Token::LessThanEqual | Token::GreaterThan @@ -681,6 +694,7 @@ fn get_precedence(token: &Token) -> i32 { | Token::Multiply => 40, Token::LeftShift | Token::RightShift => 50, + Token::Modulo => 60, Token::Period => 100, _ => -1, } @@ -947,6 +961,15 @@ fn parse_binop<'a>(input: &mut Peekable>, Box::new(Expr::FnCall(">>".to_string(), vec![lhs_copy, rhs])) ) }, + Token::Ampersand => Expr::FnCall("&".to_string(), vec![lhs_curr, rhs]), + Token::Modulo => Expr::FnCall("%".to_string(), vec![lhs_curr, rhs]), + Token::ModuloEquals => { + let lhs_copy = lhs_curr.clone(); + Expr::Assignment( + Box::new(lhs_curr), + Box::new(Expr::FnCall("%".to_string(), vec![lhs_copy, rhs])) + ) + } _ => return Err(ParseError::UnknownOperator), }; } diff --git a/src/tests.rs b/src/tests.rs index b9dd0711..c19225ef 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -688,4 +688,56 @@ fn test_right_shift_equals() { } else { assert!(false); } +} + +#[test] +fn test_modulo_equals() { + let mut engine = Engine::new(); + + if let Ok(result) = engine.eval::("let x = 10; x %= 4; x") { + assert_eq!(result, 2); + } else { + assert!(false); + } +} + +#[test] +fn test_binary_ops() { + let mut engine = Engine::new(); + + if let Ok(result) = engine.eval::("10 % 4") { + assert_eq!(result, 2); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("10 << 4") { + assert_eq!(result, 160); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("10 >> 4") { + assert_eq!(result, 0); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("10 & 4") { + assert_eq!(result, 0); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("10 | 4") { + assert_eq!(result, 14); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("10 ^ 4") { + assert_eq!(result, 14); + } else { + assert!(false); + } } \ No newline at end of file