diff options
author | Nadrieril | 2019-04-14 15:45:43 +0200 |
---|---|---|
committer | Nadrieril | 2019-04-14 15:45:43 +0200 |
commit | a72e00dc9193f82f93459a493d4f3167f9b2f6f1 (patch) | |
tree | 9776a610bba8620b0f0c8cb357c8fbd6f7fd863d /dhall | |
parent | 1fc40dc0a16a52218b69734f2540f0b65f5b8614 (diff) |
Improve visitor trait hierarchy
Diffstat (limited to '')
-rw-r--r-- | dhall_core/src/core.rs | 21 | ||||
-rw-r--r-- | dhall_core/src/visitor.rs | 292 |
2 files changed, 226 insertions, 87 deletions
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index f836294..b3f6b9c 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -198,6 +198,15 @@ pub enum ExprF<SubExpr, Label, Note, Embed> { Embed(Embed), } +impl<SE, L, N, E> ExprF<SE, L, N, E> { + pub 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, @@ -270,9 +279,7 @@ impl<N: Clone, E> Expr<N, E> { &self, f: impl FnMut(&E) -> SubExpr<N, E2>, ) -> SubExpr<N, E2> { - rc(trivial_result( - self.visit(&mut visitor::SquashEmbedVisitor(f)), - )) + rc(self.visit(&mut visitor::SquashEmbedVisitor(f))) } } @@ -463,15 +470,13 @@ impl<E: Clone> SubExpr<X, E> { impl<E: Clone> Expr<X, E> { pub fn note_absurd<N>(&self) -> Expr<N, E> { - trivial_result(self.visit(&mut visitor::NoteAbsurdVisitor)) + self.visit(&mut visitor::NoteAbsurdVisitor) } } impl<N, E: Clone> SubExpr<N, E> { pub fn unnote(&self) -> SubExpr<X, E> { - rc(trivial_result( - self.as_ref().visit(&mut visitor::UnNoteVisitor), - )) + rc(self.as_ref().visit(&mut visitor::UnNoteVisitor)) } } @@ -481,7 +486,7 @@ impl<N: Clone> Expr<N, X> { self.embed_absurd() } pub fn embed_absurd<T>(&self) -> Expr<N, T> { - trivial_result(self.visit(&mut visitor::EmbedAbsurdVisitor)) + self.visit(&mut visitor::EmbedAbsurdVisitor) } } diff --git a/dhall_core/src/visitor.rs b/dhall_core/src/visitor.rs index 3a94c7b..5eb17f6 100644 --- a/dhall_core/src/visitor.rs +++ b/dhall_core/src/visitor.rs @@ -2,7 +2,13 @@ use std::collections::BTreeMap; use crate::*; -pub trait ExprVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>: Sized { +pub trait GenericVisitor<Input, Return>: Sized { + fn visit(self, input: Input) -> Return; +} + +pub trait ExprFFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>: + Sized +{ type Error; fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result<SE2, Self::Error>; @@ -47,16 +53,20 @@ pub trait ExprVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>: Sized { } } -impl<SE, L, N, E> ExprF<SE, L, N, E> { - pub fn visit<'a, V, SE2, L2, N2, E2>( - &'a self, - mut v: V, - ) -> Result<ExprF<SE2, L2, N2, E2>, V::Error> - where - L: Ord, - L2: Ord, - V: ExprVisitor<'a, SE, SE2, L, L2, N, N2, E, E2>, - { +impl<'a, T, SE1, SE2, L1, L2, N1, N2, E1, E2> + GenericVisitor< + &'a ExprF<SE1, L1, N1, E1>, + Result<ExprF<SE2, L2, N2, E2>, T::Error>, + > for T +where + L1: Ord, + L2: Ord, + T: ExprFFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>, +{ + fn visit( + self, + input: &'a ExprF<SE1, L1, N1, E1>, + ) -> Result<ExprF<SE2, L2, N2, E2>, T::Error> { fn vec<'a, T, U, Err, F: FnMut(&'a T) -> Result<U, Err>>( x: &'a Vec<T>, f: F, @@ -79,15 +89,16 @@ impl<SE, L, N, E> ExprF<SE, L, N, E> { where L: Ord, L2: Ord, - V: ExprVisitor<'a, SE, SE2, L, L2, N, N2, E, E2>, + V: ExprFFallibleVisitor<'a, SE, SE2, L, L2, N, N2, E, E2>, { x.into_iter() .map(|(k, x)| Ok((v.visit_label(k)?, v.visit_subexpr(x)?))) .collect() } + let mut v = self; use crate::ExprF::*; - Ok(match self { + Ok(match input { Var(V(l, n)) => Var(V(v.visit_label(l)?, *n)), Lam(l, t, e) => { let t = v.visit_subexpr(t)?; @@ -149,6 +160,106 @@ impl<SE, L, N, E> ExprF<SE, L, N, E> { } } +pub trait ExprFInFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>: + Sized +{ + fn visit_subexpr(&mut self, subexpr: &'a SE1) -> SE2; + fn visit_label(&mut self, label: &'a L1) -> L2; + fn visit_note(self, note: &'a N1) -> N2; + fn visit_embed(self, embed: &'a E1) -> E2; + + fn visit_subexpr_under_binder( + mut self, + _label: &'a L1, + subexpr: &'a SE1, + ) -> SE2 { + self.visit_subexpr(subexpr) + } + + fn visit_binder(mut self, label: &'a L1, subexpr: &'a SE1) -> (L2, SE2) { + ( + self.visit_label(label), + self.visit_subexpr_under_binder(label, subexpr), + ) + } + + fn visit_embed_squash(self, embed: &'a E1) -> ExprF<SE2, L2, N2, E2> { + ExprF::Embed(self.visit_embed(embed)) + } + + fn visit_note_squash( + mut self, + note: &'a N1, + subexpr: &'a SE1, + ) -> ExprF<SE2, L2, N2, E2> { + let subexpr = self.visit_subexpr(subexpr); + let note = self.visit_note(note); + ExprF::Note(note, subexpr) + } +} + +struct InfallibleWrapper<T>(T); + +impl<'a, T, SE1, SE2, L1, L2, N1, N2, E1, E2> + ExprFFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2> + for InfallibleWrapper<T> +where + T: ExprFInFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>, +{ + type Error = X; + + fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result<SE2, Self::Error> { + Ok(self.0.visit_subexpr(subexpr)) + } + fn visit_label(&mut self, label: &'a L1) -> Result<L2, Self::Error> { + Ok(self.0.visit_label(label)) + } + fn visit_note(self, note: &'a N1) -> Result<N2, Self::Error> { + Ok(self.0.visit_note(note)) + } + fn visit_embed(self, embed: &'a E1) -> Result<E2, Self::Error> { + Ok(self.0.visit_embed(embed)) + } + + fn visit_binder( + self, + label: &'a L1, + subexpr: &'a SE1, + ) -> Result<(L2, SE2), Self::Error> { + Ok(self.0.visit_binder(label, subexpr)) + } + + fn visit_embed_squash( + self, + embed: &'a E1, + ) -> Result<ExprF<SE2, L2, N2, E2>, Self::Error> { + Ok(self.0.visit_embed_squash(embed)) + } + + fn visit_note_squash( + self, + note: &'a N1, + subexpr: &'a SE1, + ) -> Result<ExprF<SE2, L2, N2, E2>, Self::Error> { + Ok(self.0.visit_note_squash(note, subexpr)) + } +} + +impl<'a, T, SE1, SE2, L1, L2, N1, N2, E1, E2> + GenericVisitor<&'a ExprF<SE1, L1, N1, E1>, ExprF<SE2, L2, N2, E2>> for T +where + L1: Ord, + L2: Ord, + T: ExprFInFallibleVisitor<'a, SE1, SE2, L1, L2, N1, N2, E1, E2>, +{ + fn visit( + self, + input: &'a ExprF<SE1, L1, N1, E1>, + ) -> ExprF<SE2, L2, N2, E2> { + trivial_result(InfallibleWrapper(self).visit(input)) + } +} + pub struct TraverseRefVisitor<F1, F2, F3, F4, F5> { pub visit_subexpr: F1, pub visit_under_binder: F2, @@ -158,7 +269,7 @@ pub struct TraverseRefVisitor<F1, F2, F3, F4, F5> { } impl<'a, SE, L, N, E, SE2, L2, N2, E2, Err, F1, F2, F3, F4, F5> - ExprVisitor<'a, SE, SE2, L, L2, N, N2, E, E2> + ExprFFallibleVisitor<'a, SE, SE2, L, L2, N, N2, E, E2> for TraverseRefVisitor<F1, F2, F3, F4, F5> where SE: 'a, @@ -200,7 +311,8 @@ pub struct TraverseRefSimpleVisitor<F1> { pub visit_subexpr: F1, } -impl<'a, SE, L, N, E, SE2, Err, F1> ExprVisitor<'a, SE, SE2, L, L, N, N, E, E> +impl<'a, SE, L, N, E, SE2, Err, F1> + ExprFFallibleVisitor<'a, SE, SE2, L, L, N, N, E, E> for TraverseRefSimpleVisitor<F1> where SE: 'a, @@ -228,8 +340,17 @@ where pub struct TraverseEmbedVisitor<F1>(pub F1); impl<'a, 'b, N, E, E2, Err, F1> - ExprVisitor<'a, SubExpr<N, E>, SubExpr<N, E2>, Label, Label, N, N, E, E2> - for &'b mut TraverseEmbedVisitor<F1> + ExprFFallibleVisitor< + 'a, + SubExpr<N, E>, + SubExpr<N, E2>, + Label, + Label, + N, + N, + E, + E2, + > for &'b mut TraverseEmbedVisitor<F1> where N: Clone + 'a, E2: Clone, @@ -257,122 +378,135 @@ where pub struct SquashEmbedVisitor<F1>(pub F1); impl<'a, 'b, N, E, E2, F1> - ExprVisitor<'a, SubExpr<N, E>, SubExpr<N, E2>, Label, Label, N, N, E, E2> - for &'b mut SquashEmbedVisitor<F1> + ExprFInFallibleVisitor< + 'a, + SubExpr<N, E>, + SubExpr<N, E2>, + Label, + Label, + N, + N, + E, + E2, + > for &'b mut SquashEmbedVisitor<F1> where N: Clone + 'a, E2: Clone, F1: FnMut(&E) -> SubExpr<N, E2>, { - type Error = X; - - fn visit_subexpr( - &mut self, - subexpr: &'a SubExpr<N, E>, - ) -> Result<SubExpr<N, E2>, Self::Error> { - Ok(rc(subexpr.as_ref().visit(&mut **self)?)) + fn visit_subexpr(&mut self, subexpr: &'a SubExpr<N, E>) -> SubExpr<N, E2> { + rc(subexpr.as_ref().visit(&mut **self)) } - fn visit_note(self, note: &'a N) -> Result<N, Self::Error> { - Ok(N::clone(note)) + fn visit_note(self, note: &'a N) -> N { + N::clone(note) } - fn visit_embed(self, _: &'a E) -> Result<E2, Self::Error> { + fn visit_embed(self, _: &'a E) -> E2 { unreachable!() } - fn visit_embed_squash( - self, - embed: &'a E, - ) -> Result<Expr<N, E2>, Self::Error> { - Ok((self.0)(embed).unroll()) + fn visit_embed_squash(self, embed: &'a E) -> Expr<N, E2> { + (self.0)(embed).unroll() } - fn visit_label(&mut self, label: &'a Label) -> Result<Label, Self::Error> { - Ok(Label::clone(label)) + fn visit_label(&mut self, label: &'a Label) -> Label { + Label::clone(label) } } pub struct UnNoteVisitor; impl<'a, 'b, N, E> - ExprVisitor<'a, SubExpr<N, E>, SubExpr<X, E>, Label, Label, N, X, E, E> - for &'b mut UnNoteVisitor + ExprFInFallibleVisitor< + 'a, + SubExpr<N, E>, + SubExpr<X, E>, + Label, + Label, + N, + X, + E, + E, + > for &'b mut UnNoteVisitor where E: Clone + 'a, { - type Error = X; - - fn visit_subexpr( - &mut self, - subexpr: &'a SubExpr<N, E>, - ) -> Result<SubExpr<X, E>, Self::Error> { - Ok(rc(subexpr.as_ref().visit(&mut **self)?)) + fn visit_subexpr(&mut self, subexpr: &'a SubExpr<N, E>) -> SubExpr<X, E> { + rc(subexpr.as_ref().visit(&mut **self)) } - fn visit_note(self, _: &'a N) -> Result<X, Self::Error> { + fn visit_note(self, _: &'a N) -> X { unreachable!() } fn visit_note_squash( self, _: &'a N, subexpr: &'a SubExpr<N, E>, - ) -> Result<Expr<X, E>, Self::Error> { + ) -> Expr<X, E> { subexpr.as_ref().visit(self) } - fn visit_embed(self, embed: &'a E) -> Result<E, Self::Error> { - Ok(E::clone(embed)) + fn visit_embed(self, embed: &'a E) -> E { + E::clone(embed) } - fn visit_label(&mut self, label: &'a Label) -> Result<Label, Self::Error> { - Ok(Label::clone(label)) + fn visit_label(&mut self, label: &'a Label) -> Label { + Label::clone(label) } } pub struct NoteAbsurdVisitor; impl<'a, 'b, N, E> - ExprVisitor<'a, SubExpr<X, E>, SubExpr<N, E>, Label, Label, X, N, E, E> - for &'b mut NoteAbsurdVisitor + ExprFInFallibleVisitor< + 'a, + SubExpr<X, E>, + SubExpr<N, E>, + Label, + Label, + X, + N, + E, + E, + > for &'b mut NoteAbsurdVisitor where E: Clone + 'a, { - type Error = X; - - fn visit_subexpr( - &mut self, - subexpr: &'a SubExpr<X, E>, - ) -> Result<SubExpr<N, E>, Self::Error> { - Ok(rc(subexpr.as_ref().visit(&mut **self)?)) + fn visit_subexpr(&mut self, subexpr: &'a SubExpr<X, E>) -> SubExpr<N, E> { + rc(subexpr.as_ref().visit(&mut **self)) } - fn visit_note(self, note: &'a X) -> Result<N, Self::Error> { + fn visit_note(self, note: &'a X) -> N { match *note {} } - fn visit_embed(self, embed: &'a E) -> Result<E, Self::Error> { - Ok(E::clone(embed)) + fn visit_embed(self, embed: &'a E) -> E { + E::clone(embed) } - fn visit_label(&mut self, label: &'a Label) -> Result<Label, Self::Error> { - Ok(Label::clone(label)) + fn visit_label(&mut self, label: &'a Label) -> Label { + Label::clone(label) } } pub struct EmbedAbsurdVisitor; impl<'a, 'b, N, E> - ExprVisitor<'a, SubExpr<N, X>, SubExpr<N, E>, Label, Label, N, N, X, E> - for &'b mut EmbedAbsurdVisitor + ExprFInFallibleVisitor< + 'a, + SubExpr<N, X>, + SubExpr<N, E>, + Label, + Label, + N, + N, + X, + E, + > for &'b mut EmbedAbsurdVisitor where N: Clone + 'a, { - type Error = X; - - fn visit_subexpr( - &mut self, - subexpr: &'a SubExpr<N, X>, - ) -> Result<SubExpr<N, E>, Self::Error> { - Ok(rc(subexpr.as_ref().visit(&mut **self)?)) + fn visit_subexpr(&mut self, subexpr: &'a SubExpr<N, X>) -> SubExpr<N, E> { + rc(subexpr.as_ref().visit(&mut **self)) } - fn visit_note(self, note: &'a N) -> Result<N, Self::Error> { - Ok(N::clone(note)) + fn visit_note(self, note: &'a N) -> N { + N::clone(note) } - fn visit_embed(self, embed: &'a X) -> Result<E, Self::Error> { + fn visit_embed(self, embed: &'a X) -> E { match *embed {} } - fn visit_label(&mut self, label: &'a Label) -> Result<Label, Self::Error> { - Ok(Label::clone(label)) + fn visit_label(&mut self, label: &'a Label) -> Label { + Label::clone(label) } } |