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