geam_core/runtime/
error.rs1mod diagnostic;
2mod host;
3mod invariant;
4mod panic;
5
6use crate::plan::{PanicSite, SourceContext, SourceSpan};
7use crate::runtime::Value;
8use ecow::EcoString;
9
10pub(crate) use self::host::HostCallOrigin;
11pub use self::host::{HostError, HostLocation, HostOrigin};
12pub use self::invariant::InvariantError;
13pub use self::panic::{BitArraySegmentPanicReason, Panic, PanicDetails, PanicKind, PanicMessage};
14
15#[derive(Debug, Clone, PartialEq, thiserror::Error)]
16pub enum ExecutionError {
17 #[error("{0}")]
18 Panic(Panic),
19 #[error("{0}")]
20 Invariant(InvariantError),
21 #[error("{0}")]
22 Host(Box<HostError>),
23}
24
25pub(crate) type ExecutionResult<T> = Result<T, ExecutionError>;
26
27impl ExecutionError {
28 pub(crate) fn from_host_call(
29 function: &crate::plan::execution::host::HostedFunctionMetadata,
30 site: crate::plan::HostCallSite,
31 source_context: Option<&SourceContext>,
32 failure: crate::HostFailure,
33 ) -> Self {
34 Self::Host(Box::new(HostError::new(
35 function.package().clone(),
36 function.module().clone(),
37 function.name().clone(),
38 function.signature().clone(),
39 failure,
40 site,
41 source_context,
42 )))
43 }
44
45 pub(crate) fn from_host_origin(
46 function: &crate::plan::execution::host::HostedFunctionMetadata,
47 caller: HostOrigin,
48 failure: crate::HostFailure,
49 ) -> Self {
50 Self::Host(Box::new(HostError::new_from_host(
51 function.package().clone(),
52 function.module().clone(),
53 function.name().clone(),
54 function.signature().clone(),
55 failure,
56 caller,
57 )))
58 }
59
60 pub(crate) fn source_panic(
61 source_context: Option<&SourceContext>,
62 kind: PanicKind,
63 message: Option<EcoString>,
64 site: PanicSite,
65 ) -> Self {
66 Self::Panic(Panic::new(
67 kind,
68 PanicMessage::from_optional_explicit(message),
69 site,
70 source_context,
71 None,
72 ))
73 }
74
75 pub(crate) fn let_assert_panic(
76 source_context: Option<&SourceContext>,
77 message: Option<EcoString>,
78 site: PanicSite,
79 value: Value,
80 pattern_span: SourceSpan,
81 ) -> Self {
82 Self::Panic(Panic::new(
83 PanicKind::LetAssert,
84 PanicMessage::from_optional_explicit(message),
85 site,
86 source_context,
87 Some(PanicDetails::LetAssert {
88 value,
89 pattern_span,
90 }),
91 ))
92 }
93
94 pub(crate) fn bit_array_segment_panic(
95 source_context: Option<&SourceContext>,
96 reason: BitArraySegmentPanicReason,
97 site: PanicSite,
98 ) -> Self {
99 Self::Panic(Panic::new(
100 PanicKind::BitArraySegment,
101 PanicMessage::Default,
102 site,
103 source_context,
104 Some(PanicDetails::BitArraySegment { reason }),
105 ))
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::{ExecutionError, InvariantError};
112 use crate::plan::execution::function::FunctionReturnFamily;
113
114 #[test]
115 fn invariant_display_delegates_to_invariant_error() {
116 let invariant = InvariantError::FunctionReturnFamilyMismatch {
117 expected: FunctionReturnFamily::Int,
118 actual: FunctionReturnFamily::String,
119 };
120 let error = ExecutionError::Invariant(invariant);
121
122 assert_eq!(
123 error.to_string(),
124 "function return family mismatch (expected Int, got String)",
125 );
126 }
127}