From 8d26022403fc57f3ffeb1c352eac4474fb52cd62 Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 00:30:53 -0700 Subject: [PATCH 01/10] tests: implicit_mult --- src/nodes/tests.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/nodes/tests.rs b/src/nodes/tests.rs index 4c3caa6..59995fe 100644 --- a/src/nodes/tests.rs +++ b/src/nodes/tests.rs @@ -4,6 +4,14 @@ use rug::Float; use crate::nodes::{Function, Node, Nodes, Operator, PREC}; +#[test] +fn implicit_mult() { + assert_eq!( + Nodes::from_str("10 sin(10)").unwrap().evaluate().to_f64(), + -5.440211108893698 + ); +} + #[test] fn constants() { assert_eq!( From fc06e1e9813b7f2692110f718d61b749e7ecc579 Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 00:36:36 -0700 Subject: [PATCH 02/10] feat: add constant pi copy and pasted from ALEKS calculator, as I gave up trying to find what the best approximation to use would be. --- src/nodes/from_str.rs | 1 + src/nodes/tests.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/nodes/from_str.rs b/src/nodes/from_str.rs index 4f0f20d..f4b147d 100644 --- a/src/nodes/from_str.rs +++ b/src/nodes/from_str.rs @@ -9,6 +9,7 @@ impl Node { Ok(match s { "c" => Self::Number(Float::with_val(PREC, 299_792_458)), "A" => Self::Number(Float::with_val(PREC, 6.02214076e23)), + "pi" => Self::Number(Float::with_val(PREC, 3.1415926536)), _ => Self::Function(s.parse()?), }) } diff --git a/src/nodes/tests.rs b/src/nodes/tests.rs index 59995fe..81c2ab9 100644 --- a/src/nodes/tests.rs +++ b/src/nodes/tests.rs @@ -22,6 +22,10 @@ fn constants() { Nodes::from_str("A").unwrap().evaluate().to_f64(), 6.02214076e23 ); + assert_eq!( + Nodes::from_str("pi").unwrap().evaluate().to_f64(), + 3.1415926536 + ); } #[test] From ae0f2a3aafdaa60e3f95d10fb651735e4a02fa5e Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 10:51:44 -0700 Subject: [PATCH 03/10] feat: print a reasonable number of significant digits --- src/main.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 107dbf5..eeaba03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,5 +22,16 @@ fn main() { } }; - println!("{:.3}", parse_and_calc(&input)); + let result = parse_and_calc(&input); + + let result_raw_string = format!("{}", result); + let mut significant_digits = result_raw_string.len() - 1; + for (i, _) in result_raw_string.char_indices() { + if !result_raw_string[i..result_raw_string.len()].contains(|c| matches!(c, '1'..'9')) { + significant_digits = i; + break; + } + } + + println!("{result:.significant_digits$}"); } From cf8d218b11d5b5940ddea8639252f5524a3b1e0e Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 10:53:49 -0700 Subject: [PATCH 04/10] refactor: use compiler builtin constant for pi as per clippy lint --- src/nodes/from_str.rs | 3 ++- src/nodes/tests.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nodes/from_str.rs b/src/nodes/from_str.rs index f4b147d..b2d6535 100644 --- a/src/nodes/from_str.rs +++ b/src/nodes/from_str.rs @@ -1,3 +1,4 @@ +use core::f64; use std::str::FromStr; use rug::{Float, float::ParseFloatError, ops::CompleteRound}; @@ -9,7 +10,7 @@ impl Node { Ok(match s { "c" => Self::Number(Float::with_val(PREC, 299_792_458)), "A" => Self::Number(Float::with_val(PREC, 6.02214076e23)), - "pi" => Self::Number(Float::with_val(PREC, 3.1415926536)), + "pi" => Self::Number(Float::with_val(PREC, f64::consts::PI)), _ => Self::Function(s.parse()?), }) } diff --git a/src/nodes/tests.rs b/src/nodes/tests.rs index 81c2ab9..ae50576 100644 --- a/src/nodes/tests.rs +++ b/src/nodes/tests.rs @@ -1,3 +1,4 @@ +use core::f64; use std::str::FromStr; use rug::Float; @@ -24,7 +25,7 @@ fn constants() { ); assert_eq!( Nodes::from_str("pi").unwrap().evaluate().to_f64(), - 3.1415926536 + f64::consts::PI ); } From 7c4074113f4461855364762b0f029c05074c13f2 Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 11:00:15 -0700 Subject: [PATCH 05/10] feat: shorthand to concatonate arguments in the shell this allows for `tylc 1 + 1`, making it equivelent to `tylc "1+1"` this makes implementing other arguments difficult/impossible, though --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index eeaba03..e0ed1f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ pub fn parse_and_calc(s: &str) -> Float { } fn main() { - let input = match env::args().nth(1) { + let input = match env::args().skip(1).reduce(|x, a| a + &x) { Some(s) => s, None => { let mut buf = String::new(); From 50358db183f5d2d352f151a80941644000534b5b Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 11:25:48 -0700 Subject: [PATCH 06/10] refactor: significant digits calculation out of `fn main` --- src/main.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index e0ed1f9..da7de51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,20 @@ pub fn parse_and_calc(s: &str) -> Float { nodes::Nodes::from_str(s).unwrap().evaluate() } +pub fn get_significant_digits(n: &Float) -> usize { + let raw_string = format!("{n}"); + + let mut significant_digits = raw_string.len() - 1; + for (i, _) in raw_string.char_indices() { + if !raw_string[i..raw_string.len()].contains(|c| matches!(c, '1'..'9')) { + significant_digits = i; + break; + } + } + + significant_digits +} + fn main() { let input = match env::args().skip(1).reduce(|x, a| a + &x) { Some(s) => s, @@ -24,14 +38,5 @@ fn main() { let result = parse_and_calc(&input); - let result_raw_string = format!("{}", result); - let mut significant_digits = result_raw_string.len() - 1; - for (i, _) in result_raw_string.char_indices() { - if !result_raw_string[i..result_raw_string.len()].contains(|c| matches!(c, '1'..'9')) { - significant_digits = i; - break; - } - } - - println!("{result:.significant_digits$}"); + println!("{result:.0$}", get_significant_digits(&result)); } From 93d81470481377c662d7f58da8b293d1bb8e1bda Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 11:29:51 -0700 Subject: [PATCH 07/10] feat: set a max for displayed significant digits --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index da7de51..ba15d42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,5 +38,5 @@ fn main() { let result = parse_and_calc(&input); - println!("{result:.0$}", get_significant_digits(&result)); + println!("{result:.0$}", get_significant_digits(&result).max(5)); } From 4d7a806caa220be29c170e303e2b6fe9103325f1 Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 11:31:57 -0700 Subject: [PATCH 08/10] feat: support sqrt other roots may prove to be quite a challenge, since I would need to parse the syntax `root(base, value)` --- src/nodes/evaluate.rs | 2 ++ src/nodes/from_str.rs | 2 ++ src/nodes/mod.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/nodes/evaluate.rs b/src/nodes/evaluate.rs index eae3d8e..c9984bd 100644 --- a/src/nodes/evaluate.rs +++ b/src/nodes/evaluate.rs @@ -40,6 +40,8 @@ fn collapse_toplevel(nodes: &mut Vec, mut end: usize) { { match &mut nodes[start..end][index + 1] { Node::Number(n) => match variant { + Function::Sqrt => n.sqrt_mut(), + Function::Sine => n.sin_mut(), Function::ArcSine => n.asin_mut(), Function::Cosine => n.cos_mut(), diff --git a/src/nodes/from_str.rs b/src/nodes/from_str.rs index b2d6535..754e5f2 100644 --- a/src/nodes/from_str.rs +++ b/src/nodes/from_str.rs @@ -32,6 +32,8 @@ impl FromStr for Function { type Err = String; fn from_str(s: &str) -> Result { match s { + "sqrt" => Ok(Self::Sqrt), + "sin" => Ok(Self::Sine), "asin" => Ok(Self::ArcSine), "cos" => Ok(Self::Cosine), diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index a7326bf..f46ad3b 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -40,6 +40,8 @@ enum Operator { #[derive(Debug, Copy, Clone, PartialEq)] enum Function { + Sqrt, + Sine, ArcSine, Cosine, From 9372d5dfa894edd90c65d77aea16d6420ca53851 Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 11:36:21 -0700 Subject: [PATCH 09/10] feat: support unicode mult & div --- src/nodes/from_str.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nodes/from_str.rs b/src/nodes/from_str.rs index 754e5f2..a28b15a 100644 --- a/src/nodes/from_str.rs +++ b/src/nodes/from_str.rs @@ -21,8 +21,8 @@ impl TryFrom for Operator { match value { '+' => Ok(Self::Plus), '-' => Ok(Self::Minus), - '*' => Ok(Self::Mult), - '/' => Ok(Self::Div), + '*' | '×' => Ok(Self::Mult), + '/' | '÷' => Ok(Self::Div), '^' => Ok(Self::Exp), _ => Err(value), } From 42ccff8b12bb05859051f5abb22c40d127b0d563 Mon Sep 17 00:00:00 2001 From: electria Date: Thu, 16 Jul 2026 11:38:36 -0700 Subject: [PATCH 10/10] fix: maximum significant digits oops :3 --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index ba15d42..247ba53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,5 +38,5 @@ fn main() { let result = parse_and_calc(&input); - println!("{result:.0$}", get_significant_digits(&result).max(5)); + println!("{result:.0$}", get_significant_digits(&result).clamp(0, 6)); }