1use std::io;
7use std::path::PathBuf;
8use thiserror::Error;
9
10use super::parse_error::StructuredParseError;
11
12#[derive(Debug, Error)]
14pub enum ShapeError {
15 #[error("{0}")]
17 StructuredParse(#[source] Box<StructuredParseError>),
18
19 #[error("Parse error: {message}")]
21 ParseError {
22 message: String,
23 location: Option<SourceLocation>,
24 },
25
26 #[error("Lexical error: {message}")]
28 LexError {
29 message: String,
30 location: Option<SourceLocation>,
31 },
32
33 #[error("Type error: {0}")]
35 TypeError(String),
36
37 #[error("Semantic error: {message}")]
39 SemanticError {
40 message: String,
41 location: Option<SourceLocation>,
42 },
43
44 #[error("Runtime error: {message}")]
46 RuntimeError {
47 message: String,
48 location: Option<SourceLocation>,
49 },
50
51 #[error("VM error: {0}")]
53 VMError(String),
54
55 #[error("Control flow error")]
57 ControlFlow(std::sync::Arc<dyn std::any::Any + Send + Sync>),
58
59 #[error("Pattern error: {message}")]
61 PatternError {
62 message: String,
63 pattern_name: Option<String>,
64 },
65
66 #[error("Data error: {message}")]
68 DataError {
69 message: String,
70 symbol: Option<String>,
71 timeframe: Option<String>,
72 },
73
74 #[error("Module error: {message}")]
76 ModuleError {
77 message: String,
78 module_path: Option<PathBuf>,
79 },
80
81 #[error("I/O error: {0}")]
83 IoError(#[from] io::Error),
84
85 #[error("Simulation error: {message}")]
87 SimulationError {
88 message: String,
89 simulation_name: Option<String>,
90 },
91
92 #[error("Data provider error: {message}")]
94 DataProviderError {
95 message: String,
96 provider: Option<String>,
97 },
98
99 #[error("Test error: {message}")]
101 TestError {
102 message: String,
103 test_name: Option<String>,
104 },
105
106 #[error("Configuration error: {message}")]
108 ConfigError { message: String },
109
110 #[error("Stream error: {message}")]
112 StreamError {
113 message: String,
114 stream_name: Option<String>,
115 },
116
117 #[error("Cache error: {message}")]
119 CacheError { message: String },
120
121 #[error("Alignment error: {message}")]
123 AlignmentError { message: String, ids: Vec<String> },
124
125 #[error("{}", MultiError::format(.0))]
127 MultiError(Vec<ShapeError>),
128
129 #[error("Interrupted")]
131 Interrupted { snapshot_hash: Option<String> },
132
133 #[error("{0}")]
135 Custom(String),
136}
137
138pub struct MultiError;
140
141impl MultiError {
142 pub fn format(errors: &[ShapeError]) -> String {
144 errors
145 .iter()
146 .map(|e| e.to_string())
147 .collect::<Vec<_>>()
148 .join("\n\n")
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
154pub struct SourceLocation {
155 pub file: Option<String>,
156 pub line: usize,
157 pub column: usize,
158 pub length: Option<usize>,
159 pub source_line: Option<String>,
160 pub hints: Vec<String>,
161 pub notes: Vec<ErrorNote>,
162 #[serde(default)]
163 pub is_synthetic: bool,
164}
165
166impl SourceLocation {
167 pub fn new(line: usize, column: usize) -> Self {
168 Self {
169 file: None,
170 line,
171 column,
172 length: None,
173 source_line: None,
174 hints: Vec::new(),
175 notes: Vec::new(),
176 is_synthetic: false,
177 }
178 }
179
180 pub fn with_file(mut self, file: String) -> Self {
181 self.file = Some(file);
182 self
183 }
184
185 pub fn with_length(mut self, length: usize) -> Self {
186 self.length = Some(length);
187 self
188 }
189
190 pub fn with_source_line(mut self, line: String) -> Self {
191 self.source_line = Some(line);
192 self
193 }
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
198pub enum ErrorCode {
199 E0001, E0002, E0003, E0004, E0005, E0100, E0101, E0102, E0103, E0105, E0200, E0202, E0203, E0204, E0300, E0301, E0302, E0303, E0400, E0403, E0900,
231 ParseError,
232 TypeError,
233 SemanticError,
234 RuntimeError,
235 DataError,
236 ModuleError,
237}
238
239impl ErrorCode {
240 pub fn as_str(&self) -> &'static str {
241 match self {
242 ErrorCode::E0001 => "E0001",
243 ErrorCode::E0002 => "E0002",
244 ErrorCode::E0003 => "E0003",
245 ErrorCode::E0004 => "E0004",
246 ErrorCode::E0005 => "E0005",
247 ErrorCode::E0100 => "E0100",
248 ErrorCode::E0101 => "E0101",
249 ErrorCode::E0102 => "E0102",
250 ErrorCode::E0103 => "E0103",
251 ErrorCode::E0105 => "E0105",
252 ErrorCode::E0200 => "E0200",
253 ErrorCode::E0202 => "E0202",
254 ErrorCode::E0203 => "E0203",
255 ErrorCode::E0204 => "E0204",
256 ErrorCode::E0300 => "E0300",
257 ErrorCode::E0301 => "E0301",
258 ErrorCode::E0302 => "E0302",
259 ErrorCode::E0303 => "E0303",
260 ErrorCode::E0400 => "E0400",
261 ErrorCode::E0403 => "E0403",
262 ErrorCode::E0900 => "E0900",
263 ErrorCode::ParseError => "PARSE",
264 ErrorCode::TypeError => "TYPE",
265 ErrorCode::SemanticError => "SEMANTIC",
266 ErrorCode::RuntimeError => "RUNTIME",
267 ErrorCode::DataError => "DATA",
268 ErrorCode::ModuleError => "MODULE",
269 }
270 }
271}
272
273#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
275pub struct ErrorNote {
276 pub message: String,
277 pub location: Option<SourceLocation>,
278}