1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
//! Error interfaces for this crate.
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;
/// Unified error interface for all errors in this crate.
///
/// Note that the [`Display`] implementation is used for a brief message,
/// where as [`Error::help`] is used for any clarifying messages.
///
/// [`Display`]: std::fmt::Display
pub trait Error: std::error::Error {
/// The range where this error occurs in source.
///
/// If this is not known, this can be set to `None`.
fn span(&self) -> Option<crate::err::ErrSpan> {
None
}
/// A clarifying message to help aid someone in how to fix the message.
///
/// If there is none to add, this can be set to `None`.
fn help(&self) -> Option<Cow<str>>;
}
/// The possible source ranges for an error.
///
/// This can be:
/// - one contiguous span,
/// - two contiguous spans, or
/// - three or more contiguous spans
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum ErrSpan {
/// One contiguous span.
One(Span),
/// Two contiguous spans.
Two([Span; 2]),
/// Three or more contiguous spans.
///
/// This should always have at least 3 elements.
Many(Vec<Span>)
}
impl ErrSpan {
/// Gets the first span.
pub fn first(&self) -> Span {
match self {
ErrSpan::One(r) => r.clone(),
ErrSpan::Two([r, _]) => r.clone(),
ErrSpan::Many(r) => r.first().unwrap().clone(),
}
}
/// Gets an iterator over all of the spans.
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();
// It's 4:30AM and I thought it'd be funny.
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; 2]> for ErrSpan {
fn from(value: [Span; 2]) -> Self {
ErrSpan::Two(value)
}
}
impl From<Vec<Span>> for ErrSpan {
fn from(value: Vec<Span>) -> Self {
match Box::<[_; 1]>::try_from(value) {
Ok(rbox) => {
let [r] = *rbox;
ErrSpan::One(r)
},
Err(value) => match Box::try_from(value) {
Ok(rbox) => ErrSpan::Two(*rbox),
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),
}
}
}