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.
147 lines
3.2 KiB
Rust
147 lines
3.2 KiB
Rust
use std::fmt;
|
|
use std::fmt::Formatter;
|
|
use crate::ast::tree::Type;
|
|
|
|
/// 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.
|
|
#[derive(Debug)]
|
|
pub struct Error {
|
|
e: Box<dyn ErrorDetails>,
|
|
}
|
|
|
|
impl Error {
|
|
pub fn syntax_error(file: String, line: usize, col: usize, msg: String) -> Error {
|
|
Error {
|
|
e: Box::new(SyntaxError::new(file, line, col, msg))
|
|
}
|
|
}
|
|
|
|
pub fn type_error(file: String, line: usize, col: usize, expected: Type, actual: Type) -> Error {
|
|
Error {
|
|
e: Box::new(TypeError::new(file, line, col, 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)]
|
|
struct Position {
|
|
file: String,
|
|
line: usize,
|
|
col: usize,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct SyntaxError {
|
|
pos: Position,
|
|
msg: String,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct TypeError {
|
|
pos: Position,
|
|
expected: Type,
|
|
actual: Type,
|
|
}
|
|
|
|
impl fmt::Display for dyn ErrorDetails {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
write!(f, "{} in {}:{}:{}: {}", self.name(), self.file(), self.line(), self.col(), self.msg())
|
|
}
|
|
}
|
|
|
|
impl SyntaxError {
|
|
pub fn new(file: String, line: usize, col: usize, msg: String) -> SyntaxError {
|
|
SyntaxError {
|
|
pos: Position { file, line, col },
|
|
msg,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TypeError {
|
|
pub fn new(file: String, line: usize, col: usize, expected: Type, actual: Type) -> TypeError {
|
|
TypeError {
|
|
pos: Position { file, line, col },
|
|
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 {
|
|
&format!("Expected type {}, got {} instead", self.expected, self.actual)
|
|
}
|
|
|
|
fn name(&self) -> &str {
|
|
"TypeError"
|
|
}
|
|
}
|