use std::borrow::Cow;
use logos::Span;
pub use crate::asm::AsmErr;
pub use crate::ast::OffsetNewErr;
pub use crate::parse::lex::LexErr;
pub use crate::parse::ParseErr;
pub use crate::sim::SimErr;
pub trait Error: std::error::Error {
fn span(&self) -> Option<crate::err::ErrSpan> {
None
}
fn help(&self) -> Option<Cow<str>>;
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum ErrSpan {
One(Span),
Two([Span; 2]),
Many(Vec<Span>)
}
impl ErrSpan {
pub fn first(&self) -> Span {
match self {
ErrSpan::One(r) => r.clone(),
ErrSpan::Two([r, _]) => r.clone(),
ErrSpan::Many(r) => r.first().unwrap().clone(),
}
}
pub fn iter(&self) -> impl Iterator<Item=&Span> {
match self {
ErrSpan::One(r) => std::slice::from_ref(r).iter(),
ErrSpan::Two(r) => r.iter(),
ErrSpan::Many(r) => r.iter(),
}
}
}
impl Extend<Span> for ErrSpan {
fn extend<T: IntoIterator<Item = Span>>(&mut self, iter: T) {
let mut iter = iter.into_iter();
loop {
match self {
ErrSpan::One(r0) => {
let Some(r1) = iter.next() else { return };
let r0 = std::mem::replace(r0, 0..0);
*self = ErrSpan::Two([r0, r1]);
},
ErrSpan::Two([r0, r1]) => {
let Some(r2) = iter.next() else { return };
let r0 = std::mem::replace(r0, 0..0);
let r1 = std::mem::replace(r1, 0..0);
*self = ErrSpan::Many(vec![r0, r1, r2]);
},
ErrSpan::Many(mr) => {
mr.extend(iter);
return;
},
}
}
}
}
impl From<Span> for ErrSpan {
fn from(value: Span) -> Self {
ErrSpan::One(value)
}
}
impl From<&[Span]> for ErrSpan {
fn from(value: &[Span]) -> Self {
match value {
[r0] => ErrSpan::One(r0.clone()),
[r0, r1] => ErrSpan::Two([r0.clone(), r1.clone()]),
rr => ErrSpan::Many(rr.to_vec())
}
}
}
impl<const N: usize> From<[Span; N]> for ErrSpan {
fn from(value: [Span; N]) -> Self {
Self::from(value.as_slice())
}
}
impl From<Vec<Span>> for ErrSpan {
fn from(value: Vec<Span>) -> Self {
match <[_; 1]>::try_from(value) {
Ok([r]) => ErrSpan::One(r),
Err(value) => match <[_; 2]>::try_from(value) {
Ok(r2) => ErrSpan::Two(r2),
Err(value) => ErrSpan::Many(value)
}
}
}
}
impl From<Vec<ErrSpan>> for ErrSpan {
fn from(value: Vec<ErrSpan>) -> Self {
let mr: Vec<_> = value.into_iter()
.flat_map(|r| match r {
ErrSpan::One(r) => vec![r],
ErrSpan::Two(r) => r.to_vec(),
ErrSpan::Many(r) => r,
})
.collect();
ErrSpan::from(mr)
}
}
impl std::fmt::Debug for ErrSpan {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::One(r) => r.fmt(f),
Self::Two(r) => r.fmt(f),
Self::Many(mr) => mr.fmt(f),
}
}
}