rsjsonnet-lang 0.5.0

A Jsonnet evaluation library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
use super::super::{
    BuiltInFunc, FuncData, FuncKind, FuncParams, ThunkData, ThunkEnv, ThunkEnvData, ir,
};
use super::{EvalErrorKind, EvalResult, Evaluator, State, TraceItem};
use crate::gc::{Gc, GcView};
use crate::interner::InternedStr;
use crate::span::SpanId;

impl<'p> Evaluator<'_, 'p> {
    #[inline]
    pub(super) fn get_func_info(
        &self,
        func: &FuncData<'p>,
    ) -> (Option<InternedStr<'p>>, Option<Gc<ThunkEnv<'p>>>) {
        match func.kind {
            FuncKind::Identity { name } => (name, None),
            FuncKind::Normal { name, ref env, .. } => (name, Some(env.clone())),
            FuncKind::BuiltIn { name, .. } => (Some(name), None),
            FuncKind::Native { .. } => (None, None),
        }
    }

    pub(super) fn check_call_expr_args(
        &self,
        params: &FuncParams<'p>,
        positional_args: &[&'p ir::Expr<'p>],
        named_args: &[(InternedStr<'p>, SpanId, &'p ir::Expr<'p>)],
        call_env: GcView<ThunkEnv<'p>>,
        func_env: Option<Gc<ThunkEnv<'p>>>,
        call_span: SpanId,
    ) -> EvalResult<Box<[Gc<ThunkData<'p>>]>> {
        self.check_call_args_generic(
            params,
            positional_args,
            |this, expr| {
                this.program
                    .new_pending_expr_thunk(expr, Gc::from(&call_env), None)
            },
            named_args,
            |&(name, _, _)| name,
            |(_, name_span, _)| Some(*name_span),
            |this, (_, _, expr)| {
                this.program
                    .new_pending_expr_thunk(expr, Gc::from(&call_env), None)
            },
            func_env,
            Some(call_span),
        )
    }

    fn check_call_thunk_args(
        &self,
        params: &FuncParams<'p>,
        positional_args: &[GcView<ThunkData<'p>>],
        named_args: &[(InternedStr<'p>, GcView<ThunkData<'p>>)],
        func_env: Option<Gc<ThunkEnv<'p>>>,
    ) -> EvalResult<Box<[Gc<ThunkData<'p>>]>> {
        self.check_call_args_generic(
            params,
            positional_args,
            |_, thunk| Gc::from(thunk),
            named_args,
            |&(name, _)| name,
            |(_, _)| None,
            |_, (_, thunk)| Gc::from(thunk),
            func_env,
            None,
        )
    }

    #[inline]
    fn check_call_args_generic<PosArg, NamedArg>(
        &self,
        params: &FuncParams<'p>,
        positional_args: &[PosArg],
        pos_arg_thunk: impl Fn(&Self, &PosArg) -> Gc<ThunkData<'p>>,
        named_args: &[NamedArg],
        named_arg_name: impl Fn(&NamedArg) -> InternedStr<'p>,
        named_arg_name_span: impl Fn(&NamedArg) -> Option<SpanId>,
        named_arg_thunk: impl Fn(&Self, &NamedArg) -> Gc<ThunkData<'p>>,
        func_env: Option<Gc<ThunkEnv<'p>>>,
        call_span: Option<SpanId>,
    ) -> EvalResult<Box<[Gc<ThunkData<'p>>]>> {
        if positional_args.len() > params.order.len() {
            return Err(self.report_error(EvalErrorKind::TooManyCallArgs {
                span: call_span,
                num_params: params.order.len(),
            }));
        }

        // Handle positional arguments
        let mut args_thunks = Vec::with_capacity(params.order.len());
        args_thunks.extend(positional_args.iter().map(|arg| pos_arg_thunk(self, arg)));

        if args_thunks.len() == params.order.len() && named_args.is_empty() {
            // Fast path when all arguments are positional
            return Ok(args_thunks.into_boxed_slice());
        }

        // Handle named arguments into a temporary vector
        let mut named_args_tmp = vec![None; params.order.len() - args_thunks.len()];

        for named_arg in named_args.iter() {
            let param_name = named_arg_name(named_arg);
            let name_span = named_arg_name_span(named_arg);
            let Some(&param_i) = params.by_name.get(&param_name) else {
                return Err(self.report_error(EvalErrorKind::UnknownCallParam {
                    span: name_span,
                    param_name: param_name.value().into(),
                }));
            };
            if param_i < args_thunks.len() {
                return Err(self.report_error(EvalErrorKind::RepeatedCallParam {
                    span: name_span,
                    param_name: param_name.value().into(),
                }));
            }
            let arg_tmp = &mut named_args_tmp[param_i - args_thunks.len()];
            if arg_tmp.is_some() {
                return Err(self.report_error(EvalErrorKind::RepeatedCallParam {
                    span: name_span,
                    param_name: param_name.value().into(),
                }));
            }
            *arg_tmp = Some(named_arg_thunk(self, named_arg));
        }

        // Move named arguments from the temporary vector to the final vector
        let mut named_args_tmp = named_args_tmp.into_iter();
        while named_args_tmp.len() != 0 {
            if named_args_tmp.as_slice()[0].is_none() {
                // Let the next loop try to find default arguments.
                break;
            }
            let arg = named_args_tmp.next().unwrap().unwrap();
            args_thunks.push(arg);
        }

        if named_args_tmp.len() == 0 {
            // Fast path when all parameters are bound
            // without needing defaults.
            assert_eq!(args_thunks.len(), params.order.len());
            return Ok(args_thunks.into_boxed_slice());
        }

        // An environment is required to evaluate default arguments.
        let args_env = self.program.gc_alloc_view(ThunkEnv::new());

        for arg_tmp in named_args_tmp {
            if let Some(arg) = arg_tmp {
                args_thunks.push(arg);
            } else {
                let (param_name, default_arg) = params.order[args_thunks.len()];
                let Some(default_arg) = default_arg else {
                    return Err(self.report_error(EvalErrorKind::CallParamNotBound {
                        span: call_span,
                        param_name: param_name.value().into(),
                    }));
                };
                args_thunks.push(self.program.new_pending_expr_thunk(
                    default_arg,
                    Gc::from(&args_env),
                    None,
                ));
            }
        }

        let mut args_env_data = ThunkEnvData::new(func_env);
        for (&(arg_name, _), arg_thunk) in params.order.iter().zip(args_thunks.iter()) {
            args_env_data.set_var(arg_name, arg_thunk.clone());
        }

        args_env.set_data(args_env_data);

        assert_eq!(args_thunks.len(), params.order.len());
        Ok(args_thunks.into_boxed_slice())
    }

    #[inline]
    pub(super) fn check_thunk_args_and_execute_call(
        &mut self,
        func: &FuncData<'p>,
        positional_args: &[GcView<ThunkData<'p>>],
        named_args: &[(InternedStr<'p>, GcView<ThunkData<'p>>)],
        call_span: Option<SpanId>,
    ) -> EvalResult<()> {
        let (func_name, func_env) = self.get_func_info(func);
        let args_thunks =
            self.check_call_thunk_args(&func.params, positional_args, named_args, func_env)?;
        self.push_trace_item(TraceItem::Call {
            span: call_span,
            name: func_name,
        });
        self.execute_call(func, args_thunks);
        Ok(())
    }

    pub(super) fn execute_call(&mut self, func: &FuncData<'p>, args: Box<[Gc<ThunkData<'p>>]>) {
        match func.kind {
            FuncKind::Identity { .. } => {
                let [arg] = &*args else {
                    unreachable!();
                };
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            FuncKind::Normal { body, ref env, .. } => {
                self.execute_normal_call(&func.params, body, env.clone(), args);
            }
            FuncKind::BuiltIn { kind, .. } => {
                self.execute_built_in_call(kind, &args);
            }
            FuncKind::Native { name, .. } => {
                self.execute_native_call(name, &args);
            }
        }
    }

    pub(super) fn execute_normal_call(
        &mut self,
        params: &FuncParams<'p>,
        body: &'p ir::Expr<'p>,
        env: Gc<ThunkEnv<'p>>,
        args: Box<[Gc<ThunkData<'p>>]>,
    ) {
        let inner_env = self.program.gc_alloc_view(ThunkEnv::new());
        let mut inner_env_data = ThunkEnvData::new(Some(env));
        for (&(arg_name, _), arg_thunk) in params.order.iter().zip(Vec::from(args)) {
            inner_env_data.set_var(arg_name, arg_thunk);
        }
        inner_env.set_data(inner_env_data);

        self.state_stack.push(State::Expr {
            expr: body,
            env: inner_env,
        });
    }

    fn execute_built_in_call(&mut self, kind: BuiltInFunc, args: &[Gc<ThunkData<'p>>]) {
        #[inline]
        fn check_num_args<'a, 'p, const N: usize>(
            args: &'a [Gc<ThunkData<'p>>],
        ) -> &'a [Gc<ThunkData<'p>>; N] {
            args.try_into().unwrap()
        }
        match kind {
            BuiltInFunc::ExtVar => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_ext_var));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Type => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_type));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsArray => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_array));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsBoolean => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_boolean));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsFunction => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_function));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsNumber => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_number));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsObject => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_object));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsString => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_string));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsNull => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_is_null));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Length => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_length));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Prune => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdPruneValue);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ObjectHasEx => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_object_has_ex));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::ObjectFieldsEx => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_object_fields_ex));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::ObjectRemoveKey => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_object_remove_key));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::MapWithKey => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_map_with_key));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::PrimitiveEquals => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_primitive_equals));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Equals => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::BoolToValue);
                self.state_stack.push(State::EqualsValue);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Compare => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::CmpOrdToIntValueThreeWay);
                self.state_stack.push(State::CompareValue);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::CompareArray => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_compare_array));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Exponent => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_exponent));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Mantissa => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_mantissa));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Floor => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_floor));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Ceil => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_ceil));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Modulo => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_modulo));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Pow => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_pow));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Exp => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_exp));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Log => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_log));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Log2 => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_log2));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Log10 => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_log10));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sqrt => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_sqrt));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sin => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_sin));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Cos => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_cos));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Tan => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_tan));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Asin => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_asin));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Acos => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_acos));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Atan => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_atan));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Atan2 => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_atan2));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Deg2Rad => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_deg2rad));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Rad2Deg => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_rad2deg));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Hypot => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_hypot));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::IsEven => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_is_even));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsOdd => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_is_odd));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsInteger => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_is_integer));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::IsDecimal => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_is_decimal));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::AssertEqual => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_assert_equal));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::ToString => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::CoerceToStringValue);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Codepoint => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_codepoint));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Char => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_char));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Substr => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_substr));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::FindSubstr => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_find_substr));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::StartsWith => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_starts_with));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::EndsWith => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_ends_with));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::StripChars => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_strip_chars));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::LStripChars => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_lstrip_chars));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::RStripChars => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_rstrip_chars));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Split => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_split));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::SplitLimit => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_split_limit));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::SplitLimitR => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_split_limit_r));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::StrReplace => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_str_replace));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Trim => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_trim));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::EqualsIgnoreCase => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_equals_ignore_case));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::AsciiUpper => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_ascii_upper));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::AsciiLower => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_ascii_lower));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::StringChars => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_string_chars));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Format => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdFormat);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::EscapeStringJson => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_escape_string_json));
                self.state_stack.push(State::CoerceToString);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::EscapeStringPython => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_escape_string_python));
                self.state_stack.push(State::CoerceToString);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::EscapeStringBash => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_escape_string_bash));
                self.state_stack.push(State::CoerceToString);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::EscapeStringDollars => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_escape_string_dollars));
                self.state_stack.push(State::CoerceToString);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::EscapeStringXml => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnInfallible(Self::do_std_escape_string_xml));
                self.state_stack.push(State::CoerceToString);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ParseInt => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_parse_int));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ParseOctal => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_parse_octal));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ParseHex => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_parse_hex));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ParseJson => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_parse_json));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ParseYaml => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_parse_yaml));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::EncodeUtf8 => {
                self.state_stack
                    .push(State::FnFallible(Self::do_std_encode_utf8));
                self.state_stack.push(State::DoThunk(args[0].view()));
            }
            BuiltInFunc::DecodeUtf8 => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_decode_utf8));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ManifestIni => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdManifestIni);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ManifestPython => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdManifestPython);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ManifestPythonVars => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdManifestPythonVars);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ManifestJsonEx => {
                let [arg0, arg1, arg2, arg3] = check_num_args(args);
                self.state_stack.push(State::StdManifestJsonEx);
                self.state_stack.push(State::DoThunk(arg3.view()));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::ManifestYamlDoc => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdManifestYamlDoc);
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::ManifestYamlStream => {
                let [arg0, arg1, arg2, arg3] = check_num_args(args);
                self.state_stack.push(State::StdManifestYamlStream);
                self.state_stack.push(State::DoThunk(arg3.view()));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::ManifestXmlJsonml => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdManifestXmlJsonml);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::ManifestTomlEx => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdManifestTomlEx);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::MakeArray => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_make_array));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Member => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::StdMember { value: arg1.view() });
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Count => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::StdCount { value: arg1.view() });
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Find => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdFind { value: arg0.view() });
                self.state_stack.push(State::DoThunk(arg1.view()));
            }
            BuiltInFunc::Map => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_map));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::MapWithIndex => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_map_with_index));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::FilterMap => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdFilterMap);
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::FlatMap => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_flat_map));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Filter => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdFilter);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Foldl => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdFoldl { init: arg2.view() });
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Foldr => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdFoldr { init: arg2.view() });
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Range => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_range));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Repeat => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_repeat));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Slice => {
                let [arg0, arg1, arg2, arg3] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_slice));
                self.state_stack.push(State::DoThunk(arg3.view()));
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Join => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdJoin);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::DeepJoin => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_deep_join));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::FlattenArrays => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_flatten_arrays));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::FlattenDeepArray => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdFlattenDeepArray);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Reverse => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_reverse));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sort => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdSort);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Uniq => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdUniq);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::All => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdAll);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Any => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdAny);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sum => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdSum);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Avg => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdAvg);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::MinArray => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdMinArray {
                    on_empty: arg2.view(),
                });
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::MaxArray => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdMaxArray {
                    on_empty: arg2.view(),
                });
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Contains => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::StdContains { value: arg1.view() });
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Remove => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::StdRemove { value: arg1.view() });
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::RemoveAt => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_remove_at));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Set => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdSet);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::SetInter => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdSetInter);
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::SetUnion => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdSetUnion);
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::SetDiff => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack.push(State::StdSetDiff);
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::SetMember => {
                let [arg0, arg1, arg2] = check_num_args(args);
                self.state_stack
                    .push(State::StdSetMember { x: arg0.view() });
                self.state_stack.push(State::DoThunk(arg2.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
            }
            BuiltInFunc::Base64 => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdBase64);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Base64DecodeBytes => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdBase64DecodeBytes);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Base64Decode => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::StdBase64Decode);
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Md5 => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_md5));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sha1 => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_sha1));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sha256 => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_sha256));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sha512 => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_sha512));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Sha3 => {
                let [arg] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_sha3));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::MergePatch => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::StdMergePatchValue);
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Mod => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_mod));
                self.state_stack.push(State::DoThunk(arg1.view()));
                self.state_stack.push(State::DoThunk(arg0.view()));
            }
            BuiltInFunc::Native => {
                let [arg] = check_num_args(args);
                self.state_stack
                    .push(State::FnFallible(Self::do_std_native));
                self.state_stack.push(State::DoThunk(arg.view()));
            }
            BuiltInFunc::Trace => {
                let [arg0, arg1] = check_num_args(args);
                self.state_stack.push(State::FnFallible(Self::do_std_trace));
                self.state_stack.push(State::DoThunk(arg0.view()));
                self.state_stack.push(State::DoThunk(arg1.view()));
            }
        }
    }

    fn execute_native_call(&mut self, name: InternedStr<'p>, args: &[Gc<ThunkData<'p>>]) {
        self.state_stack.push(State::ExecNativeCall {
            name,
            args: args.iter().map(Gc::view).collect(),
        });

        for arg in args.iter().rev() {
            self.state_stack.push(State::DiscardValue);
            self.state_stack.push(State::DeepValue);
            self.state_stack.push(State::DoThunk(arg.view()));
        }
    }
}