Files
zen/core/expression/src/expression.rs
T
stefan-gorules ae40aff163 feat: compiled bytecode (#307)
* feat: compiled bytecode

* optimize bytecode

* add compiled expression struct

* add fetch fast and better abstraction

* fix

* rename evaluate_with for Expression<Unary>
2025-02-10 10:07:24 +01:00

89 lines
2.2 KiB
Rust

use crate::compiler::Opcode;
use crate::vm::VM;
use crate::{IsolateError, Variable};
use std::marker::PhantomData;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct Standard;
#[derive(Debug, Clone)]
pub struct Unary;
#[derive(Debug, Clone)]
pub enum ExpressionKind {
Standard,
Unary,
}
/// Compiled expression
#[derive(Debug, Clone)]
pub struct Expression<Kind> {
bytecode: Arc<Vec<Opcode>>,
_marker: PhantomData<Kind>,
}
impl<Kind> Expression<Kind> {
pub fn bytecode(&self) -> &Arc<Vec<Opcode>> {
&self.bytecode
}
}
impl Expression<Standard> {
pub fn new_standard(bytecode: Arc<Vec<Opcode>>) -> Self {
Expression {
bytecode,
_marker: PhantomData,
}
}
pub fn kind(&self) -> ExpressionKind {
ExpressionKind::Standard
}
pub fn evaluate(&self, context: Variable) -> Result<Variable, IsolateError> {
let mut vm = VM::new();
self.evaluate_with(context, &mut vm)
}
pub fn evaluate_with(&self, context: Variable, vm: &mut VM) -> Result<Variable, IsolateError> {
let output = vm.run(self.bytecode.as_slice(), context)?;
Ok(output)
}
}
impl Expression<Unary> {
pub fn new_unary(bytecode: Arc<Vec<Opcode>>) -> Self {
Expression {
bytecode,
_marker: PhantomData,
}
}
pub fn kind(&self) -> ExpressionKind {
ExpressionKind::Unary
}
pub fn evaluate(&self, context: Variable) -> Result<bool, IsolateError> {
let mut vm = VM::new();
self.evaluate_with(context, &mut vm)
}
pub fn evaluate_with(&self, context: Variable, vm: &mut VM) -> Result<bool, IsolateError> {
let Some(context_object_ref) = context.as_object() else {
return Err(IsolateError::MissingContextReference);
};
let context_object = context_object_ref.borrow();
if !context_object.contains_key("$") {
return Err(IsolateError::MissingContextReference);
}
let output = vm
.run(self.bytecode.as_slice(), context)?
.as_bool()
.ok_or_else(|| IsolateError::ValueCastError)?;
Ok(output)
}
}