use crate::error::CompilerError as OldCompilerError;
use crate::enhanced_error::{CompilerError, SourceLocation, ErrorReporter};
pub fn legacy_to_enhanced(error: OldCompilerError) -> CompilerError {
match error {
OldCompilerError::IoError(msg) => CompilerError::config_error(msg),
OldCompilerError::ParseError(msg) => {
let location = SourceLocation::new(0, 1, 1, 0, msg.len());
CompilerError::semantic_error(location, msg, None)
},
OldCompilerError::UnexpectedToken(msg) => {
let location = SourceLocation::new(0, 1, 1, 0, msg.len());
CompilerError::syntax_error(location, msg, Vec::new())
},
OldCompilerError::CompilationError(msg) => {
let location = SourceLocation::new(0, 1, 1, 0, msg.len());
CompilerError::semantic_error(location, msg, None)
},
}
}
pub fn enhanced_to_legacy(error: CompilerError) -> OldCompilerError {
match error {
CompilerError::IoError(msg) => OldCompilerError::IoError(msg),
CompilerError::LexerError { location: _, message } => {
OldCompilerError::ParseError(message)
},
CompilerError::SyntaxError { location: _, message, expected_tokens: _ } => {
OldCompilerError::UnexpectedToken(message)
},
CompilerError::SemanticError { location: _, message, suggestion: _ } => {
OldCompilerError::ParseError(message)
},
CompilerError::TypeError { location: _, message, .. } => {
OldCompilerError::ParseError(message)
},
CompilerError::CodegenError { location: _, message } => {
OldCompilerError::CompilationError(message)
},
CompilerError::OptimizerError { location: _, message } => {
OldCompilerError::CompilationError(message)
},
CompilerError::RuntimeError { location: _, message } => {
OldCompilerError::CompilationError(message)
},
CompilerError::InternalError { location: _, message } => {
OldCompilerError::CompilationError(message)
},
CompilerError::ConfigError { message } => {
OldCompilerError::IoError(message)
},
}
}
pub trait ErrorReporting {
fn report_to(&self, reporter: &mut ErrorReporter);
}
impl ErrorReporting for OldCompilerError {
fn report_to(&self, reporter: &mut ErrorReporter) {
let enhanced = legacy_to_enhanced(self.clone());
reporter.report_error(enhanced);
}
}
pub type Result<T> = std::result::Result<T, CompilerError>;
pub type LegacyResult<T> = std::result::Result<T, OldCompilerError>;
pub trait ResultExt<T> {
fn to_enhanced(self) -> Result<T>;
fn report_on_error(self, reporter: &mut ErrorReporter) -> Result<T>;
}
impl<T> ResultExt<T> for LegacyResult<T> {
fn to_enhanced(self) -> Result<T> {
self.map_err(legacy_to_enhanced)
}
fn report_on_error(self, reporter: &mut ErrorReporter) -> Result<T> {
match self {
Ok(value) => Ok(value),
Err(legacy_error) => {
legacy_error.report_to(reporter);
Err(legacy_to_enhanced(legacy_error))
}
}
}
}
pub fn format_error_message(error: &CompilerError, _source_manager: &ErrorReporter) -> String {
match error {
CompilerError::LexerError { location, message } => {
format!("Lexical error at {}: {}", location.format(), message)
},
CompilerError::SyntaxError { location, message, expected_tokens } => {
let expected = if expected_tokens.is_empty() {
"token".to_string()
} else {
expected_tokens.join(", ")
};
format!("Syntax error at {}: Expected {}, found {}",
location.format(), expected, message)
},
CompilerError::SemanticError { location, message, suggestion } => {
let suggestion_text = if let Some(s) = suggestion {
format!(" ({})", s)
} else {
"".to_string()
};
format!("Semantic error at {}: {}{}", location.format(), message, suggestion_text)
},
CompilerError::TypeError { location, message: _, expected, found } => {
format!("Type error at {}: Expected {}, found {}",
location.format(), expected, found)
},
CompilerError::CodegenError { location, message } => {
if let Some(loc) = location {
format!("Code generation error at {}: {}", loc.format(), message)
} else {
format!("Code generation error: {}", message)
}
},
CompilerError::OptimizerError { location, message } => {
if let Some(loc) = location {
format!("Optimizer error at {}: {}", loc.format(), message)
} else {
format!("Optimizer error: {}", message)
}
},
CompilerError::RuntimeError { location, message } => {
if let Some(loc) = location {
format!("Runtime error at {}: {}", loc.format(), message)
} else {
format!("Runtime error: {}", message)
}
},
CompilerError::InternalError { location, message } => {
if let Some(loc) = location {
format!("Internal error at {}: {}", loc.format(), message)
} else {
format!("Internal error: {}", message)
}
},
CompilerError::IoError(message) | CompilerError::ConfigError { message } => {
format!("{}: {}", error.severity().as_str(), message)
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::enhanced_error::SourceLocation;
#[test]
fn test_error_conversion() {
let legacy_error = OldCompilerError::ParseError("Test error".to_string());
let enhanced_error = legacy_to_enhanced(legacy_error);
assert!(matches!(enhanced_error, CompilerError::SemanticError { .. }));
}
#[test]
fn test_enhanced_to_legacy() {
let location = SourceLocation::new(0, 1, 1, 0, 0);
let enhanced_error = CompilerError::syntax_error(location, "Test error".to_string(), Vec::new());
let legacy_error = enhanced_to_legacy(enhanced_error);
assert!(matches!(legacy_error, OldCompilerError::UnexpectedToken(..)));
}
#[test]
fn test_error_reporting() {
let mut reporter = ErrorReporter::new();
let legacy_error = OldCompilerError::ParseError("Test error".to_string());
legacy_error.report_to(&mut reporter);
assert_eq!(reporter.error_count(), 1);
assert_eq!(reporter.diagnostics().len(), 1);
}
#[test]
fn test_result_extensions() {
let mut reporter = ErrorReporter::new();
let legacy_result1: LegacyResult<i32> = Err(OldCompilerError::ParseError("Test".to_string()));
let legacy_result2 = legacy_result1.clone();
let enhanced_result = legacy_result1.to_enhanced();
assert!(enhanced_result.is_err());
let result_with_reporting = legacy_result2.report_on_error(&mut reporter);
assert!(result_with_reporting.is_err());
assert_eq!(reporter.error_count(), 1);
}
}