diff --git a/core/Cargo.toml b/core/Cargo.toml index 5821ddc..65be384 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,3 +17,4 @@ num-bigint = { version = "0.4.3", features = ["serde"] } num-complex = { version = "0.4.0", features = ["serde"] } serde = { version = "1.0.136", features = ["derive"] } static_assertions = "1.1.0" +thiserror = "1.0" diff --git a/core/src/error.rs b/core/src/error.rs index 40d9734..f69b61f 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -58,3 +58,32 @@ impl BaseError { BaseError::from(self) } } + +#[derive(Debug, thiserror::Error)] +pub struct CompileError { + pub body: BaseError, + pub statement: Option, +} + +impl std::ops::Deref for CompileError { + type Target = BaseError; + fn deref(&self) -> &Self::Target { + &self.body + } +} + +impl std::fmt::Display for CompileError +where + T: std::fmt::Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let loc = self.location; + if let Some(ref stmt) = self.statement { + // visualize the error when location and statement are provided + loc.fmt_with(f, &self.error)?; + write!(f, "\n{stmt}{arrow:>pad$}", pad = loc.column(), arrow = "^") + } else { + loc.fmt_with(f, &self.error) + } + } +} diff --git a/core/src/lib.rs b/core/src/lib.rs index 7360cf7..e1f0a5b 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -7,6 +7,6 @@ mod location; mod mode; pub use bytecode::*; -pub use error::BaseError; +pub use error::{BaseError, CompileError}; pub use location::Location; pub use mode::Mode;