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
144 lines
3.0 KiB
Rust
use std::{fmt, io};
|
|
|
|
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"
|
|
}
|
|
}
|