1use std::collections::HashMap;
2
3use crate::{Error, expr::{BoxedExprFn, ExprValue}};
4
5#[macro_export]
18macro_rules! simple_context {
19 () => {
21 $crate::SimpleContext::new(std::collections::HashMap::new())
22 };
23
24 ($key:literal : $value:expr $(,)?) => {
26 $crate::SimpleContext::new(std::collections::HashMap::from([
27 ($key.to_string(), ($value).into()),
28 ]))
29 };
30
31 ($key:literal : $value:expr, $($rest_key:literal : $rest_value:expr),* $(,)?) => {
33 $crate::SimpleContext::new(std::collections::HashMap::from([
34 ($key.to_string(), ($value).into()),
35 $(($rest_key.to_string(), ($rest_value).into())),*
36 ]))
37 };
38}
39
40#[async_trait::async_trait]
42pub trait Context: Send + Sync {
43 async fn get_var(&self, name: &str) -> Result<ExprValue, Error>;
44 async fn get_fn(&self, name: &str) -> Result<Option<&BoxedExprFn>, Error>;
45}
46
47pub struct SimpleContext {
52 vars: HashMap<String, ExprValue>,
53 fns: HashMap<String, BoxedExprFn>,
54}
55
56impl SimpleContext {
57 pub fn new(vars: HashMap<String, ExprValue>) -> Self {
58 Self {
59 vars,
60 fns: HashMap::new(),
61 }
62 }
63
64 pub fn add_fn(&mut self, name: String, func: BoxedExprFn) {
65 self.fns.insert(name, func);
66 }
67}
68
69#[async_trait::async_trait]
70impl Context for SimpleContext {
71 async fn get_var(&self, name: &str) -> Result<ExprValue, Error> {
72 self.vars
73 .get(name)
74 .cloned()
75 .ok_or(Error::NoSuchVar(name.to_string()))
76 }
77
78 async fn get_fn(&self, name: &str) -> Result<Option<&BoxedExprFn>, Error> {
79 Ok(self.fns.get(name))
80 }
81}