anathema_value_resolver/functions/
mod.rs

1use std::collections::HashMap;
2use std::fmt::Debug;
3
4use crate::ValueKind;
5
6mod list;
7mod number;
8mod string;
9
10pub struct Function {
11    inner: Box<dyn for<'bp> Fn(&[ValueKind<'bp>]) -> ValueKind<'bp>>,
12}
13
14impl Function {
15    pub(crate) fn invoke<'bp>(&self, args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
16        (self.inner)(args)
17    }
18}
19
20impl Debug for Function {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        write!(f, "<fun>")
23    }
24}
25
26impl<T> From<T> for Function
27where
28    T: 'static,
29    T: for<'bp> Fn(&[ValueKind<'bp>]) -> ValueKind<'bp>,
30{
31    fn from(value: T) -> Self {
32        Self { inner: Box::new(value) }
33    }
34}
35
36pub struct FunctionTable {
37    inner: HashMap<String, Function>,
38}
39
40impl FunctionTable {
41    pub fn new() -> Self {
42        let mut inner = HashMap::new();
43        inner.insert("to_upper".into(), Function::from(string::to_upper));
44        inner.insert("to_lower".into(), Function::from(string::to_lower));
45        inner.insert("to_str".into(), Function::from(string::to_str));
46        inner.insert("to_int".into(), Function::from(number::to_int));
47        inner.insert("round".into(), Function::from(number::round));
48        inner.insert("contains".into(), Function::from(list::contains));
49        Self { inner }
50    }
51
52    pub fn insert(&mut self, ident: impl Into<String>, f: impl Into<Function>) {
53        self.inner.insert(ident.into(), f.into());
54    }
55
56    pub fn lookup(&self, ident: &str) -> Option<&Function> {
57        self.inner.get(ident)
58    }
59}
60
61#[cfg(test)]
62mod test {
63    use crate::ValueKind;
64
65    pub(crate) fn list<T, U>(items: T) -> ValueKind<'static>
66    where
67        U: Into<ValueKind<'static>>,
68        T: IntoIterator<Item = U>,
69    {
70        let inner = items.into_iter().map(Into::into).collect::<Box<[ValueKind<'_>]>>();
71
72        ValueKind::List(inner)
73    }
74
75    pub(crate) fn value<T>(val: T) -> ValueKind<'static>
76    where
77        T: Into<ValueKind<'static>>,
78    {
79        val.into()
80    }
81}