use std::collections::HashMap;
mod bind_context;
mod default_funcs;
mod default_macros;
mod type_funcs;
use crate::{
compiler::{compiler::CelCompiler, string_tokenizer::StringTokenizer},
interp::Interpreter,
program::{Program, ProgramDetails},
CelResult, CelValue,
};
pub use bind_context::{BindContext, RsCelFunction, RsCelMacro};
pub use type_funcs::construct_type;
pub struct CelContext {
progs: HashMap<String, Program>,
}
impl CelContext {
pub fn new() -> CelContext {
CelContext {
progs: HashMap::new(),
}
}
pub fn add_program(&mut self, name: &str, prog: Program) {
self.progs.insert(name.to_owned(), prog);
}
pub fn add_program_str(&mut self, name: &str, prog_str: &str) -> CelResult<()> {
let mut tokenizer = StringTokenizer::with_input(prog_str);
let prog = CelCompiler::with_tokenizer(&mut tokenizer).compile()?;
self.add_program(name, prog);
Ok(())
}
pub fn program_details<'a>(&'a self, name: &str) -> Option<&'a ProgramDetails> {
let prog = self.progs.get(name)?;
Some(prog.details())
}
pub fn get_program<'a>(&'a self, name: &str) -> Option<&'a Program> {
self.progs.get(name)
}
pub fn exec<'l>(&'l mut self, name: &str, bindings: &'l BindContext) -> CelResult<CelValue> {
let interp = Interpreter::new(&self, bindings);
interp.run_program(name)
}
}
impl Clone for CelContext {
fn clone(&self) -> Self {
CelContext {
progs: self.progs.clone(),
}
}
}
#[cfg(test)]
mod test {
use super::{BindContext, CelContext};
#[test]
fn test_eval_basic() {
let mut ctx = CelContext::new();
let exec_ctx = BindContext::new();
ctx.add_program_str("test_main", "3 + 4").unwrap();
let res = ctx.exec("test_main", &exec_ctx).unwrap();
assert!(res == 7.into())
}
}