154 lines
4.7 KiB
Rust
154 lines
4.7 KiB
Rust
use crate::frontend::source_registry::{SourcePosition, SourceRegistry, SourceSlice};
|
|||
|
|
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub enum LoxError {
|
||
|
|
LexicalError {
|
||
|
|
source_slice: SourceSlice,
|
||
|
|
message: String,
|
||
|
|
},
|
||
|
|
RuntimeError {
|
||
|
|
source_slice: SourceSlice,
|
||
|
|
message: String,
|
||
|
|
},
|
||
|
|
ParseError {
|
||
|
|
source_slice: SourceSlice,
|
||
|
|
message: String,
|
||
|
|
},
|
||
|
|
IoError {
|
||
|
|
message: String,
|
||
|
|
},
|
||
|
|
TypeMismatch {
|
||
|
|
source_slice: SourceSlice,
|
||
|
|
expected: String,
|
||
|
|
found: String,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
impl LoxError {
|
||
|
|
pub fn get_message(&self) -> String {
|
||
|
|
match self {
|
||
|
|
LoxError::LexicalError { message, .. } => message.clone(),
|
||
|
|
LoxError::RuntimeError { message, .. } => message.clone(),
|
||
|
|
LoxError::ParseError { message, .. } => message.clone(),
|
||
|
|
LoxError::IoError { message } => message.clone(),
|
||
|
|
LoxError::TypeMismatch {
|
||
|
|
expected, found, ..
|
||
|
|
} => {
|
||
|
|
format!("expected {}, found {}", expected, found)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn get_source_slice(&self) -> Option<SourceSlice> {
|
||
|
|
match self {
|
||
|
|
LoxError::LexicalError { source_slice, .. } => Some(source_slice.clone()),
|
||
|
|
LoxError::RuntimeError { source_slice, .. } => Some(source_slice.clone()),
|
||
|
|
LoxError::ParseError { source_slice, .. } => Some(source_slice.clone()),
|
||
|
|
LoxError::IoError { .. } => None,
|
||
|
|
LoxError::TypeMismatch { source_slice, .. } => Some(source_slice.clone()),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn print_with_context(&self, source_registry: &SourceRegistry) {
|
||
|
|
match self.get_source_slice() {
|
||
|
|
Some(source_slice) => {
|
||
|
|
let source_code = source_registry.get_source_code(&source_slice);
|
||
|
|
println!(
|
||
|
|
"\n =============================================== \n DATA:{} \n CODE \n {} | {}",
|
||
|
|
self, source_slice.start_position.line ,source_code
|
||
|
|
);
|
||
|
|
}
|
||
|
|
None => println!("{}", self),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn fetch_source_code(path: &str, start: SourcePosition, end: SourcePosition) -> LoxResult<String> {
|
||
|
|
let source_code = std::fs::read_to_string(path).map_err(|e| LoxError::IoError {
|
||
|
|
message: format!("Failed to read file: {}", e),
|
||
|
|
})?;
|
||
|
|
|
||
|
|
let lines: Vec<&str> = source_code.split('\n').collect();
|
||
|
|
|
||
|
|
// Verifica bounds
|
||
|
|
if start.line >= lines.len() || end.line >= lines.len() {
|
||
|
|
return Err(LoxError::IoError {
|
||
|
|
message: "Line number out of bounds".to_string(),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
let mut result = String::new();
|
||
|
|
|
||
|
|
if start.line == end.line {
|
||
|
|
// Caso speciale: stessa riga
|
||
|
|
let line = lines[start.line];
|
||
|
|
if end.column <= line.len() && start.column <= end.column {
|
||
|
|
result.push_str(&line[start.column..end.column]);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// Caso generale: righe multiple
|
||
|
|
|
||
|
|
// Prima riga: da start.column alla fine della riga
|
||
|
|
let first_line = lines[start.line];
|
||
|
|
if start.column < first_line.len() {
|
||
|
|
result.push_str(&first_line[start.column..]);
|
||
|
|
}
|
||
|
|
result.push('\n');
|
||
|
|
|
||
|
|
// Righe intermedie: complete
|
||
|
|
for i in (start.line + 1)..end.line {
|
||
|
|
result.push_str(lines[i]);
|
||
|
|
result.push('\n');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Ultima riga: dall'inizio fino a end.column
|
||
|
|
let last_line = lines[end.line];
|
||
|
|
if end.column <= last_line.len() {
|
||
|
|
result.push_str(&last_line[..end.column]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Ok(result)
|
||
|
|
}
|
||
|
|
|
||
|
|
impl std::fmt::Display for LoxError {
|
||
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
|
|
match self {
|
||
|
|
LoxError::LexicalError {
|
||
|
|
source_slice,
|
||
|
|
message,
|
||
|
|
} => {
|
||
|
|
write!(f, "Lexical error on {:?}: \n {}", source_slice, message)
|
||
|
|
}
|
||
|
|
LoxError::RuntimeError {
|
||
|
|
source_slice,
|
||
|
|
message,
|
||
|
|
} => {
|
||
|
|
write!(f, "Runtime error on {:?}: \n{}", source_slice, message)
|
||
|
|
}
|
||
|
|
LoxError::ParseError {
|
||
|
|
source_slice,
|
||
|
|
message,
|
||
|
|
} => {
|
||
|
|
write!(f, "Parse error on {:?}: \n{}", source_slice, message)
|
||
|
|
}
|
||
|
|
LoxError::IoError { message } => write!(f, "IO error: {}", message),
|
||
|
|
LoxError::TypeMismatch {
|
||
|
|
source_slice,
|
||
|
|
expected,
|
||
|
|
found,
|
||
|
|
} => {
|
||
|
|
write!(
|
||
|
|
f,
|
||
|
|
"Type mismatch on {:?}: \n expected {}, found {}",
|
||
|
|
source_slice, expected, found
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl std::error::Error for LoxError {}
|
||
|
|
|
||
|
|
pub type LoxResult<T> = Result<T, LoxError>;
|