ksl 0.1.7

KSL core library and interpreter
Documentation
//! # ksl::builtin::math
//!
//! Built-in math functions which expects one number argument.
//!
//! - Abs
//! - Cos
//! - Cosh
//! - Exp
//! - Ln
//! - Neg
//! - Sin
//! - Sinh
//! - Tan
//! - Tanh
//! - Trunc

use crate::{Environment, builtin::MathFunctionType, eval::apply::eval_apply, is_number_eq, value::Value};

pub(crate) fn builtin(args: &[Value], func_type: MathFunctionType, env: &Environment) -> Option<(Value, Environment)> {
    if let [v] = &args[..] {
        match eval_apply(v, env) {
            Some((Value::Number(n), _)) => Some((
                Value::Number(match func_type {
                    MathFunctionType::Abs => n.abs(),
                    MathFunctionType::Cos => n.cos(),
                    MathFunctionType::Cosh => n.cosh(),
                    MathFunctionType::Exp => n.exp(),
                    MathFunctionType::Ln => {
                        if n > 0.0 {
                            n.ln()
                        } else {
                            eprintln!(
                                concat!(
                                    "Error[ksl::builtin::math<{:?}>]: ",
                                    "Logarithm of non-positive number."
                                ),
                                func_type
                            );
                            return None;
                        }
                    }
                    MathFunctionType::Neg => {
                        if is_number_eq(n, 0.0) {
                            0.0
                        } else {
                            -n
                        }
                    }
                    MathFunctionType::Sin => n.sin(),
                    MathFunctionType::Sinh => n.sinh(),
                    MathFunctionType::Tan => n.tan(),
                    MathFunctionType::Tanh => n.tanh(),
                    MathFunctionType::Trunc => n.trunc(),
                }),
                Environment::new(),
            )),
            Some((e, _)) => {
                eprintln!(
                    concat!(
                        "Error[ksl::builtin::math<{:?}>]: ",
                        "Only accepts 1 number, but {:?} was passed."
                    ),
                    func_type, e
                );
                None
            }
            None => {
                eprintln!(
                    concat!(
                        "Error[ksl::builtin::math<{:?}>]: ",
                        "Cannot evaluate expression {:?}."
                    ),
                    func_type, v
                );
                None
            }
        }
    } else {
        eprintln!(
            concat!(
                "Error[ksl::builtin::math<{:?}>]: ",
                "Only accepts 1 argument, but {} were passed."
            ),
            func_type,
            args.len()
        );
        None
    }
}