1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! # 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
}
}