1#![expect(unused_assignments)]
2
3use crate::common::*;
4
5#[derive(Default, Diagnostic, Clone, Debug, thiserror::Error)]
6pub enum ExprError {
7 #[error("invalid token")]
8 #[diagnostic()]
9 InvalidToken {
10 #[label("occurs here")]
11 span: SourceSpan,
12 },
13 #[error("unrecognized token")]
14 #[diagnostic(help("expected one of: {}", expected.as_slice().join(", ")))]
15 UnrecognizedToken {
16 #[label("lexed a {token} here")]
17 span: SourceSpan,
18 token: String,
19 expected: Vec<String>,
20 },
21 #[error("unexpected trailing tokens")]
22 #[diagnostic()]
23 ExtraToken {
24 #[label("{token} was found here, but was not expected")]
25 span: SourceSpan,
26 token: String,
27 },
28 #[error("unexpected end of file")]
29 #[diagnostic(help("expected one of: {}", expected.as_slice().join(", ")))]
30 UnrecognizedEof {
31 #[label("reached end of file here")]
32 span: SourceSpan,
33 expected: Vec<String>,
34 },
35 #[error(transparent)]
36 #[diagnostic(transparent)]
37 InvalidCall(#[from] InvalidCallExprError),
38 #[error("invalid numeric expression")]
39 #[diagnostic(help("make sure the value is parseable as a 64-bit signed integer"))]
40 Number {
41 #[label("{error}")]
42 span: SourceSpan,
43 #[source]
44 error: core::num::ParseIntError,
45 },
46 #[error("invalid format specifier")]
47 #[diagnostic()]
48 InvalidFormatSpecifier {
49 #[label("this numeric format specifier is not recognized")]
50 span: SourceSpan,
51 },
52 #[error("invalid numeric precision")]
53 #[diagnostic()]
54 InvalidNumericPrecision {
55 #[label("the precision value here is too large")]
56 span: SourceSpan,
57 },
58 #[error("invalid format specifier")]
59 #[diagnostic()]
60 InvalidAlternateForm {
61 #[label("alternate form only supported for hex values")]
62 span: SourceSpan,
63 },
64 #[default]
66 #[error("an unknown error occurred")]
67 #[diagnostic()]
68 Unknown,
69}
70impl PartialEq for ExprError {
71 fn eq(&self, other: &Self) -> bool {
72 match (self, other) {
73 (Self::InvalidToken { .. }, Self::InvalidToken { .. }) => true,
74 (
75 Self::UnrecognizedToken {
76 token: at,
77 expected: a,
78 ..
79 },
80 Self::UnrecognizedToken {
81 token: bt,
82 expected: b,
83 ..
84 },
85 ) => at == bt && a == b,
86 (Self::ExtraToken { token: a, .. }, Self::ExtraToken { token: b, .. }) => a == b,
87 (
88 Self::UnrecognizedEof { expected: a, .. },
89 Self::UnrecognizedEof { expected: b, .. },
90 ) => a == b,
91 (Self::InvalidCall(a), Self::InvalidCall(b)) => a == b,
92 (Self::Number { .. }, Self::Number { .. }) => true,
93 (Self::InvalidFormatSpecifier { .. }, Self::InvalidFormatSpecifier { .. }) => true,
94 (Self::InvalidNumericPrecision { .. }, Self::InvalidNumericPrecision { .. }) => true,
95 (Self::InvalidAlternateForm { .. }, Self::InvalidAlternateForm { .. }) => true,
96 (Self::Unknown, Self::Unknown) => true,
97 _ => false,
98 }
99 }
100}
101impl Spanned for ExprError {
102 fn span(&self) -> SourceSpan {
103 match self {
104 Self::InvalidCall(err) => err.span(),
105 Self::InvalidToken { span, .. }
106 | Self::UnrecognizedToken { span, .. }
107 | Self::ExtraToken { span, .. }
108 | Self::UnrecognizedEof { span, .. }
109 | Self::Number { span, .. }
110 | Self::InvalidFormatSpecifier { span, .. }
111 | Self::InvalidNumericPrecision { span, .. }
112 | Self::InvalidAlternateForm { span, .. } => *span,
113 Self::Unknown => SourceSpan::UNKNOWN,
114 }
115 }
116}
117
118#[derive(Debug, Clone, Diagnostic, thiserror::Error)]
119pub enum InvalidCallExprError {
120 #[error("undefined function")]
121 #[diagnostic()]
122 Undefined {
123 #[label("no such function defined in this context")]
124 span: SourceSpan,
125 callee: String,
126 },
127 #[error("function '{callee}' expects {expected} arguments, but was given {given}")]
128 #[diagnostic()]
129 InvalidArity {
130 #[label("this function only takes {expected} arguments")]
131 span: SourceSpan,
132 callee: String,
133 expected: u8,
134 given: u8,
135 },
136}
137impl Spanned for InvalidCallExprError {
138 fn span(&self) -> SourceSpan {
139 match self {
140 Self::Undefined { span, .. } | Self::InvalidArity { span, .. } => *span,
141 }
142 }
143}
144impl PartialEq for InvalidCallExprError {
145 fn eq(&self, other: &Self) -> bool {
146 match (self, other) {
147 (Self::Undefined { callee: a, .. }, Self::Undefined { callee: b, .. }) => a == b,
148 (
149 Self::InvalidArity {
150 callee: a,
151 expected: ae,
152 given: ag,
153 ..
154 },
155 Self::InvalidArity {
156 callee: b,
157 expected: be,
158 given: bg,
159 ..
160 },
161 ) => a == b && ae == be && ag == bg,
162 _ => false,
163 }
164 }
165}