use crate::context::input::InputContext;
use crate::context::StreamSolver;
use crate::evaluator::Evaluator;
use crate::expression::Expression;
use crate::input::Input;
use pel::expression::Expression as PelExpression;
use pel::runtime::value::Value as PelValue;
use pel::runtime::{Evaluation, Runtime, RuntimeError};
use thiserror::Error;
pub struct ScriptingEngine {}
impl ScriptingEngine {
pub fn script(expression: &Expression) -> ScriptParser {
ScriptParser::new(expression)
}
}
pub struct ScriptParser<'a> {
expression: &'a Expression,
input_context: InputContext,
}
impl<'a> ScriptParser<'a> {
pub(crate) fn new(expression: &'a Expression) -> Self {
Self {
expression,
input_context: InputContext::default(),
}
}
pub fn input(mut self, input: Input) -> Self {
match input {
Input::Payload(fmt) => self.input_context.set_payload_input(fmt),
Input::Vars(vars) => {
self.input_context.push_var_input(vars);
}
Input::Attributes => {
self.input_context.set_attributes_input();
}
Input::Authentication => self.input_context.set_authentication_input(),
}
self
}
pub fn compile(self) -> Result<Script, ScriptError> {
let result = Runtime::new()
.eval_with_context(&self.expression.expression, &self.input_context)
.map_err(ScriptError::Error)?;
match result {
Evaluation::Complete(_, v) => Ok(Script::new(None, None, Some(v), self.input_context)),
Evaluation::Partial(e) => Ok(Script::new(
self.expression.source.as_deref(),
Some(e),
None,
self.input_context,
)),
}
}
}
#[derive(Error, Debug)]
pub enum ScriptError {
#[error("Error compiling expression: {0}")]
Error(RuntimeError),
}
#[derive(Debug, Clone)]
pub struct Script {
stream_solver: StreamSolver,
evaluation: Option<PelExpression>,
result: Option<PelValue>,
context: InputContext,
}
impl Script {
pub(crate) fn new(
source: Option<&str>,
evaluation: Option<PelExpression>,
result: Option<PelValue>,
context: InputContext,
) -> Self {
Self {
stream_solver: StreamSolver::for_source(source),
evaluation,
result,
context,
}
}
pub fn evaluator(&self) -> Evaluator {
Evaluator::new(
self.stream_solver.clone(),
self.evaluation.clone(),
self.result.clone(),
&self.context,
)
}
}