summaryrefslogtreecommitdiff
path: root/dhall/src/error/mod.rs
diff options
context:
space:
mode:
authorNadrieril2019-05-06 23:17:26 +0200
committerNadrieril2019-05-06 23:20:47 +0200
commit60129b7d1c0ea8bdf2ec666fa51957e97465e88f (patch)
tree2118155537989a1a3bfa6c51b5c476651a0ef93e /dhall/src/error/mod.rs
parent423fdeebe9247b16744fae4b50df415bbd08be04 (diff)
Consolidate errors in the error module
Diffstat (limited to 'dhall/src/error/mod.rs')
-rw-r--r--dhall/src/error/mod.rs169
1 files changed, 169 insertions, 0 deletions
diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs
new file mode 100644
index 0000000..e70b9a9
--- /dev/null
+++ b/dhall/src/error/mod.rs
@@ -0,0 +1,169 @@
+use std::io::Error as IOError;
+
+use dhall_syntax::{BinOp, Import, Label, ParseError, V};
+
+use crate::phase::resolve::ImportStack;
+use crate::phase::typecheck::TypecheckContext;
+use crate::phase::{Normalized, Type, Typed};
+
+pub type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub enum Error {
+ IO(IOError),
+ Parse(ParseError),
+ Decode(DecodeError),
+ Resolve(ImportError),
+ Typecheck(TypeError),
+ Deserialize(String),
+}
+
+#[derive(Debug)]
+pub enum ImportError {
+ Recursive(Import, Box<Error>),
+ UnexpectedImport(Import),
+ ImportCycle(ImportStack, Import),
+}
+
+#[derive(Debug)]
+pub enum DecodeError {
+ CBORError(serde_cbor::error::Error),
+ WrongFormatError(String),
+}
+
+/// A structured type error that includes context
+#[derive(Debug)]
+pub struct TypeError {
+ type_message: TypeMessage,
+ context: TypecheckContext,
+}
+
+/// The specific type error
+#[derive(Debug)]
+pub(crate) enum TypeMessage {
+ UnboundVariable(V<Label>),
+ InvalidInputType(Normalized),
+ InvalidOutputType(Normalized),
+ NotAFunction(Typed),
+ TypeMismatch(Typed, Normalized, Typed),
+ AnnotMismatch(Typed, Normalized),
+ Untyped,
+ InvalidListElement(usize, Normalized, Typed),
+ InvalidListType(Normalized),
+ InvalidOptionalType(Normalized),
+ InvalidPredicate(Typed),
+ IfBranchMismatch(Typed, Typed),
+ IfBranchMustBeTerm(bool, Typed),
+ InvalidFieldType(Label, Type),
+ NotARecord(Label, Normalized),
+ MissingRecordField(Label, Typed),
+ MissingUnionField(Label, Normalized),
+ BinOpTypeMismatch(BinOp, Typed),
+ NoDependentTypes(Normalized, Normalized),
+ InvalidTextInterpolation(Typed),
+ Sort,
+ Unimplemented,
+}
+
+impl TypeError {
+ pub(crate) fn new(
+ context: &TypecheckContext,
+ type_message: TypeMessage,
+ ) -> Self {
+ TypeError {
+ context: context.clone(),
+ type_message,
+ }
+ }
+}
+
+impl From<TypeError> for std::option::NoneError {
+ fn from(_: TypeError) -> std::option::NoneError {
+ std::option::NoneError
+ }
+}
+
+impl std::error::Error for TypeMessage {
+ fn description(&self) -> &str {
+ use TypeMessage::*;
+ match *self {
+ // UnboundVariable => "Unbound variable",
+ InvalidInputType(_) => "Invalid function input",
+ InvalidOutputType(_) => "Invalid function output",
+ NotAFunction(_) => "Not a function",
+ TypeMismatch(_, _, _) => "Wrong type of function argument",
+ _ => "Unhandled error",
+ }
+ }
+}
+
+impl std::fmt::Display for TypeMessage {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ match self {
+ // UnboundVariable(_) => {
+ // f.write_str(include_str!("errors/UnboundVariable.txt"))
+ // }
+ // TypeMismatch(e0, e1, e2) => {
+ // let template = include_str!("errors/TypeMismatch.txt");
+ // let s = template
+ // .replace("$txt0", &format!("{}", e0.as_expr()))
+ // .replace("$txt1", &format!("{}", e1.as_expr()))
+ // .replace("$txt2", &format!("{}", e2.as_expr()))
+ // .replace(
+ // "$txt3",
+ // &format!(
+ // "{}",
+ // e2.get_type()
+ // .unwrap()
+ // .as_normalized()
+ // .unwrap()
+ // .as_expr()
+ // ),
+ // );
+ // f.write_str(&s)
+ // }
+ _ => f.write_str("Unhandled error message"),
+ }
+ }
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ match self {
+ Error::IO(err) => write!(f, "{}", err),
+ Error::Parse(err) => write!(f, "{}", err),
+ Error::Decode(err) => write!(f, "{:?}", err),
+ Error::Resolve(err) => write!(f, "{:?}", err),
+ Error::Typecheck(err) => write!(f, "{:?}", err),
+ Error::Deserialize(err) => write!(f, "{}", err),
+ }
+ }
+}
+
+impl std::error::Error for Error {}
+impl From<IOError> for Error {
+ fn from(err: IOError) -> Error {
+ Error::IO(err)
+ }
+}
+impl From<ParseError> for Error {
+ fn from(err: ParseError) -> Error {
+ Error::Parse(err)
+ }
+}
+impl From<DecodeError> for Error {
+ fn from(err: DecodeError) -> Error {
+ Error::Decode(err)
+ }
+}
+impl From<ImportError> for Error {
+ fn from(err: ImportError) -> Error {
+ Error::Resolve(err)
+ }
+}
+impl From<TypeError> for Error {
+ fn from(err: TypeError) -> Error {
+ Error::Typecheck(err)
+ }
+}