mf_expression/
expression.rs

1use 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)]
14pub enum ExpressionKind {
15    Standard,
16    Unary,
17}
18
19/// Compiled expression
20#[derive(Debug, Clone)]
21pub struct Expression<Kind> {
22    bytecode: Arc<Vec<Opcode>>,
23    _marker: PhantomData<Kind>,
24}
25
26impl<Kind> Expression<Kind> {
27    pub fn bytecode(&self) -> &Arc<Vec<Opcode>> {
28        &self.bytecode
29    }
30}
31
32impl Expression<Standard> {
33    pub fn new_standard(bytecode: Arc<Vec<Opcode>>) -> Self {
34        Expression { bytecode, _marker: PhantomData }
35    }
36
37    pub fn kind(&self) -> ExpressionKind {
38        ExpressionKind::Standard
39    }
40
41    pub fn evaluate(
42        &self,
43        context: Variable,
44    ) -> Result<Variable, IsolateError> {
45        let mut vm = VM::new();
46        self.evaluate_with(context, &mut vm)
47    }
48
49    pub fn evaluate_with(
50        &self,
51        context: Variable,
52        vm: &mut VM,
53    ) -> Result<Variable, IsolateError> {
54        let output = vm.run(self.bytecode.as_slice(), context)?;
55        Ok(output)
56    }
57}
58
59impl Expression<Unary> {
60    pub fn new_unary(bytecode: Arc<Vec<Opcode>>) -> Self {
61        Expression { bytecode, _marker: PhantomData }
62    }
63
64    pub fn kind(&self) -> ExpressionKind {
65        ExpressionKind::Unary
66    }
67
68    pub fn evaluate(
69        &self,
70        context: Variable,
71    ) -> Result<bool, IsolateError> {
72        let mut vm = VM::new();
73        self.evaluate_with(context, &mut vm)
74    }
75
76    pub fn evaluate_with(
77        &self,
78        context: Variable,
79        vm: &mut VM,
80    ) -> Result<bool, IsolateError> {
81        let Some(context_object_ref) = context.as_object() else {
82            return Err(IsolateError::MissingContextReference);
83        };
84
85        let context_object = context_object_ref.borrow();
86        if !context_object.contains_key("$") {
87            return Err(IsolateError::MissingContextReference);
88        }
89
90        let output = vm
91            .run(self.bytecode.as_slice(), context)?
92            .as_bool()
93            .ok_or_else(|| IsolateError::ValueCastError)?;
94        Ok(output)
95    }
96}