1use crate::compiler::{Compare, FetchFastTarget, Jump, Opcode};
2use crate::functions::arguments::Arguments;
3use crate::functions::registry::FunctionRegistry;
4use crate::functions::{internal, MethodRegistry};
5use crate::variable::Variable;
6use crate::variable::Variable::*;
7use crate::vm::error::VMError::*;
8use crate::vm::error::VMResult;
9use crate::vm::interval::{VmInterval, VmIntervalData};
10use ahash::{HashMap, HashMapExt};
11use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
12use rust_decimal::{Decimal, MathematicalOps};
13use std::rc::Rc;
14use std::string::String as StdString;
15
16#[derive(Debug)]
17pub struct Scope {
18 array: Variable,
19 len: usize,
20 iter: usize,
21 count: usize,
22}
23
24#[derive(Debug)]
25pub struct VM {
26 scopes: Vec<Scope>,
27 stack: Vec<Variable>,
28}
29
30impl VM {
31 pub fn new() -> Self {
32 Self {
33 scopes: Default::default(),
34 stack: Default::default(),
35 }
36 }
37
38 pub fn run(&mut self, bytecode: &[Opcode], env: Variable) -> VMResult<Variable> {
39 self.stack.clear();
40 self.scopes.clear();
41
42 let s = VMInner::new(bytecode, &mut self.stack, &mut self.scopes).run(env);
43 Ok(s?)
44 }
45}
46
47struct VMInner<'parent_ref, 'bytecode_ref> {
48 scopes: &'parent_ref mut Vec<Scope>,
49 stack: &'parent_ref mut Vec<Variable>,
50 bytecode: &'bytecode_ref [Opcode],
51 ip: u32,
52}
53
54impl<'arena, 'parent_ref, 'bytecode_ref> VMInner<'parent_ref, 'bytecode_ref> {
55 pub fn new(
56 bytecode: &'bytecode_ref [Opcode],
57 stack: &'parent_ref mut Vec<Variable>,
58 scopes: &'parent_ref mut Vec<Scope>,
59 ) -> Self {
60 Self {
61 ip: 0,
62 scopes,
63 stack,
64 bytecode,
65 }
66 }
67
68 fn push(&mut self, var: Variable) {
69 self.stack.push(var);
70 }
71
72 fn pop(&mut self) -> VMResult<Variable> {
73 self.stack.pop().ok_or_else(|| StackOutOfBounds {
74 stack: format!("{:?}", self.stack),
75 })
76 }
77
78 pub fn run(&mut self, env: Variable) -> VMResult<Variable> {
79 if self.ip != 0 {
80 self.ip = 0;
81 }
82
83 while self.ip < self.bytecode.len() as u32 {
84 let op = self
85 .bytecode
86 .get(self.ip as usize)
87 .ok_or_else(|| OpcodeOutOfBounds {
88 bytecode: format!("{:?}", self.bytecode),
89 index: self.ip as usize,
90 })?;
91
92 self.ip += 1;
93
94 match op {
95 Opcode::PushNull => self.push(Null),
96 Opcode::PushBool(b) => self.push(Bool(*b)),
97 Opcode::PushNumber(n) => self.push(Number(*n)),
98 Opcode::PushString(s) => self.push(String(Rc::from(s.as_ref()))),
99 Opcode::Pop => {
100 self.pop()?;
101 }
102 Opcode::Fetch => {
103 let b = self.pop()?;
104 let a = self.pop()?;
105
106 match (a, b) {
107 (Object(o), String(s)) => {
108 let obj = o.borrow();
109 self.push(obj.get(s.as_ref()).cloned().unwrap_or(Null));
110 }
111 (Array(a), Number(n)) => {
112 let arr = a.borrow();
113 self.push(
114 arr.get(n.to_usize().ok_or_else(|| OpcodeErr {
115 opcode: "Fetch".into(),
116 message: "Failed to convert to usize".into(),
117 })?)
118 .cloned()
119 .unwrap_or(Null),
120 )
121 }
122 (String(str), Number(n)) => {
123 let index = n.to_usize().ok_or_else(|| OpcodeErr {
124 opcode: "Fetch".into(),
125 message: "Failed to convert to usize".into(),
126 })?;
127
128 if let Some(slice) = str.get(index..index + 1) {
129 self.push(String(Rc::from(slice)));
130 } else {
131 self.push(Null)
132 };
133 }
134 _ => self.push(Null),
135 }
136 }
137 Opcode::FetchFast(path) => {
138 let variable = path.iter().fold(Null, |v, p| match p {
139 FetchFastTarget::Root => env.clone(),
140 FetchFastTarget::String(key) => match v {
141 Object(obj) => {
142 let obj_ref = obj.borrow();
143 obj_ref.get(key.as_ref()).cloned().unwrap_or(Null)
144 }
145 _ => Null,
146 },
147 FetchFastTarget::Number(num) => match v {
148 Array(arr) => {
149 let arr_ref = arr.borrow();
150 arr_ref.get(*num as usize).cloned().unwrap_or(Null)
151 }
152 _ => Null,
153 },
154 });
155
156 self.push(variable);
157 }
158 Opcode::FetchEnv(f) => match &env {
159 Object(o) => {
160 let obj = o.borrow();
161 match obj.get(f.as_ref()) {
162 None => self.push(Null),
163 Some(v) => self.push(v.clone()),
164 }
165 }
166 Null => self.push(Null),
167 _ => {
168 return Err(OpcodeErr {
169 opcode: "FetchEnv".into(),
170 message: "Unsupported type".into(),
171 });
172 }
173 },
174 Opcode::FetchRootEnv => {
175 self.push(env.clone());
176 }
177 Opcode::Negate => {
178 let a = self.pop()?;
179 match a {
180 Number(n) => {
181 self.push(Number(-n));
182 }
183 _ => {
184 return Err(OpcodeErr {
185 opcode: "Negate".into(),
186 message: "Unsupported type".into(),
187 });
188 }
189 }
190 }
191 Opcode::Not => {
192 let a = self.pop()?;
193 match a {
194 Bool(b) => self.push(Bool(!b)),
195 _ => {
196 return Err(OpcodeErr {
197 opcode: "Not".into(),
198 message: "Unsupported type".into(),
199 });
200 }
201 }
202 }
203 Opcode::Equal => {
204 let b = self.pop()?;
205 let a = self.pop()?;
206 match (a, b) {
207 (Number(a), Number(b)) => {
208 self.push(Bool(a == b));
209 }
210 (Bool(a), Bool(b)) => {
211 self.push(Bool(a == b));
212 }
213 (String(a), String(b)) => {
214 self.push(Bool(a == b));
215 }
216 (Null, Null) => {
217 self.push(Bool(true));
218 }
219 (Dynamic(a), Dynamic(b)) => {
220 let a = a.as_date();
221 let b = b.as_date();
222
223 self.push(Bool(a.is_some() && b.is_some() && a == b));
224 }
225 _ => {
226 self.push(Bool(false));
227 }
228 }
229 }
230 Opcode::Jump(kind, j) => match kind {
231 Jump::Forward => self.ip += j,
232 Jump::Backward => self.ip -= j,
233 Jump::IfTrue => {
234 let a = self.stack.last().ok_or_else(|| OpcodeErr {
235 opcode: "JumpIfTrue".into(),
236 message: "Undefined object key".into(),
237 })?;
238 match a {
239 Bool(a) => {
240 if *a {
241 self.ip += j;
242 }
243 }
244 _ => {
245 return Err(OpcodeErr {
246 opcode: "JumpIfTrue".into(),
247 message: "Unsupported type".into(),
248 });
249 }
250 }
251 }
252 Jump::IfFalse => {
253 let a = self.stack.last().ok_or_else(|| OpcodeErr {
254 opcode: "JumpIfFalse".into(),
255 message: "Empty array".into(),
256 })?;
257
258 match a {
259 Bool(a) => {
260 if !*a {
261 self.ip += j;
262 }
263 }
264 _ => {
265 return Err(OpcodeErr {
266 opcode: "JumpIfFalse".into(),
267 message: "Unsupported type".into(),
268 });
269 }
270 }
271 }
272 Jump::IfNotNull => {
273 let a = self.stack.last().ok_or_else(|| OpcodeErr {
274 opcode: "JumpIfNull".into(),
275 message: "Empty array".into(),
276 })?;
277
278 match a {
279 Null => {}
280 _ => {
281 self.ip += j;
282 }
283 }
284 }
285 Jump::IfEnd => {
286 let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
287 opcode: "JumpIfEnd".into(),
288 message: "Empty stack".into(),
289 })?;
290
291 if scope.iter >= scope.len {
292 self.ip += j;
293 }
294 }
295 },
296 Opcode::In => {
297 let b = self.pop()?;
298 let a = self.pop()?;
299
300 match (a, &b) {
301 (Number(a), Array(b)) => {
302 let arr = b.borrow();
303 let is_in = arr.iter().any(|b| match b {
304 Number(b) => a == *b,
305 _ => false,
306 });
307
308 self.push(Bool(is_in));
309 }
310 (Number(v), Dynamic(d)) => {
311 let Some(i) = d.as_any().downcast_ref::<VmInterval>() else {
312 return Err(OpcodeErr {
313 opcode: "In".into(),
314 message: "Unsupported type".into(),
315 });
316 };
317
318 self.push(Bool(i.includes(VmIntervalData::Number(v)).map_err(
319 |err| OpcodeErr {
320 opcode: "In".into(),
321 message: err.to_string(),
322 },
323 )?));
324 }
325 (Dynamic(d), Dynamic(i)) => {
326 let Some(d) = d.as_date() else {
327 return Err(OpcodeErr {
328 opcode: "In".into(),
329 message: "Unsupported type".into(),
330 });
331 };
332
333 let Some(i) = i.as_any().downcast_ref::<VmInterval>() else {
334 return Err(OpcodeErr {
335 opcode: "In".into(),
336 message: "Unsupported type".into(),
337 });
338 };
339
340 self.push(Bool(i.includes(VmIntervalData::Date(d.clone())).map_err(
341 |err| OpcodeErr {
342 opcode: "In".into(),
343 message: err.to_string(),
344 },
345 )?));
346 }
347 (Dynamic(a), Array(arr)) => {
348 let Some(a) = a.as_date() else {
349 return Err(OpcodeErr {
350 opcode: "In".into(),
351 message: "Unsupported type".into(),
352 });
353 };
354
355 let arr = arr.borrow();
356 let is_in = arr.iter().any(|b| match b {
357 Dynamic(b) => Some(a) == b.as_date(),
358 _ => false,
359 });
360
361 self.push(Bool(is_in));
362 }
363 (String(a), Array(b)) => {
364 let arr = b.borrow();
365 let is_in = arr.iter().any(|b| match b {
366 String(b) => &a == b,
367 _ => false,
368 });
369
370 self.push(Bool(is_in));
371 }
372 (String(a), Object(b)) => {
373 let obj = b.borrow();
374 self.push(Bool(obj.contains_key(a.as_ref())));
375 }
376 (Bool(a), Array(b)) => {
377 let arr = b.borrow();
378 let is_in = arr.iter().any(|b| match b {
379 Bool(b) => a == *b,
380 _ => false,
381 });
382
383 self.push(Bool(is_in));
384 }
385 (Null, Array(b)) => {
386 let arr = b.borrow();
387 let is_in = arr.iter().any(|b| match b {
388 Null => true,
389 _ => false,
390 });
391
392 self.push(Bool(is_in));
393 }
394 _ => {
395 return Err(OpcodeErr {
396 opcode: "In".into(),
397 message: "Unsupported type".into(),
398 });
399 }
400 }
401 }
402 Opcode::Compare(comparison) => {
403 let b = self.pop()?;
404 let a = self.pop()?;
405
406 fn compare<T: Ord>(a: &T, b: &T, comparison: &Compare) -> bool {
407 match comparison {
408 Compare::More => a > b,
409 Compare::MoreOrEqual => a >= b,
410 Compare::Less => a < b,
411 Compare::LessOrEqual => a <= b,
412 }
413 }
414
415 match (a, b) {
416 (Number(a), Number(b)) => self.push(Bool(compare(&a, &b, comparison))),
417 (Dynamic(a), Dynamic(b)) => {
418 let (a, b) = match (a.as_date(), b.as_date()) {
419 (Some(a), Some(b)) => (a, b),
420 _ => {
421 return Err(OpcodeErr {
422 opcode: "Compare".into(),
423 message: "Unsupported type".into(),
424 })
425 }
426 };
427
428 self.push(Bool(compare(a, b, comparison)));
429 }
430 _ => {
431 return Err(OpcodeErr {
432 opcode: "Compare".into(),
433 message: "Unsupported type".into(),
434 });
435 }
436 }
437 }
438 Opcode::Add => {
439 let b = self.pop()?;
440 let a = self.pop()?;
441
442 match (a, b) {
443 (Number(a), Number(b)) => self.push(Number(a + b)),
444 (String(a), String(b)) => {
445 let mut c = StdString::with_capacity(a.len() + b.len());
446
447 c.push_str(a.as_ref());
448 c.push_str(b.as_ref());
449
450 self.push(String(Rc::from(c.as_str())));
451 }
452 _ => {
453 return Err(OpcodeErr {
454 opcode: "Add".into(),
455 message: "Unsupported type".into(),
456 });
457 }
458 }
459 }
460 Opcode::Subtract => {
461 let b = self.pop()?;
462 let a = self.pop()?;
463
464 match (a, b) {
465 (Number(a), Number(b)) => self.push(Number(a - b)),
466 _ => {
467 return Err(OpcodeErr {
468 opcode: "Subtract".into(),
469 message: "Unsupported type".into(),
470 });
471 }
472 }
473 }
474 Opcode::Multiply => {
475 let b = self.pop()?;
476 let a = self.pop()?;
477
478 match (a, b) {
479 (Number(a), Number(b)) => self.push(Number(a * b)),
480 _ => {
481 return Err(OpcodeErr {
482 opcode: "Multiply".into(),
483 message: "Unsupported type".into(),
484 });
485 }
486 }
487 }
488 Opcode::Divide => {
489 let b = self.pop()?;
490 let a = self.pop()?;
491
492 match (a, b) {
493 (Number(a), Number(b)) => self.push(Number(a / b)),
494 _ => {
495 return Err(OpcodeErr {
496 opcode: "Divide".into(),
497 message: "Unsupported type".into(),
498 });
499 }
500 }
501 }
502 Opcode::Modulo => {
503 let b = self.pop()?;
504 let a = self.pop()?;
505
506 match (a, b) {
507 (Number(a), Number(b)) => self.push(Number(a % b)),
508 _ => {
509 return Err(OpcodeErr {
510 opcode: "Modulo".into(),
511 message: "Unsupported type".into(),
512 });
513 }
514 }
515 }
516 Opcode::Exponent => {
517 let b = self.pop()?;
518 let a = self.pop()?;
519
520 match (a, b) {
521 (Number(a), Number(b)) => {
522 let result = a
523 .checked_powd(b)
524 .or_else(|| Decimal::from_f64(a.to_f64()?.powf(b.to_f64()?)))
525 .ok_or_else(|| OpcodeErr {
526 opcode: "Exponent".into(),
527 message: "Failed to calculate exponent".into(),
528 })?;
529
530 self.push(Number(result));
531 }
532 _ => {
533 return Err(OpcodeErr {
534 opcode: "Exponent".into(),
535 message: "Unsupported type".into(),
536 });
537 }
538 }
539 }
540 Opcode::Interval {
541 left_bracket,
542 right_bracket,
543 } => {
544 let b = self.pop()?;
545 let a = self.pop()?;
546
547 match (&a, &b) {
548 (Number(a), Number(b)) => {
549 let interval = VmInterval {
550 left_bracket: *left_bracket,
551 right_bracket: *right_bracket,
552 left: VmIntervalData::Number(*a),
553 right: VmIntervalData::Number(*b),
554 };
555
556 self.push(Dynamic(Rc::new(interval)));
557 }
558 (Dynamic(a), Dynamic(b)) => {
559 let (a, b) = match (a.as_date(), b.as_date()) {
560 (Some(a), Some(b)) => (a, b),
561 _ => {
562 return Err(OpcodeErr {
563 opcode: "Interval".into(),
564 message: "Unsupported type".into(),
565 })
566 }
567 };
568
569 let interval = VmInterval {
570 left_bracket: *left_bracket,
571 right_bracket: *right_bracket,
572 left: VmIntervalData::Date(a.clone()),
573 right: VmIntervalData::Date(b.clone()),
574 };
575
576 self.push(Dynamic(Rc::new(interval)));
577 }
578 _ => {
579 return Err(OpcodeErr {
580 opcode: "Interval".into(),
581 message: "Unsupported type".into(),
582 });
583 }
584 }
585 }
586 Opcode::Join => {
587 let b = self.pop()?;
588 let a = self.pop()?;
589
590 let (Array(a), String(separator)) = (a, &b) else {
591 return Err(OpcodeErr {
592 opcode: "Join".into(),
593 message: "Unsupported type".into(),
594 });
595 };
596
597 let arr = a.borrow();
598 let parts = arr
599 .iter()
600 .enumerate()
601 .map(|(i, var)| match var {
602 String(str) => Ok(str.clone()),
603 _ => Err(OpcodeErr {
604 opcode: "Join".into(),
605 message: format!("Unexpected type in array on index {i}"),
606 }),
607 })
608 .collect::<Result<Vec<_>, _>>()?;
609
610 let str_capacity = parts
611 .iter()
612 .fold(separator.len() * (parts.len() - 1), |acc, s| acc + s.len());
613
614 let mut s = StdString::with_capacity(str_capacity);
615 let mut it = parts.into_iter().peekable();
616 while let Some(part) = it.next() {
617 s.push_str(part.as_ref());
618 if it.peek().is_some() {
619 s.push_str(separator);
620 }
621 }
622
623 self.push(String(Rc::from(s)));
624 }
625 Opcode::Slice => {
626 let from_var = self.pop()?;
627 let to_var = self.pop()?;
628 let current = self.pop()?;
629
630 match (from_var, to_var) {
631 (Number(f), Number(t)) => {
632 let from = f.to_usize().ok_or_else(|| OpcodeErr {
633 opcode: "Slice".into(),
634 message: "Failed to get range from".into(),
635 })?;
636 let to = t.to_usize().ok_or_else(|| OpcodeErr {
637 opcode: "Slice".into(),
638 message: "Failed to get range to".into(),
639 })?;
640
641 match current {
642 Array(a) => {
643 let arr = a.borrow();
644 let slice = arr.get(from..=to).ok_or_else(|| OpcodeErr {
645 opcode: "Slice".into(),
646 message: "Index out of range".into(),
647 })?;
648
649 self.push(Variable::from_array(slice.to_vec()));
650 }
651 String(s) => {
652 let slice = s.get(from..=to).ok_or_else(|| OpcodeErr {
653 opcode: "Slice".into(),
654 message: "Index out of range".into(),
655 })?;
656
657 self.push(String(Rc::from(slice)));
658 }
659 _ => {
660 return Err(OpcodeErr {
661 opcode: "Slice".into(),
662 message: "Unsupported type".into(),
663 });
664 }
665 }
666 }
667 _ => {
668 return Err(OpcodeErr {
669 opcode: "Slice".into(),
670 message: "Unsupported type".into(),
671 });
672 }
673 }
674 }
675 Opcode::Array => {
676 let size = self.pop()?;
677 let Number(s) = size else {
678 return Err(OpcodeErr {
679 opcode: "Array".into(),
680 message: "Unsupported type".into(),
681 });
682 };
683
684 let to = s.round().to_usize().ok_or_else(|| OpcodeErr {
685 opcode: "Array".into(),
686 message: "Failed to extract argument".into(),
687 })?;
688
689 let mut arr = Vec::with_capacity(to);
690 for _ in 0..to {
691 arr.push(self.pop()?);
692 }
693 arr.reverse();
694
695 self.push(Variable::from_array(arr));
696 }
697 Opcode::Object => {
698 let size = self.pop()?;
699 let Number(s) = size else {
700 return Err(OpcodeErr {
701 opcode: "Array".into(),
702 message: "Unsupported type".into(),
703 });
704 };
705
706 let to = s.round().to_usize().ok_or_else(|| OpcodeErr {
707 opcode: "Array".into(),
708 message: "Failed to extract argument".into(),
709 })?;
710
711 let mut map = HashMap::with_capacity(to);
712 for _ in 0..to {
713 let value = self.pop()?;
714 let String(key) = self.pop()? else {
715 return Err(OpcodeErr {
716 opcode: "Object".into(),
717 message: "Unexpected key value".to_string(),
718 });
719 };
720
721 map.insert(key.clone(), value);
722 }
723
724 self.push(Variable::from_object(map));
725 }
726 Opcode::Len => {
727 let current = self.stack.last().ok_or_else(|| OpcodeErr {
728 opcode: "Len".into(),
729 message: "Empty stack".into(),
730 })?;
731
732 let len_var =
733 internal::imp::len(Arguments(&[current.clone()])).map_err(|err| {
734 OpcodeErr {
735 opcode: "Len".into(),
736 message: err.to_string(),
737 }
738 })?;
739
740 self.push(len_var);
741 }
742 Opcode::Flatten => {
743 let current = self.pop()?;
744 let Array(a) = current else {
745 return Err(OpcodeErr {
746 opcode: "Flatten".into(),
747 message: "Unsupported type".into(),
748 });
749 };
750
751 let arr = a.borrow();
752
753 let mut flat_arr = Vec::with_capacity(arr.len());
754 arr.iter().for_each(|v| match v {
755 Array(b) => {
756 let arr = b.borrow();
757 arr.iter().for_each(|v| flat_arr.push(v.clone()))
758 }
759 _ => flat_arr.push(v.clone()),
760 });
761
762 self.push(Variable::from_array(flat_arr));
763 }
764 Opcode::IncrementIt => {
765 let scope = self.scopes.last_mut().ok_or_else(|| OpcodeErr {
766 opcode: "IncrementIt".into(),
767 message: "Empty scope".into(),
768 })?;
769
770 scope.iter += 1;
771 }
772 Opcode::IncrementCount => {
773 let scope = self.scopes.last_mut().ok_or_else(|| OpcodeErr {
774 opcode: "IncrementCount".into(),
775 message: "Empty scope".into(),
776 })?;
777
778 scope.count += 1;
779 }
780 Opcode::GetCount => {
781 let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
782 opcode: "GetCount".into(),
783 message: "Empty scope".into(),
784 })?;
785
786 self.push(Number(scope.count.into()));
787 }
788 Opcode::GetLen => {
789 let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
790 opcode: "GetLen".into(),
791 message: "Empty scope".into(),
792 })?;
793
794 self.push(Number(scope.len.into()));
795 }
796 Opcode::Pointer => {
797 let scope = self.scopes.last().ok_or_else(|| OpcodeErr {
798 opcode: "Pointer".into(),
799 message: "Empty scope".into(),
800 })?;
801
802 match &scope.array {
803 Array(a) => {
804 let a_cloned = a.clone();
805 let arr = a_cloned.borrow();
806 let variable =
807 arr.get(scope.iter).cloned().ok_or_else(|| OpcodeErr {
808 opcode: "Pointer".into(),
809 message: "Scope array out of bounds".into(),
810 })?;
811
812 self.push(variable);
813 }
814 _ => {
815 return Err(OpcodeErr {
816 opcode: "Pointer".into(),
817 message: "Unsupported scope type".into(),
818 });
819 }
820 }
821 }
822 Opcode::Begin => {
823 let var = self.pop()?;
824 let maybe_scope = match &var {
825 Array(a) => {
826 let arr = a.borrow();
827 Some(Scope {
828 len: arr.len(),
829 array: var.clone(),
830 count: 0,
831 iter: 0,
832 })
833 }
834 _ => match var.dynamic::<VmInterval>().map(|s| s.to_array()).flatten() {
835 None => None,
836 Some(arr) => Some(Scope {
837 len: arr.len(),
838 array: Variable::from_array(arr),
839 count: 0,
840 iter: 0,
841 }),
842 },
843 };
844
845 let Some(scope) = maybe_scope else {
846 return Err(OpcodeErr {
847 opcode: "Begin".into(),
848 message: "Unsupported type".into(),
849 });
850 };
851
852 self.scopes.push(scope);
853 }
854 Opcode::End => {
855 self.scopes.pop();
856 }
857 Opcode::CallFunction { kind, arg_count } => {
858 let function =
859 FunctionRegistry::get_definition(kind).ok_or_else(|| OpcodeErr {
860 opcode: "CallFunction".into(),
861 message: format!("Function `{kind}` not found"),
862 })?;
863
864 let params_start = self.stack.len().saturating_sub(*arg_count as usize);
865 let result = function
866 .call(Arguments(&self.stack[params_start..]))
867 .map_err(|err| OpcodeErr {
868 opcode: "CallFunction".into(),
869 message: format!("Function `{kind}` failed: {err}"),
870 })?;
871
872 self.stack.drain(params_start..);
873 self.push(result);
874 }
875 Opcode::CallMethod { kind, arg_count } => {
876 let method = MethodRegistry::get_definition(kind).ok_or_else(|| OpcodeErr {
877 opcode: "CallMethod".into(),
878 message: format!("Method `{kind}` not found"),
879 })?;
880
881 let params_start = self.stack.len().saturating_sub(*arg_count as usize) - 1;
882 let result = method
883 .call(Arguments(&self.stack[params_start..]))
884 .map_err(|err| OpcodeErr {
885 opcode: "CallMethod".into(),
886 message: format!("Method `{kind}` failed: {err}"),
887 })?;
888
889 self.stack.drain(params_start..);
890 self.push(result);
891 }
892 }
893 }
894
895 self.pop()
896 }
897}