1use crate::context::input::InputContext;
6use crate::context::StreamSolver;
7use crate::evaluator::Evaluator;
8use crate::expression::Expression;
9use crate::input::Input;
10use pel::expression::Expression as PelExpression;
11use pel::runtime::value::Value as PelValue;
12use pel::runtime::{Evaluation, Runtime, RuntimeError};
13use thiserror::Error;
14
15pub struct ScriptingEngine {}
17
18impl ScriptingEngine {
19 pub fn script(expression: &Expression) -> ScriptParser {
21 ScriptParser::new(expression)
22 }
23}
24
25pub struct ScriptParser<'a> {
27 expression: &'a Expression,
28 input_context: InputContext,
29}
30
31impl<'a> ScriptParser<'a> {
32 pub(crate) fn new(expression: &'a Expression) -> Self {
33 Self {
34 expression,
35 input_context: InputContext::default(),
36 }
37 }
38
39 pub fn input(mut self, input: Input) -> Self {
41 match input {
42 Input::Payload(fmt) => self.input_context.set_payload_input(fmt),
43 Input::Vars(vars) => {
44 self.input_context.push_var_input(vars);
45 }
46 Input::Attributes => {
47 self.input_context.set_attributes_input();
48 }
49 Input::Authentication => self.input_context.set_authentication_input(),
50 }
51 self
52 }
53
54 pub fn compile(self) -> Result<Script, ScriptError> {
56 let result = Runtime::new()
57 .eval_with_context(&self.expression.expression, &self.input_context)
58 .map_err(ScriptError::Error)?;
59
60 match result {
61 Evaluation::Complete(_, v) => Ok(Script::new(None, None, Some(v), self.input_context)),
62 Evaluation::Partial(e) => Ok(Script::new(
63 self.expression.source.as_deref(),
64 Some(e),
65 None,
66 self.input_context,
67 )),
68 }
69 }
70}
71
72#[derive(Error, Debug)]
74pub enum ScriptError {
75 #[error("Error compiling expression: {0}")]
77 Error(RuntimeError),
78}
79
80#[derive(Debug, Clone)]
82pub struct Script {
83 stream_solver: StreamSolver,
84 evaluation: Option<PelExpression>,
85 result: Option<PelValue>,
86 context: InputContext,
87}
88
89impl Script {
90 pub(crate) fn new(
91 source: Option<&str>,
92 evaluation: Option<PelExpression>,
93 result: Option<PelValue>,
94 context: InputContext,
95 ) -> Self {
96 Self {
97 stream_solver: StreamSolver::for_source(source),
98 evaluation,
99 result,
100 context,
101 }
102 }
103
104 pub fn evaluator(&self) -> Evaluator {
106 Evaluator::new(
107 self.stream_solver.clone(),
108 self.evaluation.clone(),
109 self.result.clone(),
110 &self.context,
111 )
112 }
113}