diff options
Diffstat (limited to 'dhall_core/src/core.rs')
-rw-r--r-- | dhall_core/src/core.rs | 337 |
1 files changed, 159 insertions, 178 deletions
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index bfe769f..aeb6f23 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -205,135 +205,66 @@ pub enum ExprF<SubExpr, Label, Note, Embed> { } impl<SE, L, N, E> ExprF<SE, L, N, E> { - pub fn visit<'a, V, Return>(&'a self, v: V) -> Return + pub(crate) fn visit<'a, V, Return>(&'a self, v: V) -> Return where V: visitor::GenericVisitor<&'a ExprF<SE, L, N, E>, Return>, { v.visit(self) } -} - -impl<S, A> Expr<S, A> { - pub fn map_shallow<T, B, F1, F2, F3, F4>( - &self, - map_expr: F1, - map_note: F2, - map_embed: F3, - map_label: F4, - ) -> Expr<T, B> - where - A: Clone, - T: Clone, - S: Clone, - F1: Fn(&Self) -> Expr<T, B>, - F2: Fn(&S) -> T, - F3: Fn(&A) -> B, - F4: Fn(&Label) -> Label, - { - self.map_ref( - |x| rc(map_expr(x.as_ref())), - |_, x| rc(map_expr(x.as_ref())), - map_note, - map_embed, - map_label, - ) - } - - pub fn map_embed<B, F>(&self, map_embed: &F) -> Expr<S, B> - where - A: Clone, - S: Clone, - F: Fn(&A) -> B, - { - let recurse = |e: &Expr<S, A>| -> Expr<S, B> { e.map_embed(map_embed) }; - self.map_shallow(recurse, S::clone, map_embed, Label::clone) - } - - pub fn traverse_embed<B, Err, F>( - &self, - map_embed: F, - ) -> Result<Expr<S, B>, Err> - where - S: Clone, - B: Clone, - F: FnMut(&A) -> Result<B, Err>, - { - self.visit(&mut visitor::TraverseEmbedVisitor(map_embed)) - } - - pub fn map_label<F>(&self, map_label: &F) -> Self - where - A: Clone, - S: Clone, - F: Fn(&Label) -> Label, - { - let recurse = |e: &Self| -> Self { e.map_label(map_label) }; - self.map_shallow(recurse, S::clone, A::clone, map_label) - } - pub fn roll(&self) -> SubExpr<S, A> + fn traverse_ref_with_special_handling_of_binders<'a, SE2, L2, N2, E2, Err>( + &'a self, + visit_subexpr: impl FnMut(&'a SE) -> Result<SE2, Err>, + visit_under_binder: impl FnOnce(&'a L, &'a SE) -> Result<SE2, Err>, + visit_note: impl FnOnce(&'a N) -> Result<N2, Err>, + visit_embed: impl FnOnce(&'a E) -> Result<E2, Err>, + visit_label: impl FnMut(&'a L) -> Result<L2, Err>, + ) -> Result<ExprF<SE2, L2, N2, E2>, Err> where - S: Clone, - A: Clone, + L: Ord, + L2: Ord, { - rc(ExprF::clone(self)) - } -} - -impl<N: Clone, E> Expr<N, E> { - pub fn squash_embed<E2: Clone>( - &self, - f: impl FnMut(&E) -> SubExpr<N, E2>, - ) -> SubExpr<N, E2> { - rc(self.visit(&mut visitor::SquashEmbedVisitor(f))) + self.visit(visitor::TraverseRefWithBindersVisitor { + visit_subexpr, + visit_under_binder, + visit_note, + visit_embed, + visit_label, + }) } -} -impl<SE, L, N, E> ExprF<SE, L, N, E> { - pub fn traverse_ref<'a, SE2, L2, N2, E2, Err, F1, F2, F3, F4, F5>( + fn traverse_ref<'a, SE2, L2, N2, E2, Err>( &'a self, - visit_subexpr: F1, - visit_under_binder: F2, - visit_note: F3, - visit_embed: F4, - visit_label: F5, + visit_subexpr: impl FnMut(&'a SE) -> Result<SE2, Err>, + visit_note: impl FnOnce(&'a N) -> Result<N2, Err>, + visit_embed: impl FnOnce(&'a E) -> Result<E2, Err>, + visit_label: impl FnMut(&'a L) -> Result<L2, Err>, ) -> Result<ExprF<SE2, L2, N2, E2>, Err> where L: Ord, L2: Ord, - F1: FnMut(&'a SE) -> Result<SE2, Err>, - F2: FnOnce(&'a L, &'a SE) -> Result<SE2, Err>, - F3: FnOnce(&'a N) -> Result<N2, Err>, - F4: FnOnce(&'a E) -> Result<E2, Err>, - F5: FnMut(&'a L) -> Result<L2, Err>, { self.visit(visitor::TraverseRefVisitor { visit_subexpr, - visit_under_binder, visit_note, visit_embed, visit_label, }) } - pub fn map_ref<'a, SE2, L2, N2, E2, F1, F2, F3, F4, F5>( + pub fn map_ref_with_special_handling_of_binders<'a, SE2, L2, N2, E2>( &'a self, - mut map_subexpr: F1, - mut map_under_binder: F2, - mut map_note: F3, - mut map_embed: F4, - mut map_label: F5, + mut map_subexpr: impl FnMut(&'a SE) -> SE2, + mut map_under_binder: impl FnMut(&'a L, &'a SE) -> SE2, + map_note: impl FnOnce(&'a N) -> N2, + map_embed: impl FnOnce(&'a E) -> E2, + mut map_label: impl FnMut(&'a L) -> L2, ) -> ExprF<SE2, L2, N2, E2> where L: Ord, L2: Ord, - F1: FnMut(&'a SE) -> SE2, - F2: FnMut(&'a L, &'a SE) -> SE2, - F3: FnMut(&'a N) -> N2, - F4: FnMut(&'a E) -> E2, - F5: FnMut(&'a L) -> L2, { - trivial_result(self.traverse_ref( + trivial_result(self.traverse_ref_with_special_handling_of_binders( |x| Ok(map_subexpr(x)), |l, x| Ok(map_under_binder(l, x)), |x| Ok(map_note(x)), @@ -342,31 +273,101 @@ impl<SE, L, N, E> ExprF<SE, L, N, E> { )) } - pub fn traverse_ref_simple<'a, SE2, Err, F1>( + pub fn map_ref<'a, SE2, L2, N2, E2>( &'a self, - visit_subexpr: F1, + mut map_subexpr: impl FnMut(&'a SE) -> SE2, + map_note: impl FnOnce(&'a N) -> N2, + map_embed: impl FnOnce(&'a E) -> E2, + mut map_label: impl FnMut(&'a L) -> L2, + ) -> ExprF<SE2, L2, N2, E2> + where + L: Ord, + L2: Ord, + { + trivial_result(self.traverse_ref( + |x| Ok(map_subexpr(x)), + |x| Ok(map_note(x)), + |x| Ok(map_embed(x)), + |x| Ok(map_label(x)), + )) + } + + pub fn traverse_ref_simple<'a, SE2, Err>( + &'a self, + visit_subexpr: impl FnMut(&'a SE) -> Result<SE2, Err>, ) -> Result<ExprF<SE2, L, N, E>, Err> where L: Ord + Clone, N: Clone, E: Clone, - F1: FnMut(&'a SE) -> Result<SE2, Err>, { - self.visit(visitor::TraverseRefSimpleVisitor { visit_subexpr }) + self.traverse_ref( + visit_subexpr, + |x| Ok(N::clone(x)), + |x| Ok(E::clone(x)), + |x| Ok(L::clone(x)), + ) } - pub fn map_ref_simple<'a, SE2, F1>( + pub fn map_ref_simple<'a, SE2>( &'a self, - map_subexpr: F1, + map_subexpr: impl Fn(&'a SE) -> SE2, ) -> ExprF<SE2, L, N, E> where - L: Ord, - L: Clone, + L: Ord + Clone, N: Clone, E: Clone, - F1: Fn(&'a SE) -> SE2, { - trivial_result(self.traverse_ref_simple(|x| Ok(map_subexpr(x)))) + self.map_ref(map_subexpr, N::clone, E::clone, L::clone) + } +} + +impl<N, E> Expr<N, E> { + fn traverse_embed<E2, Err>( + &self, + visit_embed: impl FnMut(&E) -> Result<E2, Err>, + ) -> Result<Expr<N, E2>, Err> + where + N: Clone, + { + self.visit(&mut visitor::TraverseEmbedVisitor(visit_embed)) + } + + fn map_embed<E2>(&self, mut map_embed: impl FnMut(&E) -> E2) -> Expr<N, E2> + where + N: Clone, + { + trivial_result(self.traverse_embed(|x| Ok(map_embed(x)))) + } + + pub fn roll(&self) -> SubExpr<N, E> + where + N: Clone, + E: Clone, + { + rc(ExprF::clone(self)) + } + + pub fn squash_embed<E2>( + &self, + f: impl FnMut(&E) -> SubExpr<N, E2>, + ) -> SubExpr<N, E2> + where + N: Clone, + { + trivial_result(self.visit(&mut visitor::SquashEmbedVisitor(f))) + } +} + +impl<E: Clone> Expr<X, E> { + pub fn note_absurd<N>(&self) -> Expr<N, E> { + self.visit(&mut visitor::NoteAbsurdVisitor) + } +} + +impl<N: Clone> Expr<N, X> { + pub fn embed_absurd<E>(&self) -> Expr<N, E> { + self.visit(&mut visitor::EmbedAbsurdVisitor) } } @@ -375,17 +376,42 @@ impl<N, E> SubExpr<N, E> { self.0.as_ref() } - fn map_ref<'a, F1, F2>(&'a self, map_expr: F1, map_under_binder: F2) -> Self + pub fn traverse_embed<E2, Err>( + &self, + visit_embed: impl FnMut(&E) -> Result<E2, Err>, + ) -> Result<SubExpr<N, E2>, Err> where - F1: FnMut(&'a Self) -> Self, - F2: FnMut(&'a Label, &'a Self) -> Self, + N: Clone, + { + Ok(rc(self.as_ref().traverse_embed(visit_embed)?)) + } + + pub fn map_embed<E2>( + &self, + map_embed: impl FnMut(&E) -> E2, + ) -> SubExpr<N, E2> + where + N: Clone, { + rc(self.as_ref().map_embed(map_embed)) + } + + pub fn map_subexprs_with_special_handling_of_binders<'a>( + &'a self, + map_expr: impl FnMut(&'a Self) -> Self, + map_under_binder: impl FnMut(&'a Label, &'a Self) -> Self, + ) -> Self { match self.as_ref() { ExprF::Embed(_) => SubExpr::clone(self), // Recursive call - ExprF::Note(_, e) => e.map_ref(map_expr, map_under_binder), + // TODO: don't discard the note ! + ExprF::Note(_, e) => e + .map_subexprs_with_special_handling_of_binders( + map_expr, + map_under_binder, + ), // Call ExprF::map_ref - e => rc(e.map_ref( + e => rc(e.map_ref_with_special_handling_of_binders( map_expr, map_under_binder, |_| unreachable!(), @@ -395,25 +421,25 @@ impl<N, E> SubExpr<N, E> { } } - pub fn map_ref_simple<F1>(&self, map_expr: F1) -> Self + pub fn unroll(&self) -> Expr<N, E> where - F1: Fn(&Self) -> Self, + N: Clone, + E: Clone, { - self.map_ref(&map_expr, |_, e| map_expr(e)) + ExprF::clone(self.as_ref()) } - pub fn unroll(&self) -> Expr<N, E> + pub fn unnote(&self) -> SubExpr<X, E> where - N: Clone, E: Clone, { - ExprF::clone(self.as_ref()) + rc(self.as_ref().visit(&mut visitor::UnNoteVisitor)) } } impl<N: Clone> SubExpr<N, X> { - pub fn absurd<T>(&self) -> SubExpr<N, T> { - rc(self.as_ref().absurd_rec()) + pub fn embed_absurd<T>(&self) -> SubExpr<N, T> { + rc(self.as_ref().embed_absurd()) } } @@ -423,34 +449,6 @@ impl<E: Clone> SubExpr<X, E> { } } -impl<E: Clone> Expr<X, E> { - pub fn note_absurd<N>(&self) -> Expr<N, E> { - self.visit(&mut visitor::NoteAbsurdVisitor) - } -} - -impl<N, E: Clone> SubExpr<N, E> { - pub fn unnote(&self) -> SubExpr<X, E> { - rc(self.as_ref().visit(&mut visitor::UnNoteVisitor)) - } -} - -impl<N: Clone> Expr<N, X> { - // Deprecated, use embed_absurd instead - pub fn absurd_rec<T>(&self) -> Expr<N, T> { - self.embed_absurd() - } - pub fn embed_absurd<T>(&self) -> Expr<N, T> { - self.visit(&mut visitor::EmbedAbsurdVisitor) - } -} - -impl<N: Clone> SubExpr<N, X> { - pub fn embed_absurd<T>(&self) -> SubExpr<N, T> { - rc(self.as_ref().embed_absurd()) - } -} - impl<N, E> Clone for SubExpr<N, E> { fn clone(&self) -> Self { SubExpr(Rc::clone(&self.0)) @@ -462,25 +460,8 @@ pub fn rc<N, E>(x: Expr<N, E>) -> SubExpr<N, E> { SubExpr(Rc::new(x)) } -pub fn app<N, E>(f: Expr<N, E>, args: Vec<SubExpr<N, E>>) -> Expr<N, E> { - if args.is_empty() { - f - } else { - ExprF::App(rc(f), args) - } -} - -pub fn app_rc<N, E>( - f: SubExpr<N, E>, - args: Vec<SubExpr<N, E>>, -) -> SubExpr<N, E> { - if args.is_empty() { - f - } else { - rc(ExprF::App(f, args)) - } -} - +/// Add an isize to an usize +/// Panics on over/underflow fn add_ui(u: usize, i: isize) -> usize { if i < 0 { u.checked_sub(i.checked_neg().unwrap() as usize).unwrap() @@ -505,15 +486,15 @@ fn shift_var(delta: isize, var: &V<Label>, in_expr: &V<Label>) -> V<Label> { /// capture by shifting variable indices /// See https://github.com/dhall-lang/dhall-lang/blob/master/standard/semantics.md#shift /// for details -pub fn shift<S, A>( +pub fn shift<N, E>( delta: isize, var: &V<Label>, - in_expr: &SubExpr<S, A>, -) -> SubExpr<S, A> { + in_expr: &SubExpr<N, E>, +) -> SubExpr<N, E> { use crate::ExprF::*; match in_expr.as_ref() { Var(v) => rc(Var(shift_var(delta, var, v))), - _ => in_expr.map_ref( + _ => in_expr.map_subexprs_with_special_handling_of_binders( |e| shift(delta, var, e), |l: &Label, e| { let vl = V(l.clone(), 0); @@ -532,16 +513,16 @@ pub fn shift<S, A>( /// subst_shift(x, v, e) = ↑(-1, x, e[x := ↑(1, x, v)]) /// ``` /// -pub fn subst_shift<S, A>( +pub fn subst_shift<N, E>( var: &V<Label>, - value: &SubExpr<S, A>, - in_expr: &SubExpr<S, A>, -) -> SubExpr<S, A> { + value: &SubExpr<N, E>, + in_expr: &SubExpr<N, E>, +) -> SubExpr<N, E> { use crate::ExprF::*; match in_expr.as_ref() { Var(v) if v == var => SubExpr::clone(value), Var(v) => rc(Var(shift_var(-1, var, v))), - _ => in_expr.map_ref( + _ => in_expr.map_subexprs_with_special_handling_of_binders( |e| subst_shift(var, &value, e), |l: &Label, e| { let vl = V(l.clone(), 0); |