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, ParseError,
220 TypeError,
221 SemanticError,
222 RuntimeError,
223 DataError,
224 ModuleError,
225}
226
227impl ErrorCode {
228 pub fn as_str(&self) -> &'static str {
229 match self {
230 ErrorCode::E0001 => "E0001",
231 ErrorCode::E0002 => "E0002",
232 ErrorCode::E0003 => "E0003",
233 ErrorCode::E0004 => "E0004",
234 ErrorCode::E0005 => "E0005",
235 ErrorCode::E0100 => "E0100",
236 ErrorCode::E0101 => "E0101",
237 ErrorCode::E0102 => "E0102",
238 ErrorCode::E0103 => "E0103",
239 ErrorCode::E0105 => "E0105",
240 ErrorCode::E0200 => "E0200",
241 ErrorCode::E0202 => "E0202",
242 ErrorCode::E0203 => "E0203",
243 ErrorCode::E0204 => "E0204",
244 ErrorCode::E0300 => "E0300",
245 ErrorCode::E0301 => "E0301",
246 ErrorCode::E0302 => "E0302",
247 ErrorCode::E0303 => "E0303",
248 ErrorCode::E0400 => "E0400",
249 ErrorCode::E0403 => "E0403",
250 ErrorCode::ParseError => "PARSE",
251 ErrorCode::TypeError => "TYPE",
252 ErrorCode::SemanticError => "SEMANTIC",
253 ErrorCode::RuntimeError => "RUNTIME",
254 ErrorCode::DataError => "DATA",
255 ErrorCode::ModuleError => "MODULE",
256 }
257 }
258}
259
260#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
262pub struct ErrorNote {
263 pub message: String,
264 pub location: Option<SourceLocation>,
265}