resolved merge conflicts
This commit is contained in:
commit
7f6edf732f
@ -7,7 +7,7 @@ use std::fmt;
|
|||||||
use parser::{lex, parse, Expr, Stmt, FnDef};
|
use parser::{lex, parse, Expr, Stmt, FnDef};
|
||||||
use fn_register::FnRegister;
|
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};
|
use std::cmp::{PartialOrd, PartialEq};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -1417,6 +1417,7 @@ impl Engine {
|
|||||||
fn binary_xor<T: BitXor>(x: T, y: T) -> <T as BitXor>::Output { x ^ y }
|
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 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 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, "+", add, i32, i64, u32, u64, f32, f64);
|
||||||
reg_op!(engine, "-", sub, 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, "^", binary_xor, i32, i64, u32, u64);
|
||||||
reg_op!(engine, "<<", left_shift, 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, ">>", 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, "-", neg, i32, i64, f32, f64);
|
||||||
reg_un!(engine, "!", not, bool);
|
reg_un!(engine, "!", not, bool);
|
||||||
|
@ -168,6 +168,8 @@ pub enum Token {
|
|||||||
LeftShift,
|
LeftShift,
|
||||||
RightShift,
|
RightShift,
|
||||||
XOr,
|
XOr,
|
||||||
|
Modulo,
|
||||||
|
ModuloEquals,
|
||||||
LexErr(LexError),
|
LexErr(LexError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,6 +678,15 @@ impl<'a> TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
_ => return Some(Token::XOr)
|
_ => 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() => (),
|
_x if _x.is_whitespace() => (),
|
||||||
_ => return Some(Token::LexErr(LexError::UnexpectedChar)),
|
_ => return Some(Token::LexErr(LexError::UnexpectedChar)),
|
||||||
@ -714,11 +725,13 @@ fn get_precedence(token: &Token) -> i32 {
|
|||||||
| Token::RightShiftEquals
|
| Token::RightShiftEquals
|
||||||
| Token::AndEquals
|
| Token::AndEquals
|
||||||
| Token::OrEquals
|
| Token::OrEquals
|
||||||
| Token::XOrEquals => 10,
|
| Token::XOrEquals
|
||||||
|
| Token::ModuloEquals => 10,
|
||||||
Token::Or
|
Token::Or
|
||||||
| Token::XOr
|
| Token::XOr
|
||||||
| Token::Pipe => 11,
|
| Token::Pipe => 11,
|
||||||
Token::And => 12,
|
Token::And
|
||||||
|
| Token::Ampersand => 12,
|
||||||
Token::LessThan
|
Token::LessThan
|
||||||
| Token::LessThanEqual
|
| Token::LessThanEqual
|
||||||
| Token::GreaterThan
|
| Token::GreaterThan
|
||||||
@ -731,6 +744,7 @@ fn get_precedence(token: &Token) -> i32 {
|
|||||||
| Token::Multiply => 40,
|
| Token::Multiply => 40,
|
||||||
Token::LeftShift
|
Token::LeftShift
|
||||||
| Token::RightShift => 50,
|
| Token::RightShift => 50,
|
||||||
|
Token::Modulo => 60,
|
||||||
Token::Period => 100,
|
Token::Period => 100,
|
||||||
_ => -1,
|
_ => -1,
|
||||||
}
|
}
|
||||||
@ -997,6 +1011,15 @@ fn parse_binop<'a>(input: &mut Peekable<TokenIterator<'a>>,
|
|||||||
Box::new(Expr::FnCall(">>".to_string(), vec![lhs_copy, rhs]))
|
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),
|
_ => return Err(ParseError::UnknownOperator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
54
src/tests.rs
54
src/tests.rs
@ -707,6 +707,17 @@ fn test_hex_literal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
fn test_octal_literal() {
|
fn test_octal_literal() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
@ -714,7 +725,7 @@ fn test_octal_literal() {
|
|||||||
if let Ok(result) = engine.eval::<i64>("let x = 0o77; x") {
|
if let Ok(result) = engine.eval::<i64>("let x = 0o77; x") {
|
||||||
assert_eq!(result, 63);
|
assert_eq!(result, 63);
|
||||||
} else {
|
} else {
|
||||||
assert!(false);
|
assert!(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(result) = engine.eval::<i64>("let x = 0o1234; x") {
|
if let Ok(result) = engine.eval::<i64>("let x = 0o1234; x") {
|
||||||
@ -740,3 +751,44 @@ fn test_binary_literal() {
|
|||||||
assert!(false);
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user