use finx::{Finx, register_function};
use std::io::{self, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Finx Calculator Example ===");
println!("Type expressions to evaluate, 'help' for commands, 'quit' to exit\n");
let mut calc = create_calculator()?;
loop {
print!("> ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let input = input.trim();
if input.is_empty() {
continue;
}
match input {
"quit" | "exit" => break,
"help" => show_help(),
"clear" => {
calc.clear_output();
println!("Output cleared.");
}
"vars" => show_variables(&mut calc),
"history" => show_history(&calc),
_ => {
match calc.eval(input) {
Ok(result) => {
println!("= {}", result);
calc.execute(&format!("let ans = {}", result)).ok();
}
Err(e) => {
println!("Error: {}", e);
}
}
}
}
}
println!("Goodbye!");
Ok(())
}
fn create_calculator() -> Result<Finx, Box<dyn std::error::Error>> {
let mut calc = Finx::new();
register_function!(calc, "sin", 1, |x: f64| -> f64 { x.sin() });
register_function!(calc, "cos", 1, |x: f64| -> f64 { x.cos() });
register_function!(calc, "tan", 1, |x: f64| -> f64 { x.tan() });
register_function!(calc, "asin", 1, |x: f64| -> f64 { x.asin() });
register_function!(calc, "acos", 1, |x: f64| -> f64 { x.acos() });
register_function!(calc, "atan", 1, |x: f64| -> f64 { x.atan() });
register_function!(calc, "log", 1, |x: f64| -> f64 { x.ln() });
register_function!(calc, "log10", 1, |x: f64| -> f64 { x.log10() });
register_function!(calc, "exp", 1, |x: f64| -> f64 { x.exp() });
register_function!(calc, "sqrt", 1, |x: f64| -> f64 { x.sqrt() });
register_function!(calc, "cbrt", 1, |x: f64| -> f64 { x.cbrt() });
register_function!(calc, "pow", 2, |base: f64, exp: f64| -> f64 {
base.powf(exp)
});
register_function!(calc, "abs", 1, |x: f64| -> f64 { x.abs() });
register_function!(calc, "ceil", 1, |x: f64| -> f64 { x.ceil() });
register_function!(calc, "floor", 1, |x: f64| -> f64 { x.floor() });
register_function!(calc, "round", 1, |x: f64| -> f64 { x.round() });
register_function!(calc, "min", 2, |a: f64, b: f64| -> f64 { a.min(b) });
register_function!(calc, "max", 2, |a: f64, b: f64| -> f64 { a.max(b) });
register_function!(calc, "deg", 1, |rad: f64| -> f64 {
rad * 180.0 / std::f64::consts::PI
});
register_function!(calc, "rad", 1, |deg: f64| -> f64 {
deg * std::f64::consts::PI / 180.0
});
calc.execute(&format!("let pi = {}", std::f64::consts::PI))?;
calc.execute(&format!("let e = {}", std::f64::consts::E))?;
calc.execute("let ans = 0")?;
calc.execute(
r#"
fn factorial(n) {
if n <= 1 {
return 1;
}
return n * factorial(n - 1);
}
fn fibonacci(n) {
if n <= 1 {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
fn gcd(a, b) {
if b == 0 {
return a;
}
return gcd(b, a % b);
}
fn lcm(a, b) {
return abs(a * b) / gcd(a, b);
}
fn quadratic(a, b, c) {
let discriminant = b * b - 4 * a * c;
if discriminant < 0 {
print("No real solutions");
return null;
}
let sqrt_disc = sqrt(discriminant);
let x1 = (-b + sqrt_disc) / (2 * a);
let x2 = (-b - sqrt_disc) / (2 * a);
print("x1 = " + x1 + ", x2 = " + x2);
return x1;
}
"#,
)?;
Ok(calc)
}
fn show_help() {
println!("Available commands:");
println!(" help - Show this help");
println!(" quit/exit - Exit the calculator");
println!(" clear - Clear output history");
println!(" vars - Show defined variables");
println!(" history - Show calculation history");
println!();
println!("Available functions:");
println!(" Basic: +, -, *, /, %");
println!(" Trig: sin, cos, tan, asin, acos, atan");
println!(" Log: log (natural), log10, exp");
println!(" Power: sqrt, cbrt, pow(base, exp)");
println!(" Rounding: abs, ceil, floor, round");
println!(" Comparison: min, max");
println!(" Conversion: deg (rad→deg), rad (deg→rad)");
println!(" Advanced: factorial, fibonacci, gcd, lcm, quadratic");
println!();
println!("Constants: pi, e, ans (previous result)");
println!();
println!("Examples:");
println!(" sin(rad(30)) # sine of 30 degrees");
println!(" sqrt(2) * pi # square root of 2 times pi");
println!(" factorial(5) # 5! = 120");
println!(" quadratic(1, -5, 6) # solve x² - 5x + 6 = 0");
}
fn show_variables(calc: &mut Finx) {
println!("Defined variables:");
let vars = ["pi", "e", "ans"];
for var in &vars {
match calc.eval(var) {
Ok(value) => println!(" {} = {}", var, value),
Err(_) => {} }
}
}
fn show_history(calc: &Finx) {
let output = calc.get_output();
if output.is_empty() {
println!("No calculation history.");
} else {
println!("Recent output:");
for (i, line) in output.iter().rev().take(10).enumerate() {
println!(" [{}] {}", output.len() - i, line);
}
}
}