diff --git a/src/engine.rs b/src/engine.rs index e18b9386..51789068 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -8,7 +8,7 @@ use parser::{lex, parse, Expr, Stmt, FnDef}; use fn_register::FnRegister; use std::ops::{Add, Sub, Mul, Div, Neg}; -use std::cmp::{Ord, Eq}; +use std::cmp::{PartialOrd, PartialEq}; #[derive(Debug)] pub enum EvalAltResult { @@ -96,10 +96,10 @@ pub enum FnType { /// ```rust /// extern crate rhai; /// use rhai::Engine; -/// +/// /// fn main() { /// let mut engine = Engine::new(); -/// +/// /// if let Ok(result) = engine.eval::("40 + 2") { /// println!("Answer: {}", result); // prints 42 /// } @@ -114,10 +114,10 @@ pub struct Engine { /// /// ```rust /// use rhai::{Engine, Scope}; -/// +/// /// let mut engine = Engine::new(); /// let mut my_scope = Scope::new(); -/// +/// /// assert!(engine.eval_with_scope::<()>(&mut my_scope, "let x = 5;").is_ok()); /// assert_eq!(engine.eval_with_scope::(&mut my_scope, "x + 1").unwrap(), 6); /// ``` @@ -948,6 +948,7 @@ impl Engine { fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result, EvalAltResult> { match *expr { Expr::IntConst(i) => Ok(Box::new(i)), + Expr::FloatConst(i) => Ok(Box::new(i)), Expr::StringConst(ref s) => Ok(Box::new(s.clone())), Expr::CharConst(ref c) => Ok(Box::new(*c)), Expr::Identifier(ref id) => { @@ -1400,12 +1401,12 @@ impl Engine { fn mul(x: T, y: T) -> ::Output { x * y } fn div(x: T, y: T) -> ::Output { x / y } fn neg(x: T) -> ::Output { -x } - fn lt(x: T, y: T) -> bool { x < y } - fn lte(x: T, y: T) -> bool { x <= y } - fn gt(x: T, y: T) -> bool { x > y } - fn gte(x: T, y: T) -> bool { x >= y } - fn eq(x: T, y: T) -> bool { x == y } - fn ne(x: T, y: T) -> bool { x != y } + fn lt(x: T, y: T) -> bool { x < y } + fn lte(x: T, y: T) -> bool { x <= y } + fn gt(x: T, y: T) -> bool { x > y } + fn gte(x: T, y: T) -> bool { x >= y } + fn eq(x: T, y: T) -> bool { x == y } + fn ne(x: T, y: T) -> bool { x != y } fn and(x: bool, y: bool) -> bool { x && y } fn or(x: bool, y: bool) -> bool { x || y } fn not(x: bool) -> bool { !x } @@ -1416,12 +1417,12 @@ impl Engine { reg_op!(engine, "*", mul, i32, i64, u32, u64, f32, f64); reg_op!(engine, "/", div, i32, i64, u32, u64, f32, f64); - reg_cmp!(engine, "<", lt, i32, i64, u32, u64, String); - reg_cmp!(engine, "<=", lte, i32, i64, u32, u64, String); - reg_cmp!(engine, ">", gt, i32, i64, u32, u64, String); - reg_cmp!(engine, ">=", gte, i32, i64, u32, u64, String); - reg_cmp!(engine, "==", eq, i32, i64, u32, u64, bool, String); - reg_cmp!(engine, "!=", ne, i32, i64, u32, u64, bool, String); + reg_cmp!(engine, "<", lt, i32, i64, u32, u64, String, f64); + reg_cmp!(engine, "<=", lte, i32, i64, u32, u64, String, f64); + reg_cmp!(engine, ">", gt, i32, i64, u32, u64, String, f64); + reg_cmp!(engine, ">=", gte, i32, i64, u32, u64, String, f64); + reg_cmp!(engine, "==", eq, i32, i64, u32, u64, bool, String, f64); + reg_cmp!(engine, "!=", ne, i32, i64, u32, u64, bool, String, f64); reg_op!(engine, "||", or, bool); reg_op!(engine, "&&", and, bool); diff --git a/src/parser.rs b/src/parser.rs index 8c62aa08..a713ddc3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -98,6 +98,7 @@ pub enum Stmt { #[derive(Debug, Clone)] pub enum Expr { IntConst(i64), + FloatConst(f64), Identifier(String), CharConst(char), StringConst(String), @@ -113,6 +114,7 @@ pub enum Expr { #[derive(Debug, Clone)] pub enum Token { IntConst(i64), + FloatConst(f64), Identifier(String), CharConst(char), StringConst(String), @@ -366,6 +368,19 @@ impl<'a> TokenIterator<'a> { result.push(nxt); self.char_stream.next(); } + '.' => { + result.push(nxt); + self.char_stream.next(); + while let Some(&nxt_float) = self.char_stream.peek() { + match nxt_float { + '0'...'9' => { + result.push(nxt_float); + self.char_stream.next(); + } + _ => break, + } + } + } _ => break, } } @@ -374,6 +389,8 @@ impl<'a> TokenIterator<'a> { if let Ok(val) = out.parse::() { return Some(Token::IntConst(val)); + } else if let Ok(val) = out.parse::() { + return Some(Token::FloatConst(val)); } return Some(Token::LexErr(LexError::MalformedNumber)); } @@ -392,7 +409,6 @@ impl<'a> TokenIterator<'a> { } let out: String = result.iter().cloned().collect(); - match out.as_ref() { "true" => return Some(Token::True), "false" => return Some(Token::False), @@ -404,7 +420,7 @@ impl<'a> TokenIterator<'a> { "break" => return Some(Token::Break), "return" => return Some(Token::Return), "fn" => return Some(Token::Fn), - x => return Some(Token::Identifier(x.to_string())) + x => return Some(Token::Identifier(x.to_string())), } } '"' => { @@ -698,6 +714,7 @@ fn parse_primary<'a>(input: &mut Peekable>) -> Result Ok(Expr::IntConst(*x)), + Token::FloatConst(ref x) => Ok(Expr::FloatConst(*x)), Token::StringConst(ref s) => Ok(Expr::StringConst(s.clone())), Token::CharConst(ref c) => Ok(Expr::CharConst(*c)), Token::Identifier(ref s) => parse_ident_expr(s.clone(), input), diff --git a/src/tests.rs b/src/tests.rs index cd0b1e53..a812d663 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -402,6 +402,75 @@ fn test_array_with_structs() { } } +#[test] +fn test_float() { + let mut engine = Engine::new(); + + if let Ok(result) = engine.eval::("let x = 0.0; let y = 1.0; x < y") { + assert!(result); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("let x = 0.0; let y = 1.0; x > y") { + assert!(!result); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("let x = 9.9999; x") { + assert_eq!(result, 9.9999); + } else { + assert!(false); + } +} + +#[test] +fn struct_with_float() { + #[derive(Clone)] + struct TestStruct { + x: f64, + } + + impl TestStruct { + fn update(&mut self) { + self.x += 5.789_f64; + } + + fn get_x(&mut self) -> f64 { + self.x + } + + fn set_x(&mut self, new_x: f64) { + self.x = new_x; + } + + fn new() -> TestStruct { + TestStruct { x: 1.0 } + } + } + + let mut engine = Engine::new(); + + engine.register_type::(); + + engine.register_get_set("x", TestStruct::get_x, TestStruct::set_x); + engine.register_fn("update", TestStruct::update); + engine.register_fn("new_ts", TestStruct::new); + + if let Ok(result) = engine.eval::("let ts = new_ts(); ts.update(); ts.x") { + assert_eq!(result, 6.789); + } else { + assert!(false); + } + + if let Ok(result) = engine.eval::("let ts = new_ts(); ts.x = 10.1001; ts.x") { + assert_eq!(result, 10.1001); + } else { + assert!(false); + } +} + #[test] fn test_comments() { let mut engine = Engine::new();