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