From f846a5b59eb810cacfc25dc9d9f1fdf5962065d5 Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Wed, 3 Apr 2024 01:34:35 +0200 Subject: [PATCH] Allow big numbers as input, #130 --- kalk/src/ast.rs | 7 ++----- kalk/src/interpreter.rs | 17 +++++------------ kalk/src/kalk_value/mod.rs | 6 ++++++ kalk/src/parser.rs | 23 +++++------------------ kalk/src/radix.rs | 14 +++++++++++--- 5 files changed, 29 insertions(+), 38 deletions(-) diff --git a/kalk/src/ast.rs b/kalk/src/ast.rs index c328dec..d0fe2a3 100644 --- a/kalk/src/ast.rs +++ b/kalk/src/ast.rs @@ -1,4 +1,4 @@ -use crate::lexer::TokenKind; +use crate::{kalk_value::KalkFloat, lexer::TokenKind}; /// A tree structure of a statement. #[derive(Debug, Clone, PartialEq)] @@ -19,10 +19,7 @@ pub enum Expr { Var(Identifier), Group(Box), FnCall(Identifier, Vec), - #[cfg(feature="rug")] - Literal(rug::Float), - #[cfg(not(feature="rug"))] - Literal(f64), + Literal(KalkFloat), Boolean(bool), Piecewise(Vec), Vector(Vec), diff --git a/kalk/src/interpreter.rs b/kalk/src/interpreter.rs index 8c0d23d..cf3ae71 100644 --- a/kalk/src/interpreter.rs +++ b/kalk/src/interpreter.rs @@ -2,6 +2,7 @@ use crate::ast::{Expr, Stmt}; use crate::ast::{Identifier, RangedVar}; use crate::calculation_result::CalculationResult; use crate::errors::KalkError; +use crate::kalk_value::KalkFloat; use crate::kalk_value::KalkValue; use crate::lexer::TokenKind; use crate::parser::DECL_UNIT; @@ -323,28 +324,20 @@ fn eval_var_expr( } #[allow(unused_variables)] -#[cfg(feature = "rug")] fn eval_literal_expr( context: &mut Context, - value: rug::Float, + value: KalkFloat, unit: Option<&String>, ) -> Result { + + #[allow(unused_mut)] let mut float = float!(value); + #[cfg(feature = "rug")] float.set_prec(context.precision); Ok(KalkValue::Number(float, float!(0), unit.cloned())) } -#[allow(unused_variables)] -#[cfg(not(feature = "rug"))] -fn eval_literal_expr( - context: &mut Context, - value: f64, - unit: Option<&String>, -) -> Result { - Ok(KalkValue::Number(float!(value), float!(0), unit.cloned())) -} - fn eval_group_expr( context: &mut Context, expr: &Expr, diff --git a/kalk/src/kalk_value/mod.rs b/kalk/src/kalk_value/mod.rs index 4d3ff48..26d8780 100644 --- a/kalk/src/kalk_value/mod.rs +++ b/kalk/src/kalk_value/mod.rs @@ -18,6 +18,12 @@ use self::rounding::EstimationResult; const ACCEPTABLE_COMPARISON_MARGIN: f64 = 0.00000001; +#[cfg(feature = "rug")] +pub(crate) type KalkFloat = rug::Float; + +#[cfg(not(feature = "rug"))] +pub(crate) type KalkFloat = f64; + #[macro_export] #[cfg(not(feature = "rug"))] macro_rules! float { diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index b8f4b54..e9f7369 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -4,6 +4,7 @@ use crate::analysis; use crate::ast::Identifier; use crate::calculation_result::CalculationResult; use crate::errors::KalkError; +use crate::kalk_value::KalkFloat; use crate::{ ast::{Expr, Stmt}, interpreter, @@ -770,8 +771,8 @@ fn skip_newlines(context: &mut Context) { } } -#[cfg(feature = "rug")] -fn string_to_num(value: &str) -> Result { +fn string_to_num(value: &str) -> Result { + #[cfg(feature = "rug")] use rug::ops::Pow; if value.contains('E') { @@ -779,24 +780,10 @@ fn string_to_num(value: &str) -> Result { let left = crate::float!(string_to_num(parts[0])?); let right = crate::float!(string_to_num(parts[1])?); + #[cfg(feature = "rug")] return Ok(left * 10.pow(right)); - } - - let base = get_base(value)?; - if let Some(result) = crate::radix::parse_float_radix(&value.replace(' ', ""), base) { - Ok(crate::float!(result)) - } else { - Err(KalkError::InvalidNumberLiteral(value.into())) - } -} - -#[cfg(not(feature = "rug"))] -fn string_to_num(value: &str) -> Result { - if value.contains('E') { - let parts = value.split('E').collect::>(); - let left = crate::float!(string_to_num(parts[0])?); - let right = crate::float!(string_to_num(parts[1])?); + #[cfg(not(feature = "rug"))] return Ok(left * 10_f64.powf(right)); } diff --git a/kalk/src/radix.rs b/kalk/src/radix.rs index 79067c0..1807252 100644 --- a/kalk/src/radix.rs +++ b/kalk/src/radix.rs @@ -1,13 +1,21 @@ -pub fn parse_float_radix(value: &str, radix: u8) -> Option { +use crate::{float, kalk_value::KalkFloat}; + +pub fn parse_float_radix(value: &str, radix: u8) -> Option { if radix == 10 { - return if let Ok(result) = value.parse::() { + #[cfg(feature = "rug")] + let parsed = rug::Float::parse(value).map(|valid| crate::float!(valid)); + + #[cfg(not(feature = "rug"))] + let parsed = value.parse::(); + + return if let Ok(result) = parsed { Some(result) } else { None }; } - let mut sum = 0f64; + let mut sum = float!(0f64); let length = value.find('_').unwrap_or(value.len()); let mut i = (value.find('.').unwrap_or(length) as i32) - 1; for c in value.chars() {