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 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}
|
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, "+", 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);
|
||||||
@ -1441,6 +1444,9 @@ impl Engine {
|
|||||||
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_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, "-", neg, i32, i64, f32, f64);
|
||||||
reg_un!(engine, "!", not, bool);
|
reg_un!(engine, "!", not, bool);
|
||||||
|
@ -46,8 +46,8 @@ mod engine;
|
|||||||
mod fn_register;
|
mod fn_register;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
//#[cfg(test)]
|
#[cfg(test)]
|
||||||
//mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use engine::{Engine, Scope, EvalAltResult};
|
pub use engine::{Engine, Scope, EvalAltResult};
|
||||||
pub use fn_register::FnRegister;
|
pub use fn_register::FnRegister;
|
||||||
|
@ -170,6 +170,8 @@ pub enum Token {
|
|||||||
XOr,
|
XOr,
|
||||||
Modulo,
|
Modulo,
|
||||||
ModuloEquals,
|
ModuloEquals,
|
||||||
|
PowerOf,
|
||||||
|
PowerOfEquals,
|
||||||
LexErr(LexError),
|
LexErr(LexError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +225,9 @@ impl Token {
|
|||||||
XOr |
|
XOr |
|
||||||
Modulo |
|
Modulo |
|
||||||
ModuloEquals |
|
ModuloEquals |
|
||||||
Return => true,
|
Return |
|
||||||
|
PowerOf |
|
||||||
|
PowerOfEquals => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,7 +256,8 @@ impl Token {
|
|||||||
Pipe |
|
Pipe |
|
||||||
Or |
|
Or |
|
||||||
Ampersand |
|
Ampersand |
|
||||||
And => true,
|
And |
|
||||||
|
PowerOf => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -701,7 +706,16 @@ impl<'a> TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
_ => return Some(Token::Modulo)
|
_ => 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() => (),
|
_x if _x.is_whitespace() => (),
|
||||||
_ => return Some(Token::LexErr(LexError::UnexpectedChar)),
|
_ => return Some(Token::LexErr(LexError::UnexpectedChar)),
|
||||||
}
|
}
|
||||||
@ -740,7 +754,8 @@ fn get_precedence(token: &Token) -> i32 {
|
|||||||
| Token::AndEquals
|
| Token::AndEquals
|
||||||
| Token::OrEquals
|
| Token::OrEquals
|
||||||
| Token::XOrEquals
|
| Token::XOrEquals
|
||||||
| Token::ModuloEquals => 10,
|
| Token::ModuloEquals
|
||||||
|
| Token::PowerOfEquals => 10,
|
||||||
Token::Or
|
Token::Or
|
||||||
| Token::XOr
|
| Token::XOr
|
||||||
| Token::Pipe => 11,
|
| Token::Pipe => 11,
|
||||||
@ -755,7 +770,8 @@ fn get_precedence(token: &Token) -> i32 {
|
|||||||
Token::Plus
|
Token::Plus
|
||||||
| Token::Minus => 20,
|
| Token::Minus => 20,
|
||||||
Token::Divide
|
Token::Divide
|
||||||
| Token::Multiply => 40,
|
| Token::Multiply
|
||||||
|
| Token::PowerOf => 40,
|
||||||
Token::LeftShift
|
Token::LeftShift
|
||||||
| Token::RightShift => 50,
|
| Token::RightShift => 50,
|
||||||
Token::Modulo => 60,
|
Token::Modulo => 60,
|
||||||
@ -1033,7 +1049,15 @@ fn parse_binop<'a>(input: &mut Peekable<TokenIterator<'a>>,
|
|||||||
Box::new(lhs_curr),
|
Box::new(lhs_curr),
|
||||||
Box::new(Expr::FnCall("%".to_string(), vec![lhs_copy, rhs]))
|
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),
|
_ => return Err(ParseError::UnknownOperator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ mod mismatched_op;
|
|||||||
mod not;
|
mod not;
|
||||||
mod number_literals;
|
mod number_literals;
|
||||||
mod ops;
|
mod ops;
|
||||||
|
mod power_of;
|
||||||
mod string;
|
mod string;
|
||||||
mod unary_after_binary;
|
mod unary_after_binary;
|
||||||
mod unary_minus;
|
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