1#![allow(unused, unused_assignments)]
7
8use crate::{
9 eval::*,
10 lower::{LowerError, ir},
11 model::OutputType,
12 resolve::*,
13 ty::*,
14 value::*,
15};
16use microcad_lang_base::{DiagError, Identifier, SrcRef};
17use miette::Diagnostic;
18use thiserror::Error;
19
20#[derive(Debug, Error, Diagnostic)]
22#[allow(missing_docs)]
23pub enum EvalError {
24 #[error("Not implemented: {0}")]
26 Todo(String),
27
28 #[error("List index out of bounds: {index} >= {len}")]
30 ListIndexOutOfBounds {
31 index: usize,
33 len: usize,
35 },
36
37 #[error("Type mismatch for `{id}`: expected {expected}, got {found}")]
39 TypeMismatch {
40 id: Identifier,
42 expected: Type,
44 found: Type,
46 },
47
48 #[error("Array elements have different types: {0}")]
50 ArrayElementsDifferentTypes(TypeList),
51
52 #[error("Symbol {0} not found.")]
54 SymbolNotFound(ir::QualifiedName),
55
56 #[error("Symbol `{0}` cannot be called.")]
58 SymbolCannotBeCalled(ir::QualifiedName),
59
60 #[error("Ambiguous symbol {0} might be one of the following: {1}")]
62 AmbiguousSymbol(ir::QualifiedName, ir::QualifiedNames),
63
64 #[error("Local symbol not found: {0}")]
66 LocalNotFound(Identifier),
67
68 #[error("Property not found: {0}")]
70 PropertyNotFound(Identifier),
71
72 #[error("Not a property id: {0}")]
74 NoPropertyId(ir::QualifiedName),
75
76 #[error("Argument count mismatch: expected {expected}, got {found} in {args}")]
78 ArgumentCountMismatch {
79 args: String,
81 expected: usize,
83 found: usize,
85 },
86
87 #[error("Assertion failed: {0}")]
89 AssertionFailed(String),
90
91 #[error("Expected type `{expected}`, found type `{found}")]
93 ExpectedType {
94 expected: Type,
96 found: Type,
98 },
99
100 #[error("Diagnostic error: {0}")]
102 DiagError(#[from] DiagError),
103
104 #[error("Local stack needed to store {0}")]
106 LocalStackEmpty(Identifier),
107
108 #[error("Unexpected stack frame of type '{1}' cannot store {0}")]
110 WrongStackFrame(Identifier, &'static str),
111
112 #[error("Value Error: {0}")]
114 ValueError(#[from] ValueError),
115
116 #[error("Unknown method `{0}`")]
118 UnknownMethod(ir::QualifiedName),
119
120 #[error("Parsing error {0}")]
122 LowerError(#[from] LowerError),
123
124 #[error("Unexpected {0} {1} within expression")]
126 UnexpectedNested(&'static str, Identifier),
127
128 #[error("Missing arguments: {0}")]
130 MissingArguments(ir::IdentifierList),
131
132 #[error("Too many arguments: {0}")]
134 TooManyArguments(ir::IdentifierList),
135
136 #[error("Arguments match by identifier but have incompatible types: {0}")]
138 IdMatchButNotType(String),
139
140 #[error("Builtin error: {0}")]
142 BuiltinError(String),
143
144 #[error("Multiplicity not allowed '{0}'")]
146 MultiplicityNotAllowed(ir::IdentifierList),
147
148 #[error("Cannot mix 2d and 3d geometries")]
150 CannotMixGeometry,
151
152 #[error("If condition is not a boolean: {condition}")]
154 IfConditionIsNotBool {
155 condition: String,
156 #[label("Not a boolean")]
157 src_ref: SrcRef,
158 },
159
160 #[error("Workbench {name} cannot find initialization for those arguments")]
162 #[diagnostic(help("Possible initializations: \n\t{}", possible_params.join("\n\t")))]
163 NoInitializationFound {
164 #[label("Got: {name}( {actual_params} )")]
165 src_ref: SrcRef,
166 name: Identifier,
167 actual_params: String,
168 possible_params: Vec<String>,
169 },
170 #[error("Workbench {name} has ambiguous initialization for those arguments")]
172 #[diagnostic(help("Ambiguous initializations: \n\t{}", ambiguous_params.join("\n\t")))]
173 AmbiguousInitialization {
174 #[label("Got: {name}( {actual_params} )")]
175 src_ref: SrcRef,
176 name: Identifier,
177 actual_params: String,
178 ambiguous_params: Vec<String>,
179 },
180
181 #[error("Building plan incomplete. Missing properties: {0}")]
183 BuildingPlanIncomplete(ir::IdentifierList),
184
185 #[error("This expression statement did not produce any model")]
187 EmptyModelExpression,
188
189 #[error("The {kind} workbench produced a {produced} output, but expected a {expected} output.")]
191 WorkbenchInvalidOutput {
192 kind: ir::WorkbenchKind,
193 produced: OutputType,
194 expected: OutputType,
195 },
196
197 #[error("Resolve error: {0}")]
199 #[diagnostic(transparent)]
200 ResolveError(ResolveError),
201
202 #[error("Cannot call operation without workpiece.")]
204 CannotCallOperationWithoutWorkpiece,
205
206 #[error("Missing model in workbench")]
208 NoModelInWorkbench,
209
210 #[error("Value {name} already in defined: {value}")]
212 #[diagnostic(help("Values in microcad are immutable"))]
213 ValueAlreadyDefined {
214 #[label(primary, "{name} is already defined")]
216 location: SrcRef,
217 name: Identifier,
219 value: String,
221 #[label("Previously defined here")]
223 previous_location: SrcRef,
224 },
225
226 #[error("Assignment failed because {0} is not an l-value")]
228 NotAnLValue(Identifier),
229
230 #[error("Symbol {what} is private from within {within}")]
232 SymbolIsPrivate {
233 what: ir::QualifiedName,
235 within: ir::QualifiedName,
237 },
238
239 #[error("Unused global symbol {0}.")]
241 UnusedGlobalSymbol(String),
242
243 #[error("Unused local {0}.")]
245 UnusedLocal(Identifier),
246
247 #[error("Evaluation aborted because of prior resolve errors!")]
249 ResolveFailed,
250
251 #[error("Bad range, first number ({0}) must be smaller than last ({1})")]
253 BadRange(i64, i64),
254
255 #[error("Ambiguous type '{ty}' in tuple")]
257 AmbiguousType {
258 ty: Type,
259 #[label(
260 "Some unnamed values in this tuple share the same type '{ty}'.\nMaybe check the units or use identifiers in this tuple."
261 )]
262 src_ref: SrcRef,
263 },
264}
265
266pub type EvalResult<T> = std::result::Result<T, Box<EvalError>>;
268
269impl From<ResolveError> for EvalError {
270 fn from(err: ResolveError) -> Self {
271 match err {
272 ResolveError::SymbolNotFound(name) => EvalError::SymbolNotFound(name),
273 other => EvalError::ResolveError(other),
274 }
275 }
276}
277
278impl From<Box<EvalError>> for miette::Report {
279 fn from(value: Box<EvalError>) -> Self {
280 miette::Report::new(*value)
281 }
282}
283
284impl From<DiagError> for Box<EvalError> {
285 fn from(value: DiagError) -> Self {
286 Box::new(value.into())
287 }
288}
289
290impl From<ValueError> for Box<EvalError> {
291 fn from(value: ValueError) -> Self {
292 Box::new(value.into())
293 }
294}
295
296impl From<ResolveError> for Box<EvalError> {
297 fn from(value: ResolveError) -> Self {
298 Box::new(value.into())
299 }
300}