diff --git a/Cargo.lock b/Cargo.lock index 4eb7985..9b5e381 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,6 +152,7 @@ dependencies = [ "libloading", "serde", "serde_json", + "thiserror", ] [[package]] @@ -227,6 +228,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index e09cc8b..09966f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" clap = { version = "4.5.9", features = ["derive"] } indoc = "2.0.5" libloading = "0.8.5" +thiserror = "1.0.64" [lib] name = "meraki" diff --git a/src/archs/error.rs b/src/archs/error.rs index a3533c8..8018b62 100644 --- a/src/archs/error.rs +++ b/src/archs/error.rs @@ -2,37 +2,16 @@ use crate::{ parser::ExprError, register::allocator::AllocatorError, symbol_table::SymbolTableError, types::TypeError, }; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum ArchError { - Type(TypeError), - Allocator(AllocatorError), - SymbolTable(SymbolTableError), -} - -impl From for ArchError { - fn from(value: TypeError) -> Self { - Self::Type(value) - } -} - -impl From for ArchError { - fn from(value: AllocatorError) -> Self { - Self::Allocator(value) - } -} - -impl From for ArchError { - fn from(value: SymbolTableError) -> Self { - Self::SymbolTable(value) - } -} - -impl From for ArchError { - fn from(value: ExprError) -> Self { - match value { - ExprError::Type(e) => Self::Type(e), - ExprError::SymbolTable(e) => Self::SymbolTable(e), - } - } + #[error(transparent)] + Type(#[from] TypeError), + #[error(transparent)] + Allocator(#[from] AllocatorError), + #[error(transparent)] + SymbolTable(#[from] SymbolTableError), + #[error(transparent)] + Expr(#[from] ExprError), } diff --git a/src/codegen/error.rs b/src/codegen/error.rs index b1c4f1c..1179565 100644 --- a/src/codegen/error.rs +++ b/src/codegen/error.rs @@ -1,73 +1,24 @@ use crate::{ archs::ArchError, - parser::{Expr, ExprError, OpParseError}, + parser::{ExprError, OpParseError}, register::allocator::AllocatorError, symbol_table::SymbolTableError, types::TypeError, }; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum CodeGenError { - OpParse(OpParseError), - Type(TypeError), - Allocator(AllocatorError), - Assign(Expr), - SymbolTable(SymbolTableError), -} - -impl std::error::Error for CodeGenError {} - -impl std::fmt::Display for CodeGenError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::OpParse(e) => e.fmt(f), - Self::Type(e) => e.fmt(f), - Self::Allocator(e) => e.fmt(f), - Self::Assign(expr) => write!(f, "Can't assign to rvalue expression {expr:?}"), - Self::SymbolTable(e) => e.fmt(f), - } - } -} - -impl From for CodeGenError { - fn from(value: TypeError) -> Self { - Self::Type(value) - } -} - -impl From for CodeGenError { - fn from(value: AllocatorError) -> Self { - Self::Allocator(value) - } -} - -impl From for CodeGenError { - fn from(value: OpParseError) -> Self { - Self::OpParse(value) - } -} - -impl From for CodeGenError { - fn from(value: SymbolTableError) -> Self { - Self::SymbolTable(value) - } -} - -impl From for CodeGenError { - fn from(value: ExprError) -> Self { - match value { - ExprError::Type(e) => Self::Type(e), - ExprError::SymbolTable(e) => Self::SymbolTable(e), - } - } -} - -impl From for CodeGenError { - fn from(value: ArchError) -> Self { - match value { - ArchError::Type(e) => Self::Type(e), - ArchError::Allocator(e) => Self::Allocator(e), - ArchError::SymbolTable(e) => Self::SymbolTable(e), - } - } + #[error(transparent)] + OpParse(#[from] OpParseError), + #[error(transparent)] + Type(#[from] TypeError), + #[error(transparent)] + Allocator(#[from] AllocatorError), + #[error(transparent)] + SymbolTable(#[from] SymbolTableError), + #[error(transparent)] + Arch(#[from] ArchError), + #[error(transparent)] + Expr(#[from] ExprError), } diff --git a/src/lexer/error.rs b/src/lexer/error.rs index 2bb53bb..5540a26 100644 --- a/src/lexer/error.rs +++ b/src/lexer/error.rs @@ -1,12 +1,7 @@ -#[derive(Debug)] +use thiserror::Error; + +#[derive(Error, Debug)] pub enum LexerError { + #[error("Failed to parse char {0}")] UnknownCharacter(char), } - -impl std::fmt::Display for LexerError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::UnknownCharacter(ch) => write!(f, "Failed to parse char {ch}"), - } - } -} diff --git a/src/parser/error.rs b/src/parser/error.rs index 4bdccfc..431e167 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -1,86 +1,48 @@ +use super::{ExprError, IntLitReprError, OpParseError}; use crate::{ lexer::{LexerError, Token}, symbol_table::SymbolTableError, types::{Type, TypeError}, }; +use thiserror::Error; -use super::{ExprError, IntLitReprError, OpParseError}; - -#[derive(Debug)] +#[derive(Error, Debug)] pub enum ParserError { + #[error(transparent)] + Expr(#[from] ExprError), + #[error(transparent)] + Lexer(#[from] LexerError), + #[error(transparent)] + Type(#[from] TypeError), + #[error(transparent)] + Operator(#[from] OpParseError), + #[error(transparent)] + Int(#[from] IntLitReprError), + #[error(transparent)] + SymbolTable(#[from] SymbolTableError), + #[error("Expected token {0}, got {1}")] UnexpectedToken(Token, Token), + #[error("Expected {0}")] Expected(Token), + #[error("Failed to parse type, found {0}")] ParseType(Token), + #[error("Failed to parse prefix token {0}")] Prefix(Token), + #[error("Failed to parse infix token {0}")] Infix(Token), - Lexer(LexerError), - Type(TypeError), - Operator(OpParseError), - Int(IntLitReprError), - SymbolTable(SymbolTableError), + #[error("Call to undeclared function {0}")] UndeclaredFunction(String), + #[error("Function has signature ({}), got called with ({})", + .0 + .iter() + .map(|type_| type_.to_string()) + .collect::>() + .join(", "), + .1 + .iter() + .map(|type_| type_.to_string()) + .collect::>() + .join(", ") + )] FunctionArguments(Vec, Vec), } - -impl std::error::Error for ParserError {} - -impl std::fmt::Display for ParserError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::UnexpectedToken(expected, actual) => { - write!(f, "Expected token {expected}, got {actual}") - } - Self::Expected(token) => write!(f, "Expected {token}"), - Self::ParseType(token) => write!(f, "Failed to parse type, found {token}"), - Self::Prefix(token) => write!(f, "Failed to parse prefix token {token}"), - Self::Infix(token) => write!(f, "Failed to parse infix token {token}"), - Self::Lexer(e) => e.fmt(f), - Self::Type(e) => e.fmt(f), - Self::Operator(e) => e.fmt(f), - Self::Int(e) => e.fmt(f), - Self::SymbolTable(e) => e.fmt(f), - Self::UndeclaredFunction(name) => write!(f, "Call to undeclared function {name}"), - Self::FunctionArguments(expected, actual) => write!( - f, - "Function has signature ({}), got called with ({})", - expected - .iter() - .map(|type_| type_.to_string()) - .collect::>() - .join(", "), - actual - .iter() - .map(|type_| type_.to_string()) - .collect::>() - .join(", ") - ), - } - } -} - -impl From for ParserError { - fn from(value: TypeError) -> Self { - Self::Type(value) - } -} - -impl From for ParserError { - fn from(value: SymbolTableError) -> Self { - Self::SymbolTable(value) - } -} - -impl From for ParserError { - fn from(value: LexerError) -> Self { - Self::Lexer(value) - } -} - -impl From for ParserError { - fn from(value: ExprError) -> Self { - match value { - ExprError::Type(e) => Self::Type(e), - ExprError::SymbolTable(e) => Self::SymbolTable(e), - } - } -} diff --git a/src/parser/expr/error.rs b/src/parser/expr/error.rs index 167b0ec..7e9c3f0 100644 --- a/src/parser/expr/error.rs +++ b/src/parser/expr/error.rs @@ -1,19 +1,10 @@ use crate::{symbol_table::SymbolTableError, types::TypeError}; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum ExprError { - Type(TypeError), - SymbolTable(SymbolTableError), -} - -impl From for ExprError { - fn from(value: TypeError) -> Self { - Self::Type(value) - } -} - -impl From for ExprError { - fn from(value: SymbolTableError) -> Self { - Self::SymbolTable(value) - } + #[error(transparent)] + Type(#[from] TypeError), + #[error(transparent)] + SymbolTable(#[from] SymbolTableError), } diff --git a/src/parser/expr/int_repr.rs b/src/parser/expr/int_repr.rs index d3c640a..8347da4 100644 --- a/src/parser/expr/int_repr.rs +++ b/src/parser/expr/int_repr.rs @@ -1,5 +1,6 @@ use crate::types::{IntType, Type, UintType}; -use std::{fmt::Display, num::ParseIntError}; +use std::num::ParseIntError; +use thiserror::Error; const I8_MIN: i64 = i8::MIN as i64; const I8_MAX: i64 = i8::MAX as i64; @@ -103,23 +104,10 @@ impl TryFrom<&str> for UIntLitRepr { } } -#[derive(Debug)] +#[derive(Error, Debug)] pub enum IntLitReprError { + #[error("{0} bits integers are not supported")] TooLarge(usize), - ParseInt(ParseIntError), -} - -impl From for IntLitReprError { - fn from(value: ParseIntError) -> Self { - Self::ParseInt(value) - } -} - -impl Display for IntLitReprError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::TooLarge(bits) => write!(f, "{bits} bits integers are not supported"), - Self::ParseInt(e) => e.fmt(f), - } - } + #[error(transparent)] + ParseInt(#[from] ParseIntError), } diff --git a/src/parser/op.rs b/src/parser/op.rs index 025c8ad..4df0201 100644 --- a/src/parser/op.rs +++ b/src/parser/op.rs @@ -1,38 +1,18 @@ use crate::lexer::Token; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum OpParseError { + #[error("Failed to parse binary operator from {0}")] Bin(Token), + #[error("Failed to parse unary operator from {0}")] Un(Token), + #[error("Failed to parse comparison operator from binary operator {0:?}")] Cmp(BinOp), + #[error("Failed to parse bitwise operator from binary operator {0:?}")] Bitwise(BinOp), } -impl std::fmt::Display for OpParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Un(token) => { - write!(f, "Failed to parse unary operator from {token}") - } - Self::Bin(token) => { - write!(f, "Failed to parse binary operator from {token}") - } - Self::Cmp(op) => { - write!( - f, - "Failed to parse comparison operator from binary operator {op:?}", - ) - } - Self::Bitwise(op) => { - write!( - f, - "Failed to parse bitwise operator from binary operator {op:?}", - ) - } - } - } -} - #[derive(Debug, Clone, PartialEq)] pub enum BinOp { Add, diff --git a/src/register/allocator/error.rs b/src/register/allocator/error.rs index 25a5301..0ad21d0 100644 --- a/src/register/allocator/error.rs +++ b/src/register/allocator/error.rs @@ -1,18 +1,12 @@ use crate::register::Register; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum AllocatorError { + #[error("Register was double freed")] DoubleFree, + #[error("Ran out of registers, whoops!")] RanOutOfRegisters, + #[error("Register {} is already in use", .0.from_size(8))] AlreadyInUse(Register), } - -impl std::fmt::Display for AllocatorError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::DoubleFree => write!(f, "Register was double freed"), - Self::RanOutOfRegisters => write!(f, "Ran out of registers, whoops!"), - Self::AlreadyInUse(r) => write!(f, "Register {} is already in use", r.from_size(8)), - } - } -} diff --git a/src/symbol_table/error.rs b/src/symbol_table/error.rs index 481e6c5..7bf4e9b 100644 --- a/src/symbol_table/error.rs +++ b/src/symbol_table/error.rs @@ -1,24 +1,12 @@ use crate::types::TypeError; +use thiserror::Error; -#[derive(Debug, PartialEq)] +#[derive(Error, Debug, PartialEq)] pub enum SymbolTableError { + #[error("Redeclaration of '{0}'")] Redeclaration(String), + #[error("Symbol '{0}' not found")] NotFound(String), + #[error(transparent)] Type(TypeError), } - -impl std::fmt::Display for SymbolTableError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Redeclaration(name) => write!(f, "Redeclaration of '{name}'"), - Self::NotFound(name) => write!(f, "Symbol '{name}' not found"), - Self::Type(e) => e.fmt(f), - } - } -} - -impl From for SymbolTableError { - fn from(value: TypeError) -> Self { - Self::Type(value) - } -} diff --git a/src/types/error.rs b/src/types/error.rs index 70b5592..d332af2 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -1,37 +1,24 @@ use super::Type; +use thiserror::Error; -#[derive(Debug, PartialEq)] +#[derive(Error, Debug, PartialEq)] pub enum TypeError { + #[error("Operation between {0} and {1} are not allowed")] Promotion(Type, Type), + #[error("Ident {0} not found")] IdentNotFound(String), + #[error("Can't assign {0} to {1}")] Assignment(Type, Type), + #[error("Can't cast {0} into {1}")] Cast(Type, Type), + #[error("Expected return value of type {1}, got {0} instead")] Return(Type, Type), + #[error("Variable can't be of type void")] VoidVariable, + #[error("Type '{0}' doens't exits")] Nonexistent(String), + #[error("Type {0} is not pointer")] Deref(Type), + #[error("Mismatched types expected {0}, found {1}")] Mismatched(Type, Type), } - -impl std::fmt::Display for TypeError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::IdentNotFound(ident) => write!(f, "Ident {ident} not found"), - Self::Promotion(lhs, rhs) => { - write!(f, "Operation between {lhs} and {rhs} are not allowed") - } - Self::Assignment(lhs, rhs) => write!(f, "Can't assign {lhs} to {rhs}"), - Self::Cast(from, to) => write!(f, "Can't cast {from} into {to}"), - Self::Return(left, right) => write!( - f, - "Expected return value of type {right}, got {left} instead", - ), - Self::VoidVariable => write!(f, "Variable can't be of type void"), - Self::Nonexistent(name) => write!(f, "Type '{name}' doens't exits"), - Self::Deref(type_) => write!(f, "Type {type_} is not pointer"), - Self::Mismatched(expected, actual) => { - write!(f, "Mismatched types expected {expected}, found {actual}") - } - } - } -}