Merge pull request #54 from rustysec/power_of
i64 and f64 exponent implementation
This commit is contained in:
commit
ecf143b649
@ -1418,6 +1418,9 @@ impl Engine {
|
||||
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}
|
||||
fn pow_i64_i64(x: i64, y: i64) -> i64 { x.pow(y as u32) }
|
||||
fn pow_f64_f64(x: f64, y: f64) -> f64 { x.powf(y) }
|
||||
fn pow_f64_i64(x: f64, y: i64) -> f64 { x.powi(y as i32) }
|
||||
|
||||
reg_op!(engine, "+", add, i32, i64, u32, u64, f32, f64);
|
||||
reg_op!(engine, "-", sub, i32, i64, u32, u64, f32, f64);
|
||||
@ -1441,6 +1444,9 @@ impl Engine {
|
||||
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);
|
||||
engine.register_fn("~", pow_i64_i64);
|
||||
engine.register_fn("~", pow_f64_f64);
|
||||
engine.register_fn("~", pow_f64_i64);
|
||||
|
||||
reg_un!(engine, "-", neg, i32, i64, f32, f64);
|
||||
reg_un!(engine, "!", not, bool);
|
||||
|
@ -46,8 +46,8 @@ mod engine;
|
||||
mod fn_register;
|
||||
mod parser;
|
||||
|
||||
//#[cfg(test)]
|
||||
//mod tests;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use engine::{Engine, Scope, EvalAltResult};
|
||||
pub use fn_register::FnRegister;
|
||||
|
@ -170,6 +170,8 @@ pub enum Token {
|
||||
XOr,
|
||||
Modulo,
|
||||
ModuloEquals,
|
||||
PowerOf,
|
||||
PowerOfEquals,
|
||||
LexErr(LexError),
|
||||
}
|
||||
|
||||
@ -223,7 +225,9 @@ impl Token {
|
||||
XOr |
|
||||
Modulo |
|
||||
ModuloEquals |
|
||||
Return => true,
|
||||
Return |
|
||||
PowerOf |
|
||||
PowerOfEquals => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -252,7 +256,8 @@ impl Token {
|
||||
Pipe |
|
||||
Or |
|
||||
Ampersand |
|
||||
And => true,
|
||||
And |
|
||||
PowerOf => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -701,7 +706,16 @@ impl<'a> TokenIterator<'a> {
|
||||
}
|
||||
_ => return Some(Token::Modulo)
|
||||
}
|
||||
}
|
||||
},
|
||||
'~' => {
|
||||
match self.char_stream.peek() {
|
||||
Some(&'=') => {
|
||||
self.char_stream.next();
|
||||
return Some(Token::PowerOfEquals);
|
||||
}
|
||||
_ => return Some(Token::PowerOf)
|
||||
}
|
||||
},
|
||||
_x if _x.is_whitespace() => (),
|
||||
_ => return Some(Token::LexErr(LexError::UnexpectedChar)),
|
||||
}
|
||||
@ -740,7 +754,8 @@ fn get_precedence(token: &Token) -> i32 {
|
||||
| Token::AndEquals
|
||||
| Token::OrEquals
|
||||
| Token::XOrEquals
|
||||
| Token::ModuloEquals => 10,
|
||||
| Token::ModuloEquals
|
||||
| Token::PowerOfEquals => 10,
|
||||
Token::Or
|
||||
| Token::XOr
|
||||
| Token::Pipe => 11,
|
||||
@ -755,7 +770,8 @@ fn get_precedence(token: &Token) -> i32 {
|
||||
Token::Plus
|
||||
| Token::Minus => 20,
|
||||
Token::Divide
|
||||
| Token::Multiply => 40,
|
||||
| Token::Multiply
|
||||
| Token::PowerOf => 40,
|
||||
Token::LeftShift
|
||||
| Token::RightShift => 50,
|
||||
Token::Modulo => 60,
|
||||
@ -1033,7 +1049,15 @@ fn parse_binop<'a>(input: &mut Peekable<TokenIterator<'a>>,
|
||||
Box::new(lhs_curr),
|
||||
Box::new(Expr::FnCall("%".to_string(), vec![lhs_copy, rhs]))
|
||||
)
|
||||
}
|
||||
},
|
||||
Token::PowerOf => Expr::FnCall("~".to_string(), vec![lhs_curr, rhs]),
|
||||
Token::PowerOfEquals => {
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ mod mismatched_op;
|
||||
mod not;
|
||||
mod number_literals;
|
||||
mod ops;
|
||||
mod power_of;
|
||||
mod string;
|
||||
mod unary_after_binary;
|
||||
mod unary_minus;
|
||||
|
27
src/tests/power_of.rs
Normal file
27
src/tests/power_of.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use engine::Engine;
|
||||
|
||||
#[test]
|
||||
fn test_power_of() {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
assert_eq!(engine.eval::<i64>("2 ~ 3").unwrap(), 8);
|
||||
assert_eq!(engine.eval::<i64>("(-2 ~ 3)").unwrap(), -8);
|
||||
assert_eq!(engine.eval::<f64>("2.2 ~ 3.3").unwrap(), 13.489468760533386_f64);
|
||||
assert_eq!(engine.eval::<f64>("2.0~-2.0").unwrap(), 0.25_f64);
|
||||
assert_eq!(engine.eval::<f64>("(-2.0~-2.0)").unwrap(), 0.25_f64);
|
||||
assert_eq!(engine.eval::<f64>("(-2.0~-2)").unwrap(), 0.25_f64);
|
||||
assert_eq!(engine.eval::<i64>("4~3").unwrap(), 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_power_of_equals() {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
assert_eq!(engine.eval::<i64>("let x = 2; x ~= 3; x").unwrap(), 8);
|
||||
assert_eq!(engine.eval::<i64>("let x = -2; x ~= 3; x").unwrap(), -8);
|
||||
assert_eq!(engine.eval::<f64>("let x = 2.2; x ~= 3.3; x").unwrap(), 13.489468760533386_f64);
|
||||
assert_eq!(engine.eval::<f64>("let x = 2.0; x ~= -2.0; x").unwrap(), 0.25_f64);
|
||||
assert_eq!(engine.eval::<f64>("let x = -2.0; x ~= -2.0; x").unwrap(), 0.25_f64);
|
||||
assert_eq!(engine.eval::<f64>("let x = -2.0; x ~= -2; x").unwrap(), 0.25_f64);
|
||||
assert_eq!(engine.eval::<i64>("let x =4; x ~= 3; x").unwrap(), 64);
|
||||
}
|
Loading…
Reference in New Issue
Block a user