2020-05-20 14:41:12 -04:00
|
|
|
use crate::syn::ast::prelude::*;
|
2020-05-19 15:26:38 -04:00
|
|
|
|
2020-05-20 14:41:12 -04:00
|
|
|
pub trait Visit<A: Accept> {
|
2020-05-19 15:26:38 -04:00
|
|
|
type Out;
|
2020-05-20 14:41:12 -04:00
|
|
|
fn visit(&mut self, acceptor: &A) -> Self::Out;
|
|
|
|
|
}
|
2020-05-19 15:26:38 -04:00
|
|
|
|
2020-05-20 14:41:12 -04:00
|
|
|
pub trait Accept {
|
|
|
|
|
fn accept<V: Visit<Self>>(&self, visitor: &mut V) -> V::Out
|
|
|
|
|
where
|
|
|
|
|
Self: Sized;
|
2020-05-19 15:26:38 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-20 15:25:10 -04:00
|
|
|
pub trait DefaultAccept<V: Visit<Self>>: Accept + Sized {
|
2020-05-20 14:41:12 -04:00
|
|
|
fn default_accept(&self, visitor: &mut V) -> V::Out;
|
2020-05-19 15:26:38 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-20 14:41:12 -04:00
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! default_visitor {
|
|
|
|
|
($default:ident for $visitor:ty where Out = $out:ty) => {
|
2020-05-21 19:09:48 -04:00
|
|
|
impl crate::visit::Visit<$default> for $visitor {
|
2020-05-20 14:41:12 -04:00
|
|
|
type Out = $out;
|
|
|
|
|
fn visit(&mut self, acceptor: &$default) -> Self::Out {
|
|
|
|
|
acceptor.default_accept(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-05-19 15:26:38 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-20 14:41:12 -04:00
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! empty_visitor {
|
|
|
|
|
($default:ident for $visitor:ty) => {
|
2020-05-21 19:09:48 -04:00
|
|
|
impl crate::visit::Visit<$default> for $visitor {
|
2020-05-20 14:41:12 -04:00
|
|
|
type Out = ();
|
|
|
|
|
fn visit(&mut self, _: &$default) -> Self::Out {}
|
|
|
|
|
}
|
2020-05-20 15:25:10 -04:00
|
|
|
};
|
2020-05-19 15:26:38 -04:00
|
|
|
}
|
2020-05-20 14:41:12 -04:00
|
|
|
|
|
|
|
|
macro_rules! impl_accept {
|
|
|
|
|
($what:ident) => {
|
2020-05-21 19:09:48 -04:00
|
|
|
impl crate::visit::Accept for $what {
|
2020-05-20 14:41:12 -04:00
|
|
|
fn accept<V: Visit<Self>>(&self, visitor: &mut V) -> V::Out {
|
|
|
|
|
visitor.visit(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! impl_default_accept {
|
|
|
|
|
($what:ident : $($requires:ident),+ => $($tail:tt)+) => {
|
|
|
|
|
impl<V, Out> DefaultAccept<V> for $what
|
|
|
|
|
where V: Visit<Self, Out=Out> $(+ Visit<$requires, Out=Out>)+
|
|
|
|
|
{
|
|
|
|
|
$($tail)+
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl_accept!(Stmt);
|
|
|
|
|
impl_default_accept!(Stmt : AssignStmt, Expr =>
|
|
|
|
|
fn default_accept(&self, visitor: &mut V) -> Out {
|
|
|
|
|
match self {
|
|
|
|
|
Stmt::Assign(a) => visitor.visit(a),
|
|
|
|
|
Stmt::Expr(e) => visitor.visit(e),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
impl_accept!(AssignStmt);
|
|
|
|
|
impl_accept!(Expr);
|
|
|
|
|
|
|
|
|
|
impl_default_accept!(Expr: BinExpr, UnExpr, FunCallExpr, IndexExpr, FunExpr, BaseExpr =>
|
|
|
|
|
fn default_accept(&self, visitor: &mut V) -> Out {
|
|
|
|
|
match self {
|
|
|
|
|
Expr::Bin(b) => visitor.visit(b.as_ref()),
|
|
|
|
|
Expr::Un(u) => visitor.visit(u.as_ref()),
|
|
|
|
|
Expr::FunCall(f) => visitor.visit(f.as_ref()),
|
|
|
|
|
Expr::Index(i) => visitor.visit(i.as_ref()),
|
|
|
|
|
Expr::Fun(f) => visitor.visit(f.as_ref()),
|
|
|
|
|
Expr::Base(b) => visitor.visit(b),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
impl_accept!(BinExpr);
|
|
|
|
|
impl_accept!(UnExpr);
|
|
|
|
|
impl_accept!(FunCallExpr);
|
|
|
|
|
impl_accept!(IndexExpr);
|
|
|
|
|
impl_accept!(FunExpr);
|
|
|
|
|
impl_accept!(BaseExpr);
|