From 0e4f4c5af67b4075174ace5a1c7800dae60a9d11 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 10:52:57 +0000 Subject: Move Span definition to its own file And prepare for more variants --- dhall_syntax/src/core/expr.rs | 35 ---------------------------------- dhall_syntax/src/core/mod.rs | 2 ++ dhall_syntax/src/core/span.rs | 44 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 35 deletions(-) create mode 100644 dhall_syntax/src/core/span.rs (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 2ad3ba8..70ce1dc 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -1,4 +1,3 @@ -use std::rc::Rc; use crate::map::{DupTreeMap, DupTreeSet}; use crate::visitor::{self, ExprFMutVisitor, ExprFVisitor}; @@ -15,40 +14,6 @@ pub fn trivial_result(x: Result) -> T { } } -/// A location in the source text -#[derive(Debug, Clone)] -pub struct Span { - input: Rc, - /// # 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, 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); 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..ad5a3a9 --- /dev/null +++ b/dhall_syntax/src/core/span.rs @@ -0,0 +1,44 @@ +use std::rc::Rc; + +/// A location in the source text +#[derive(Debug, Clone)] +pub struct ParsedSpan { + input: Rc, + /// # Safety + /// + /// Must be a valid character boundary index into `input`. + start: usize, + /// # Safety + /// + /// Must be a valid character boundary index into `input`. + end: usize, +} + +/// A location in the source text +#[derive(Debug, Clone)] +pub enum Span { + Parsed(ParsedSpan), +} + +impl Span { + pub(crate) fn make(input: Rc, sp: pest::Span) -> Self { + Span::Parsed(ParsedSpan { + 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}; + use Span::*; + match (self, other) { + (Parsed(x), Parsed(y)) => Span::Parsed(ParsedSpan { + input: x.input.clone(), + start: min(x.start, y.start), + end: max(x.start, y.start), + }), + } + } +} -- cgit v1.2.3 From a8cb6926cbafb2ac806f7bec27a29b0528ed5056 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 10:53:29 +0000 Subject: Fix typo --- dhall_syntax/src/core/span.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index ad5a3a9..f0eb89a 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -37,7 +37,7 @@ impl Span { (Parsed(x), Parsed(y)) => Span::Parsed(ParsedSpan { input: x.input.clone(), start: min(x.start, y.start), - end: max(x.start, y.start), + end: max(x.end, y.end), }), } } -- cgit v1.2.3 From b68c3af578d1f6b0d1e32e7d88ef57774fb468d8 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 11:20:32 +0000 Subject: Capture absence of span in Span itself --- dhall_syntax/src/core/expr.rs | 18 ++++-------------- dhall_syntax/src/core/span.rs | 13 +++++++++++-- dhall_syntax/src/parser.rs | 14 +++++--------- 3 files changed, 20 insertions(+), 25 deletions(-) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 70ce1dc..750b58b 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -1,4 +1,3 @@ - use crate::map::{DupTreeMap, DupTreeSet}; use crate::visitor::{self, ExprFMutVisitor, ExprFVisitor}; use crate::*; @@ -143,7 +142,7 @@ pub enum Builtin { // Each node carries an annotation. #[derive(Debug, Clone)] -pub struct Expr(Box<(RawExpr, Option)>); +pub struct Expr(Box<(RawExpr, Span)>); pub type RawExpr = ExprF, Embed>; @@ -299,16 +298,12 @@ impl Expr { pub fn as_mut(&mut self) -> &mut RawExpr { &mut self.0.as_mut().0 } - pub fn span(&self) -> Option { + pub fn span(&self) -> Span { self.0.as_ref().1.clone() } - pub(crate) fn new(x: RawExpr, n: Span) -> Self { - Expr(Box::new((x, Some(n)))) - } - - pub fn from_expr_no_span(x: RawExpr) -> Self { - Expr(Box::new((x, None))) + pub fn new(x: RawExpr, n: Span) -> Self { + Expr(Box::new((x, n))) } pub fn rewrap(&self, x: RawExpr) -> Expr { @@ -353,11 +348,6 @@ impl Expr { } } -// Should probably rename this -pub fn rc(x: RawExpr) -> Expr { - Expr::from_expr_no_span(x) -} - /// Add an isize to an usize /// Panics on over/underflow fn add_ui(u: usize, i: isize) -> Option { diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index f0eb89a..fc8de6e 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -14,10 +14,14 @@ pub struct ParsedSpan { end: usize, } -/// A location in the source text #[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 { @@ -28,17 +32,22 @@ impl Span { 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}; use Span::*; match (self, other) { - (Parsed(x), Parsed(y)) => Span::Parsed(ParsedSpan { + (Parsed(x), Parsed(y)) => 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 + ), } } } 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), -- cgit v1.2.3 From 5d5a356b8eb36e277c312e5550d1cb0a2f82e9fa Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 11:34:29 +0000 Subject: Store a `Span` in `Value` --- dhall_syntax/src/core/span.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index fc8de6e..fa89c30 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -22,6 +22,9 @@ pub enum Span { Decoded, /// For expressions constructed during normalization/typecheck Artificial, + /// For when there should be a span but it's not done yet + /// TODO: properly handle spans + PlaceHolder, } impl Span { -- cgit v1.2.3 From 330f063e80a51f8f399864f9d01412e1bff34fe9 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 12:43:09 +0000 Subject: Display first pretty type error --- dhall_syntax/src/core/span.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index fa89c30..e2bf26d 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -53,4 +53,18 @@ impl Span { ), } } + + pub fn error(&self, message: impl Into) -> 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) + } } -- cgit v1.2.3 From d28d114552e6c6cb913dce48893fa87e87bf11e2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 13:36:30 +0000 Subject: Propagate more spans --- dhall_syntax/src/core/span.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index e2bf26d..d10a53d 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -22,9 +22,6 @@ pub enum Span { Decoded, /// For expressions constructed during normalization/typecheck Artificial, - /// For when there should be a span but it's not done yet - /// TODO: properly handle spans - PlaceHolder, } impl Span { -- cgit v1.2.3 From 207d10c4b7d838d712b135dca56bc31f3fe5b648 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 13:42:31 +0000 Subject: Clarify Span::union and add Span::merge --- dhall_syntax/src/core/span.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index d10a53d..4012cfb 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -33,8 +33,9 @@ impl Span { }) } - /// 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. + /// 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::*; @@ -51,6 +52,17 @@ impl Span { } } + /// 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 { use pest::error::{Error, ErrorVariant}; use pest::Span; -- cgit v1.2.3 From c9c248a4cab21fa1ae7692cd193e3b2c698d431d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 13:49:47 +0000 Subject: Add a few more pretty errors --- dhall_syntax/src/core/span.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index 4012cfb..d63a619 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -69,7 +69,7 @@ impl Span { let message: String = message.into(); let span = match self { self::Span::Parsed(span) => span, - _ => return format!("Unknown location: {}", message), + _ => return format!("[unknown location] {}", message), }; let span = Span::new(&*span.input, span.start, span.end).unwrap(); let err: ErrorVariant = ErrorVariant::CustomError { message }; -- cgit v1.2.3 From 1c2460bf6ba944d970c6bb6d47863d0244621887 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 11 Nov 2019 13:55:51 +0000 Subject: Ensure spans are compatible in Span::union --- dhall_syntax/src/core/span.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'dhall_syntax/src') diff --git a/dhall_syntax/src/core/span.rs b/dhall_syntax/src/core/span.rs index d63a619..f9c7008 100644 --- a/dhall_syntax/src/core/span.rs +++ b/dhall_syntax/src/core/span.rs @@ -40,11 +40,13 @@ impl Span { use std::cmp::{max, min}; use Span::*; match (self, other) { - (Parsed(x), Parsed(y)) => Parsed(ParsedSpan { - input: x.input.clone(), - start: min(x.start, y.start), - end: max(x.end, y.end), - }), + (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 -- cgit v1.2.3