summaryrefslogtreecommitdiff
path: root/dhall_syntax
diff options
context:
space:
mode:
authorNadrieril Feneanar2019-11-11 17:01:02 +0100
committerGitHub2019-11-11 17:01:02 +0100
commit84cd6f386d6f4c7952fbc1da87dcd754f26ee404 (patch)
treed348f580a00c4b97f04f3a2e41ea2a23d67af824 /dhall_syntax
parentf58ff637c8d53af1fcee43bfba5a9f8de799084c (diff)
parent8b566b2575096562c2e15d6ac9ee8750db2cf14f (diff)
Merge pull request #114 from Nadrieril/nice-type-errors
Ground work for pretty type errors
Diffstat (limited to 'dhall_syntax')
-rw-r--r--dhall_syntax/src/core/expr.rs53
-rw-r--r--dhall_syntax/src/core/mod.rs2
-rw-r--r--dhall_syntax/src/core/span.rs81
-rw-r--r--dhall_syntax/src/parser.rs14
4 files changed, 92 insertions, 58 deletions
diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs
index 2ad3ba8..750b58b 100644
--- a/dhall_syntax/src/core/expr.rs
+++ b/dhall_syntax/src/core/expr.rs
@@ -1,5 +1,3 @@
-use std::rc::Rc;
-
use crate::map::{DupTreeMap, DupTreeSet};
use crate::visitor::{self, ExprFMutVisitor, ExprFVisitor};
use crate::*;
@@ -15,40 +13,6 @@ pub fn trivial_result<T>(x: Result<T, !>) -> T {
}
}
-/// A location in the source text
-#[derive(Debug, Clone)]
-pub struct Span {
- input: Rc<str>,
- /// # Safety
- ///
- /// Must be a valid character boundary index into `input`.
- start: usize,
- /// # Safety
- ///
- /// Must be a valid character boundary index into `input`.
- end: usize,
-}
-
-impl Span {
- pub(crate) fn make(input: Rc<str>, sp: pest::Span) -> Self {
- Span {
- input,
- start: sp.start(),
- end: sp.end(),
- }
- }
- /// Takes the union of the two spans. Assumes that the spans come from the same input.
- /// This will also capture any input between the spans.
- pub fn union(&self, other: &Span) -> Self {
- use std::cmp::{max, min};
- Span {
- input: self.input.clone(),
- start: min(self.start, other.start),
- end: max(self.start, other.start),
- }
- }
-}
-
/// Double with bitwise equality
#[derive(Debug, Copy, Clone)]
pub struct NaiveDouble(f64);
@@ -178,7 +142,7 @@ pub enum Builtin {
// Each node carries an annotation.
#[derive(Debug, Clone)]
-pub struct Expr<Embed>(Box<(RawExpr<Embed>, Option<Span>)>);
+pub struct Expr<Embed>(Box<(RawExpr<Embed>, Span)>);
pub type RawExpr<Embed> = ExprF<Expr<Embed>, Embed>;
@@ -334,16 +298,12 @@ impl<E> Expr<E> {
pub fn as_mut(&mut self) -> &mut RawExpr<E> {
&mut self.0.as_mut().0
}
- pub fn span(&self) -> Option<Span> {
+ pub fn span(&self) -> Span {
self.0.as_ref().1.clone()
}
- pub(crate) fn new(x: RawExpr<E>, n: Span) -> Self {
- Expr(Box::new((x, Some(n))))
- }
-
- pub fn from_expr_no_span(x: RawExpr<E>) -> Self {
- Expr(Box::new((x, None)))
+ pub fn new(x: RawExpr<E>, n: Span) -> Self {
+ Expr(Box::new((x, n)))
}
pub fn rewrap<E2>(&self, x: RawExpr<E2>) -> Expr<E2> {
@@ -388,11 +348,6 @@ impl<E> Expr<E> {
}
}
-// Should probably rename this
-pub fn rc<E>(x: RawExpr<E>) -> Expr<E> {
- Expr::from_expr_no_span(x)
-}
-
/// Add an isize to an usize
/// Panics on over/underflow
fn add_ui(u: usize, i: isize) -> Option<usize> {
diff --git a/dhall_syntax/src/core/mod.rs b/dhall_syntax/src/core/mod.rs
index fe2c0be..66bf229 100644
--- a/dhall_syntax/src/core/mod.rs
+++ b/dhall_syntax/src/core/mod.rs
@@ -4,6 +4,8 @@ mod import;
pub use import::*;
mod label;
pub use label::*;
+mod span;
+pub use span::*;
mod text;
pub use text::*;
pub mod context;
diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs
new file mode 100644
index 0000000..f9c7008
--- /dev/null
+++ b/dhall_syntax/src/core/span.rs
@@ -0,0 +1,81 @@
+use std::rc::Rc;
+
+/// A location in the source text
+#[derive(Debug, Clone)]
+pub struct ParsedSpan {
+ input: Rc<str>,
+ /// # Safety
+ ///
+ /// Must be a valid character boundary index into `input`.
+ start: usize,
+ /// # Safety
+ ///
+ /// Must be a valid character boundary index into `input`.
+ end: usize,
+}
+
+#[derive(Debug, Clone)]
+pub enum Span {
+ /// A location in the source text
+ Parsed(ParsedSpan),
+ /// For expressions obtained from decoding binary
+ Decoded,
+ /// For expressions constructed during normalization/typecheck
+ Artificial,
+}
+
+impl Span {
+ pub(crate) fn make(input: Rc<str>, sp: pest::Span) -> Self {
+ Span::Parsed(ParsedSpan {
+ input,
+ start: sp.start(),
+ end: sp.end(),
+ })
+ }
+
+ /// Takes the union of the two spans, i.e. the range of input covered by the two spans plus any
+ /// input between them. Assumes that the spans come from the same input. Fails if one of the
+ /// spans does not point to an input location.
+ pub fn union(&self, other: &Span) -> Self {
+ use std::cmp::{max, min};
+ use Span::*;
+ match (self, other) {
+ (Parsed(x), Parsed(y)) if Rc::ptr_eq(&x.input, &y.input) => {
+ Parsed(ParsedSpan {
+ input: x.input.clone(),
+ start: min(x.start, y.start),
+ end: max(x.end, y.end),
+ })
+ }
+ _ => panic!(
+ "Tried to union incompatible spans: {:?} and {:?}",
+ self, other
+ ),
+ }
+ }
+
+ /// Merges two spans assumed to point to a similar thing. If only one of them points to an
+ /// input location, use that one.
+ pub fn merge(&self, other: &Span) -> Self {
+ use Span::*;
+ match (self, other) {
+ (Parsed(x), _) | (_, Parsed(x)) => Parsed(x.clone()),
+ (Artificial, _) | (_, Artificial) => Artificial,
+ (Decoded, Decoded) => Decoded,
+ }
+ }
+
+ pub fn error(&self, message: impl Into<String>) -> String {
+ use pest::error::{Error, ErrorVariant};
+ use pest::Span;
+ let message: String = message.into();
+ let span = match self {
+ self::Span::Parsed(span) => span,
+ _ => return format!("[unknown location] {}", message),
+ };
+ let span = Span::new(&*span.input, span.start, span.end).unwrap();
+ let err: ErrorVariant<!> = ErrorVariant::CustomError { message };
+ let err = Error::new_from_span(err, span);
+ format!("{}", err)
+ }
+}
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index 83f62ee..eaded50 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -650,7 +650,7 @@ impl DhallParser {
final_expr,
|acc, x| {
spanned_union(
- acc.span().unwrap(),
+ acc.span(),
x.3,
Let(x.0, x.1, x.2, acc)
)
@@ -717,11 +717,7 @@ impl DhallParser {
r => Err(op.error(format!("Rule {:?} isn't an operator", r)))?,
};
- Ok(spanned_union(
- l.span().unwrap(),
- r.span().unwrap(),
- BinOp(op, l, r),
- ))
+ Ok(spanned_union(l.span(), r.span(), BinOp(op, l, r)))
}
fn Some_(_input: ParseInput) -> ParseResult<()> {
@@ -739,8 +735,8 @@ impl DhallParser {
first,
|acc, e| {
spanned_union(
- acc.span().unwrap(),
- e.span().unwrap(),
+ acc.span(),
+ e.span(),
App(acc, e)
)
}
@@ -778,7 +774,7 @@ impl DhallParser {
first,
|acc, e| {
spanned_union(
- acc.span().unwrap(),
+ acc.span(),
e.1,
match e.0 {
Either::Left(l) => Field(acc, l),