Skip to main content

zen_vm/
opcodes.rs

1use std::collections::HashMap;
2use std::fmt::{Display, Formatter};
3use std::str::FromStr;
4
5use bumpalo::Bump;
6use hashbrown::hash_map::DefaultHashBuilder;
7use hashbrown::BumpWrapper;
8
9use rust_decimal::Decimal;
10use serde_json::{Map, Number, Value};
11
12#[derive(Debug)]
13pub enum Variable<'a> {
14    Null,
15    Bool(bool),
16    Int(i64),
17    Number(Decimal),
18    String(&'a str),
19    Array(&'a [&'a Variable<'a>]),
20    Object(hashbrown::HashMap<&'a str, &'a Variable<'a>, DefaultHashBuilder, BumpWrapper<'a>>),
21    Interval {
22        left_bracket: &'a str,
23        right_bracket: &'a str,
24        left: &'a Variable<'a>,
25        right: &'a Variable<'a>,
26    },
27}
28
29impl<'a> Display for Variable<'a> {
30    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31        write!(f, "{self:?}")
32    }
33}
34
35impl<'a> Clone for Variable<'a> {
36    fn clone(&self) -> Self {
37        match self {
38            Variable::Null => Variable::Null,
39            Variable::Bool(b) => Variable::Bool((*b).clone()),
40            Variable::Int(i) => Variable::Int((*i).clone()),
41            Variable::Number(n) => Variable::Number(n.clone()),
42            Variable::String(s) => Variable::String(s.clone()),
43            Variable::Array(a) => Variable::Array(a.clone()),
44            Variable::Object(o) => Variable::Object(o.clone()),
45            Variable::Interval {
46                left_bracket,
47                right_bracket,
48                left,
49                right,
50            } => Variable::Interval {
51                left_bracket: left_bracket.clone(),
52                right_bracket: right_bracket.clone(),
53                left: left.clone(),
54                right: right.clone(),
55            },
56        }
57    }
58}
59
60impl<'a> Variable<'a> {
61    pub fn empty_object_in(bump: &'a Bump) -> Self {
62        Variable::Object(hashbrown::HashMap::new_in(BumpWrapper(bump)))
63    }
64
65    pub fn from_serde(v: &Value, bump: &'a Bump) -> Self {
66        match v {
67            Value::String(str) => Variable::String(bump.alloc_str(str)),
68            Value::Number(f) => {
69                Variable::Number(Decimal::from_str_exact(f.to_string().as_str()).unwrap())
70            }
71            Value::Bool(b) => Variable::Bool((*b).clone()),
72            Value::Array(v) => {
73                let mut arr: Vec<&'a Variable> = Vec::with_capacity(v.len());
74                for i in v {
75                    arr.push(bump.alloc(Variable::from_serde(i, bump)));
76                }
77
78                Variable::Array(bump.alloc_slice_copy(arr.as_slice()))
79            }
80            Value::Object(bt) => {
81                let mut tree: hashbrown::HashMap<&'a str, &'a Variable, _, _> =
82                    hashbrown::HashMap::new_in(BumpWrapper(bump));
83                for k in bt.keys() {
84                    let v = bt.get(k).unwrap();
85                    tree.insert(
86                        bump.alloc_str(k.as_str()),
87                        bump.alloc(Variable::from_serde(v, bump)),
88                    );
89                }
90
91                Variable::Object(tree)
92            }
93            Value::Null => Variable::Null,
94        }
95    }
96}
97
98#[derive(Debug)]
99pub enum Opcode<'a> {
100    Push(Variable<'a>),
101    Pop,
102    Rot,
103    Fetch,
104    FetchField(&'a str),
105    FetchEnv(&'a str),
106    Negate,
107    Not,
108    Equal,
109    Jump(usize),
110    JumpIfTrue(usize),
111    JumpIfFalse(usize),
112    JumpIfEnd(usize),
113    JumpBackward(usize),
114    In,
115    Less,
116    More,
117    LessOrEqual,
118    MoreOrEqual,
119    Abs,
120    Average,
121    Min,
122    Max,
123    Round,
124    Floor,
125    Ceil,
126    Sum,
127    Random,
128    Add,
129    Subtract,
130    Multiply,
131    Divide,
132    Modulo,
133    Exponent,
134    Interval {
135        left_bracket: &'a str,
136        right_bracket: &'a str,
137    },
138    Contains,
139    DateManipulation(&'a str),
140    Uppercase,
141    Lowercase,
142    StartsWith,
143    EndsWith,
144    Slice,
145    Array,
146    Len,
147    ParseTime,
148    ParseDuration,
149    IncrementIt,
150    IncrementCount,
151    GetCount,
152    GetLen,
153    Pointer,
154    Begin,
155    End,
156}
157
158impl<'a> Display for Opcode<'a> {
159    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
160        write!(f, "{:?}", self)
161    }
162}
163
164#[derive(Debug, PartialEq, Clone)]
165pub enum ExecResult {
166    Null,
167    Bool(bool),
168    Number(Decimal),
169    String(String),
170    Array(Vec<ExecResult>),
171    Object(HashMap<String, ExecResult>),
172}
173
174impl TryFrom<&Variable<'_>> for ExecResult {
175    type Error = ();
176
177    fn try_from(value: &Variable) -> Result<Self, Self::Error> {
178        match value {
179            Variable::Null => Ok(ExecResult::Null),
180            Variable::Bool(b) => Ok(ExecResult::Bool((*b).clone())),
181            Variable::Number(n) => Ok(ExecResult::Number(*n)),
182            Variable::String(s) => Ok(ExecResult::String(s.to_string())),
183            Variable::Array(arr) => {
184                let mut v = Vec::<ExecResult>::with_capacity(arr.len());
185                for i in *arr {
186                    v.push(ExecResult::try_from(*i)?)
187                }
188
189                Ok(ExecResult::Array(v))
190            }
191            Variable::Object(obj) => {
192                let mut t = HashMap::new();
193
194                for k in obj.keys() {
195                    let v = *obj.get(k).ok_or_else(|| ())?;
196                    t.insert(k.to_string(), ExecResult::try_from(v)?);
197                }
198
199                Ok(ExecResult::Object(t))
200            }
201            _ => Err(()),
202        }
203    }
204}
205
206impl ExecResult {
207    pub fn to_variable<'a>(&self, bump: &'a Bump) -> Result<&'a Variable<'a>, ()> {
208        match self {
209            ExecResult::Null => Ok(bump.alloc(Variable::Null)),
210            ExecResult::Bool(b) => Ok(bump.alloc(Variable::Bool((*b).clone()))),
211            ExecResult::Number(n) => Ok(bump.alloc(Variable::Number(*n))),
212            ExecResult::String(str) => Ok(bump.alloc(Variable::String(bump.alloc_str(str)))),
213            ExecResult::Array(arr) => {
214                let mut v = Vec::<&'a Variable<'a>>::with_capacity(arr.len());
215                for i in arr {
216                    v.push(i.to_variable(bump)?)
217                }
218
219                Ok(bump.alloc(Variable::Array(bump.alloc_slice_copy(v.as_slice()))))
220            }
221            ExecResult::Object(obj) => {
222                let mut t = hashbrown::HashMap::<&'a str, _, _, _>::new_in(BumpWrapper(bump));
223
224                for k in obj.keys() {
225                    let v = obj.get(k).ok_or_else(|| ())?;
226                    t.insert(bump.alloc_str(k), v.to_variable(bump)?);
227                }
228
229                Ok(bump.alloc(Variable::Object(t)))
230            }
231        }
232    }
233
234    pub fn to_value(&self) -> Result<Value, ()> {
235        match self {
236            ExecResult::Null => Ok(Value::Null),
237            ExecResult::Bool(b) => Ok(Value::Bool((*b).clone())),
238            ExecResult::Number(n) => Ok(Value::Number(
239                Number::from_str(n.to_string().as_str()).map_err(|_| ())?,
240            )),
241            ExecResult::String(s) => Ok(Value::String(s.clone())),
242            ExecResult::Array(arr) => {
243                let mut v = Vec::<Value>::with_capacity(arr.len());
244                for i in arr {
245                    v.push(i.to_value()?)
246                }
247
248                Ok(Value::Array(v))
249            }
250            ExecResult::Object(obj) => {
251                let mut t = Map::new();
252
253                for k in obj.keys() {
254                    let v = obj.get(k).ok_or_else(|| ())?;
255                    t.insert(k.to_string(), v.to_value()?);
256                }
257
258                Ok(Value::Object(t))
259            }
260        }
261    }
262
263    pub fn bool(&self) -> Result<bool, ()> {
264        match self {
265            ExecResult::Bool(b) => Ok((*b).clone()),
266            _ => Err(()),
267        }
268    }
269}