#![cfg_attr(
test,
allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::float_cmp
)
)]
#![allow(clippy::disallowed_methods)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
pub mod core;
pub mod driver;
#[cfg(feature = "tui")]
pub mod tui;
pub mod wasm;
#[cfg(test)]
mod probar_tests;
pub mod prelude {
pub use crate::core::evaluator::Evaluator;
pub use crate::core::history::{History, HistoryEntry};
pub use crate::core::parser::{AstNode, Parser, Token, Tokenizer};
pub use crate::core::{
AnomalyValidator, AnomalyViolation, CalcError, CalcResult, Calculator, Operation,
};
pub use crate::driver::{CalculatorDriver, HistoryItem};
#[cfg(feature = "tui")]
pub use crate::driver::TuiDriver;
pub use crate::wasm::{DomElement, DomEvent, MockDom, WasmCalculator, WasmDriver};
}
#[cfg(test)]
mod tests {
use super::prelude::*;
#[test]
fn test_prelude_imports() {
let mut eval = Evaluator::new();
let result = eval.evaluate_str("2 + 3").unwrap();
assert_eq!(result, 5.0);
}
#[test]
fn test_calculator_direct() {
let mut calc = Calculator::new();
let result = calc.calculate(6.0, 7.0, Operation::Multiply).unwrap();
assert_eq!(result, 42.0);
}
#[test]
fn test_parser_direct() {
let ast = Parser::parse_str("1 + 2 * 3").unwrap();
let mut eval = Evaluator::new();
assert_eq!(eval.evaluate(&ast).unwrap(), 7.0);
}
#[test]
fn test_history_tracking() {
let mut history = History::new();
history.record("10 / 2", 5.0);
assert_eq!(history.len(), 1);
assert_eq!(history.last().unwrap().display(), "10 / 2 = 5");
}
#[test]
fn test_jidoka_validation() {
let validator = AnomalyValidator::with_max_magnitude(50.0);
let mut eval = Evaluator::with_validator(validator);
assert!(eval.evaluate_str("5 * 5").is_ok());
assert!(matches!(
eval.evaluate_str("10 * 10"),
Err(CalcError::AnomalyViolation(_))
));
}
#[test]
fn test_error_handling() {
let mut eval = Evaluator::new();
assert!(matches!(
eval.evaluate_str("1 / 0"),
Err(CalcError::DivisionByZero)
));
assert!(matches!(
eval.evaluate_str(""),
Err(CalcError::EmptyExpression)
));
assert!(matches!(
eval.evaluate_str("1 + + 2"),
Err(CalcError::ParseError(_))
));
}
#[test]
fn test_all_operations() {
let mut eval = Evaluator::new();
assert_eq!(eval.evaluate_str("10 + 5").unwrap(), 15.0);
assert_eq!(eval.evaluate_str("10 - 3").unwrap(), 7.0);
assert_eq!(eval.evaluate_str("6 * 7").unwrap(), 42.0);
assert_eq!(eval.evaluate_str("20 / 4").unwrap(), 5.0);
assert_eq!(eval.evaluate_str("17 % 5").unwrap(), 2.0);
assert_eq!(eval.evaluate_str("2 ^ 10").unwrap(), 1024.0);
}
#[test]
fn test_complex_expressions() {
let mut eval = Evaluator::new();
assert_eq!(eval.evaluate_str("2 + 3 * 4").unwrap(), 14.0);
assert_eq!(eval.evaluate_str("(2 + 3) * 4").unwrap(), 20.0);
assert_eq!(eval.evaluate_str("2 ^ 3 ^ 2").unwrap(), 512.0);
assert_eq!(eval.evaluate_str("42 * (3 + 7)").unwrap(), 420.0);
assert_eq!(eval.evaluate_str("-5 + 10").unwrap(), 5.0);
}
}