From b13c459aeef391036868b1b1b6c326f9b7837fed Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Tue, 24 Jan 2023 19:11:35 +0100 Subject: [PATCH] Add 'base' command for setting output radix, closes #109 --- cli/help.txt | 6 ++++-- cli/src/main.rs | 7 ++++++- cli/src/output.rs | 8 +++++--- cli/src/repl.rs | 26 ++++++++++++++++++++++---- kalk/src/calculation_result.rs | 3 ++- kalk/src/kalk_value/mod.rs | 2 +- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/cli/help.txt b/cli/help.txt index 375e512..df867c3 100644 --- a/cli/help.txt +++ b/cli/help.txt @@ -15,10 +15,12 @@ Overview of features Different number bases: Either with a format like 0b1101, 0o5.3, 0xff or a format like 1101_2. The latter does not support letters, as they - would be interpreted as variables + would be interpreted as variables. The "base" command can be used to + tell the REPL to also show output in another number base. For example, + "base 16" would make it show results in hexadecimal as well as decimal. Root finding using Newton's method (eg. x^2 = 64). Note: estimation and - limited to one root + limited to one root. Derivation (prime notation) and integration (eg. integral(a, b, x dx) The value of an integral is estimated using Simpson's 3/8 rule, diff --git a/cli/src/main.rs b/cli/src/main.rs index 97b6e78..a93fbf7 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -68,7 +68,12 @@ fn default_action(context: &Context) { repl::start(&mut parser_context, precision); } else { // Direct output - output::eval(&mut parser_context, &context.args.join(" "), precision); + output::eval( + &mut parser_context, + &context.args.join(" "), + precision, + 10u8, + ); } } diff --git a/cli/src/output.rs b/cli/src/output.rs index 9b186ca..01cd6df 100644 --- a/cli/src/output.rs +++ b/cli/src/output.rs @@ -3,9 +3,11 @@ use kalk::parser; pub(crate) const DEFAULT_PRECISION: u32 = 63; -pub fn eval(parser: &mut parser::Context, input: &str, precision: u32) { +pub fn eval(parser: &mut parser::Context, input: &str, precision: u32, base: u8) { match parser::eval(parser, input, precision) { - Ok(Some(result)) => { + Ok(Some(mut result)) => { + result.set_radix(base); + if precision == DEFAULT_PRECISION { println!("{}", result.to_string_pretty()) } else { @@ -19,5 +21,5 @@ pub fn eval(parser: &mut parser::Context, input: &str, precision: u32) { pub fn print_err(msg: &str) { Red.paint(msg).to_string(); - println!("{}", msg); + eprintln!("{}", msg); } diff --git a/cli/src/repl.rs b/cli/src/repl.rs index 0b07a68..1ffcbcf 100644 --- a/cli/src/repl.rs +++ b/cli/src/repl.rs @@ -20,6 +20,10 @@ use std::collections::HashMap; use std::fs; use std::process; +struct Context { + base: u8, +} + pub fn start(parser: &mut parser::Context, precision: u32) { let mut editor = Editor::::new(); editor.set_helper(Some(RLHelper { @@ -50,6 +54,7 @@ pub fn start(parser: &mut parser::Context, precision: u32) { ); } + let mut repl = Context { base: 10u8 }; loop { let prompt = if cfg!(windows) { String::from(">> ") @@ -61,7 +66,7 @@ pub fn start(parser: &mut parser::Context, precision: u32) { match readline { Ok(input) => { editor.add_history_entry(input.as_str()); - eval_repl(parser, &input, precision); + eval_repl(&mut repl, parser, &input, precision); } Err(ReadlineError::Interrupted) => break, _ => break, @@ -73,22 +78,35 @@ pub fn start(parser: &mut parser::Context, precision: u32) { } } -fn eval_repl(parser: &mut parser::Context, input: &str, precision: u32) { +fn eval_repl(repl: &mut self::Context, parser: &mut parser::Context, input: &str, precision: u32) { if let Some(file_name) = input.strip_prefix("load ") { if let Some(file_path) = crate::get_input_file_by_name(file_name) { crate::load_input_file(&file_path, precision, parser); } else { - println!("Unable to find '{}'", file_name); + eprintln!("Unable to find '{}'", file_name); } + return; } + if let Some(base_str) = input.strip_prefix("base ") { + if !base_str.is_empty() && base_str.chars().next().unwrap().is_ascii_digit() { + if let Ok(base) = base_str.parse::() { + repl.base = base; + } else { + eprintln!("Invalid number base"); + } + + return; + } + } + match input { "" => eprint!(""), "clear" => print!("\x1B[2J"), "exit" => process::exit(0), "help" => print_cli_help(), - _ => output::eval(parser, input, precision), + _ => output::eval(parser, input, precision, repl.base), } } diff --git a/kalk/src/calculation_result.rs b/kalk/src/calculation_result.rs index 976572b..46d724c 100644 --- a/kalk/src/calculation_result.rs +++ b/kalk/src/calculation_result.rs @@ -65,7 +65,8 @@ impl CalculationResult { self.value.imaginary_to_f64() } - pub(crate) fn set_radix(&mut self, radix: u8) { + #[wasm_bindgen(js_name = setRadix)] + pub fn set_radix(&mut self, radix: u8) { self.radix = radix; } diff --git a/kalk/src/kalk_value/mod.rs b/kalk/src/kalk_value/mod.rs index 92562e9..16fced2 100644 --- a/kalk/src/kalk_value/mod.rs +++ b/kalk/src/kalk_value/mod.rs @@ -288,7 +288,7 @@ impl KalkValue { } } - pub(crate) fn to_string_pretty_radix(&self, radix: u8) -> String { + pub fn to_string_pretty_radix(&self, radix: u8) -> String { let (real, imaginary, unit) = match self { KalkValue::Number(real, imaginary, unit) => (real, imaginary, unit), _ => return self.to_string(),