use std::io;
use std::path::PathBuf;
use thiserror::Error;
use super::parse_error::StructuredParseError;
#[derive(Debug, Error)]
pub enum ShapeError {
#[error("{0}")]
StructuredParse(#[source] Box<StructuredParseError>),
#[error("Parse error: {message}")]
ParseError {
message: String,
location: Option<SourceLocation>,
},
#[error("Lexical error: {message}")]
LexError {
message: String,
location: Option<SourceLocation>,
},
#[error("Type error: {0}")]
TypeError(String),
#[error("Semantic error: {message}")]
SemanticError {
message: String,
location: Option<SourceLocation>,
},
#[error("Runtime error: {message}")]
RuntimeError {
message: String,
location: Option<SourceLocation>,
},
#[error("VM error: {0}")]
VMError(String),
#[error("Control flow error")]
ControlFlow(std::sync::Arc<dyn std::any::Any + Send + Sync>),
#[error("Pattern error: {message}")]
PatternError {
message: String,
pattern_name: Option<String>,
},
#[error("Data error: {message}")]
DataError {
message: String,
symbol: Option<String>,
timeframe: Option<String>,
},
#[error("Module error: {message}")]
ModuleError {
message: String,
module_path: Option<PathBuf>,
},
#[error("I/O error: {0}")]
IoError(#[from] io::Error),
#[error("Simulation error: {message}")]
SimulationError {
message: String,
simulation_name: Option<String>,
},
#[error("Data provider error: {message}")]
DataProviderError {
message: String,
provider: Option<String>,
},
#[error("Test error: {message}")]
TestError {
message: String,
test_name: Option<String>,
},
#[error("Configuration error: {message}")]
ConfigError { message: String },
#[error("Stream error: {message}")]
StreamError {
message: String,
stream_name: Option<String>,
},
#[error("Cache error: {message}")]
CacheError { message: String },
#[error("Alignment error: {message}")]
AlignmentError { message: String, ids: Vec<String> },
#[error("{}", MultiError::format(.0))]
MultiError(Vec<ShapeError>),
#[error("Interrupted")]
Interrupted { snapshot_hash: Option<String> },
#[error("{0}")]
Custom(String),
}
pub struct MultiError;
impl MultiError {
pub fn format(errors: &[ShapeError]) -> String {
errors
.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join("\n\n")
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct SourceLocation {
pub file: Option<String>,
pub line: usize,
pub column: usize,
pub length: Option<usize>,
pub source_line: Option<String>,
pub hints: Vec<String>,
pub notes: Vec<ErrorNote>,
#[serde(default)]
pub is_synthetic: bool,
}
impl SourceLocation {
pub fn new(line: usize, column: usize) -> Self {
Self {
file: None,
line,
column,
length: None,
source_line: None,
hints: Vec::new(),
notes: Vec::new(),
is_synthetic: false,
}
}
pub fn with_file(mut self, file: String) -> Self {
self.file = Some(file);
self
}
pub fn with_length(mut self, length: usize) -> Self {
self.length = Some(length);
self
}
pub fn with_source_line(mut self, line: String) -> Self {
self.source_line = Some(line);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum ErrorCode {
E0001, E0002, E0003, E0004, E0005, E0100, E0101, E0102, E0103, E0105, E0200, E0202, E0203, E0204, E0300, E0301, E0302, E0303, E0400, E0403, ParseError,
TypeError,
SemanticError,
RuntimeError,
DataError,
ModuleError,
}
impl ErrorCode {
pub fn as_str(&self) -> &'static str {
match self {
ErrorCode::E0001 => "E0001",
ErrorCode::E0002 => "E0002",
ErrorCode::E0003 => "E0003",
ErrorCode::E0004 => "E0004",
ErrorCode::E0005 => "E0005",
ErrorCode::E0100 => "E0100",
ErrorCode::E0101 => "E0101",
ErrorCode::E0102 => "E0102",
ErrorCode::E0103 => "E0103",
ErrorCode::E0105 => "E0105",
ErrorCode::E0200 => "E0200",
ErrorCode::E0202 => "E0202",
ErrorCode::E0203 => "E0203",
ErrorCode::E0204 => "E0204",
ErrorCode::E0300 => "E0300",
ErrorCode::E0301 => "E0301",
ErrorCode::E0302 => "E0302",
ErrorCode::E0303 => "E0303",
ErrorCode::E0400 => "E0400",
ErrorCode::E0403 => "E0403",
ErrorCode::ParseError => "PARSE",
ErrorCode::TypeError => "TYPE",
ErrorCode::SemanticError => "SEMANTIC",
ErrorCode::RuntimeError => "RUNTIME",
ErrorCode::DataError => "DATA",
ErrorCode::ModuleError => "MODULE",
}
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ErrorNote {
pub message: String,
pub location: Option<SourceLocation>,
}