use crate::expr::{Expr, ExprType, Span}; use thiserror::Error; pub type AstResult = Result; #[derive(Debug, PartialEq, Eq, Error)] pub enum AstError { #[error("Definition invalid")] InvalidDefinition(Option), #[error("Expected a {1}, but got nothing")] MissingNode(Option, ExprType), #[error("Wrong type of expression: Expected {1} but got {2}")] WrongExprType(Option, ExprType, ExprType), } pub fn spanned(span: Span, err: impl Into) -> AstError { use AstError::*; match err.into() { AstError::InvalidDefinition(None) => AstError::InvalidDefinition(Some(span)), AstError::MissingNode(None, x) => AstError::MissingNode(Some(span), x), AstError::WrongExprType(None, x, y) => AstError::WrongExprType(Some(span), x, y), x => x, } } pub trait OptionAstErrorExt { fn or_missing(self, t: ExprType) -> Result; } impl OptionAstErrorExt for Option { fn or_missing(self, t: ExprType) -> Result { self.ok_or(AstError::MissingNode(None, t)) } } pub trait AstResultExt { fn at(self, span: Span) -> Result; } impl> AstResultExt for Result { fn at(self, span: Span) -> Result { self.map_err(|err| spanned(span, err)) } } #[macro_export] macro_rules! spanned { ($span:expr, $block:expr) => {{ let span = $span; let result: Result<_, AstError> = try { $block }; result.at(span) }}; }