mod error_std;
use std::{
convert::Infallible,
error::Error,
fmt::{self, Debug, Display, Formatter},
ops::Range,
};
pub type Result<T> = std::result::Result<T, GGError>;
pub type MaybeRanged = Option<Range<usize>>;
#[derive(Debug)]
pub enum GGError {
IOError(std::io::Error),
FormatError(std::fmt::Error),
SyntaxError(String),
TypeMismatch(String),
RuntimeError(String),
UndefinedVariable {
name: String,
},
Unreachable,
}
macro_rules! error_msg {
($name:ident => $t:ident) => {
pub fn $name(msg: impl Into<String>) -> Self {
GGError::$t(msg.into())
}
};
($($name:ident => $t:ident),+ $(,)?) => (
impl GGError { $(error_msg!($name=>$t);)+ }
);
}
error_msg![
syntax_error => SyntaxError,
type_mismatch => TypeMismatch,
runtime_error => RuntimeError,
];
impl Error for GGError {}
impl Display for GGError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::IOError(e) => {
write!(f, "{}", e)
}
Self::FormatError(e) => {
write!(f, "{}", e)
}
Self::SyntaxError(msg) => {
f.write_str("SyntaxError: ")?;
f.write_str(msg)
}
Self::TypeMismatch(msg) => {
f.write_str("TypeError: ")?;
f.write_str(msg)
}
Self::RuntimeError(msg) => {
f.write_str("RuntimeError: ")?;
f.write_str(msg)
}
Self::UndefinedVariable { name } => {
write!(f, "RuntimeError: Variable {} not found in scope", name)
}
Self::Unreachable => {
f.write_str("InternalError: ")?;
f.write_str("Entered unreachable code!")
}
}
}
}