Skip to main content

zen_expression/
expression.rs

1use crate::compiler::Opcode;
2use crate::scope::Scope;
3use crate::vm::VM;
4use crate::{IsolateError, Variable};
5use std::marker::PhantomData;
6use std::sync::Arc;
7
8#[derive(Debug, Clone)]
9pub struct Standard;
10
11#[derive(Debug, Clone)]
12pub struct Unary;
13
14#[derive(Debug, Clone, Eq, PartialEq, Hash)]
15pub enum ExpressionKind {
16    Standard,
17    Unary,
18}
19
20#[derive(Clone, Debug, Eq, PartialEq)]
21pub struct OpcodeCache {
22    pub standard: ahash::HashMap<Arc<str>, Arc<[Opcode]>>,
23    pub unary: ahash::HashMap<Arc<str>, Arc<[Opcode]>>,
24}
25
26impl OpcodeCache {
27    pub fn new() -> Self {
28        Self {
29            standard: Default::default(),
30            unary: Default::default(),
31        }
32    }
33}
34
35/// Compiled expression
36#[derive(Debug, Clone)]
37pub struct Expression<Kind> {
38    bytecode: Arc<[Opcode]>,
39    _marker: PhantomData<Kind>,
40}
41
42impl<Kind> Expression<Kind> {
43    pub fn bytecode(&self) -> &Arc<[Opcode]> {
44        &self.bytecode
45    }
46}
47
48impl Expression<Standard> {
49    pub fn new_standard(bytecode: Arc<[Opcode]>) -> Self {
50        Expression {
51            bytecode,
52            _marker: PhantomData,
53        }
54    }
55
56    pub fn kind(&self) -> ExpressionKind {
57        ExpressionKind::Standard
58    }
59
60    pub fn evaluate(&self, context: Variable) -> Result<Variable, IsolateError> {
61        let mut vm = VM::new();
62        self.evaluate_with(context, &mut vm)
63    }
64
65    pub fn evaluate_with(&self, context: Variable, vm: &mut VM) -> Result<Variable, IsolateError> {
66        self.evaluate_with_scope(&Scope::new(context), vm)
67    }
68
69    pub fn evaluate_with_scope(
70        &self,
71        scope: &Scope,
72        vm: &mut VM,
73    ) -> Result<Variable, IsolateError> {
74        let output = vm.run(self.bytecode.as_ref(), scope)?;
75        Ok(output)
76    }
77}
78
79impl Expression<Unary> {
80    pub fn new_unary(bytecode: Arc<[Opcode]>) -> Self {
81        Expression {
82            bytecode,
83            _marker: PhantomData,
84        }
85    }
86
87    pub fn kind(&self) -> ExpressionKind {
88        ExpressionKind::Unary
89    }
90
91    pub fn evaluate(&self, context: Variable) -> Result<bool, IsolateError> {
92        let mut vm = VM::new();
93        self.evaluate_with(context, &mut vm)
94    }
95
96    pub fn evaluate_with(&self, context: Variable, vm: &mut VM) -> Result<bool, IsolateError> {
97        self.evaluate_with_scope(&Scope::new(context), vm)
98    }
99
100    pub fn evaluate_with_scope(&self, scope: &Scope, vm: &mut VM) -> Result<bool, IsolateError> {
101        if scope.get(&Variable::dollar_key()).is_none() {
102            return Err(IsolateError::MissingContextReference);
103        }
104
105        let output = vm
106            .run(self.bytecode.as_ref(), scope)?
107            .as_bool()
108            .ok_or_else(|| IsolateError::ValueCastError)?;
109        Ok(output)
110    }
111}