From 5895c3aa6552f75d7e5202be561f9734fe8945e7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 13 Aug 2019 19:31:23 +0200 Subject: No need to track the absence of `Span`s at the type level --- dhall_syntax/src/core/expr.rs | 131 +++++++++++++++++++-------------------- dhall_syntax/src/core/visitor.rs | 40 ++++-------- 2 files changed, 74 insertions(+), 97 deletions(-) (limited to 'dhall_syntax/src/core') diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 6522cb1..0cbece3 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -19,6 +19,30 @@ 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(), + } + } +} + /// Double with bitwise equality #[derive(Debug, Copy, Clone)] pub struct NaiveDouble(f64); @@ -137,23 +161,19 @@ pub enum Builtin { TextShow, } -pub type ParsedExpr = SubExpr; -pub type ResolvedExpr = SubExpr; -pub type DhallExpr = ResolvedExpr; - // Each node carries an annotation. In practice it's either X (no annotation) or a Span. #[derive(Debug)] -pub struct SubExpr(Rc<(Expr, Option)>); +pub struct SubExpr(Rc<(Expr, Option)>); -impl std::cmp::PartialEq for SubExpr { +impl std::cmp::PartialEq for SubExpr { fn eq(&self, other: &Self) -> bool { self.0.as_ref().0 == other.0.as_ref().0 } } -impl std::cmp::Eq for SubExpr {} +impl std::cmp::Eq for SubExpr {} -pub type Expr = ExprF, Embed>; +pub type Expr = ExprF, Embed>; /// Syntax tree for expressions // Having the recursion out of the enum definition enables writing @@ -293,31 +313,22 @@ impl ExprF { } } -impl Expr { +impl Expr { fn traverse_embed( &self, visit_embed: impl FnMut(&E) -> Result, - ) -> Result, Err> - where - N: Clone, - { + ) -> Result, Err> { self.visit(&mut visitor::TraverseEmbedVisitor(visit_embed)) } - fn map_embed(&self, mut map_embed: impl FnMut(&E) -> E2) -> Expr - where - N: Clone, - { + fn map_embed(&self, mut map_embed: impl FnMut(&E) -> E2) -> Expr { trivial_result(self.traverse_embed(|x| Ok(map_embed(x)))) } pub fn traverse_resolve( &self, visit_embed: impl FnMut(&E) -> Result, - ) -> Result, Err> - where - N: Clone, - { + ) -> Result, Err> { self.traverse_resolve_with_visitor(&mut visitor::ResolveVisitor( visit_embed, )) @@ -326,9 +337,8 @@ impl Expr { pub(crate) fn traverse_resolve_with_visitor( &self, visitor: &mut visitor::ResolveVisitor, - ) -> Result, Err> + ) -> Result, Err> where - N: Clone, F1: FnMut(&E) -> Result, { match self { @@ -341,59 +351,44 @@ impl Expr { } } -impl Expr { - pub fn absurd(&self) -> Expr { +impl Expr { + pub fn absurd(&self) -> Expr { self.visit(&mut visitor::AbsurdVisitor) } } -impl Expr { - pub fn note_absurd(&self) -> Expr { - self.visit(&mut visitor::NoteAbsurdVisitor) - } -} - -impl SubExpr { - pub fn as_ref(&self) -> &Expr { +impl SubExpr { + pub fn as_ref(&self) -> &Expr { &self.0.as_ref().0 } - pub fn new(x: Expr, n: N) -> Self { + pub fn new(x: Expr, n: Span) -> Self { SubExpr(Rc::new((x, Some(n)))) } - pub fn from_expr_no_note(x: Expr) -> Self { + pub fn from_expr_no_span(x: Expr) -> Self { SubExpr(Rc::new((x, None))) } pub fn from_builtin(b: Builtin) -> Self { - SubExpr::from_expr_no_note(ExprF::Builtin(b)) + SubExpr::from_expr_no_span(ExprF::Builtin(b)) } - pub fn rewrap(&self, x: Expr) -> SubExpr - where - N: Clone, - { + pub fn rewrap(&self, x: Expr) -> SubExpr { SubExpr(Rc::new((x, (self.0).1.clone()))) } pub fn traverse_embed( &self, visit_embed: impl FnMut(&E) -> Result, - ) -> Result, Err> - where - N: Clone, - { + ) -> Result, Err> { Ok(self.rewrap(self.as_ref().traverse_embed(visit_embed)?)) } pub fn map_embed( &self, map_embed: impl FnMut(&E) -> E2, - ) -> SubExpr - where - N: Clone, - { + ) -> SubExpr { self.rewrap(self.as_ref().map_embed(map_embed)) } @@ -401,10 +396,7 @@ impl SubExpr { &'a self, map_expr: impl FnMut(&'a Self) -> Self, map_under_binder: impl FnMut(&'a Label, &'a Self) -> Self, - ) -> Self - where - N: Clone, - { + ) -> Self { match self.as_ref() { ExprF::Embed(_) => SubExpr::clone(self), // This calls ExprF::map_ref @@ -419,35 +411,38 @@ impl SubExpr { pub fn traverse_resolve( &self, visit_embed: impl FnMut(&E) -> Result, - ) -> Result, Err> - where - N: Clone, - { + ) -> Result, Err> { Ok(self.rewrap(self.as_ref().traverse_resolve(visit_embed)?)) } } -impl SubExpr { - pub fn absurd(&self) -> SubExpr { - SubExpr::from_expr_no_note(self.as_ref().absurd()) - } -} - -impl SubExpr { - pub fn note_absurd(&self) -> SubExpr { - SubExpr::from_expr_no_note(self.as_ref().note_absurd()) +impl SubExpr { + pub fn absurd(&self) -> SubExpr { + SubExpr::from_expr_no_span(self.as_ref().absurd()) } } -impl Clone for SubExpr { +impl Clone for SubExpr { fn clone(&self) -> Self { SubExpr(Rc::clone(&self.0)) } } // Should probably rename this -pub fn rc(x: Expr) -> SubExpr { - SubExpr::from_expr_no_note(x) +pub fn rc(x: Expr) -> SubExpr { + SubExpr::from_expr_no_span(x) +} + +pub(crate) fn spanned( + span: Span, + x: crate::parser::ParsedExpr, +) -> crate::parser::ParsedSubExpr { + SubExpr::new(x, span) +} +pub(crate) fn unspanned( + x: crate::parser::ParsedExpr, +) -> crate::parser::ParsedSubExpr { + SubExpr::from_expr_no_span(x) } /// Add an isize to an usize diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs index 18f76d9..50ec68a 100644 --- a/dhall_syntax/src/core/visitor.rs +++ b/dhall_syntax/src/core/visitor.rs @@ -336,19 +336,18 @@ where pub struct TraverseEmbedVisitor(pub F1); -impl<'a, 'b, N, E, E2, Err, F1> - ExprFFallibleVisitor<'a, SubExpr, SubExpr, E, E2> +impl<'a, 'b, E, E2, Err, F1> + ExprFFallibleVisitor<'a, SubExpr, SubExpr, E, E2> for &'b mut TraverseEmbedVisitor where - N: Clone + 'a, F1: FnMut(&E) -> Result, { type Error = Err; fn visit_subexpr( &mut self, - subexpr: &'a SubExpr, - ) -> Result, Self::Error> { + subexpr: &'a SubExpr, + ) -> Result, Self::Error> { Ok(subexpr.rewrap(subexpr.as_ref().visit(&mut **self)?)) } fn visit_embed(self, embed: &'a E) -> Result { @@ -358,19 +357,18 @@ where pub struct ResolveVisitor(pub F1); -impl<'a, 'b, N, E, E2, Err, F1> - ExprFFallibleVisitor<'a, SubExpr, SubExpr, E, E2> +impl<'a, 'b, E, E2, Err, F1> + ExprFFallibleVisitor<'a, SubExpr, SubExpr, E, E2> for &'b mut ResolveVisitor where - N: Clone + 'a, F1: FnMut(&E) -> Result, { type Error = Err; fn visit_subexpr( &mut self, - subexpr: &'a SubExpr, - ) -> Result, Self::Error> { + subexpr: &'a SubExpr, + ) -> Result, Self::Error> { Ok(subexpr.rewrap( subexpr .as_ref() @@ -381,30 +379,14 @@ where (self.0)(embed) } } -pub struct NoteAbsurdVisitor; - -impl<'a, 'b, N, E> - ExprFInFallibleVisitor<'a, SubExpr, SubExpr, E, E> - for &'b mut NoteAbsurdVisitor -where - E: Clone + 'a, -{ - fn visit_subexpr(&mut self, subexpr: &'a SubExpr) -> SubExpr { - SubExpr::from_expr_no_note(subexpr.as_ref().visit(&mut **self)) - } - fn visit_embed(self, embed: &'a E) -> E { - E::clone(embed) - } -} pub struct AbsurdVisitor; -impl<'a, 'b, N, E> - ExprFInFallibleVisitor<'a, SubExpr, SubExpr, X, E> +impl<'a, 'b, E> ExprFInFallibleVisitor<'a, SubExpr, SubExpr, X, E> for &'b mut AbsurdVisitor { - fn visit_subexpr(&mut self, subexpr: &'a SubExpr) -> SubExpr { - SubExpr::from_expr_no_note(subexpr.as_ref().visit(&mut **self)) + fn visit_subexpr(&mut self, subexpr: &'a SubExpr) -> SubExpr { + SubExpr::from_expr_no_span(subexpr.as_ref().visit(&mut **self)) } fn visit_embed(self, embed: &'a X) -> E { match *embed {} -- cgit v1.3.1 From 77af0bbc171618f48531cc6b1d77e18089928885 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 13 Aug 2019 20:54:15 +0200 Subject: Stop tracking the absence of Embed values at the type level --- dhall/src/core/thunk.rs | 12 ++++++------ dhall/src/core/value.rs | 10 +++++----- dhall/src/phase/mod.rs | 4 ++-- dhall/src/phase/normalize.rs | 21 +++++++++++---------- dhall/src/phase/typecheck.rs | 11 ++++------- dhall_syntax/src/core/context.rs | 2 +- dhall_syntax/src/core/expr.rs | 16 ++-------------- dhall_syntax/src/core/visitor.rs | 15 +-------------- dhall_syntax/src/printer.rs | 6 ------ 9 files changed, 32 insertions(+), 65 deletions(-) (limited to 'dhall_syntax/src/core') diff --git a/dhall/src/core/thunk.rs b/dhall/src/core/thunk.rs index c18014e..4d193f9 100644 --- a/dhall/src/core/thunk.rs +++ b/dhall/src/core/thunk.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::cell::{Ref, RefCell}; use std::rc::Rc; -use dhall_syntax::{Const, ExprF, X}; +use dhall_syntax::{Const, ExprF}; use crate::core::context::{NormalizationContext, TypecheckContext}; use crate::core::value::Value; @@ -12,7 +12,7 @@ use crate::phase::normalize::{ apply_any, normalize_one_layer, normalize_whnf, InputSubExpr, OutputSubExpr, }; use crate::phase::typecheck::type_of_const; -use crate::phase::{NormalizedSubExpr, Type, Typed}; +use crate::phase::{Normalized, NormalizedSubExpr, Type, Typed}; #[derive(Debug, Clone, Copy)] enum Marker { @@ -30,7 +30,7 @@ enum ThunkInternal { /// Partially normalized value whose subexpressions have been thunked (this is returned from /// typechecking). Note that this is different from `Value::PartialExpr` because there is no /// requirement of WHNF here. - PartialExpr(ExprF), + PartialExpr(ExprF), /// Partially normalized value. /// Invariant: if the marker is `NF`, the value must be fully normalized Value(Marker, Value), @@ -123,7 +123,7 @@ impl Thunk { ThunkInternal::Value(WHNF, v).into_thunk() } - pub fn from_partial_expr(e: ExprF) -> Thunk { + pub fn from_partial_expr(e: ExprF) -> Thunk { ThunkInternal::PartialExpr(e).into_thunk() } @@ -309,7 +309,7 @@ impl Shift for ThunkInternal { e.traverse_ref_with_special_handling_of_binders( |v| Ok(v.shift(delta, var)?), |x, v| Ok(v.shift(delta, &var.under_binder(x))?), - |x| Ok(X::clone(x)), + |x| Ok(Normalized::clone(x)), )?, ), ThunkInternal::Value(m, v) => { @@ -356,7 +356,7 @@ impl Subst for ThunkInternal { &val.under_binder(x), ) }, - X::clone, + Normalized::clone, ), ), ThunkInternal::Value(_, v) => { diff --git a/dhall/src/core/value.rs b/dhall/src/core/value.rs index 8486d6e..88d7a20 100644 --- a/dhall/src/core/value.rs +++ b/dhall/src/core/value.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use dhall_syntax::{ rc, Builtin, Const, ExprF, Integer, InterpolatedTextContents, Label, - NaiveDouble, Natural, X, + NaiveDouble, Natural, }; use crate::core::thunk::{Thunk, TypedThunk}; @@ -10,7 +10,7 @@ use crate::core::var::{AlphaLabel, AlphaVar, Shift, Subst}; use crate::phase::normalize::{ apply_builtin, normalize_one_layer, squash_textlit, OutputSubExpr, }; -use crate::phase::Typed; +use crate::phase::{Normalized, Typed}; /// A semantic value. The invariants ensure this value represents a Weak-Head /// Normal Form (WHNF). This means that this first constructor is the first constructor of the @@ -59,7 +59,7 @@ pub enum Value { TextLit(Vec>), Equivalence(TypedThunk, TypedThunk), // Invariant: this must not contain a value captured by one of the variants above. - PartialExpr(ExprF), + PartialExpr(ExprF), } impl Value { @@ -475,7 +475,7 @@ impl Shift for Value { e.traverse_ref_with_special_handling_of_binders( |v| Ok(v.shift(delta, var)?), |x, v| Ok(v.shift(delta, &var.under_binder(x))?), - |x| Ok(X::clone(x)), + |x| Ok(Normalized::clone(x)), )?, ), }) @@ -500,7 +500,7 @@ impl Subst for Value { &val.under_binder(x), ) }, - X::clone, + Normalized::clone, )) } // Retry normalizing since substituting may allow progress diff --git a/dhall/src/phase/mod.rs b/dhall/src/phase/mod.rs index 8c93889..7364949 100644 --- a/dhall/src/phase/mod.rs +++ b/dhall/src/phase/mod.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::fmt::Display; use std::path::Path; -use dhall_syntax::{Const, Import, SubExpr, X}; +use dhall_syntax::{Const, Import, SubExpr}; use crate::core::thunk::{Thunk, TypedThunk}; use crate::core::value::Value; @@ -20,7 +20,7 @@ pub(crate) mod typecheck; pub type ParsedSubExpr = SubExpr; pub type DecodedSubExpr = SubExpr; pub type ResolvedSubExpr = SubExpr; -pub type NormalizedSubExpr = SubExpr; +pub type NormalizedSubExpr = SubExpr; #[derive(Debug, Clone)] pub struct Parsed(ParsedSubExpr, ImportRoot); diff --git a/dhall/src/phase/normalize.rs b/dhall/src/phase/normalize.rs index 644f98c..f1045a5 100644 --- a/dhall/src/phase/normalize.rs +++ b/dhall/src/phase/normalize.rs @@ -2,14 +2,14 @@ use std::collections::HashMap; use dhall_syntax::{ BinOp, Builtin, ExprF, InterpolatedText, InterpolatedTextContents, - NaiveDouble, X, + NaiveDouble, }; use crate::core::context::NormalizationContext; use crate::core::thunk::{Thunk, TypedThunk}; use crate::core::value::Value; use crate::core::var::Subst; -use crate::phase::{NormalizedSubExpr, ResolvedSubExpr, Typed}; +use crate::phase::{Normalized, NormalizedSubExpr, ResolvedSubExpr, Typed}; pub type InputSubExpr = ResolvedSubExpr; pub type OutputSubExpr = NormalizedSubExpr; @@ -86,7 +86,7 @@ pub fn apply_builtin(b: Builtin, args: Vec) -> Value { // Empty string literal. [] => { // Printing InterpolatedText takes care of all the escaping - let txt: InterpolatedText = + let txt: InterpolatedText = std::iter::empty().collect(); let s = txt.to_string(); Ok(( @@ -98,10 +98,11 @@ pub fn apply_builtin(b: Builtin, args: Vec) -> Value { // interpolations, there is a single Text item) in the literal. [InterpolatedTextContents::Text(s)] => { // Printing InterpolatedText takes care of all the escaping - let txt: InterpolatedText = std::iter::once( - InterpolatedTextContents::Text(s.clone()), - ) - .collect(); + let txt: InterpolatedText = + std::iter::once(InterpolatedTextContents::Text( + s.clone(), + )) + .collect(); let s = txt.to_string(); Ok(( r, @@ -376,7 +377,7 @@ pub fn normalize_whnf(ctx: NormalizationContext, expr: InputSubExpr) -> Value { } // Thunk subexpressions - let expr: ExprF = + let expr: ExprF = expr.as_ref().map_ref_with_special_handling_of_binders( |e| Thunk::new(ctx.clone(), e.clone()), |x, e| Thunk::new(ctx.skip(x), e.clone()), @@ -391,7 +392,7 @@ enum Ret<'a> { Value(Value), Thunk(Thunk), ThunkRef(&'a Thunk), - Expr(ExprF), + Expr(ExprF), } /// Performs an intersection of two HashMaps. @@ -636,7 +637,7 @@ fn apply_binop<'a>(o: BinOp, x: &'a Thunk, y: &'a Thunk) -> Option> { }) } -pub fn normalize_one_layer(expr: ExprF) -> Value { +pub fn normalize_one_layer(expr: ExprF) -> Value { use Value::{ AppliedBuiltin, BoolLit, DoubleLit, EmptyListLit, IntegerLit, Lam, NEListLit, NEOptionalLit, NaturalLit, Pi, RecordLit, RecordType, diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index ecf9793..96ff246 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use dhall_syntax::{ rc, Builtin, Const, Expr, ExprF, InterpolatedTextContents, Label, SubExpr, - X, }; use crate::core::context::{NormalizationContext, TypecheckContext}; @@ -214,7 +213,7 @@ macro_rules! make_type { }; } -fn type_of_builtin(b: Builtin) -> Expr { +fn type_of_builtin(b: Builtin) -> Expr { use dhall_syntax::Builtin::*; match b { Bool | Natural | Integer | Double | Text => make_type!(Type), @@ -398,7 +397,7 @@ fn type_with( /// layer. fn type_last_layer( ctx: &TypecheckContext, - e: &ExprF, + e: &ExprF, ) -> Result { use crate::error::TypeMessage::*; use dhall_syntax::BinOp::*; @@ -598,9 +597,7 @@ fn type_last_layer( } } Const(c) => Ok(RetWhole(Typed::from_const(*c))), - Builtin(b) => { - Ok(RetTypeOnly(mktype(ctx, rc(type_of_builtin(*b)).absurd())?)) - } + Builtin(b) => Ok(RetTypeOnly(mktype(ctx, rc(type_of_builtin(*b)))?)), BoolLit(_) => Ok(RetTypeOnly(builtin_to_type(Bool)?)), NaturalLit(_) => Ok(RetTypeOnly(builtin_to_type(Natural)?)), IntegerLit(_) => Ok(RetTypeOnly(builtin_to_type(Integer)?)), @@ -1016,7 +1013,7 @@ pub fn typecheck(e: Resolved) -> Result { pub fn typecheck_with(e: Resolved, ty: &Type) -> Result { let expr: SubExpr<_> = e.0; - let ty: SubExpr<_> = ty.to_expr().absurd(); + let ty: SubExpr<_> = ty.to_expr(); type_of(expr.rewrap(ExprF::Annot(expr.clone(), ty))) } pub fn skip_typecheck(e: Resolved) -> Typed { diff --git a/dhall_syntax/src/core/context.rs b/dhall_syntax/src/core/context.rs index eeec121..6844baa 100644 --- a/dhall_syntax/src/core/context.rs +++ b/dhall_syntax/src/core/context.rs @@ -4,7 +4,7 @@ use std::hash::Hash; /// A `(Context a)` associates `Text` labels with values of type `a` /// -/// The `Context` is used for type-checking when `(a = Expr X)` +/// The `Context` is used for type-checking when `(a = Expr)` /// /// * You create a `Context` using `empty` and `insert` /// * You transform a `Context` using `fmap` diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 0cbece3..e08d816 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -10,9 +10,9 @@ pub type Double = NaiveDouble; /// An empty type #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum X {} +pub enum Void {} -pub fn trivial_result(x: Result) -> T { +pub fn trivial_result(x: Result) -> T { match x { Ok(x) => x, Err(e) => match e {}, @@ -351,12 +351,6 @@ impl Expr { } } -impl Expr { - pub fn absurd(&self) -> Expr { - self.visit(&mut visitor::AbsurdVisitor) - } -} - impl SubExpr { pub fn as_ref(&self) -> &Expr { &self.0.as_ref().0 @@ -416,12 +410,6 @@ impl SubExpr { } } -impl SubExpr { - pub fn absurd(&self) -> SubExpr { - SubExpr::from_expr_no_span(self.as_ref().absurd()) - } -} - impl Clone for SubExpr { fn clone(&self) -> Self { SubExpr(Rc::clone(&self.0)) diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs index 50ec68a..e39e95b 100644 --- a/dhall_syntax/src/core/visitor.rs +++ b/dhall_syntax/src/core/visitor.rs @@ -243,7 +243,7 @@ impl<'a, T, SE1, SE2, E1, E2> ExprFFallibleVisitor<'a, SE1, SE2, E1, E2> where T: ExprFInFallibleVisitor<'a, SE1, SE2, E1, E2>, { - type Error = X; + type Error = Void; fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result { Ok(self.0.visit_subexpr(subexpr)) @@ -379,16 +379,3 @@ where (self.0)(embed) } } - -pub struct AbsurdVisitor; - -impl<'a, 'b, E> ExprFInFallibleVisitor<'a, SubExpr, SubExpr, X, E> - for &'b mut AbsurdVisitor -{ - fn visit_subexpr(&mut self, subexpr: &'a SubExpr) -> SubExpr { - SubExpr::from_expr_no_span(subexpr.as_ref().visit(&mut **self)) - } - fn visit_embed(self, embed: &'a X) -> E { - match *embed {} - } -} diff --git a/dhall_syntax/src/printer.rs b/dhall_syntax/src/printer.rs index 95eafe5..25d4ca8 100644 --- a/dhall_syntax/src/printer.rs +++ b/dhall_syntax/src/printer.rs @@ -491,9 +491,3 @@ impl Display for V