From ef8d8bd17b55853d8286033ffe548deeb0f459a6 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 26 Oct 2024 00:18:57 +0200 Subject: [PATCH 1/6] Fix implicit Mul priority in division --- core/src/eval.rs | 4 ++++ core/src/parser.rs | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/core/src/eval.rs b/core/src/eval.rs index 3d9a40f9..db4818a1 100644 --- a/core/src/eval.rs +++ b/core/src/eval.rs @@ -11,6 +11,7 @@ pub(crate) fn evaluate_to_value( context: &mut crate::Context, int: &I, ) -> FResult { + println!("evaluate_to_value"); let lex = lexer::lex(input, context, int); let mut tokens = vec![]; let mut missing_open_parens: i32 = 0; @@ -24,7 +25,9 @@ pub(crate) fn evaluate_to_value( for _ in 0..missing_open_parens { tokens.insert(0, lexer::Token::Symbol(lexer::Symbol::OpenParens)); } + println!("\t{:?}", tokens); let parsed = parser::parse_tokens(&tokens)?; + println!("parsed: {:#?}", parsed); let result = ast::evaluate(parsed, scope, attrs, context, int)?; Ok(result) } @@ -80,6 +83,7 @@ pub(crate) fn evaluate_to_spans( ) -> FResult<(Vec, bool, Attrs)> { let (attrs, input) = parse_attrs(input); let value = evaluate_to_value(input, scope, attrs, context, int)?; + println!("{} {:#?}", value.type_name(), value); context.variables.insert("_".to_string(), value.clone()); context.variables.insert("ans".to_string(), value.clone()); Ok(( diff --git a/core/src/parser.rs b/core/src/parser.rs index 94f26d0d..6be91a99 100644 --- a/core/src/parser.rs +++ b/core/src/parser.rs @@ -207,7 +207,12 @@ fn parse_apply_cont<'a>(input: &'a [Token], lhs: &Expr) -> ParseResult<'a> { (_, Expr::Literal(Value::Num(_))) => { Expr::ApplyFunctionCall(Box::new(lhs.clone()), Box::new(rhs)) } - (Expr::Literal(Value::Num(_)) | Expr::ApplyMul(_, _), _) => { + (Expr::ApplyMul(_, _), _) => { + println!("\t-> ApplyMul *"); + Expr::ApplyMul(Box::new(lhs.clone()), Box::new(rhs)) + } + (Expr::Literal(Value::Num(_)), _) => { + println!("\t-> ApplyMul implicit, rhs {:?}", rhs); Expr::ApplyMul(Box::new(lhs.clone()), Box::new(rhs)) } _ => Expr::Apply(Box::new(lhs.clone()), Box::new(rhs)), @@ -268,13 +273,15 @@ fn parse_mixed_fraction<'a>(input: &'a [Token], lhs: &Expr) -> ParseResult<'a> { fn parse_multiplication_cont(input: &[Token]) -> ParseResult<'_> { let ((), input) = parse_fixed_symbol(input, Symbol::Mul)?; + println!("\t\tparse_multiplication_cont2 {:?}", input.to_vec()); let (b, input) = parse_power(input, true)?; + println!("\t\tparse_multiplication_cont3 {:?}", input.to_vec()); Ok((b, input)) } fn parse_division_cont(input: &[Token]) -> ParseResult<'_> { let ((), input) = parse_fixed_symbol(input, Symbol::Div)?; - let (b, input) = parse_power(input, true)?; + let (b, input) = parse_implicit_multiplication(input)?; Ok((b, input)) } @@ -305,25 +312,47 @@ fn parse_modulo2_cont(input: &[Token]) -> ParseResult<'_> { Ok((b, input)) } -fn parse_multiplicative(input: &[Token]) -> ParseResult<'_> { +fn parse_implicit_multiplication(input: &[Token]) -> ParseResult<'_> { let (mut res, mut input) = parse_power(input, true)?; + println!("parse_implicit_multiplication {:?}", input.to_vec()); + loop { + if let Ok((new_res, remaining)) = parse_apply_cont(input, &res) { + println!("\tparse_apply_cont {:?}", remaining.to_vec()); + res = new_res; + input = remaining; + } else { + break; + } + } + Ok((res, input)) +} + +fn parse_multiplicative(input: &[Token]) -> ParseResult<'_> { + let (mut res, mut input) = parse_implicit_multiplication(input)?; + println!("parse_multiplicative {:?}", input.to_vec()); loop { if let Ok((term, remaining)) = parse_multiplication_cont(input) { + println!("\tparse_multiplication_cont {:?}", remaining.to_vec()); res = Expr::Bop(Bop::Mul, Box::new(res.clone()), Box::new(term)); input = remaining; } else if let Ok((term, remaining)) = parse_division_cont(input) { + println!("\tparse_division_cont {:?}", remaining.to_vec()); res = Expr::Bop(Bop::Div, Box::new(res.clone()), Box::new(term)); input = remaining; } else if let Ok((term, remaining)) = parse_modulo_cont(input) { + println!("\tparse_modulo_cont {:?}", remaining.to_vec()); res = Expr::Bop(Bop::Mod, Box::new(res.clone()), Box::new(term)); input = remaining; } else if let Ok((term, remaining)) = parse_modulo2_cont(input) { + println!("\tparse_modulo2_cont {:?}", remaining.to_vec()); res = Expr::Bop(Bop::Mod, Box::new(res.clone()), Box::new(term)); input = remaining; } else if let Ok((new_res, remaining)) = parse_mixed_fraction(input, &res) { + println!("\tparse_mixed_fraction {:?}", remaining.to_vec()); res = new_res; input = remaining; } else if let Ok((new_res, remaining)) = parse_apply_cont(input, &res) { + println!("\tparse_apply_cont {:?}", remaining.to_vec()); res = new_res; input = remaining; } else { From 4dd5e91a07f38ba638be6c9a4040c764ed2244b1 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 26 Oct 2024 00:52:24 +0200 Subject: [PATCH 2/6] Modulo --- core/src/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/parser.rs b/core/src/parser.rs index 6be91a99..139dea36 100644 --- a/core/src/parser.rs +++ b/core/src/parser.rs @@ -308,7 +308,7 @@ fn parse_modulo2_cont(input: &[Token]) -> ParseResult<'_> { }) { return Err(ParseError::UnexpectedInput); } - let (b, input) = parse_power(input, true)?; + let (b, input) = parse_implicit_multiplication(input)?; Ok((b, input)) } From 1c567bc3c23ce6e13b454061ad3f99e9748d0b02 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 26 Oct 2024 01:09:41 +0200 Subject: [PATCH 3/6] Fix `1 % 1` being parsed as `(1*%)`+1 Not sure why --- core/src/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/parser.rs b/core/src/parser.rs index 139dea36..7371252b 100644 --- a/core/src/parser.rs +++ b/core/src/parser.rs @@ -328,7 +328,7 @@ fn parse_implicit_multiplication(input: &[Token]) -> ParseResult<'_> { } fn parse_multiplicative(input: &[Token]) -> ParseResult<'_> { - let (mut res, mut input) = parse_implicit_multiplication(input)?; + let (mut res, mut input) = parse_power(input, true)?; println!("parse_multiplicative {:?}", input.to_vec()); loop { if let Ok((term, remaining)) = parse_multiplication_cont(input) { From 1388182a72b36ddfec3bdaf8e414e5a7ab2d73fc Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 26 Oct 2024 01:54:27 +0200 Subject: [PATCH 4/6] Attempt division fix --- core/src/ast.rs | 9 ++++++++- core/src/num/unit.rs | 25 +++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/core/src/ast.rs b/core/src/ast.rs index 0a625c19..bb108f8a 100644 --- a/core/src/ast.rs +++ b/core/src/ast.rs @@ -489,7 +489,14 @@ pub(crate) fn evaluate( } Expr::Bop(bop, a, b) => eval!(*a)?.handle_two_nums( eval!(*b)?, - |a, b| a.bop(bop, b, attrs, context, int), + |a, b| { + // println!("====== .bop() '{}'", bop); + // println!("\t{:?}", a); + // println!("\t{:?}", b); + // println!("\tattr {:?}", attrs); + // println!("\t context {:?}", context); + a.bop(bop, b, attrs, context, int) + }, |a| |f| Expr::Bop(bop, f, Box::new(Expr::Literal(Value::Num(Box::new(a))))), |a| |f| Expr::Bop(bop, Box::new(Expr::Literal(Value::Num(Box::new(a)))), f), scope, diff --git a/core/src/num/unit.rs b/core/src/num/unit.rs index 40dfa2a3..db4a8108 100644 --- a/core/src/num/unit.rs +++ b/core/src/num/unit.rs @@ -278,12 +278,29 @@ impl Value { } pub(crate) fn div(self, rhs: Self, int: &I) -> FResult { + println!("====== div"); + println!("\t{:?}", self); + println!("\t{:?}", rhs); let mut components = self.unit.components.clone(); for rhs_component in rhs.unit.components { - components.push(UnitExponent::new( - rhs_component.unit, - -rhs_component.exponent, - )); + let mut self_has_unit = false; + for self_component in &self.unit.components { + if compare_hashmaps( + &self_component.unit.base_units, + &rhs_component.unit.base_units, + int, + )? { + self_has_unit = true; + break; + } + } + let new_exponent = if self_has_unit { + -rhs_component.exponent + } else { + rhs_component.exponent + }; + println!("\t\t{:?}", new_exponent); + components.push(UnitExponent::new(rhs_component.unit, new_exponent)); } let value = Exact::new(self.value, self.exact).div(&Exact::new(rhs.value, rhs.exact), int)?; From 78495d449e33bb5e66c61a976927bbecd5fcfde9 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 26 Oct 2024 03:20:43 +0200 Subject: [PATCH 5/6] Add tests --- core/tests/integration_tests.rs | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/tests/integration_tests.rs b/core/tests/integration_tests.rs index 936be9a6..a663d42b 100644 --- a/core/tests/integration_tests.rs +++ b/core/tests/integration_tests.rs @@ -795,6 +795,15 @@ fn order_of_operations_17() { test_eval("-3 -1/2", "-3.5"); } +#[test] +fn order_of_operations_18() { + test_eval("1/2/4", "0.125"); +} +#[test] +fn order_of_operations_19() { + test_eval("19 % 7 % 3", "2"); +} + #[test] fn yobibyte() { test_eval("1 YiB to bytes", "1208925819614629174706176 bytes"); @@ -6078,3 +6087,33 @@ fn european_formatting() { "approx. 0,9320390859" ); } + +#[test] +fn implitic_mul_priority_1() { + test_eval("10m/2s", "2 m / s"); +} + +#[test] +fn implitic_mul_priority_2() { + test_eval("10m/2s * 5 s", "25 m"); +} + +#[test] +fn implitic_mul_priority_3() { + test_eval("sin pi/2", "0") +} + +#[test] +fn implitic_mul_priority_4() { + test_eval("1 3/8 inches", "1.375 inches") +} + +#[test] +fn implitic_mul_priority_5() { + test_eval("-sin (pi/2)", "-1") +} + +#[test] +fn implitic_mul_priority_6() { + test_eval("-sin (pi/2)", "-1") +} From b7b78e255474da47a263901246dfb48203082783 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 26 Oct 2024 03:35:50 +0200 Subject: [PATCH 6/6] Revert ast change --- core/src/num/unit.rs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/core/src/num/unit.rs b/core/src/num/unit.rs index db4a8108..d5c16207 100644 --- a/core/src/num/unit.rs +++ b/core/src/num/unit.rs @@ -283,24 +283,10 @@ impl Value { println!("\t{:?}", rhs); let mut components = self.unit.components.clone(); for rhs_component in rhs.unit.components { - let mut self_has_unit = false; - for self_component in &self.unit.components { - if compare_hashmaps( - &self_component.unit.base_units, - &rhs_component.unit.base_units, - int, - )? { - self_has_unit = true; - break; - } - } - let new_exponent = if self_has_unit { - -rhs_component.exponent - } else { - rhs_component.exponent - }; - println!("\t\t{:?}", new_exponent); - components.push(UnitExponent::new(rhs_component.unit, new_exponent)); + components.push(UnitExponent::new( + rhs_component.unit, + -rhs_component.exponent, + )); } let value = Exact::new(self.value, self.exact).div(&Exact::new(rhs.value, rhs.exact), int)?;