zen_expression/
isolate.rs

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