1use crate::ast::ArgSep;
20use crate::ast::ExprType;
21use crate::bytecode::TaggedRegisterRef;
22use crate::bytecode::VarArgTag;
23use crate::mem::HeapOverflowError;
24use crate::mem::{ArrayData, ConstantDatum, DatumPtr, Heap, HeapDatum};
25use crate::reader::LineCol;
26use async_trait::async_trait;
27use std::borrow::Cow;
28use std::fmt;
29use std::io;
30use std::ops::RangeInclusive;
31use std::rc::Rc;
32use std::str::Lines;
33
34#[derive(Debug, thiserror::Error)]
36pub enum CallError {
37 #[error("{0}")]
39 Argument(String),
40
41 #[error("{0}")]
43 Eval(String),
44
45 #[error("{0}")]
47 IoError(io::Error),
48
49 #[error("{0}")]
51 Precondition(String),
52
53 #[error("{0}: {1}")]
55 Syntax(LineCol, String),
56}
57
58impl From<io::Error> for CallError {
59 fn from(value: io::Error) -> Self {
60 Self::IoError(value)
61 }
62}
63
64impl From<HeapOverflowError> for CallError {
65 fn from(value: HeapOverflowError) -> Self {
66 Self::Eval(value.to_string())
67 }
68}
69
70impl CallError {
71 pub(crate) fn to_upcall_error(&self, default_pos: LineCol) -> UpcallError {
76 match self {
77 CallError::Argument(message) => UpcallError::Argument(default_pos, message.clone()),
78
79 CallError::Eval(message) => UpcallError::Eval(default_pos, message.clone()),
80
81 CallError::IoError(e) => UpcallError::IoError(default_pos, e.to_string()),
82
83 CallError::Precondition(message) => {
84 UpcallError::Precondition(default_pos, message.clone())
85 }
86
87 CallError::Syntax(pos, message) => UpcallError::Syntax(*pos, message.clone()),
88 }
89 }
90}
91
92pub type CallResult<T> = Result<T, CallError>;
94
95#[derive(Debug, thiserror::Error)]
99pub enum UpcallError {
100 #[error("{0}: {1}")]
102 Argument(LineCol, String),
103
104 #[error("{0}: {1}")]
106 Eval(LineCol, String),
107
108 #[error("{0}: {1}")]
110 IoError(LineCol, String),
111
112 #[error("{0}: {1}")]
114 Precondition(LineCol, String),
115
116 #[error("{0}: {1}")]
118 Syntax(LineCol, String),
119}
120
121impl UpcallError {
122 pub fn parts(&self) -> (LineCol, String) {
124 match self {
125 UpcallError::Argument(pos, message) => (*pos, message.clone()),
126 UpcallError::Eval(pos, message) => (*pos, message.clone()),
127 UpcallError::IoError(pos, message) => (*pos, message.clone()),
128 UpcallError::Precondition(pos, message) => (*pos, message.clone()),
129 UpcallError::Syntax(pos, message) => (*pos, message.clone()),
130 }
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_io_error_has_no_source() {
140 let error = CallError::from(io::Error::other("Some I/O error"));
141
142 assert!(std::error::Error::source(&error).is_none());
143 }
144}
145
146#[derive(Clone, Debug, PartialEq)]
148pub struct RequiredValueSyntax {
149 pub name: Cow<'static, str>,
151
152 pub vtype: ExprType,
154}
155
156#[derive(Clone, Debug, PartialEq)]
158pub struct RequiredRefSyntax {
159 pub name: Cow<'static, str>,
161
162 pub require_array: bool,
164
165 pub define_undefined: bool,
169}
170
171#[derive(Clone, Debug, PartialEq)]
175pub struct OptionalValueSyntax {
176 pub name: Cow<'static, str>,
178
179 pub vtype: ExprType,
181}
182
183#[derive(Clone, Debug, PartialEq)]
185pub enum RepeatedTypeSyntax {
186 AnyValue,
189
190 TypedValue(ExprType),
192
193 VariableRef,
195}
196
197#[derive(Clone, Debug, PartialEq)]
201pub struct RepeatedSyntax {
202 pub name: Cow<'static, str>,
204
205 pub type_syn: RepeatedTypeSyntax,
207
208 pub sep: ArgSepSyntax,
211
212 pub require_one: bool,
214
215 pub allow_missing: bool,
217}
218
219impl RepeatedSyntax {
220 fn describe(&self, output: &mut String, last_singular_sep: Option<&ArgSepSyntax>) {
225 if !self.require_one {
226 output.push('[');
227 }
228
229 if let Some(sep) = last_singular_sep {
230 sep.describe(output);
231 }
232
233 output.push_str(&self.name);
234 output.push('1');
235 if let RepeatedTypeSyntax::TypedValue(vtype) = self.type_syn {
236 output.push(vtype.annotation());
237 }
238
239 if self.require_one {
240 output.push('[');
241 }
242
243 self.sep.describe(output);
244 output.push_str("..");
245 self.sep.describe(output);
246
247 output.push_str(&self.name);
248 output.push('N');
249 if let RepeatedTypeSyntax::TypedValue(vtype) = self.type_syn {
250 output.push(vtype.annotation());
251 }
252
253 output.push(']');
254 }
255}
256
257#[derive(Clone, Debug, PartialEq)]
259pub struct AnyValueSyntax {
260 pub name: Cow<'static, str>,
262
263 pub allow_missing: bool,
265}
266
267#[derive(Copy, Clone, Debug, PartialEq)]
269pub enum ArgSepSyntax {
270 Exactly(ArgSep),
272
273 OneOf(&'static [ArgSep]),
275
276 End,
278}
279
280impl ArgSepSyntax {
281 fn describe(&self, output: &mut String) {
283 match self {
284 ArgSepSyntax::Exactly(sep) => {
285 let (text, needs_space) = sep.describe();
286
287 if !text.is_empty() && needs_space {
288 output.push(' ');
289 }
290 output.push_str(text);
291 if !text.is_empty() {
292 output.push(' ');
293 }
294 }
295
296 ArgSepSyntax::OneOf(seps) => {
297 output.push_str(" <");
298 for (i, sep) in seps.iter().enumerate() {
299 let (text, _needs_space) = sep.describe();
300 output.push_str(text);
301 if i < seps.len() - 1 {
302 output.push('|');
303 }
304 }
305 output.push_str("> ");
306 }
307
308 ArgSepSyntax::End => (),
309 };
310 }
311}
312
313#[derive(Clone, Debug, PartialEq)]
318pub enum SingularArgSyntax {
319 RequiredValue(RequiredValueSyntax, ArgSepSyntax),
321
322 RequiredRef(RequiredRefSyntax, ArgSepSyntax),
324
325 OptionalValue(OptionalValueSyntax, ArgSepSyntax),
327
328 AnyValue(AnyValueSyntax, ArgSepSyntax),
330}
331
332#[derive(Clone, Debug, PartialEq)]
340pub(crate) struct CallableSyntax {
341 pub(crate) singular: Cow<'static, [SingularArgSyntax]>,
343
344 pub(crate) repeated: Option<Cow<'static, RepeatedSyntax>>,
346}
347
348impl CallableSyntax {
349 pub(crate) fn new_static(
352 singular: &'static [SingularArgSyntax],
353 repeated: Option<&'static RepeatedSyntax>,
354 ) -> Self {
355 Self { singular: Cow::Borrowed(singular), repeated: repeated.map(Cow::Borrowed) }
356 }
357
358 pub(crate) fn new_dynamic(
361 singular: Vec<SingularArgSyntax>,
362 repeated: Option<RepeatedSyntax>,
363 ) -> Self {
364 Self { singular: Cow::Owned(singular), repeated: repeated.map(Cow::Owned) }
365 }
366
367 pub(crate) fn expected_nargs(&self) -> RangeInclusive<usize> {
369 let mut min = self.singular.len();
370 let mut max = self.singular.len();
371
372 if let Some(syn) = self.repeated.as_ref() {
373 if syn.require_one {
374 min += 1;
375 }
376 max = usize::MAX;
377 }
378
379 min..=max
380 }
381
382 pub(crate) fn is_empty(&self) -> bool {
384 self.singular.is_empty() && self.repeated.is_none()
385 }
386
387 pub(crate) fn describe(&self) -> String {
389 let mut description = String::new();
390 let mut last_singular_sep = None;
391 for (i, s) in self.singular.iter().enumerate() {
392 let sep = match s {
393 SingularArgSyntax::RequiredValue(details, sep) => {
394 description.push_str(&details.name);
395 description.push(details.vtype.annotation());
396 sep
397 }
398
399 SingularArgSyntax::RequiredRef(details, sep) => {
400 description.push_str(&details.name);
401 sep
402 }
403
404 SingularArgSyntax::OptionalValue(details, sep) => {
405 description.push('[');
406 description.push_str(&details.name);
407 description.push(details.vtype.annotation());
408 description.push(']');
409 sep
410 }
411
412 SingularArgSyntax::AnyValue(details, sep) => {
413 if details.allow_missing {
414 description.push('[');
415 }
416 description.push_str(&details.name);
417 if details.allow_missing {
418 description.push(']');
419 }
420 sep
421 }
422 };
423
424 if self.repeated.is_none() || i < self.singular.len() - 1 {
425 sep.describe(&mut description);
426 }
427 if i == self.singular.len() - 1 {
428 last_singular_sep = Some(sep);
429 }
430 }
431
432 if let Some(syn) = &self.repeated {
433 syn.describe(&mut description, last_singular_sep);
434 }
435
436 description
437 }
438}
439
440pub struct CallableMetadataBuilder {
442 name: Cow<'static, str>,
444
445 return_type: Option<ExprType>,
447
448 is_async: bool,
450
451 category: Option<&'static str>,
453
454 syntaxes: Vec<CallableSyntax>,
456
457 description: Option<&'static str>,
459}
460
461impl CallableMetadataBuilder {
462 pub fn new(name: &'static str) -> Self {
468 assert!(name == name.to_ascii_uppercase(), "Callable name must be in uppercase");
469
470 Self {
471 name: Cow::Borrowed(name),
472 return_type: None,
473 is_async: false,
474 syntaxes: vec![],
475 category: None,
476 description: None,
477 }
478 }
479
480 pub fn new_dynamic<S: Into<String>>(name: S) -> Self {
485 Self {
486 name: Cow::Owned(name.into().to_ascii_uppercase()),
487 return_type: None,
488 is_async: false,
489 syntaxes: vec![],
490 category: Some("User defined"),
491 description: Some("User defined symbol."),
492 }
493 }
494
495 pub fn with_return_type(mut self, return_type: ExprType) -> Self {
497 self.return_type = Some(return_type);
498 self
499 }
500
501 pub fn with_async(mut self, is_async: bool) -> Self {
503 self.is_async = is_async;
504 self
505 }
506
507 pub fn with_syntax(
509 mut self,
510 syntaxes: &'static [(&'static [SingularArgSyntax], Option<&'static RepeatedSyntax>)],
511 ) -> Self {
512 self.syntaxes = syntaxes
513 .iter()
514 .map(|s| CallableSyntax::new_static(s.0, s.1))
515 .collect::<Vec<CallableSyntax>>();
516 self
517 }
518
519 pub(crate) fn with_syntaxes<S: Into<Vec<CallableSyntax>>>(mut self, syntaxes: S) -> Self {
521 self.syntaxes = syntaxes.into();
522 self
523 }
524
525 pub(crate) fn with_dynamic_syntax(
527 self,
528 syntaxes: Vec<(Vec<SingularArgSyntax>, Option<RepeatedSyntax>)>,
529 ) -> Self {
530 let syntaxes = syntaxes
531 .into_iter()
532 .map(|s| CallableSyntax::new_dynamic(s.0, s.1))
533 .collect::<Vec<CallableSyntax>>();
534 self.with_syntaxes(syntaxes)
535 }
536
537 pub fn with_category(mut self, category: &'static str) -> Self {
540 self.category = Some(category);
541 self
542 }
543
544 pub fn with_description(mut self, description: &'static str) -> Self {
549 for l in description.lines() {
550 assert!(!l.is_empty(), "Description cannot contain empty lines");
551 }
552 self.description = Some(description);
553 self
554 }
555
556 pub fn build(self) -> Rc<CallableMetadata> {
558 assert!(!self.syntaxes.is_empty(), "All callables must specify a syntax");
559 Rc::from(CallableMetadata {
560 name: self.name,
561 return_type: self.return_type,
562 is_async: self.is_async,
563 syntaxes: self.syntaxes,
564 category: self.category.expect("All callables must specify a category"),
565 description: self.description.expect("All callables must specify a description"),
566 })
567 }
568
569 pub fn test_build(mut self) -> Rc<CallableMetadata> {
572 if self.syntaxes.is_empty() {
573 self.syntaxes.push(CallableSyntax::new_static(&[], None));
574 }
575 Rc::from(CallableMetadata {
576 name: self.name,
577 return_type: self.return_type,
578 is_async: self.is_async,
579 syntaxes: self.syntaxes,
580 category: self.category.unwrap_or(""),
581 description: self.description.unwrap_or(""),
582 })
583 }
584}
585
586#[derive(Clone, Debug, PartialEq)]
591pub struct CallableMetadata {
592 name: Cow<'static, str>,
594
595 return_type: Option<ExprType>,
597
598 is_async: bool,
600
601 syntaxes: Vec<CallableSyntax>,
603
604 category: &'static str,
606
607 description: &'static str,
609}
610
611impl CallableMetadata {
612 pub fn name(&self) -> &str {
614 &self.name
615 }
616
617 pub fn return_type(&self) -> Option<ExprType> {
619 self.return_type
620 }
621
622 pub fn is_async(&self) -> bool {
624 self.is_async
625 }
626
627 pub fn syntax(&self) -> String {
629 fn format_one(cs: &CallableSyntax) -> String {
630 let mut syntax = cs.describe();
631 if syntax.is_empty() {
632 syntax.push_str("no arguments");
633 }
634 syntax
635 }
636
637 match self.syntaxes.as_slice() {
638 [] => panic!("Callables without syntaxes are not allowed at construction time"),
639 [one] => format_one(one),
640 many => many
641 .iter()
642 .map(|syn| format!("<{}>", syn.describe()))
643 .collect::<Vec<String>>()
644 .join(" | "),
645 }
646 }
647
648 fn is_function_sep(sep: &ArgSepSyntax) -> bool {
651 match sep {
652 ArgSepSyntax::Exactly(ArgSep::Long) | ArgSepSyntax::End => true,
653 ArgSepSyntax::OneOf(seps) => seps.iter().all(|s| *s == ArgSep::Long),
654 _ => false,
655 }
656 }
657
658 fn debug_assert_function_seps(&self, syntax: &CallableSyntax) {
662 if self.return_type().is_none() {
663 return;
664 }
665 for syn in syntax.singular.iter() {
666 let sep = match syn {
667 SingularArgSyntax::RequiredValue(_, sep) => sep,
668 SingularArgSyntax::RequiredRef(_, sep) => sep,
669 SingularArgSyntax::OptionalValue(_, sep) => sep,
670 SingularArgSyntax::AnyValue(_, sep) => sep,
671 };
672 debug_assert!(
673 Self::is_function_sep(sep),
674 "Function {} has a non-comma separator in its singular args syntax",
675 self.name()
676 );
677 }
678 if let Some(repeated) = syntax.repeated.as_ref() {
679 debug_assert!(
680 Self::is_function_sep(&repeated.sep),
681 "Function {} has a non-comma separator in its repeated args syntax",
682 self.name()
683 );
684 }
685 }
686
687 pub(crate) fn find_syntax(&self, nargs: usize) -> Option<&CallableSyntax> {
692 let mut matches = self.syntaxes.iter().filter(|s| s.expected_nargs().contains(&nargs));
693 let syntax = matches.next();
694 match syntax {
695 Some(syntax) => {
696 debug_assert!(matches.next().is_none(), "Ambiguous syntax definitions");
697 if cfg!(debug_assertions) {
698 self.debug_assert_function_seps(syntax);
699 }
700 Some(syntax)
701 }
702 None => None,
703 }
704 }
705
706 #[allow(unused)]
709 pub fn category(&self) -> &'static str {
710 self.category
711 }
712
713 #[allow(unused)]
716 pub fn description(&self) -> Lines<'static> {
717 self.description.lines()
718 }
719
720 #[allow(unused)]
722 pub fn is_argless(&self) -> bool {
723 self.syntaxes.is_empty() || (self.syntaxes.len() == 1 && self.syntaxes[0].is_empty())
724 }
725
726 #[allow(unused)]
728 pub(crate) fn is_function(&self) -> bool {
729 self.return_type.is_some()
730 }
731
732 pub(crate) fn is_user_defined(&self) -> bool {
734 self.category == "User defined"
735 }
736}
737
738fn deref_boolean(regs: &[u64], index: usize, vtype: ExprType) -> bool {
740 assert_eq!(ExprType::Boolean, vtype);
741 regs[index] != 0
742}
743
744fn deref_double(regs: &[u64], index: usize, vtype: ExprType) -> f64 {
746 assert_eq!(ExprType::Double, vtype);
747 f64::from_bits(regs[index])
748}
749
750fn deref_integer(regs: &[u64], index: usize, vtype: ExprType) -> i32 {
752 assert_eq!(ExprType::Integer, vtype);
753 regs[index] as i32
754}
755
756fn deref_string<'a>(
758 regs: &[u64],
759 index: usize,
760 vtype: ExprType,
761 constants: &'a [ConstantDatum],
762 heap: &'a Heap,
763) -> &'a str {
764 assert_eq!(ExprType::Text, vtype);
765 let ptr = DatumPtr::from(regs[index]);
766 ptr.resolve_string(constants, heap)
767}
768
769fn array_data<'a>(regs: &'a [u64], index: usize, heap: &'a Heap) -> &'a ArrayData {
771 let ptr = DatumPtr::from(regs[index]);
772 let heap_idx = ptr.heap_index();
773 let HeapDatum::Array(a) = heap.get(heap_idx) else {
774 panic!("Scalar variable does not point to an array on the heap");
775 };
776 a
777}
778
779fn array_dimensions<'a>(regs: &'a [u64], index: usize, heap: &'a Heap) -> &'a [usize] {
781 let a = array_data(regs, index, heap);
782 &a.dimensions
783}
784
785fn deref_array_integer(
787 regs: &[u64],
788 index: usize,
789 vtype: ExprType,
790 heap: &Heap,
791 subscripts: &[i32],
792) -> Result<i32, String> {
793 assert_eq!(ExprType::Integer, vtype);
794 let a = array_data(regs, index, heap);
795 let flat_idx = a.flat_index(subscripts)?;
796 Ok(a.values[flat_idx] as i32)
797}
798
799pub struct RegisterRef<'a, 'vm> {
802 scope: &'a Scope<'vm>,
804
805 index: usize,
807
808 pub vtype: ExprType,
810}
811
812impl<'a, 'vm> RegisterRef<'a, 'vm> {
813 pub fn deref_boolean(&self) -> bool {
815 deref_boolean(self.scope.regs, self.index, self.vtype)
816 }
817
818 pub fn deref_double(&self) -> f64 {
820 deref_double(self.scope.regs, self.index, self.vtype)
821 }
822
823 pub fn deref_integer(&self) -> i32 {
825 deref_integer(self.scope.regs, self.index, self.vtype)
826 }
827
828 pub fn deref_string(&self) -> &str {
830 deref_string(self.scope.regs, self.index, self.vtype, self.scope.constants, self.scope.heap)
831 }
832
833 pub fn array_dimensions(&self) -> &[usize] {
835 array_dimensions(self.scope.regs, self.index, self.scope.heap)
836 }
837
838 pub fn deref_array_integer(&self, subscripts: &[i32]) -> Result<i32, String> {
840 deref_array_integer(self.scope.regs, self.index, self.vtype, self.scope.heap, subscripts)
841 }
842}
843
844impl<'a, 'vm> fmt::Display for RegisterRef<'a, 'vm> {
845 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
846 write!(f, "&[R{}]{}", self.index, self.vtype)
847 }
848}
849
850pub struct RegisterRefMut<'a, 'vm> {
853 scope: &'a mut Scope<'vm>,
855
856 index: usize,
858
859 pub vtype: ExprType,
861}
862
863impl<'a, 'vm> RegisterRefMut<'a, 'vm> {
864 pub fn deref_boolean(&self) -> bool {
866 deref_boolean(self.scope.regs, self.index, self.vtype)
867 }
868
869 pub fn deref_double(&self) -> f64 {
871 deref_double(self.scope.regs, self.index, self.vtype)
872 }
873
874 pub fn deref_integer(&self) -> i32 {
876 deref_integer(self.scope.regs, self.index, self.vtype)
877 }
878
879 pub fn deref_string(&self) -> &str {
881 deref_string(self.scope.regs, self.index, self.vtype, self.scope.constants, self.scope.heap)
882 }
883
884 pub fn array_dimensions(&self) -> &[usize] {
886 array_dimensions(self.scope.regs, self.index, self.scope.heap)
887 }
888
889 pub fn deref_array_integer(&self, subscripts: &[i32]) -> Result<i32, String> {
891 deref_array_integer(self.scope.regs, self.index, self.vtype, self.scope.heap, subscripts)
892 }
893
894 pub fn set_boolean(&mut self, b: bool) {
896 assert_eq!(ExprType::Boolean, self.vtype);
897 self.scope.regs[self.index] = if b { 1 } else { 0 };
898 }
899
900 pub fn set_double(&mut self, d: f64) {
902 assert_eq!(ExprType::Double, self.vtype);
903 self.scope.regs[self.index] = d.to_bits();
904 }
905
906 pub fn set_integer(&mut self, i: i32) {
908 assert_eq!(ExprType::Integer, self.vtype);
909 self.scope.regs[self.index] = i as u64;
910 }
911
912 pub fn set_string<S: Into<String>>(&mut self, s: S) -> CallResult<()> {
914 assert_eq!(ExprType::Text, self.vtype);
915 self.scope.regs[self.index] = self.scope.heap.push(HeapDatum::Text(s.into()))?;
916 Ok(())
917 }
918}
919
920impl<'a, 'vm> fmt::Display for RegisterRefMut<'a, 'vm> {
921 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
922 write!(f, "&[R{}]{}", self.index, self.vtype)
923 }
924}
925
926pub struct Scope<'a> {
928 pub(crate) regs: &'a mut [u64],
930
931 pub(crate) constants: &'a [ConstantDatum],
933
934 pub(crate) heap: &'a mut Heap,
936
937 pub(crate) fp: usize,
939
940 pub(crate) arg_offset: usize,
947
948 pub(crate) arg_linecols: &'a [LineCol],
954
955 pub(crate) last_error: &'a Option<(LineCol, String)>,
957
958 pub(crate) data: &'a [Option<ConstantDatum>],
960}
961
962impl<'a> Scope<'a> {
963 pub fn data(&self) -> &[Option<ConstantDatum>] {
965 self.data
966 }
967
968 pub fn nargs(&self) -> usize {
970 self.arg_linecols.len()
971 }
972
973 pub fn get_pos(&self, arg: u8) -> LineCol {
977 self.arg_linecols[usize::from(arg)]
978 }
979
980 pub fn get_type(&self, arg: u8) -> VarArgTag {
982 VarArgTag::parse_u64(self.regs[self.fp + self.arg_offset + (arg as usize)]).unwrap()
983 }
984
985 pub fn get_boolean(&self, arg: u8) -> bool {
987 self.regs[self.fp + self.arg_offset + (arg as usize)] != 0
988 }
989
990 pub fn get_double(&self, arg: u8) -> f64 {
992 f64::from_bits(self.regs[self.fp + self.arg_offset + (arg as usize)])
993 }
994
995 pub fn get_integer(&self, arg: u8) -> i32 {
997 self.regs[self.fp + self.arg_offset + (arg as usize)] as i32
998 }
999
1000 pub fn get_ref(&self, arg: u8) -> RegisterRef<'_, 'a> {
1002 let tagged_ptr = self.regs[self.fp + self.arg_offset + (arg as usize)];
1003 let (index, vtype) = TaggedRegisterRef::from_u64(tagged_ptr).parse();
1004 RegisterRef { scope: self, index, vtype }
1005 }
1006
1007 pub fn get_mut_ref(&mut self, arg: u8) -> RegisterRefMut<'_, 'a> {
1009 let tagged_ptr = self.regs[self.fp + self.arg_offset + (arg as usize)];
1010 let (index, vtype) = TaggedRegisterRef::from_u64(tagged_ptr).parse();
1011 RegisterRefMut { scope: self, index, vtype }
1012 }
1013
1014 pub fn get_string(&self, arg: u8) -> &str {
1016 let index = self.regs[self.fp + self.arg_offset + (arg as usize)];
1017 let ptr = DatumPtr::from(index);
1018 ptr.resolve_string(self.constants, self.heap)
1019 }
1020
1021 pub fn last_error(&self) -> Option<(LineCol, &str)> {
1023 self.last_error.as_ref().map(|(pos, message)| (*pos, message.as_str()))
1024 }
1025
1026 pub fn return_boolean(self, b: bool) -> CallResult<()> {
1031 self.regs[self.fp] = if b { 1 } else { 0 };
1032 Ok(())
1033 }
1034
1035 pub fn return_double(self, d: f64) -> CallResult<()> {
1040 self.regs[self.fp] = d.to_bits();
1041 Ok(())
1042 }
1043
1044 pub fn return_integer(self, i: i32) -> CallResult<()> {
1049 self.regs[self.fp] = i as u64;
1050 Ok(())
1051 }
1052
1053 pub fn return_string<S: Into<String>>(self, s: S) -> CallResult<()> {
1058 self.regs[self.fp] = self.heap.push(HeapDatum::Text(s.into()))?;
1059 Ok(())
1060 }
1061}
1062
1063#[async_trait(?Send)]
1072pub trait Callable {
1073 fn metadata(&self) -> Rc<CallableMetadata>;
1078
1079 fn exec(&self, _scope: Scope<'_>) -> CallResult<()> {
1081 unimplemented!("Must be implemented for !is_async callables")
1082 }
1083
1084 async fn async_exec(&self, _scope: Scope<'_>) -> CallResult<()> {
1086 unimplemented!("Must be implemented for is_async callables")
1087 }
1088}