use pochoir_common::Spanned;
use std::result;
use thiserror::Error;
pub type Result<T> = result::Result<T, Spanned<Error>>;
#[derive(Error, Debug, PartialEq, Eq, Clone)]
pub enum Error {
#[error("unknown statement {0:?}")]
UnknownStatement(String),
#[error("unbounded ranges are forbidden in `for` loops, if you want to index an array you can use its length as the end bound")]
UnboundedRangeInForLoop,
#[error("an `elif` statement cannot be used after an `else` statement, you probably forgot an `endif` statement")]
ElifAfterElse,
#[error(transparent)]
LanguageError(#[from] pochoir_lang::Error),
#[error(transparent)]
StreamParserError(#[from] pochoir_common::Error),
}
pub(crate) trait AutoError<T>
where
Self: Sized,
{
fn auto_error(self) -> T;
}
pub(crate) trait AutoErrorOffset<T>
where
Self: Sized,
{
fn auto_error_offset(self, file_offset: usize) -> T;
}
impl<T> AutoErrorOffset<result::Result<T, Spanned<Error>>>
for result::Result<T, Spanned<pochoir_common::Error>>
{
fn auto_error_offset(self, file_offset: usize) -> result::Result<T, Spanned<Error>> {
self.map_err(|e| {
let span = e.span().clone();
e.map_spanned(Error::StreamParserError)
.with_span(span.start + file_offset..span.end + file_offset)
})
}
}
impl<T> AutoError<result::Result<T, Spanned<Error>>>
for result::Result<T, Spanned<pochoir_lang::Error>>
{
fn auto_error(self) -> result::Result<T, Spanned<Error>> {
self.map_err(|e| e.map_spanned(Error::LanguageError))
}
}