zen_expression/
expression.rs1use 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#[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}