[DEV-7084] TAMER: AsgBuilderError: Introduce proper error variants

This is a union (sum type) of three other errors types, plus errors specific
to this builder.

This commit does a good job demonstrating the boilerplate, as well as a need
for additional context (in the case of `IdentKindError`), that we'll want to
work on abstracting away.
master
Mike Gerwitz 2020-04-20 15:39:22 -04:00
parent ef79a763ac
commit 21a0bdcce1
3 changed files with 89 additions and 22 deletions

View File

@ -29,7 +29,7 @@ use crate::ir::asg::{
SortableAsg,
};
use crate::obj::xmle::writer::XmleWriter;
use crate::obj::xmlo::reader::{XmloError, XmloReader};
use crate::obj::xmlo::reader::XmloReader;
use crate::obj::xmlo::{AsgBuilder, AsgBuilderState};
use crate::sym::{DefaultInterner, Interner, Symbol};
use fxhash::FxBuildHasher;
@ -148,11 +148,11 @@ fn load_xmlo<'a, 'i, I: Interner<'i>, P: AsRef<Path>>(
fn get_ident<'a, 'i>(
depgraph: &'a LinkerAsg<'i>,
name: &'i Symbol<'i>,
) -> Result<&'a IdentObject<'i>, XmloError> {
) -> Result<&'a IdentObject<'i>, String> {
depgraph
.lookup(name)
.and_then(|id| depgraph.get(id))
.ok_or(XmloError::MissingFragment(String::from(name as &str)))
.ok_or(format!("missing identifier: {}", name))
}
fn output_xmle<'a, 'i, I: Interner<'i>>(

View File

@ -19,17 +19,18 @@
use super::reader::{XmloError, XmloEvent, XmloResult};
use crate::ir::asg::{
Asg, IdentKind, IdentObjectState, IndexType, ObjectRef, Source,
Asg, AsgError, IdentKind, IdentKindError, IdentObjectState, IndexType,
ObjectRef, Source,
};
use crate::sym::Symbol;
use std::collections::HashSet;
use std::convert::TryInto;
use std::error::Error;
use std::fmt::Display;
use std::hash::BuildHasher;
// TODO error type
pub type Result<'i, S, Ix> =
std::result::Result<AsgBuilderState<'i, S, Ix>, Box<dyn Error>>;
std::result::Result<AsgBuilderState<'i, S, Ix>, AsgBuilderError<Ix>>;
#[derive(Debug, Default)]
pub struct AsgBuilderState<'i, S, Ix>
@ -99,10 +100,7 @@ where
} else {
let owned = attrs.src.is_none();
let extern_ = attrs.extern_;
let kindval = (&attrs).try_into().map_err(|err| {
format!("sym `{}` attrs error: {}", sym, err)
})?;
let kindval = (&attrs).try_into()?;
let mut src: Source = attrs.into();
@ -133,10 +131,9 @@ where
}
XmloEvent::Fragment(sym, text) => {
let frag =
self.lookup(sym).ok_or(XmloError::MissingFragment(
String::from("missing fragment"),
))?;
let frag = self.lookup(sym).ok_or(
AsgBuilderError::MissingFragmentIdent(sym.to_string()),
)?;
self.set_fragment(frag, text)?;
}
@ -148,11 +145,86 @@ where
}
if let Some(elig_sym) = elig {
state.roots.push(self.lookup(elig_sym).expect(
"internal error: package elig references nonexistant symbol",
));
state
.roots
.push(self.lookup(elig_sym).ok_or(
AsgBuilderError::BadEligRef(elig_sym.to_string()),
)?);
}
Ok(state)
}
}
/// Error populating graph with [`XmloResult`]-derived data.
#[derive(Debug)]
pub enum AsgBuilderError<Ix: IndexType> {
/// Error with the source `xmlo` file.
XmloError(XmloError),
/// Error parsing into [`IdentKind`].
IdentKindError(IdentKindError),
/// [`Asg`] operation error.
AsgError(AsgError<Ix>),
/// Fragment encountered for an unknown identifier.
MissingFragmentIdent(String),
/// Eligibility classification references unknown identifier.
///
/// This is generated by the compiler and so should never happen.
/// (That's not to say that it won't, but it shouldn't.)
BadEligRef(String),
}
impl<Ix: IndexType> Display for AsgBuilderError<Ix> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::XmloError(e) => e.fmt(fmt),
Self::IdentKindError(e) => e.fmt(fmt),
Self::AsgError(e) => e.fmt(fmt),
Self::MissingFragmentIdent(name) => write!(
fmt,
"encountered fragment for unknown identifier `{}`",
name,
),
Self::BadEligRef(name) => write!(
fmt,
"internal error: package elig references nonexistant symbol `{}`",
name,
),
}
}
}
impl<Ix: IndexType> From<XmloError> for AsgBuilderError<Ix> {
fn from(src: XmloError) -> Self {
Self::XmloError(src)
}
}
impl<Ix: IndexType> From<IdentKindError> for AsgBuilderError<Ix> {
fn from(src: IdentKindError) -> Self {
Self::IdentKindError(src)
}
}
impl<Ix: IndexType> From<AsgError<Ix>> for AsgBuilderError<Ix> {
fn from(src: AsgError<Ix>) -> Self {
Self::AsgError(src)
}
}
impl<Ix: IndexType> Error for AsgBuilderError<Ix> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::XmloError(e) => Some(e),
Self::IdentKindError(e) => Some(e),
Self::AsgError(e) => Some(e),
_ => None,
}
}
}

View File

@ -796,8 +796,6 @@ pub enum XmloError {
UnassociatedFragment,
/// A `preproc:fragment` element was found, but is missing `text()`.
MissingFragmentText(String),
/// A `preproc:fragment` element was not found
MissingFragment(String),
}
impl From<XmlError> for XmloError {
@ -845,9 +843,6 @@ impl Display for XmloError {
"fragment found, but missing text for symbol `{}`",
symname,
),
XmloError::MissingFragment(symname) => {
write!(fmt, "fragment not found `{}`", symname,)
}
}
}
}