Skip to main content

ksl/builtin/
multi.rs

1//! # ksl::builtin::apply
2//!
3//! Built-in functions which accept multiple arguments.
4//!
5//! - Add
6//! - Concat
7//! - Mul
8
9use crate::{Environment, builtin::MultiFunctionType, eval::apply::eval_apply, value::Value};
10
11pub(crate) fn builtin(args: &[Value], func_type: MultiFunctionType, env: Environment) -> Result<Value, std::sync::Arc<str>> {
12    if let [v1, rest @ ..] = args {
13        match (eval_apply(v1, env.clone())?, &func_type) {
14            (Value::Number(n1), MultiFunctionType::Add) => {
15                let mut result = n1;
16                for val in rest.iter() {
17                    match eval_apply(val, env.clone())? {
18                        Value::Number(n) => result += n,
19                        e => {
20                            return Err(std::sync::Arc::from(format!(
21                                concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
22                                func_type, e
23                            )));
24                        }
25                    }
26                }
27                Ok(Value::Number(result))
28            }
29            (Value::Number(n1), MultiFunctionType::Mul) => {
30                let mut result = n1;
31                for val in rest.iter() {
32                    match eval_apply(val, env.clone())? {
33                        Value::Number(n) => result *= n,
34                        e => {
35                            return Err(std::sync::Arc::from(format!(
36                                concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
37                                func_type, e
38                            )));
39                        }
40                    }
41                }
42                Ok(Value::Number(result))
43            }
44            (Value::String(s1), MultiFunctionType::Concat) => {
45                let mut result = s1.to_string();
46                for val in rest.iter() {
47                    match eval_apply(val, env.clone())? {
48                        Value::String(s) => result.push_str(&s),
49                        e => {
50                            return Err(std::sync::Arc::from(format!(
51                                concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
52                                func_type, e
53                            )));
54                        }
55                    }
56                }
57                Ok(Value::String(std::sync::Arc::from(result)))
58            }
59            (Value::List(lst1), MultiFunctionType::Concat) => {
60                let mut result = lst1.to_vec();
61                for val in rest.iter() {
62                    match eval_apply(val, env.clone())? {
63                        Value::List(lst) => result.extend_from_slice(&lst),
64                        e => {
65                            return Err(std::sync::Arc::from(format!(
66                                concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
67                                func_type, e
68                            )));
69                        }
70                    }
71                }
72                Ok(Value::List(std::sync::Arc::from(result)))
73            }
74
75            (e @ (Value::String(_) | Value::List(_)), MultiFunctionType::Add | MultiFunctionType::Mul) => {
76                Err(std::sync::Arc::from(format!(
77                    concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
78                    func_type, e
79                )))
80            }
81            (e @ Value::Number(_), MultiFunctionType::Concat) => Err(std::sync::Arc::from(format!(
82                concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
83                func_type, e
84            ))),
85            (e, _) => Err(std::sync::Arc::from(format!(
86                concat!("Error[ksl::builtin::{:?}]: ", "Unexpected value: `{}`."),
87                func_type, e
88            ))),
89        }
90    } else {
91        Err(std::sync::Arc::from(format!(
92            concat!(
93                "Error[ksl::builtin::{:?}]: ",
94                "Expected at least 1 parameter, but {} were passed."
95            ),
96            func_type,
97            args.len()
98        )))
99    }
100}