Merge pull request #47 from rustysec/modulo_and_bugfix

bugfix for binary and, modulo, binary ops tests
This commit is contained in:
Lukáš Hozda [magnusi] 2017-11-01 18:25:23 +01:00 committed by GitHub
commit 1c6a3fa5fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 3 deletions

View File

@ -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<T: BitXor>(x: T, y: T) -> <T as BitXor>::Output { x ^ y }
fn left_shift<T: Shl<T>>(x: T, y: T) -> <T as Shl<T>>::Output { x.shl(y) }
fn right_shift<T: Shr<T>>(x: T, y: T) -> <T as Shr<T>>::Output { x.shr(y) }
fn modulo<T: Rem<T>>(x: T, y: T) -> <T as Rem<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);

View File

@ -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<TokenIterator<'a>>,
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),
};
}

View File

@ -689,3 +689,55 @@ fn test_right_shift_equals() {
assert!(false);
}
}
#[test]
fn test_modulo_equals() {
let mut engine = Engine::new();
if let Ok(result) = engine.eval::<i64>("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::<i64>("10 % 4") {
assert_eq!(result, 2);
} else {
assert!(false);
}
if let Ok(result) = engine.eval::<i64>("10 << 4") {
assert_eq!(result, 160);
} else {
assert!(false);
}
if let Ok(result) = engine.eval::<i64>("10 >> 4") {
assert_eq!(result, 0);
} else {
assert!(false);
}
if let Ok(result) = engine.eval::<i64>("10 & 4") {
assert_eq!(result, 0);
} else {
assert!(false);
}
if let Ok(result) = engine.eval::<i64>("10 | 4") {
assert_eq!(result, 14);
} else {
assert!(false);
}
if let Ok(result) = engine.eval::<i64>("10 ^ 4") {
assert_eq!(result, 14);
} else {
assert!(false);
}
}