1use std::{
36 collections::hash_map::Entry,
37 error::Error as StdError,
38 fmt::{Debug, Display, Formatter},
39 ops::Range,
40 result::Result as StdResult,
41 str::Utf8Error,
42 sync::Arc,
43};
44
45use ahash::{AHashMap, AHashSet};
46use lady_deirdre::{arena::Identifiable, format::AnnotationPriority, lexis::ToSpan};
47
48use crate::{
49 analysis::ModuleTextResolver,
50 format::{format_script_path, ScriptSnippet},
51 runtime::{ops::OperatorKind, Origin, TypeMeta},
52};
53
54pub type RuntimeResult<T> = StdResult<T, RuntimeError>;
57
58pub trait RuntimeResultExt {
65 type OkType;
67
68 fn expect_blame(self, message: &str) -> Self::OkType;
72}
73
74impl<T> RuntimeResultExt for RuntimeResult<T> {
75 type OkType = T;
76
77 #[inline(always)]
78 fn expect_blame(self, message: &str) -> Self::OkType {
79 match self {
80 Ok(ok) => ok,
81
82 Err(error) => {
83 let origin = *error.primary_origin();
84
85 match origin {
86 Origin::Rust(origin) => origin.blame(&format!("{message}\n{error}")),
87
88 Origin::Script(origin) => {
89 panic!(
90 "{}: {message}\n{error}",
91 format_script_path(origin.id(), None),
92 );
93 }
94 }
95 }
96 }
97 }
98}
99
100#[derive(Clone, Debug)]
109#[non_exhaustive]
110pub enum RuntimeError {
111 Nil {
114 access_origin: Origin,
116 },
117
118 NonSingleton {
121 access_origin: Origin,
123
124 actual: usize,
126 },
127
128 ShortSlice {
131 access_origin: Origin,
133
134 minimum: usize,
136
137 actual: usize,
139 },
140
141 OutOfBounds {
144 access_origin: Origin,
146
147 index: usize,
149
150 length: usize,
152 },
153
154 ReadOnly {
157 access_origin: Origin,
159
160 data_origin: Origin,
162 },
163
164 WriteOnly {
167 access_origin: Origin,
169
170 data_origin: Origin,
172 },
173
174 ReadToWrite {
177 access_origin: Origin,
179
180 borrow_origin: Origin,
183 },
184
185 WriteToRead {
188 access_origin: Origin,
190
191 borrow_origin: Origin,
194 },
195
196 WriteToWrite {
199 access_origin: Origin,
201
202 borrow_origin: Origin,
205 },
206
207 Utf8Decoding {
210 access_origin: Origin,
212
213 cause: Box<Utf8Error>,
215 },
216
217 BorrowLimit {
219 access_origin: Origin,
221
222 limit: usize,
224 },
225
226 TypeMismatch {
229 access_origin: Origin,
231
232 data_type: &'static TypeMeta,
234
235 expected_types: Vec<&'static TypeMeta>,
237 },
238
239 DowncastStatic {
242 access_origin: Origin,
244 },
245
246 UpcastResult {
248 access_origin: Origin,
251
252 cause: Arc<dyn StdError + Send + Sync + 'static>,
254 },
255
256 NumberCast {
260 access_origin: Origin,
263
264 from: &'static TypeMeta,
267
268 to: &'static TypeMeta,
271
272 cause: NumberCastCause,
274
275 value: Arc<dyn NumValue>,
277 },
278
279 NumericOperation {
283 invoke_origin: Origin,
286
287 kind: NumericOperationKind,
289
290 lhs: (&'static TypeMeta, Arc<dyn NumValue>),
292
293 rhs: Option<(&'static TypeMeta, Arc<dyn NumValue>)>,
296
297 target: &'static TypeMeta,
299 },
300
301 RangeCast {
305 access_origin: Origin,
308
309 from: Range<usize>,
312
313 to: &'static str,
315 },
316
317 MalformedRange {
319 access_origin: Origin,
322
323 start_bound: usize,
325
326 end_bound: usize,
328 },
329
330 PrimitiveParse {
334 access_origin: Origin,
337
338 from: String,
340
341 to: &'static TypeMeta,
343
344 cause: Arc<dyn StdError + Send + Sync + 'static>,
346 },
347
348 ArityMismatch {
351 invocation_origin: Origin,
354
355 function_origin: Origin,
358
359 parameters: usize,
361
362 arguments: usize,
365 },
366
367 UndefinedOperator {
370 access_origin: Origin,
373
374 receiver_origin: Option<Origin>,
378
379 receiver_type: &'static TypeMeta,
381
382 operator: OperatorKind,
384 },
385
386 UnknownField {
389 access_origin: Origin,
391
392 receiver_origin: Origin,
395
396 receiver_type: &'static TypeMeta,
398
399 field: String,
401 },
402
403 FormatError {
406 access_origin: Origin,
409
410 receiver_origin: Origin,
412 },
413
414 UnknownPackage {
417 access_origin: Origin,
420
421 name: &'static str,
423
424 version: &'static str,
426 },
427
428 Interrupted {
431 origin: Origin,
434 },
435
436 StackOverflow {
439 origin: Origin,
442 },
443}
444
445impl Display for RuntimeError {
446 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
447 match self {
448 Self::Nil { .. } => formatter.write_str("inaccessible data"),
449
450 Self::NonSingleton { actual, .. } => formatter.write_fmt(format_args!(
451 "expected a single data instance, but the array with {actual} \
452 elements provided",
453 )),
454
455 Self::ShortSlice {
456 minimum, actual, ..
457 } => formatter.write_fmt(format_args!(
458 "expected an array with at least {minimum} elements, but the \
459 array with {actual} elements provided",
460 )),
461
462 Self::OutOfBounds { index, length, .. } => {
463 formatter.write_fmt(format_args!("index {index} out of 0..{length} bounds",))
464 }
465
466 Self::ReadOnly { .. } => formatter.write_str("read-only data"),
467
468 Self::WriteOnly { .. } => formatter.write_str("write-only data"),
469
470 Self::ReadToWrite { .. } => {
471 formatter.write_str("cannot access data for write while it is being read")
472 }
473
474 Self::WriteToRead { .. } => {
475 formatter.write_str("cannot access data for read while it is being written")
476 }
477
478 Self::WriteToWrite { .. } => {
479 formatter.write_str("cannot access data for write more than once")
480 }
481
482 Self::Utf8Decoding { .. } => formatter.write_str("invalid utf-8 encoding"),
483
484 Self::BorrowLimit { .. } => formatter.write_str("too many simultaneous data accesses"),
485
486 Self::TypeMismatch {
487 data_type,
488 expected_types,
489 ..
490 } => {
491 let partition = Self::partition_types(expected_types);
492
493 match partition.is_empty() {
494 true => formatter.write_fmt(format_args!("unexpected '{data_type}' data type")),
495
496 false => {
497 let partition = partition.join(", or ");
498
499 formatter.write_fmt(format_args!(
500 "expected {partition}, but '{data_type}' data type provided"
501 ))
502 }
503 }
504 }
505
506 Self::DowncastStatic { .. } => formatter
507 .write_str("cannot get static reference to the data owned by the script engine"),
508
509 Self::UpcastResult { .. } => {
510 formatter.write_str("the function returned explicit error")
511 }
512
513 Self::NumberCast {
514 from,
515 to,
516 cause,
517 value,
518 ..
519 } => {
520 use NumberCastCause::*;
521
522 match cause {
523 Infinite => formatter.write_fmt(format_args!(
524 "cannot cast infinity value of {from} type to {to}"
525 )),
526
527 NAN => formatter
528 .write_fmt(format_args!("cannot cast NAN value of {from} type to {to}")),
529
530 Overflow => {
531 formatter.write_fmt(format_args!("cannot cast {value}{from} to {to} type"))
532 }
533
534 Underflow => {
535 formatter.write_fmt(format_args!("cannot cast {value}{from} to {to} type"))
536 }
537 }
538 }
539
540 Self::NumericOperation { kind, lhs, rhs, .. } => {
541 use NumericOperationKind::*;
542
543 match (lhs, kind, rhs) {
544 ((lhs_ty, lhs_value), Add, Some((rhs_ty, rhs_value))) => formatter.write_fmt(
545 format_args!("cannot add {rhs_value}{rhs_ty} to {lhs_value}{lhs_ty}"),
546 ),
547
548 ((lhs_ty, lhs_value), Sub, Some((rhs_ty, rhs_value))) => {
549 formatter.write_fmt(format_args!(
550 "cannot subtract {rhs_value}{rhs_ty} from {lhs_value}{lhs_ty}"
551 ))
552 }
553
554 ((lhs_ty, lhs_value), Mul, Some((rhs_ty, rhs_value))) => formatter.write_fmt(
555 format_args!("cannot multiply {rhs_value}{rhs_ty} by {lhs_value}{lhs_ty}"),
556 ),
557
558 ((lhs_ty, lhs_value), Div, Some((rhs_ty, rhs_value))) => formatter.write_fmt(
559 format_args!("cannot divide {rhs_value}{rhs_ty} by {lhs_value}{lhs_ty}"),
560 ),
561
562 ((lhs_ty, lhs_value), Neg, None) => formatter.write_fmt(format_args!(
563 "cannot get negative number of {lhs_value}{lhs_ty}"
564 )),
565
566 ((lhs_ty, lhs_value), Shl, Some((rhs_ty, rhs_value))) => {
567 formatter.write_fmt(format_args!(
568 "cannot shift {lhs_value}{lhs_ty} left by {rhs_value}{rhs_ty} bits"
569 ))
570 }
571
572 ((lhs_ty, lhs_value), Shr, Some((rhs_ty, rhs_value))) => {
573 formatter.write_fmt(format_args!(
574 "cannot shift {lhs_value}{lhs_ty} right by {rhs_value}{rhs_ty} bits"
575 ))
576 }
577
578 ((lhs_ty, lhs_value), Rem, Some((_rhs_ty, _rhs_value))) => {
579 formatter.write_fmt(format_args!(
580 "cannot get {lhs_value}{lhs_ty} reminder of \
581 division by {lhs_value}{lhs_ty}"
582 ))
583 }
584
585 _ => formatter.write_str("invalid numeric operation"),
586 }
587 }
588
589 Self::RangeCast { from, to, .. } => formatter.write_fmt(format_args!(
590 "cannot cast {from:?} range to {to} type. target type bounds mismatch"
591 )),
592
593 Self::MalformedRange {
594 start_bound,
595 end_bound,
596 ..
597 } => formatter.write_fmt(format_args!(
598 "range {start_bound} start bound is greater than the range end bound {end_bound}"
599 )),
600
601 Self::PrimitiveParse { from, to, .. } => {
602 formatter.write_fmt(format_args!("failed to parse {from:?} as {to}"))
603 }
604
605 Self::ArityMismatch {
606 parameters,
607 arguments,
608 ..
609 } => match *parameters == 1 {
610 true => formatter.write_fmt(format_args!(
611 "the function requires 1 argument, but {arguments} provided"
612 )),
613 false => formatter.write_fmt(format_args!(
614 "the function requires {parameters} arguments, but {arguments} provided"
615 )),
616 },
617
618 Self::UndefinedOperator {
619 receiver_type,
620 operator,
621 ..
622 } => formatter.write_fmt(format_args!(
623 "type '{receiver_type}' does not implement {operator}"
624 )),
625
626 Self::UnknownField {
627 receiver_type,
628 field,
629 ..
630 } => formatter.write_fmt(format_args!(
631 "type '{receiver_type}' does not have field '{field}'"
632 )),
633
634 Self::FormatError { .. } => formatter
635 .write_str("an error occurred during Debug or Display format function call"),
636
637 Self::UnknownPackage { name, version, .. } => {
638 formatter.write_fmt(format_args!("unknown {name}@{version} script package"))
639 }
640
641 Self::Interrupted { .. } => formatter.write_str("script evaluation interrupted"),
642
643 Self::StackOverflow { .. } => formatter.write_str("script engine stack overflow"),
644 }
645 }
646}
647
648impl StdError for RuntimeError {
649 #[inline]
650 fn source(&self) -> Option<&(dyn StdError + 'static)> {
651 match self {
652 Self::Utf8Decoding { cause, .. } => Some(cause),
653 Self::UpcastResult { cause, .. } => Some(cause),
654 Self::PrimitiveParse { cause, .. } => Some(cause),
655 _ => None,
656 }
657 }
658}
659
660impl RuntimeError {
661 pub fn display<'a>(&self, resolver: &'a impl ModuleTextResolver) -> impl Display + 'a {
682 enum DisplayError<'a> {
683 Snippet(ScriptSnippet<'a>),
684 String(String),
685 }
686
687 impl<'a> Display for DisplayError<'a> {
688 #[inline(always)]
689 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
690 match self {
691 Self::Snippet(display) => Display::fmt(display, formatter),
692 Self::String(display) => Display::fmt(display, formatter),
693 }
694 }
695 }
696
697 let primary_description = self.primary_description();
698
699 let Origin::Script(primary_origin) = self.primary_origin() else {
700 return DisplayError::String(primary_description);
701 };
702
703 let Some(primary_text) = resolver.resolve(primary_origin.id()) else {
704 return DisplayError::String(primary_description);
705 };
706
707 if !primary_origin.is_valid_span(primary_text) {
708 return DisplayError::String(primary_description);
709 }
710
711 let secondary_description = self.secondary_description();
712
713 let mut snippet = primary_text.snippet();
714
715 snippet.set_caption("runtime error");
716 snippet.annotate(
717 primary_origin,
718 AnnotationPriority::Primary,
719 primary_description,
720 );
721
722 let mut summary = self.summary();
723
724 match self.secondary_origin() {
725 Some(Origin::Script(secondary_origin))
726 if secondary_origin.id() == primary_origin.id() =>
727 {
728 snippet.annotate(
729 secondary_origin,
730 AnnotationPriority::Secondary,
731 secondary_description,
732 );
733 }
734
735 Some(Origin::Script(secondary_origin)) => {
736 if let Some(secondary_text) = resolver.resolve(primary_origin.id()) {
737 if secondary_origin.is_valid_span(secondary_text) {
738 summary.push_str("\n\n");
739
740 let mut inner_snippet = secondary_text.snippet();
741
742 inner_snippet.annotate(
743 secondary_origin,
744 AnnotationPriority::Secondary,
745 secondary_description,
746 );
747
748 summary.push_str(&inner_snippet.to_string());
749 }
750 }
751 }
752
753 Some(Origin::Rust(secondary_origin)) => {
754 if let Some(code) = secondary_origin.code {
755 summary.push_str(&format!("\n\n{code}: {secondary_description}"));
756 }
757 }
758
759 None => (),
760 }
761
762 snippet.set_summary(summary);
763
764 DisplayError::Snippet(snippet)
765 }
766
767 pub fn primary_origin(&self) -> &Origin {
769 match self {
770 Self::Nil { access_origin, .. } => access_origin,
771
772 Self::NonSingleton { access_origin, .. } => access_origin,
773
774 Self::ShortSlice { access_origin, .. } => access_origin,
775
776 Self::OutOfBounds { access_origin, .. } => access_origin,
777
778 Self::ReadOnly { access_origin, .. } => access_origin,
779
780 Self::WriteOnly { access_origin, .. } => access_origin,
781
782 Self::ReadToWrite { access_origin, .. } => access_origin,
783
784 Self::WriteToRead { access_origin, .. } => access_origin,
785
786 Self::WriteToWrite { access_origin, .. } => access_origin,
787
788 Self::Utf8Decoding { access_origin, .. } => access_origin,
789
790 Self::BorrowLimit { access_origin, .. } => access_origin,
791
792 Self::TypeMismatch { access_origin, .. } => access_origin,
793
794 Self::DowncastStatic { access_origin, .. } => access_origin,
795
796 Self::UpcastResult { access_origin, .. } => access_origin,
797
798 Self::NumberCast { access_origin, .. } => access_origin,
799
800 Self::RangeCast { access_origin, .. } => access_origin,
801
802 Self::MalformedRange { access_origin, .. } => access_origin,
803
804 Self::NumericOperation { invoke_origin, .. } => invoke_origin,
805
806 Self::PrimitiveParse { access_origin, .. } => access_origin,
807
808 Self::ArityMismatch {
809 invocation_origin, ..
810 } => invocation_origin,
811
812 Self::UndefinedOperator { access_origin, .. } => access_origin,
813
814 Self::UnknownField { access_origin, .. } => access_origin,
815
816 Self::FormatError { access_origin, .. } => access_origin,
817
818 Self::UnknownPackage { access_origin, .. } => access_origin,
819
820 Self::Interrupted { origin } => origin,
821
822 Self::StackOverflow { origin, .. } => origin,
823 }
824 }
825
826 pub fn secondary_origin(&self) -> Option<&Origin> {
835 match self {
836 Self::Nil { .. } => None,
837
838 Self::NonSingleton { .. } => None,
839
840 Self::ShortSlice { .. } => None,
841
842 Self::OutOfBounds { .. } => None,
843
844 Self::ReadOnly { data_origin, .. } => Some(data_origin),
845
846 Self::WriteOnly { data_origin, .. } => Some(data_origin),
847
848 Self::ReadToWrite { borrow_origin, .. } => Some(borrow_origin),
849
850 Self::WriteToRead { borrow_origin, .. } => Some(borrow_origin),
851
852 Self::WriteToWrite { borrow_origin, .. } => Some(borrow_origin),
853
854 Self::Utf8Decoding { .. } => None,
855
856 Self::BorrowLimit { .. } => None,
857
858 Self::TypeMismatch { .. } => None,
859
860 Self::DowncastStatic { .. } => None,
861
862 Self::UpcastResult { .. } => None,
863
864 Self::NumberCast { .. } => None,
865
866 Self::NumericOperation { .. } => None,
867
868 Self::RangeCast { .. } => None,
869
870 Self::MalformedRange { .. } => None,
871
872 Self::PrimitiveParse { .. } => None,
873
874 Self::ArityMismatch {
875 function_origin, ..
876 } => Some(function_origin),
877
878 Self::UndefinedOperator {
879 receiver_origin, ..
880 } => receiver_origin.as_ref(),
881
882 Self::UnknownField {
883 receiver_origin, ..
884 } => Some(receiver_origin),
885
886 Self::FormatError {
887 receiver_origin, ..
888 } => Some(receiver_origin),
889
890 Self::UnknownPackage { .. } => None,
891
892 Self::Interrupted { .. } => None,
893
894 Self::StackOverflow { .. } => None,
895 }
896 }
897
898 #[inline(always)]
904 pub fn primary_description(&self) -> String {
905 self.to_string()
906 }
907
908 pub fn secondary_description(&self) -> String {
914 match self {
915 Self::Nil { .. } => String::new(),
916
917 Self::NonSingleton { .. } => String::new(),
918
919 Self::ShortSlice { .. } => String::new(),
920
921 Self::OutOfBounds { .. } => String::new(),
922
923 Self::ReadOnly { .. } => String::from("data object origin"),
924
925 Self::WriteOnly { .. } => String::from("data object origin"),
926
927 Self::ReadToWrite { .. } => String::from("active read access"),
928
929 Self::WriteToRead { .. } => String::from("active write access"),
930
931 Self::WriteToWrite { .. } => String::from("active write access"),
932
933 Self::Utf8Decoding { .. } => String::new(),
934
935 Self::BorrowLimit { .. } => String::new(),
936
937 Self::TypeMismatch { .. } => String::new(),
938
939 Self::DowncastStatic { .. } => String::new(),
940
941 Self::UpcastResult { .. } => String::new(),
942
943 Self::NumberCast { .. } => String::new(),
944
945 Self::NumericOperation { .. } => String::new(),
946
947 Self::RangeCast { .. } => String::new(),
948
949 Self::MalformedRange { .. } => String::new(),
950
951 Self::PrimitiveParse { .. } => String::new(),
952
953 Self::ArityMismatch { .. } => String::from("function origin"),
954
955 Self::UndefinedOperator {
956 receiver_origin, ..
957 } if receiver_origin.is_some() => String::from("receiver origin"),
958
959 Self::UndefinedOperator { .. } => String::new(),
960
961 Self::UnknownField { .. } => String::from("receiver origin"),
962
963 Self::FormatError { .. } => String::from("receiver object"),
964
965 Self::UnknownPackage { .. } => String::new(),
966
967 Self::Interrupted { .. } => String::new(),
968
969 Self::StackOverflow { .. } => String::new(),
970 }
971 }
972
973 pub fn summary(&self) -> String {
978 let result = match self {
979 Self::Nil { .. } => {
980 r#"The requested operation has been applied on the void data.
981
982The source of the void data could be:
983 - an empty array "[]",
984 - a struct field that does not exists in the struct,
985 - a function or operator that does not return any value,
986 - a function that returns "Option::None",
987 - or any other source.
988
989Use the ? operator to check if the value is void: "if a? {...}"."#
990 }
991
992 Self::NonSingleton { .. } => {
993 r#"Most script operations require singleton objects (just normal objects)
994and cannot be applied to arrays with zero or more than one element.
995
996Consider using the index operator to retrieve a single element from the array:
997 "my_array[3] + 10" instead of "my_array + 10"."#
998 }
999
1000 Self::ShortSlice { .. } => {
1001 r#"The underlying operation requires an array of longer length."#
1002 }
1003
1004 Self::OutOfBounds { .. } => {
1005 r#"The specified range or an index is out of the array bounds."#
1006 }
1007
1008 Self::ReadOnly { .. } => {
1009 r#"The underlying operation requires write access to one of its arguments,
1010but the argument reference provides read-only access."#
1011 }
1012
1013 Self::WriteOnly { .. } => {
1014 r#"The underlying operation requires read access to one of its arguments,
1015but the argument reference provides write-only access."#
1016 }
1017
1018 Self::ReadToWrite { .. } => {
1019 r#"The underlying operation requires write access to one of its arguments,
1020but the argument object is currently being read.
1021
1022The script engine does not allow simultaneous read and write access
1023to the same data.
1024
1025For instance, if the script calls a function (or an operator) with this object
1026as an argument and the function returns a reference that indirectly points
1027to the argument's data, the object is blocked for writing until the reference's
1028lifetime ends."#
1029 }
1030
1031 Self::WriteToRead { .. } => {
1032 r#"The underlying operation requires read access to one of its arguments,
1033but the argument object is currently being written.
1034
1035The script engine does not allow simultaneous read and write access
1036to the same data.
1037
1038For instance, if the script calls a function (or an operator) with this object
1039as an argument and the function returns a reference that indirectly modifies
1040argument's data, the object is blocked for reading until the reference's
1041lifetime ends."#
1042 }
1043
1044 Self::WriteToWrite { .. } => {
1045 r#"The underlying operation requires write access to one of its arguments,
1046but the argument object is currently being written.
1047
1048The script engine mandates that the ongoing write access to the data object
1049is exclusive.
1050
1051For instance, if the script calls a function (or an operator) with this object
1052as an argument and the function returns a reference that indirectly modifies
1053argument's data, the object is blocked from another write access until
1054the reference's lifetime ends."#
1055 }
1056
1057 Self::Utf8Decoding { cause, .. } => {
1058 let mut result = String::from(
1059 r#"The underlying operation is attempting to reinterpret an array of bytes
1060as a UTF-8 encoding of the Unicode text, but the script engine has detected
1061that this encoding is invalid.
1062
1063Error description:"#,
1064 );
1065
1066 for line in cause.to_string().split("\n") {
1067 result.push_str("\n ");
1068 result.push_str(line);
1069 }
1070
1071 return result;
1072 }
1073
1074 Self::BorrowLimit { .. } => {
1075 r#"The script engine has a predefined limit for active references
1076to the same data object.
1077
1078This limit may be exceeded, for example, if a recursive function attempts
1079to access the same object too many times."#
1080 }
1081
1082 Self::TypeMismatch { .. } => {
1083 r#"The underlying function (or operator) requires an argument of a different type
1084than the one being provided."#
1085 }
1086
1087 Self::DowncastStatic { .. } => {
1088 r#"The underlying function (or operator) requested a data object
1089with a lifetime that may be different from the actual object's lifetime."#
1090 }
1091
1092 Self::UpcastResult { cause, .. } => {
1093 let mut result = String::from(
1094 r#"The invoked function (or operator) returned explicit error.
1095
1096Error description:"#,
1097 );
1098
1099 for line in cause.to_string().split("\n") {
1100 result.push_str("\n ");
1101 result.push_str(line);
1102 }
1103
1104 return result;
1105 }
1106
1107 Self::NumberCast { cause, .. } => match cause {
1108 NumberCastCause::Infinite | NumberCastCause::NAN => {
1109 r#"Failed to cast primitive numeric type to another numeric type."#
1110 }
1111
1112 NumberCastCause::Overflow => {
1113 r#"Failed to cast primitive numeric type to another numeric type.
1114
1115The source value is bigger than the target type upper bound.
1116"#
1117 }
1118
1119 NumberCastCause::Underflow => {
1120 r#"Failed to cast primitive numeric type to another numeric type.
1121
1122The source value is lesser than the target type lower bound.
1123"#
1124 }
1125 },
1126
1127 Self::NumericOperation { target, .. } => {
1128 let mut result = String::from(
1129 r#"Failed to perform numeric operation between two primitive types
1130
1131The result overflows "#,
1132 );
1133
1134 result.push_str(&format!("{target}"));
1135
1136 result.push_str(" bounds.");
1137
1138 return result;
1139 }
1140
1141 Self::RangeCast { .. } => r#"Failed to cast a range to another range type."#,
1142
1143 Self::MalformedRange { .. } => r#"Malformed range bounds."#,
1144
1145 Self::PrimitiveParse { cause, .. } => {
1146 let mut result = String::from(r#"String parse error:"#);
1147
1148 for line in cause.to_string().split("\n") {
1149 result.push_str("\n ");
1150 result.push_str(line);
1151 }
1152
1153 return result;
1154 }
1155
1156 Self::ArityMismatch {
1157 parameters,
1158 arguments,
1159 ..
1160 } => match *parameters > *arguments {
1161 true => r#"Not enough arguments."#,
1162 false => r#"Too many arguments."#,
1163 },
1164
1165 Self::UndefinedOperator { .. } => {
1166 r#"The object's type that is responsible to perform specified operation does not
1167implement this operator."#
1168 }
1169
1170 Self::UnknownField { .. } => r#"The object does not have specified field."#,
1171
1172 Self::FormatError { .. } => r#"Failed to turn the object into string representation."#,
1173
1174 Self::UnknownPackage { .. } => r#"Package lookup failure."#,
1175
1176 Self::Interrupted { .. } => r#"The script explicitly terminated by the host request."#,
1177
1178 Self::StackOverflow { .. } => {
1179 r#"The script engine failed to invoke the function,
1180because the engine's thread stack exceeded its limit.
1181
1182This situation may occur in functions with unlimited recursion."#
1183 }
1184 };
1185
1186 String::from(result)
1187 }
1188
1189 fn partition_types(types: &[&'static TypeMeta]) -> Vec<String> {
1190 let mut result = Vec::new();
1191 let type_metas = types.iter().copied().collect::<AHashSet<_>>();
1192 let mut type_families = AHashMap::new();
1193
1194 for ty in type_metas {
1195 let family = ty.family();
1196
1197 if family.is_fn() || family.len() <= 1 {
1198 result.push(format!("'{}'", ty.name()));
1199 continue;
1200 }
1201
1202 match type_families.entry(family) {
1203 Entry::Vacant(entry) => {
1204 let _ = entry.insert(AHashSet::from([ty]));
1205 }
1206
1207 Entry::Occupied(mut entry) => {
1208 let _ = entry.get_mut().insert(ty);
1209 }
1210 }
1211 }
1212
1213 for (family, types) in type_families {
1214 if family.len() == types.len() {
1215 result.push(format!("'{}'", family.name()));
1216 continue;
1217 }
1218
1219 for ty in types {
1220 result.push(format!("'{}'", ty.name()));
1221 }
1222 }
1223
1224 result.sort();
1225
1226 result
1227 }
1228}
1229
1230#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1235pub enum NumberCastCause {
1236 Infinite,
1238
1239 NAN,
1241
1242 Overflow,
1244
1245 Underflow,
1247}
1248
1249#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1253pub enum NumericOperationKind {
1254 Add,
1256
1257 Sub,
1259
1260 Mul,
1262
1263 Div,
1265
1266 Neg,
1268
1269 Shl,
1271
1272 Shr,
1274
1275 Rem,
1277}
1278
1279pub trait NumValue: Debug + Display + Send + Sync + 'static {}
1280
1281impl<T: Debug + Display + Send + Sync + 'static> NumValue for T {}