use crate::*;
use std::iter::FromIterator;
/// A way too generic Visitor trait.
pub trait GenericVisitor: Sized {
fn visit(self, input: Input) -> Output;
}
/// A visitor trait that can be used to traverse `ExprF`s. We need this pattern so that Rust lets
/// us have as much mutability as we can.
/// For example, `traverse_ref_with_special_handling_of_binders` cannot be made using only
/// `traverse_ref`, because `traverse_ref` takes a `FnMut` so we would need to pass multiple
/// mutable reverences to this argument to `traverse_ref`. But Rust's ownership system is all about
/// preventing exactly this ! So we have to be more clever. The visitor pattern allows us to have
/// only one mutable thing the whole time: the visitor itself. The visitor can then carry around
/// multiple closures or just one, and Rust is ok with either. See for example TraverseRefVisitor.
pub trait ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>: Sized {
type Error;
fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result;
fn visit_embed(self, embed: &'a E1) -> Result;
fn visit_subexpr_under_binder(
mut self,
_label: &'a Label,
subexpr: &'a SE1,
) -> Result {
self.visit_subexpr(subexpr)
}
}
/// Like ExprFFallibleVisitor, but without the error handling.
pub trait ExprFInFallibleVisitor<'a, SE1, SE2, E1, E2>: Sized {
fn visit_subexpr(&mut self, subexpr: &'a SE1) -> SE2;
fn visit_embed(self, embed: &'a E1) -> E2;
fn visit_subexpr_under_binder(
mut self,
_label: &'a Label,
subexpr: &'a SE1,
) -> SE2 {
self.visit_subexpr(subexpr)
}
}
impl<'a, T, SE1, SE2, E1, E2>
GenericVisitor<&'a ExprF, Result, T::Error>> for T
where
T: ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>,
{
fn visit(
self,
input: &'a ExprF,
) -> Result, T::Error> {
fn vec<'a, T, U, Err, F: FnMut(&'a T) -> Result>(
x: &'a [T],
f: F,
) -> Result, Err> {
x.iter().map(f).collect()
}
fn opt<'a, T, U, Err, F: FnOnce(&'a T) -> Result>(
x: &'a Option,
f: F,
) -> Result