use std::collections::BTreeMap;
use crate::*;
pub trait GenericVisitor: 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;
fn visit_label(&mut self, label: &'a L1) -> Result;
fn visit_note(self, note: &'a N1) -> Result;
fn visit_embed(self, embed: &'a E1) -> Result;
fn visit_subexpr_under_binder(
mut self,
_label: &'a L1,
subexpr: &'a SE1,
) -> Result {
self.visit_subexpr(subexpr)
}
fn visit_binder(
mut self,
label: &'a L1,
subexpr: &'a SE1,
) -> Result<(L2, SE2), Self::Error> {
Ok((
self.visit_label(label)?,
self.visit_subexpr_under_binder(label, subexpr)?,
))
}
fn visit_embed_squash(
self,
embed: &'a E1,
) -> Result, Self::Error> {
Ok(ExprF::Embed(self.visit_embed(embed)?))
}
fn visit_note_squash(
mut self,
note: &'a N1,
subexpr: &'a SE1,
) -> Result, Self::Error> {
let subexpr = self.visit_subexpr(subexpr)?;
let note = self.visit_note(note)?;
Ok(ExprF::Note(note, subexpr))
}
}
impl<'a, T, SE1, SE2, L1, L2, N1, N2, E1, E2>
GenericVisitor<
&'a ExprF,
Result, 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,
) -> Result, T::Error> {
fn vec<'a, T, U, Err, F: FnMut(&'a T) -> Result>(
x: &'a Vec,
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