You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.0 KiB
Rust

use std::fmt;
use crate::ast::tree::Type;
use crate::lex::token::Position;
/// This is just a wrapper for the actual error types.
/// I have no idea whether this is good design (probably not),
/// but idc for now. Shouldn't be too hard to change the API
/// later on bc each component of the compiler has its own
/// wrappers for instantiating errors anyway.
pub struct Error {
e: Box<dyn ErrorDetails>,
}
impl Error {
pub fn syntax_error(pos: Position, msg: String) -> Error {
Error {
e: Box::new(SyntaxError::new(pos, msg)),
}
}
pub fn type_error(pos: Position, expected: Type, actual: Type) -> Error {
Error {
e: Box::new(TypeError::new(pos, expected, actual)),
}
}
pub fn file(&self) -> &String {
self.e.file()
}
pub fn line(&self) -> usize {
self.e.line()
}
pub fn col(&self) -> usize {
self.e.col()
}
pub fn msg(&self) -> &String {
self.e.msg()
}
}
/// Anything that can go wrong while compiling and executing the build script.
trait ErrorDetails {
/// Name of the file that the error originated from.
fn file(&self) -> &String;
/// Line (starting from 1) of the first erroneous character.
fn line(&self) -> usize;
/// Column (starting from 1) of the first erroneous character.
fn col(&self) -> usize;
/// Human readable error message.
fn msg(&self) -> &String;
/// Human readable error name (mostly for internal use; see the `fmt::Display` impl).
fn name(&self) -> &str;
}
#[derive(Debug)]
pub struct SyntaxError {
pos: Position,
msg: String,
}
#[derive(Debug)]
pub struct TypeError {
pos: Position,
msg: String,
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let e = &self.e;
write!(
f,
"{} in {}:{}:{}: {}",
e.name(),
e.file(),
e.line(),
e.col(),
e.msg()
)
}
}
impl SyntaxError {
pub fn new(pos: Position, msg: String) -> SyntaxError {
SyntaxError { pos, msg }
}
}
impl TypeError {
pub fn new(pos: Position, expected: Type, actual: Type) -> TypeError {
TypeError {
pos,
msg: format!("Expected type {}, got {} instead", expected, actual),
}
}
}
impl ErrorDetails for SyntaxError {
fn file(&self) -> &String {
&self.pos.file
}
fn line(&self) -> usize {
self.pos.line
}
fn col(&self) -> usize {
self.pos.col
}
fn msg(&self) -> &String {
&self.msg
}
fn name(&self) -> &str {
"SyntaxError"
}
}
impl ErrorDetails for TypeError {
fn file(&self) -> &String {
&self.pos.file
}
fn line(&self) -> usize {
self.pos.line
}
fn col(&self) -> usize {
self.pos.col
}
fn msg(&self) -> &String {
&self.msg
}
fn name(&self) -> &str {
"TypeError"
}
}