From e49dbab859c8e135307d0ac1ab6be205c359ce13 Mon Sep 17 00:00:00 2001 From: Roman Godmaire Date: Mon, 6 May 2024 08:50:38 -0400 Subject: [PATCH] feat: rudimentary float support --- src/env/core.rs | 16 ++++++++++++++++ src/evaluator.rs | 5 +++++ src/node.rs | 2 ++ src/parser/lexer.rs | 9 +++++++-- src/parser/mod.rs | 1 + 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/env/core.rs b/src/env/core.rs index 3ad505b..bb9d5f8 100644 --- a/src/env/core.rs +++ b/src/env/core.rs @@ -102,6 +102,10 @@ pub(super) fn core() -> HashMap { Node::Int128(lhs as i128 + rhs as i128) } (Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs + rhs as i128), + + (Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs + rhs), + (Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 + rhs), + (Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs + rhs as f64), _ => todo!(), }) .unwrap_or(Node::Int(0)); @@ -124,6 +128,10 @@ pub(super) fn core() -> HashMap { Node::Int128(lhs as i128 - rhs as i128) } (Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs - rhs as i128), + + (Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs - rhs), + (Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs - rhs as f64), + (Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 - rhs), _ => todo!(), }) .unwrap_or(Node::Int(0)); @@ -146,6 +154,10 @@ pub(super) fn core() -> HashMap { Node::Int128(lhs as i128 * rhs as i128) } (Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs * rhs as i128), + + (Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs * rhs), + (Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs * rhs as f64), + (Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 * rhs), _ => todo!(), }) .unwrap_or(Node::Int(0)); @@ -168,6 +180,10 @@ pub(super) fn core() -> HashMap { Node::Int128(lhs as i128 / rhs as i128) } (Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs / rhs as i128), + + (Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs / rhs), + (Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs / rhs as f64), + (Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 / rhs), _ => todo!(), }) .unwrap_or(Node::Int(0)); diff --git a/src/evaluator.rs b/src/evaluator.rs index 31342ba..cbc5c10 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -109,6 +109,10 @@ mod test { #[case("(* 8 9)", "72")] #[case("(/ 86 2)", "43")] #[case("(+ 1 2 (- 3 4))", "2")] + #[case("(+ 1 0.5)", "1.5")] + #[case("(- 1 0.5)", "0.5")] + #[case("(* 1 0.5)", "0.5")] + #[case("(/ 1.0 2.0)", "0.5")] // Native functions defaults #[case("(+)", "0")] #[case("(-)", "0")] @@ -198,6 +202,7 @@ mod test { #[case("(str (+ 1 2))", "3")] #[case("(str (list 1 2 3))", "(1 2 3)")] fn test_evaluator(#[case] input: &str, #[case] expected: &str) { + dbg!(input); let env = Environment::default(); let ast = parser::parse_str(input).unwrap(); let res = eval(&env, ast) diff --git a/src/node.rs b/src/node.rs index c8865ef..940daf8 100644 --- a/src/node.rs +++ b/src/node.rs @@ -12,6 +12,7 @@ pub enum Node { Keyword(String), Int(i64), Int128(i128), + Float(f64), String(String), Boolean(bool), Nil, @@ -44,6 +45,7 @@ impl std::fmt::Display for Node { Node::Int(val) => write!(f, "{}", val), Node::Int128(val) => write!(f, "{}", val), + Node::Float(val) => write!(f, "{}", val), Node::Boolean(true) => write!(f, "true"), Node::Boolean(false) => write!(f, "false"), Node::Symbol(val) => write!(f, "{}", val), diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 5735c02..133afc8 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -34,6 +34,7 @@ pub enum Token { // Values Keyword(String), Int(i64), + Float(f64), String(String), Ident(String), True, @@ -178,14 +179,18 @@ fn read_int(input: &mut Peekable, first: char) -> Token { continue; } - if !c.is_ascii_digit() { + if !c.is_ascii_digit() && *c != '.' { break; } raw_int.push(input.next().unwrap()); } - Token::Int(raw_int.iter().collect::().parse::().unwrap()) + if raw_int.iter().any(|c| *c == '.') { + Token::Float(raw_int.iter().collect::().parse::().unwrap()) + } else { + Token::Int(raw_int.iter().collect::().parse::().unwrap()) + } } fn read_ident(input: &mut Peekable, first: char) -> Token { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8699f01..d711fb5 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -60,6 +60,7 @@ fn next_statement(tokens: &mut Peekable>) -> Result Token::Ident(val) => Node::Symbol(val), Token::String(val) => Node::String(val), Token::Int(int) => Node::Int(int), + Token::Float(float) => Node::Float(float), Token::True => Node::Boolean(true), Token::False => Node::Boolean(false), Token::Nil => Node::Nil,