Skip to main content

zen_expression/
isolate.rs

1use ahash::HashMap;
2use serde::ser::SerializeMap;
3use serde::{Serialize, Serializer};
4use std::rc::Rc;
5use std::sync::Arc;
6use thiserror::Error;
7
8use crate::arena::UnsafeArena;
9use crate::compiler::{Compiler, CompilerError, Opcode};
10use crate::expression::{OpcodeCache, Standard, Unary};
11use crate::lexer::{Lexer, LexerError};
12use crate::parser::{Parser, ParserError};
13use crate::variable::Variable;
14use crate::vm::{VMError, VM};
15use crate::{Expression, ExpressionKind};
16
17/// Isolate is a component that encapsulates an isolated environment for executing expressions.
18///
19/// Rerunning the Isolate allows for efficient memory reuse through an arena allocator.
20/// The arena allocator optimizes memory management by reusing memory blocks for subsequent evaluations,
21/// contributing to improved performance and resource utilization in scenarios where the Isolate is reused multiple times.
22#[derive(Debug)]
23pub struct Isolate<'arena> {
24    lexer: Lexer<'arena>,
25    compiler: Compiler,
26    vm: VM,
27
28    bump: UnsafeArena<'arena>,
29
30    environment: Option<Variable>,
31    references: HashMap<String, Variable>,
32    cache: Option<Arc<OpcodeCache>>,
33}
34
35impl<'a> Isolate<'a> {
36    pub fn new() -> Self {
37        Self {
38            lexer: Lexer::new(),
39            compiler: Compiler::new(),
40            vm: VM::new(),
41
42            bump: UnsafeArena::new(),
43
44            environment: None,
45            references: Default::default(),
46            cache: None,
47        }
48    }
49
50    pub fn with_environment(variable: Variable) -> Self {
51        let mut isolate = Isolate::new();
52        isolate.set_environment(variable);
53
54        isolate
55    }
56
57    pub fn with_cache(mut self, cache: Option<Arc<OpcodeCache>>) -> Self {
58        self.cache = cache;
59        self
60    }
61
62    pub fn set_environment(&mut self, variable: Variable) {
63        self.environment.replace(variable);
64    }
65
66    pub fn set_cache(&mut self, cache: Arc<OpcodeCache>) {
67        self.cache = Some(cache);
68    }
69
70    pub fn update_environment<F>(&mut self, mut updater: F)
71    where
72        F: FnMut(Option<&mut Variable>),
73    {
74        updater(self.environment.as_mut());
75    }
76
77    pub fn set_reference(&mut self, reference: &'a str) -> Result<(), IsolateError> {
78        let reference_value = match self.references.get(reference) {
79            Some(value) => value.clone(),
80            None => {
81                let result = self.run_standard(reference)?;
82                self.references
83                    .insert(reference.to_string(), result.clone());
84                result
85            }
86        };
87
88        if !matches!(&mut self.environment, Some(Variable::Object(_))) {
89            self.environment.replace(Variable::empty_object());
90        }
91
92        let Some(Variable::Object(environment_object_ref)) = &self.environment else {
93            return Err(IsolateError::ReferenceError);
94        };
95
96        let mut environment_object = environment_object_ref.borrow_mut();
97        environment_object.insert(Rc::from("$"), reference_value);
98
99        Ok(())
100    }
101
102    pub fn get_reference(&self, reference: &str) -> Option<Variable> {
103        self.references.get(reference).cloned()
104    }
105
106    pub fn clear_references(&mut self) {
107        self.references.clear();
108    }
109
110    fn run_internal(&mut self, source: &'a str, kind: ExpressionKind) -> Result<(), IsolateError> {
111        self.bump.with_mut(|b| b.reset());
112        let bump = self.bump.get();
113
114        let tokens = self.lexer.tokenize(source)?;
115
116        let base_parser = Parser::try_new(tokens, bump)?;
117        let parser_result = match kind {
118            ExpressionKind::Unary => base_parser.unary().parse(),
119            ExpressionKind::Standard => base_parser.standard().parse(),
120        };
121
122        parser_result.error()?;
123
124        self.compiler.compile(parser_result.root)?;
125
126        Ok(())
127    }
128
129    pub fn compile_standard(
130        &mut self,
131        source: &'a str,
132    ) -> Result<Expression<Standard>, IsolateError> {
133        self.run_internal(source, ExpressionKind::Standard)?;
134        let bytecode = self.compiler.get_bytecode().to_vec();
135
136        Ok(Expression::new_standard(Arc::from(bytecode)))
137    }
138
139    pub fn run_standard(&mut self, source: &'a str) -> Result<Variable, IsolateError> {
140        let cached = self
141            .cache
142            .as_ref()
143            .and_then(|c| c.standard.get(source).cloned());
144        if let Some(codes) = cached {
145            return self.run_compiled(codes.as_ref());
146        }
147
148        self.run_internal(source, ExpressionKind::Standard)?;
149
150        let bytecode = self.compiler.get_bytecode();
151        let result = self
152            .vm
153            .run(bytecode, self.environment.clone().unwrap_or(Variable::Null))?;
154
155        Ok(result)
156    }
157    pub fn run_compiled(&mut self, source: &[Opcode]) -> Result<Variable, IsolateError> {
158        let result = self
159            .vm
160            .run(source, self.environment.clone().unwrap_or(Variable::Null))?;
161
162        Ok(result)
163    }
164
165    pub fn compile_unary(&mut self, source: &'a str) -> Result<Expression<Unary>, IsolateError> {
166        self.run_internal(source, ExpressionKind::Unary)?;
167        let bytecode = self.compiler.get_bytecode().to_vec();
168
169        Ok(Expression::new_unary(Arc::from(bytecode)))
170    }
171
172    pub fn run_unary(&mut self, source: &'a str) -> Result<bool, IsolateError> {
173        let cached = self
174            .cache
175            .as_ref()
176            .and_then(|c| c.unary.get(source).cloned());
177        if let Some(codes) = cached {
178            return self.run_unary_compiled(codes.as_ref());
179        }
180
181        self.run_internal(source, ExpressionKind::Unary)?;
182
183        let bytecode = self.compiler.get_bytecode();
184        let result = self
185            .vm
186            .run(bytecode, self.environment.clone().unwrap_or(Variable::Null))?;
187
188        result.as_bool().ok_or_else(|| IsolateError::ValueCastError)
189    }
190
191    pub fn run_unary_compiled(&mut self, code: &[Opcode]) -> Result<bool, IsolateError> {
192        let result = self
193            .vm
194            .run(code, self.environment.clone().unwrap_or(Variable::Null))?;
195
196        result.as_bool().ok_or_else(|| IsolateError::ValueCastError)
197    }
198}
199
200/// Errors which happen within isolate or during evaluation
201#[derive(Debug, Error)]
202pub enum IsolateError {
203    #[error("Lexer error: {source}")]
204    LexerError { source: LexerError },
205
206    #[error("Parser error: {source}")]
207    ParserError { source: ParserError },
208
209    #[error("Compiler error: {source}")]
210    CompilerError { source: CompilerError },
211
212    #[error("VM error: {source}")]
213    VMError { source: VMError },
214
215    #[error("Value cast error")]
216    ValueCastError,
217
218    #[error("Failed to compute reference")]
219    ReferenceError,
220
221    #[error("Missing context reference")]
222    MissingContextReference,
223}
224
225impl Serialize for IsolateError {
226    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
227    where
228        S: Serializer,
229    {
230        let mut map = serializer.serialize_map(None)?;
231
232        match &self {
233            IsolateError::ReferenceError => {
234                map.serialize_entry("type", "referenceError")?;
235            }
236            IsolateError::MissingContextReference => {
237                map.serialize_entry("type", "missingContextReference")?;
238            }
239            IsolateError::ValueCastError => {
240                map.serialize_entry("type", "valueCastError")?;
241            }
242            IsolateError::LexerError { source } => {
243                map.serialize_entry("type", "lexerError")?;
244                map.serialize_entry("source", source.to_string().as_str())?;
245            }
246            IsolateError::ParserError { source } => {
247                map.serialize_entry("type", "parserError")?;
248                map.serialize_entry("source", source.to_string().as_str())?;
249            }
250            IsolateError::CompilerError { source } => {
251                map.serialize_entry("type", "compilerError")?;
252                map.serialize_entry("source", source.to_string().as_str())?;
253            }
254            IsolateError::VMError { source } => {
255                map.serialize_entry("type", "vmError")?;
256                map.serialize_entry("source", source.to_string().as_str())?;
257            }
258        }
259
260        map.end()
261    }
262}
263
264impl From<LexerError> for IsolateError {
265    fn from(source: LexerError) -> Self {
266        IsolateError::LexerError { source }
267    }
268}
269
270impl From<ParserError> for IsolateError {
271    fn from(source: ParserError) -> Self {
272        IsolateError::ParserError { source }
273    }
274}
275
276impl From<VMError> for IsolateError {
277    fn from(source: VMError) -> Self {
278        IsolateError::VMError { source }
279    }
280}
281
282impl From<CompilerError> for IsolateError {
283    fn from(source: CompilerError) -> Self {
284        IsolateError::CompilerError { source }
285    }
286}