This repository has been archived on 2020-09-15. You can view files and clone it, but cannot push or open issues or pull requests.
Files
not-python-old.2020-08-27/src/visit.rs

91 lines
2.4 KiB
Rust
Raw Normal View History

use crate::syn::ast::prelude::*;
pub trait Visit<A: Accept> {
type Out;
fn visit(&mut self, acceptor: &A) -> Self::Out;
}
pub trait Accept {
fn accept<V: Visit<Self>>(&self, visitor: &mut V) -> V::Out
where
Self: Sized;
}
pub trait DefaultAccept<V: Visit<Self>>: Accept + Sized {
fn default_accept(&self, visitor: &mut V) -> V::Out;
}
#[macro_export]
macro_rules! default_visitor {
($default:ident for $visitor:ty where Out = $out:ty) => {
impl crate::visit::Visit<$default> for $visitor {
type Out = $out;
fn visit(&mut self, acceptor: &$default) -> Self::Out {
acceptor.default_accept(self)
}
}
};
}
#[macro_export]
macro_rules! empty_visitor {
($default:ident for $visitor:ty) => {
impl crate::visit::Visit<$default> for $visitor {
type Out = ();
fn visit(&mut self, _: &$default) -> Self::Out {}
}
};
}
macro_rules! impl_accept {
($what:ident) => {
impl crate::visit::Accept for $what {
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);