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}