Skip to main content

zen_vm/
vm.rs

1use bumpalo::Bump;
2use chrono::Datelike;
3use chrono::NaiveDateTime;
4use rust_decimal::prelude::ToPrimitive;
5use rust_decimal::{Decimal, MathematicalOps};
6use thiserror::Error;
7
8use crate::helpers::date_time;
9use crate::opcodes::Variable::{Array, Bool, Int, Interval, Null, Number, Object, String};
10use crate::opcodes::{Opcode, Variable};
11use crate::vm::VMError::{OpcodeErr, OpcodeOutOfBounds, ParseTimeErr, StackOutOfBounds};
12
13#[derive(Debug, Error)]
14pub enum VMError {
15    #[error("Unsupported opcode type")]
16    OpcodeErr {
17        opcode: std::string::String,
18        message: std::string::String,
19    },
20
21    #[error("Opcode out of bounds")]
22    OpcodeOutOfBounds {
23        index: usize,
24        bytecode: std::string::String,
25    },
26
27    #[error("Stack out of bounds")]
28    StackOutOfBounds { stack: std::string::String },
29
30    #[error("Failed to parse time")]
31    ParseTimeErr { timestamp: std::string::String },
32}
33
34pub struct Scope<'a> {
35    array: &'a Variable<'a>,
36    len: usize,
37    iter: usize,
38    count: usize,
39}
40
41pub struct VM<'a> {
42    scopes: &'a mut Vec<Scope<'a>>,
43    stack: &'a mut Vec<&'a Variable<'a>>,
44    ip: usize,
45    bytecode: &'a Vec<&'a Opcode<'a>>,
46    bump: &'a Bump,
47}
48
49impl<'a> VM<'a> {
50    pub fn new(
51        bytecode: &'a Vec<&'a Opcode<'a>>,
52        stack: &'a mut Vec<&'a Variable<'a>>,
53        scopes: &'a mut Vec<Scope<'a>>,
54        bump: &'a Bump,
55    ) -> Self {
56        Self {
57            scopes,
58            stack,
59            ip: 0,
60            bytecode,
61            bump,
62        }
63    }
64
65    fn push(&mut self, var: Variable<'a>) {
66        self.stack.push(self.bump.alloc(var));
67    }
68
69    fn pop(&mut self) -> Result<&'a Variable<'a>, VMError> {
70        self.stack.pop().ok_or_else(|| StackOutOfBounds {
71            stack: format!("{:?}", self.stack),
72        })
73    }
74
75    fn push_ref(&mut self, var: &'a Variable<'a>) {
76        self.stack.push(var);
77    }
78
79    pub fn run(&mut self, env: &'a Variable<'a>) -> Result<&'a Variable<'a>, VMError> {
80        if self.ip != 0 {
81            self.ip = 0;
82        }
83
84        while self.ip < self.bytecode.len() {
85            let op = self
86                .bytecode
87                .get(self.ip)
88                .ok_or_else(|| OpcodeOutOfBounds {
89                    bytecode: format!("{:?}", self.bytecode),
90                    index: self.ip,
91                })?;
92
93            self.ip += 1;
94
95            match op {
96                Opcode::Push(v) => match v {
97                    Int(a) => self.push(Number(Decimal::from(*a))),
98                    _ => self.push_ref(v),
99                },
100                Opcode::Pop => {
101                    self.pop()?;
102                }
103                Opcode::Rot => {
104                    let b = self.stack.len() - 1;
105                    let a = self.stack.len() - 2;
106                    self.stack.swap(a, b);
107                }
108                Opcode::Fetch => {
109                    let b = self.pop()?;
110                    let a = self.pop()?;
111
112                    match (a, b) {
113                        (Object(o), String(s)) => {
114                            self.push_ref(o.get(*s).ok_or_else(|| OpcodeErr {
115                                opcode: "Fetch".into(),
116                                message: "Undefined object key".into(),
117                            })?);
118                        }
119                        (Array(arr), Number(n)) => self.push_ref(
120                            arr.get(n.to_usize().ok_or_else(|| OpcodeErr {
121                                opcode: "Fetch".into(),
122                                message: "Failed to convert to usize".into(),
123                            })?)
124                            .ok_or_else(|| OpcodeErr {
125                                opcode: "Fetch".into(),
126                                message: "Undefined array index".into(),
127                            })?,
128                        ),
129                        _ => {
130                            return Err(OpcodeErr {
131                                opcode: "Fetch".into(),
132                                message: "Unsupported types".into(),
133                            })
134                        }
135                    }
136                }
137                Opcode::FetchField(f) => {
138                    let a = self.pop()?;
139                    match a {
140                        Object(o) => {
141                            self.push_ref(o.get(*f).ok_or_else(|| OpcodeErr {
142                                opcode: "FetchField".into(),
143                                message: "Undefined object key".into(),
144                            })?);
145                        }
146                        _ => {
147                            return Err(OpcodeErr {
148                                opcode: "FetchField".into(),
149                                message: "Unsupported type".into(),
150                            })
151                        }
152                    }
153                }
154                Opcode::FetchEnv(f) => match env {
155                    Object(o) => {
156                        self.push_ref(o.get(*f).ok_or_else(|| OpcodeErr {
157                            opcode: "FetchEnv".into(),
158                            message: "Undefined object key".into(),
159                        })?);
160                    }
161                    Null => self.push(Null),
162                    _ => {
163                        return Err(OpcodeErr {
164                            opcode: "FetchEnv".into(),
165                            message: "Unsupported type".into(),
166                        })
167                    }
168                },
169                Opcode::Negate => {
170                    let a = self.pop()?;
171                    match a {
172                        Number(n) => {
173                            self.stack.push(self.bump.alloc(Number(-*n)));
174                        }
175                        _ => {
176                            return Err(OpcodeErr {
177                                opcode: "Negate".into(),
178                                message: "Unsupported type".into(),
179                            })
180                        }
181                    }
182                }
183                Opcode::Not => {
184                    let a = self.pop()?;
185                    match a {
186                        Bool(b) => self.stack.push(self.bump.alloc(Bool(!(*b)))),
187                        _ => {
188                            return Err(OpcodeErr {
189                                opcode: "Not".into(),
190                                message: "Unsupported type".into(),
191                            })
192                        }
193                    }
194                }
195                Opcode::Equal => {
196                    let b = self.pop()?;
197                    let a = self.pop()?;
198                    match (a, b) {
199                        (Number(a), Number(b)) => {
200                            self.stack.push(self.bump.alloc(Bool(a == b)));
201                        }
202                        (Bool(a), Bool(b)) => {
203                            self.stack.push(self.bump.alloc(Bool(a == b)));
204                        }
205                        (String(a), String(b)) => {
206                            self.stack.push(self.bump.alloc(Bool(a == b)));
207                        }
208                        (Null, Null) => {
209                            self.stack.push(self.bump.alloc(Bool(true)));
210                        }
211                        _ => {
212                            return Err(OpcodeErr {
213                                opcode: "Equal".into(),
214                                message: "Unsupported type".into(),
215                            })
216                        }
217                    }
218                }
219                Opcode::Jump(j) => self.ip += j,
220                Opcode::JumpIfTrue(j) => {
221                    let a = self.stack.last().ok_or_else(|| OpcodeErr {
222                        opcode: "JumpIfTrue".into(),
223                        message: "Undefined object key".into(),
224                    })?;
225                    match a {
226                        Bool(a) => {
227                            if *a {
228                                self.ip += j;
229                            }
230                        }
231                        _ => {
232                            return Err(OpcodeErr {
233                                opcode: "JumpIfTrue".into(),
234                                message: "Unsupported type".into(),
235                            })
236                        }
237                    }
238                }
239                Opcode::JumpIfFalse(j) => {
240                    let a = self.stack.last().ok_or_else(|| OpcodeErr {
241                        opcode: "JumpIfFalse".into(),
242                        message: "Empty array".into(),
243                    })?;
244
245                    match a {
246                        Bool(a) => {
247                            if !*a {
248                                self.ip += j;
249                            }
250                        }
251                        _ => {
252                            return Err(OpcodeErr {
253                                opcode: "JumpIfFalse".into(),
254                                message: "Unsupported type".into(),
255                            })
256                        }
257                    }
258                }
259                Opcode::JumpBackward(j) => {
260                    self.ip -= j;
261                }
262                Opcode::In => {
263                    let b = self.pop()?;
264                    let a = self.pop()?;
265
266                    match (a, b) {
267                        (Number(a), Array(arr)) => {
268                            let is_in = arr.iter().any(|b| match b {
269                                Number(b) => a == b,
270                                _ => false,
271                            });
272
273                            self.stack.push(self.bump.alloc(Bool(is_in)));
274                        }
275                        (
276                            Number(v),
277                            Interval {
278                                left_bracket,
279                                right_bracket,
280                                left,
281                                right,
282                            },
283                        ) => match (left, right) {
284                            (Number(l), Number(r)) => {
285                                let mut is_open = false;
286
287                                let first = match *left_bracket {
288                                    "[" => l <= v,
289                                    "(" => l < v,
290                                    "]" => {
291                                        is_open = true;
292                                        l >= v
293                                    }
294                                    ")" => {
295                                        is_open = true;
296                                        l > v
297                                    }
298                                    _ => {
299                                        return Err(OpcodeErr {
300                                            opcode: "In".into(),
301                                            message: "Unsupported bracket".into(),
302                                        })
303                                    }
304                                };
305
306                                let second = match *right_bracket {
307                                    "]" => r >= v,
308                                    ")" => r > v,
309                                    "[" => r <= v,
310                                    "(" => r < v,
311                                    _ => {
312                                        return Err(OpcodeErr {
313                                            opcode: "In".into(),
314                                            message: "Unsupported bracket".into(),
315                                        })
316                                    }
317                                };
318
319                                let open_stmt = is_open && (first || second);
320                                let closed_stmt = !is_open && first && second;
321
322                                self.stack
323                                    .push(self.bump.alloc(Bool(open_stmt || closed_stmt)));
324                            }
325                            _ => {
326                                return Err(OpcodeErr {
327                                    opcode: "In".into(),
328                                    message: "Unsupported type".into(),
329                                })
330                            }
331                        },
332                        (String(a), Array(arr)) => {
333                            let is_in = arr.iter().any(|b| match b {
334                                String(b) => a == b,
335                                _ => false,
336                            });
337
338                            self.stack.push(self.bump.alloc(Bool(is_in)));
339                        }
340                        (Bool(a), Array(arr)) => {
341                            let is_in = arr.iter().any(|b| match b {
342                                Bool(b) => a == b,
343                                _ => false,
344                            });
345
346                            self.stack.push(self.bump.alloc(Bool(is_in)));
347                        }
348                        _ => {
349                            return Err(OpcodeErr {
350                                opcode: "In".into(),
351                                message: "Unsupported type".into(),
352                            })
353                        }
354                    }
355                }
356                Opcode::Less => {
357                    let b = self.pop()?;
358                    let a = self.pop()?;
359
360                    match (a, b) {
361                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Bool(*a < *b))),
362                        _ => {
363                            return Err(OpcodeErr {
364                                opcode: "Less".into(),
365                                message: "Unsupported type".into(),
366                            })
367                        }
368                    }
369                }
370                Opcode::More => {
371                    let b = self.pop()?;
372                    let a = self.pop()?;
373
374                    match (a, b) {
375                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Bool(*a > *b))),
376                        _ => {
377                            return Err(OpcodeErr {
378                                opcode: "More".into(),
379                                message: "Unsupported type".into(),
380                            })
381                        }
382                    }
383                }
384                Opcode::LessOrEqual => {
385                    let b = self.pop()?;
386                    let a = self.pop()?;
387
388                    match (a, b) {
389                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Bool(*a <= *b))),
390                        _ => {
391                            return Err(OpcodeErr {
392                                opcode: "LessOrEqual".into(),
393                                message: "Unsupported type".into(),
394                            })
395                        }
396                    }
397                }
398                Opcode::MoreOrEqual => {
399                    let b = self.pop()?;
400                    let a = self.pop()?;
401
402                    match (a, b) {
403                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Bool(*a >= *b))),
404                        _ => {
405                            return Err(OpcodeErr {
406                                opcode: "MoreOrEqual".into(),
407                                message: "Unsupported type".into(),
408                            })
409                        }
410                    }
411                }
412                Opcode::Abs => {
413                    let a = self.pop()?;
414
415                    match a {
416                        Number(a) => self.stack.push(self.bump.alloc(Number(a.abs()))),
417                        _ => {
418                            return Err(OpcodeErr {
419                                opcode: "Abs".into(),
420                                message: "Unsupported type".into(),
421                            })
422                        }
423                    }
424                }
425                Opcode::Round => {
426                    let var = self.pop()?;
427
428                    match var {
429                        Number(a) => self.stack.push(self.bump.alloc(Number(a.round()))),
430                        _ => {
431                            return Err(OpcodeErr {
432                                opcode: "Round".into(),
433                                message: "Unsupported type".into(),
434                            })
435                        }
436                    }
437                }
438                Opcode::Ceil => {
439                    let var = self.pop()?;
440
441                    match var {
442                        Number(a) => self.stack.push(self.bump.alloc(Number(a.round()))),
443                        _ => {
444                            return Err(OpcodeErr {
445                                opcode: "Ceil".into(),
446                                message: "Unsupported type".into(),
447                            })
448                        }
449                    }
450                }
451                Opcode::Floor => {
452                    let var = self.pop()?;
453
454                    match var {
455                        Number(a) => self.stack.push(self.bump.alloc(Number(a.floor()))),
456                        _ => {
457                            return Err(OpcodeErr {
458                                opcode: "Floor".into(),
459                                message: "Unsupported type".into(),
460                            })
461                        }
462                    }
463                }
464                Opcode::Random => {
465                    let var = self.pop()?;
466                    match var {
467                        Number(a) => {
468                            let upper_range = a.round().to_i64().ok_or_else(|| OpcodeErr {
469                                opcode: "Random".into(),
470                                message: "Failed to determine upper range".into(),
471                            })?;
472
473                            let random_number = fastrand::i64(0..=upper_range);
474                            self.stack
475                                .push(self.bump.alloc(Number(Decimal::from(random_number))));
476                        }
477                        _ => {
478                            return Err(OpcodeErr {
479                                opcode: "Random".into(),
480                                message: "Unsupported type".into(),
481                            })
482                        }
483                    }
484                }
485                Opcode::Average => {
486                    let var = self.pop()?;
487
488                    match var {
489                        Array(arr) => {
490                            let mut sum = Decimal::ZERO;
491                            arr.iter().try_for_each(|a| match a {
492                                Number(a) => {
493                                    sum += a;
494                                    Ok(())
495                                }
496                                _ => Err(OpcodeErr {
497                                    opcode: "Average".into(),
498                                    message: "Invalid array value".into(),
499                                }),
500                            })?;
501
502                            let avg = sum / Decimal::from(arr.len());
503                            self.stack.push(self.bump.alloc(Number(avg)));
504                        }
505                        _ => {
506                            return Err(OpcodeErr {
507                                opcode: "Average".into(),
508                                message: "Unsupported type".into(),
509                            })
510                        }
511                    }
512                }
513                Opcode::Min => {
514                    let var = self.pop()?;
515
516                    match var {
517                        Array(arr) => {
518                            let first_item = arr.get(0).ok_or_else(|| OpcodeErr {
519                                opcode: "Min".into(),
520                                message: "Empty array".into(),
521                            })?;
522
523                            let mut min: Decimal = match first_item {
524                                Number(a) => *a,
525                                _ => {
526                                    return Err(OpcodeErr {
527                                        opcode: "Min".into(),
528                                        message: "Unsupported array value".into(),
529                                    })
530                                }
531                            };
532
533                            arr.iter().try_for_each(|a| match a {
534                                Number(a) => {
535                                    if *a < min {
536                                        min = *a;
537                                    }
538                                    Ok(())
539                                }
540                                _ => Err(OpcodeErr {
541                                    opcode: "Min".into(),
542                                    message: "Unsupported array value".into(),
543                                }),
544                            })?;
545
546                            self.stack.push(self.bump.alloc(Number(min)));
547                        }
548                        _ => {
549                            return Err(OpcodeErr {
550                                opcode: "Min".into(),
551                                message: "Unsupported type".into(),
552                            })
553                        }
554                    }
555                }
556                Opcode::Max => {
557                    let var = self.pop()?;
558
559                    match var {
560                        Array(arr) => {
561                            let first_item = arr.get(0).ok_or_else(|| OpcodeErr {
562                                opcode: "Max".into(),
563                                message: "Empty array".into(),
564                            })?;
565
566                            let mut max: Decimal = match first_item {
567                                Number(a) => *a,
568                                _ => {
569                                    return Err(OpcodeErr {
570                                        opcode: "Max".into(),
571                                        message: "Unsupported array value".into(),
572                                    })
573                                }
574                            };
575
576                            arr.iter().try_for_each(|a| match a {
577                                Number(a) => {
578                                    if *a > max {
579                                        max = *a;
580                                    }
581                                    Ok(())
582                                }
583                                _ => Err(OpcodeErr {
584                                    opcode: "Max".into(),
585                                    message: "Unsupported array value".into(),
586                                }),
587                            })?;
588
589                            self.stack.push(self.bump.alloc(Number(max)));
590                        }
591                        _ => {
592                            return Err(OpcodeErr {
593                                opcode: "Max".into(),
594                                message: "Unsupported type".into(),
595                            })
596                        }
597                    }
598                }
599                Opcode::Sum => {
600                    let var = self.pop()?;
601
602                    match var {
603                        Array(arr) => {
604                            let mut sum = Decimal::ZERO;
605                            arr.iter().try_for_each(|a| match a {
606                                Number(a) => {
607                                    sum += a;
608                                    Ok(())
609                                }
610                                _ => Err(OpcodeErr {
611                                    opcode: "Sum".into(),
612                                    message: "Unsupported array value".into(),
613                                }),
614                            })?;
615
616                            self.stack.push(self.bump.alloc(Number(sum)));
617                        }
618                        _ => {
619                            return Err(OpcodeErr {
620                                opcode: "Sum".into(),
621                                message: "Unsupported type".into(),
622                            })
623                        }
624                    }
625                }
626                Opcode::Add => {
627                    let b = self.pop()?;
628                    let a = self.pop()?;
629
630                    match (a, b) {
631                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Number(a + b))),
632                        (String(a), String(b)) => {
633                            let mut str1 = std::string::String::with_capacity(a.len() + b.len());
634                            str1.push_str(a);
635                            str1.push_str(b);
636
637                            self.stack
638                                .push(self.bump.alloc(String(self.bump.alloc_str(&str1))))
639                        }
640                        _ => {
641                            return Err(OpcodeErr {
642                                opcode: "Add".into(),
643                                message: "Unsupported type".into(),
644                            })
645                        }
646                    }
647                }
648                Opcode::Subtract => {
649                    let b = self.pop()?;
650                    let a = self.pop()?;
651
652                    match (a, b) {
653                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Number(a - b))),
654                        _ => {
655                            return Err(OpcodeErr {
656                                opcode: "Subtract".into(),
657                                message: "Unsupported type".into(),
658                            })
659                        }
660                    }
661                }
662                Opcode::Multiply => {
663                    let b = self.pop()?;
664                    let a = self.pop()?;
665
666                    match (a, b) {
667                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Number(a * b))),
668                        _ => {
669                            return Err(OpcodeErr {
670                                opcode: "Multiply".into(),
671                                message: "Unsupported type".into(),
672                            })
673                        }
674                    }
675                }
676                Opcode::Divide => {
677                    let b = self.pop()?;
678                    let a = self.pop()?;
679
680                    match (a, b) {
681                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Number(a / b))),
682                        _ => {
683                            return Err(OpcodeErr {
684                                opcode: "Divide".into(),
685                                message: "Unsupported type".into(),
686                            })
687                        }
688                    }
689                }
690                Opcode::Modulo => {
691                    let b = self.pop()?;
692                    let a = self.pop()?;
693
694                    match (a, b) {
695                        (Number(a), Number(b)) => self.stack.push(self.bump.alloc(Number(a % b))),
696                        _ => {
697                            return Err(OpcodeErr {
698                                opcode: "Modulo".into(),
699                                message: "Unsupported type".into(),
700                            })
701                        }
702                    }
703                }
704                Opcode::Exponent => {
705                    let b = self.pop()?;
706                    let a = self.pop()?;
707
708                    match (a, b) {
709                        (Number(a), Number(b)) => {
710                            self.stack.push(self.bump.alloc(Number(a.powd(*b))))
711                        }
712                        _ => {
713                            return Err(OpcodeErr {
714                                opcode: "Exponent".into(),
715                                message: "Unsupported type".into(),
716                            })
717                        }
718                    }
719                }
720                Opcode::Interval {
721                    left_bracket,
722                    right_bracket,
723                } => {
724                    let b = self.pop()?;
725                    let a = self.pop()?;
726
727                    match (a, b) {
728                        (Number(_), Number(_)) => self.stack.push(self.bump.alloc(Interval {
729                            left_bracket,
730                            right_bracket,
731                            left: a,
732                            right: b,
733                        })),
734                        _ => {
735                            return Err(OpcodeErr {
736                                opcode: "Interval".into(),
737                                message: "Unsupported type".into(),
738                            })
739                        }
740                    }
741                }
742                Opcode::Uppercase => {
743                    let a = self.pop()?;
744
745                    match a {
746                        String(a) => {
747                            let str = a.to_uppercase();
748                            self.stack
749                                .push(self.bump.alloc(String(self.bump.alloc_str(&str))))
750                        }
751                        _ => {
752                            return Err(OpcodeErr {
753                                opcode: "Uppercase".into(),
754                                message: "Unsupported type".into(),
755                            })
756                        }
757                    }
758                }
759                Opcode::Lowercase => {
760                    let a = self.pop()?;
761
762                    match a {
763                        String(a) => {
764                            let str = a.to_lowercase();
765                            self.stack
766                                .push(self.bump.alloc(String(self.bump.alloc_str(&str))))
767                        }
768                        _ => {
769                            return Err(OpcodeErr {
770                                opcode: "Lowercase".into(),
771                                message: "Unsupported type".into(),
772                            })
773                        }
774                    }
775                }
776                Opcode::Contains => {
777                    let b = self.pop()?;
778                    let a = self.pop()?;
779
780                    match (a, b) {
781                        (String(a), String(b)) => {
782                            self.stack.push(self.bump.alloc(Bool(a.contains(b))))
783                        }
784                        _ => match a {
785                            Array(arr) => {
786                                let is_in = arr.iter().any(|a| match (a, b) {
787                                    (Number(a), Number(b)) => a == b,
788                                    (String(a), String(b)) => a == b,
789                                    (Bool(a), Bool(b)) => a == b,
790                                    _ => false,
791                                });
792
793                                self.stack.push(self.bump.alloc(Bool(is_in)));
794                            }
795                            _ => {
796                                return Err(OpcodeErr {
797                                    opcode: "Contains".into(),
798                                    message: "Unsupported type".into(),
799                                })
800                            }
801                        },
802                    }
803                }
804                Opcode::StartsWith => {
805                    let b = self.pop()?;
806                    let a = self.pop()?;
807
808                    match (a, b) {
809                        (String(a), String(b)) => {
810                            self.stack.push(self.bump.alloc(Bool(a.starts_with(b))))
811                        }
812                        _ => {
813                            return Err(OpcodeErr {
814                                opcode: "StartsWith".into(),
815                                message: "Unsupported type".into(),
816                            })
817                        }
818                    }
819                }
820                Opcode::EndsWith => {
821                    let b = self.pop()?;
822                    let a = self.pop()?;
823
824                    match (a, b) {
825                        (String(a), String(b)) => {
826                            self.stack.push(self.bump.alloc(Bool(a.ends_with(b))))
827                        }
828                        _ => {
829                            return Err(OpcodeErr {
830                                opcode: "EndsWith".into(),
831                                message: "Unsupported type".into(),
832                            })
833                        }
834                    }
835                }
836                Opcode::DateManipulation(operation) => {
837                    let timestamp = self.pop()?;
838
839                    let time = match timestamp {
840                        String(a) => date_time(a)?,
841                        Number(a) => NaiveDateTime::from_timestamp_opt(
842                            a.to_i64().ok_or_else(|| OpcodeErr {
843                                opcode: "DateManipulation".into(),
844                                message: "Failed to extract date".into(),
845                            })?,
846                            0,
847                        )
848                        .ok_or_else(|| ParseTimeErr {
849                            timestamp: a.to_string(),
850                        })?,
851                        _ => {
852                            return Err(OpcodeErr {
853                                opcode: "DateManipulation".into(),
854                                message: "Unsupported type".into(),
855                            })
856                        }
857                    };
858
859                    let var = match *operation {
860                        "dayOfWeek" => Number(time.weekday().number_from_monday().into()),
861                        "dayOfMonth" => Number(time.day().into()),
862                        "dayOfYear" => Number(time.ordinal().into()),
863                        "weekOfYear" => Number(time.iso_week().week().into()),
864                        "monthOfYear" => Number(time.month().into()),
865                        "monthString" => {
866                            String(self.bump.alloc_str(&time.format("%b").to_string()))
867                        }
868                        "weekdayString" => String(self.bump.alloc_str(&time.weekday().to_string())),
869                        _ => {
870                            return Err(OpcodeErr {
871                                opcode: "DateManipulation".into(),
872                                message: "Unsupported operation".into(),
873                            })
874                        }
875                    };
876
877                    self.stack.push(self.bump.alloc(var));
878                }
879                Opcode::Slice => {
880                    let from_var = self.pop()?;
881                    let to_var = self.pop()?;
882                    let slice = self.pop()?;
883
884                    match (from_var, to_var) {
885                        (Number(f), Number(t)) => {
886                            let from = f.to_usize().ok_or_else(|| OpcodeErr {
887                                opcode: "Slice".into(),
888                                message: "Failed to get range from".into(),
889                            })?;
890                            let to = t.to_usize().ok_or_else(|| OpcodeErr {
891                                opcode: "Slice".into(),
892                                message: "Failed to get range to".into(),
893                            })?;
894
895                            match slice {
896                                Array(arr) => {
897                                    self.stack.push(self.bump.alloc(Array(&arr[from..=to])))
898                                }
899                                String(s) => {
900                                    self.stack.push(self.bump.alloc(String(&s[from..=to])))
901                                }
902                                _ => {
903                                    return Err(OpcodeErr {
904                                        opcode: "Slice".into(),
905                                        message: "Unsupported type".into(),
906                                    })
907                                }
908                            }
909                        }
910                        _ => {
911                            return Err(OpcodeErr {
912                                opcode: "Slice".into(),
913                                message: "Unsupported type".into(),
914                            })
915                        }
916                    }
917                }
918                Opcode::Array => {
919                    let size = self.pop()?;
920                    let mut arr = Vec::new();
921
922                    match size {
923                        Number(s) => {
924                            let to = s.round().to_usize().ok_or_else(|| OpcodeErr {
925                                opcode: "Array".into(),
926                                message: "Failed to extract argument".into(),
927                            })?;
928
929                            for _ in 0..to {
930                                arr.push(self.pop()?);
931                            }
932                        }
933                        _ => {
934                            return Err(OpcodeErr {
935                                opcode: "Array".into(),
936                                message: "Unsupported type".into(),
937                            })
938                        }
939                    }
940
941                    arr.reverse();
942
943                    self.stack.push(
944                        self.bump
945                            .alloc(Array(self.bump.alloc_slice_copy(arr.as_slice()))),
946                    );
947                }
948                Opcode::Len => {
949                    let current = self.stack.last().ok_or_else(|| OpcodeErr {
950                        opcode: "Len".into(),
951                        message: "Empty stack".into(),
952                    })?;
953
954                    let len = match current {
955                        String(s) => s.len(),
956                        Array(s) => s.len(),
957                        _ => {
958                            return Err(OpcodeErr {
959                                opcode: "Len".into(),
960                                message: "Unsupported type".into(),
961                            })
962                        }
963                    };
964
965                    self.stack.push(self.bump.alloc(Number(len.into())))
966                }
967                Opcode::ParseTime => {
968                    let a = self.pop()?;
969                    let ts = match a {
970                        String(a) => date_time(a)?.timestamp(),
971                        _ => {
972                            return Err(OpcodeErr {
973                                opcode: "ParseTime".into(),
974                                message: "Unsupported type".into(),
975                            })
976                        }
977                    };
978
979                    self.stack.push(self.bump.alloc(Number(ts.into())))
980                }
981                Opcode::ParseDuration => {
982                    let a = self.pop()?;
983
984                    let dur = match a {
985                        String(a) => humantime::parse_duration(a)
986                            .map_err(|_| ParseTimeErr {
987                                timestamp: a.to_string(),
988                            })?
989                            .as_secs(),
990                        _ => {
991                            return Err(OpcodeErr {
992                                opcode: "ParseDuration".into(),
993                                message: "Unsupported type".into(),
994                            })
995                        }
996                    };
997
998                    self.stack.push(self.bump.alloc(Number(dur.into())));
999                }
1000                Opcode::JumpIfEnd(j) => {
1001                    let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
1002                        opcode: "JumpIfEnd".into(),
1003                        message: "Empty stack".into(),
1004                    })?;
1005
1006                    if scope.iter >= scope.len {
1007                        self.ip += j;
1008                    }
1009                }
1010                Opcode::IncrementIt => {
1011                    let scope = self.scopes.last_mut().ok_or_else(|| OpcodeErr {
1012                        opcode: "IncrementIt".into(),
1013                        message: "Empty scope".into(),
1014                    })?;
1015
1016                    scope.iter += 1;
1017                }
1018                Opcode::IncrementCount => {
1019                    let scope = self.scopes.last_mut().ok_or_else(|| OpcodeErr {
1020                        opcode: "IncrementCount".into(),
1021                        message: "Empty scope".into(),
1022                    })?;
1023
1024                    scope.count += 1;
1025                }
1026                Opcode::GetCount => {
1027                    let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
1028                        opcode: "GetCount".into(),
1029                        message: "Empty scope".into(),
1030                    })?;
1031
1032                    self.push(Number(scope.count.into()));
1033                }
1034                Opcode::GetLen => {
1035                    let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
1036                        opcode: "GetLen".into(),
1037                        message: "Empty scope".into(),
1038                    })?;
1039
1040                    self.push(Number(scope.len.into()));
1041                }
1042                Opcode::Pointer => {
1043                    let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
1044                        opcode: "Pointer".into(),
1045                        message: "Empty scope".into(),
1046                    })?;
1047
1048                    match scope.array {
1049                        Array(arr) => {
1050                            let variable = *arr.get(scope.iter).ok_or_else(|| OpcodeErr {
1051                                opcode: "Pointer".into(),
1052                                message: "Scope array out of bounds".into(),
1053                            })?;
1054
1055                            self.push_ref(variable);
1056                        }
1057                        _ => {
1058                            return Err(OpcodeErr {
1059                                opcode: "Pointer".into(),
1060                                message: "Unsupported scope type".into(),
1061                            })
1062                        }
1063                    }
1064                }
1065                Opcode::Begin => {
1066                    let a = self.pop()?;
1067                    match a {
1068                        Array(arr) => self.scopes.push(Scope {
1069                            array: a,
1070                            count: 0,
1071                            len: arr.len(),
1072                            iter: 0,
1073                        }),
1074                        _ => {
1075                            return Err(OpcodeErr {
1076                                opcode: "Begin".into(),
1077                                message: "Unsupported type".into(),
1078                            })
1079                        }
1080                    }
1081                }
1082                Opcode::End => self.scopes.clear(),
1083            }
1084        }
1085
1086        self.pop()
1087    }
1088}