1use crate::parser::Expression;
2use crate::parser::cel::ExpressionParser;
3use std::fmt;
4use std::result::Result;
5use crate::context::Context;
6use crate::eval::{Bag, Eval};
7use crate::Value;
8
9pub struct Program {
10 expr: Expression
11}
12
13#[derive(Debug)]
14pub struct ParseError {
15 message: String,
16}
17
18
19impl fmt::Display for ParseError {
20 fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result {
21 write!(f, "{}", self.message)
22 }
23}
24
25impl Program {
26 pub fn new(source: &str) -> Result<Program, ParseError> {
27 match ExpressionParser::new().parse(source) {
28 Ok(expr) => Ok(Program {expr}),
29 Err(e) => Err(ParseError{message: format!("{}", e)}),
30 }
31 }
32
33 pub fn execute(self, context: &mut Context) -> bool {
34 self.eval(context).unpack().into()
35 }
36
37 pub fn eval(self, context: &mut Context) -> Value {
38 let e = Eval::default();
39 e.eval(self.expr, context).unpack()
40 }
41}
42
43
44
45#[cfg(test)]
46pub mod tests {
47 use std::rc::Rc;
48
49 use crate::{program, value::{FnValue, Overload}, Value};
50
51 macro_rules! string {
52 ($q:literal) => {
53 crate::Value::String(std::rc::Rc::new($q.into()))
54 };
55 }
56 macro_rules! eval_program {
57 ($expr:literal) => ({
58 eval_program!($expr, &mut crate::context::Context::default())
59 });
60 ($expr:literal, $ctx:expr) => ({
61 let program = crate::program::Program::new($expr);
62 assert!(program.is_ok(), "failed to create the program {:?}", program.err());
63 let program = program.unwrap();
64 program.eval($ctx)
65 });
66 }
67
68 #[test]
69 fn basic_test() {
70 assert_eq!(eval_program!(r#"r"""#), string!(""));
71 }
72
73 fn calc_string_string(lhs: &Value, rhs: &Value) -> Value {
74 Value::Null
75 }
76
77 #[test]
78 fn fn_test() {
79 let func = FnValue {
80 name: "calc",
81 overloads: &[
82 Overload {
83 key: "calc_string",
84 func: calc_string_string
85 }
86 ],
87 };
88 let mut ctx = program::Context::default()
89 .add_variable("a", Value::String(Rc::new("".into())))
90 .add_variable("b", Value::Int(0))
91 .add_variable("calc", crate::Value::Function(Rc::new(func)));
92 assert_eq!(eval_program!(r#"b.calc(a)"#, &mut ctx), string!(""));
93 }
94}