Update visitor pattern for AST
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
compile::ctx::Ctx,
|
compile::ctx::Ctx,
|
||||||
obj::prelude::*,
|
obj::prelude::*,
|
||||||
syn::{ast::prelude::*, span::*},
|
syn::{ast::prelude::*, span::*, visit::*},
|
||||||
visit::*,
|
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@@ -87,85 +86,39 @@ impl NameStack {
|
|||||||
// CollectNames
|
// CollectNames
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pub struct CollectLocalNames<'c, 't> {
|
||||||
|
|
||||||
// TODO : redo visitor and accept (again) for CollectNames and CollectSyms
|
|
||||||
//
|
|
||||||
// Needs to be visitor-centric and not accept-centric
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Collect local stack names and push them to the top layer of the name stack.
|
|
||||||
pub struct CollectNames<'c, 't> {
|
|
||||||
ctx: &'c mut Ctx,
|
ctx: &'c mut Ctx,
|
||||||
text: &'t str,
|
text: &'t str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visit for CollectNames<'_, '_> {
|
impl<'c, 't> CollectLocalNames<'c, 't> {
|
||||||
type Out = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_empty_accept!(FunCallExpr for CollectNames<'_, '_>);
|
|
||||||
impl_empty_accept!(FunExpr for CollectNames<'_, '_>);
|
|
||||||
|
|
||||||
impl<'c, 't> CollectNames<'c, 't> {
|
|
||||||
pub fn new(ctx: &'c mut Ctx, text: &'t str) -> Self {
|
pub fn new(ctx: &'c mut Ctx, text: &'t str) -> Self {
|
||||||
CollectNames { ctx, text }
|
CollectLocalNames { ctx, text }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect(&mut self, stmts: &Vec<Stmt>) {
|
pub fn collect(&mut self, ast: &Vec<Stmt>) {
|
||||||
// Collect all LHS assignments
|
ast.iter()
|
||||||
for stmt in stmts.iter() {
|
.for_each(|stmt| self.visit_stmt(stmt))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisitAst for CollectLocalNames<'_, '_> {
|
||||||
|
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||||
if let Stmt::Assign(stmt) = stmt {
|
if let Stmt::Assign(stmt) = stmt {
|
||||||
self.visit(stmt);
|
self.visit_assign_stmt(stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_assign_stmt(&mut self, stmt: &AssignStmt) {
|
||||||
|
self.visit_expr(&stmt.lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_ident(&mut self, span: Span) {
|
||||||
|
let name = span.text_at(self.text).to_string();
|
||||||
|
self.ctx.name_stack_mut().add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Accept<CollectNames<'_, '_>> for AssignStmt {
|
|
||||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
|
||||||
visitor.visit(&self.lhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectNames<'_, '_>> for Expr {
|
|
||||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
|
||||||
self.default_accept(visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectNames<'_, '_>> for BinExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
|
||||||
visitor.visit(&self.lhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectNames<'_, '_>> for UnExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
|
||||||
visitor.visit(&self.expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectNames<'_, '_>> for IndexExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
|
||||||
visitor.visit(&self.expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectNames<'_, '_>> for BaseExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
|
||||||
// This is a LHS standalone expr
|
|
||||||
if let BaseExpr {
|
|
||||||
kind: BaseExprKind::Ident,
|
|
||||||
..
|
|
||||||
} = self
|
|
||||||
{
|
|
||||||
let name = self.text_at(visitor.text).to_string();
|
|
||||||
visitor.ctx.name_stack_mut().add(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// CollectSyms
|
// CollectSyms
|
||||||
@@ -186,85 +139,22 @@ impl<'c, 't> CollectSyms<'c, 't> {
|
|||||||
|
|
||||||
pub fn collect(&mut self, stmts: &Vec<Stmt>) {
|
pub fn collect(&mut self, stmts: &Vec<Stmt>) {
|
||||||
// Collect all LHS assignments
|
// Collect all LHS assignments
|
||||||
for stmt in stmts.iter() {
|
stmts.iter()
|
||||||
stmt.accept(self);
|
.for_each(|stmt| self.visit(stmt))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visit for CollectSyms<'_, '_> {
|
impl VisitAst for CollectSyms<'_, '_> {
|
||||||
type Out = ();
|
fn visit_ident(&mut self, span: Span) {
|
||||||
}
|
let name = span.text_at(self.text).to_string();
|
||||||
|
self.ctx.syms_mut().add(name);
|
||||||
|
}
|
||||||
|
|
||||||
impl_default_accept!(Stmt for CollectSyms<'_, '_>);
|
fn visit_sym(&mut self, span: Span) {
|
||||||
|
let name = span.text_at(self.text)
|
||||||
impl Accept<CollectSyms<'_, '_>> for AssignStmt {
|
.chars()
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
.skip(1)
|
||||||
visitor.visit(&self.lhs);
|
.collect::<String>();
|
||||||
visitor.visit(&self.rhs);
|
self.ctx.syms_mut().add(name);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_default_accept!(Expr for CollectSyms<'_, '_>);
|
|
||||||
|
|
||||||
impl Accept<CollectSyms<'_, '_>> for BinExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
|
||||||
visitor.visit(&self.lhs);
|
|
||||||
visitor.visit(&self.rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectSyms<'_, '_>> for UnExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
|
||||||
visitor.visit(&self.expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectSyms<'_, '_>> for FunCallExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
|
||||||
visitor.visit(&self.expr);
|
|
||||||
self.args.iter().for_each(|expr| visitor.visit(expr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectSyms<'_, '_>> for IndexExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
|
||||||
visitor.visit(&self.expr);
|
|
||||||
visitor.visit(&self.index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectSyms<'_, '_>> for FunExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
|
||||||
self.params.iter().for_each(|name| {
|
|
||||||
visitor.ctx.syms_mut().add(name.clone());
|
|
||||||
});
|
|
||||||
visitor.visit(&self.expr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accept<CollectSyms<'_, '_>> for BaseExpr {
|
|
||||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
|
||||||
match &self.kind {
|
|
||||||
BaseExprKind::Ident => {
|
|
||||||
let name = self.text_at(visitor.text).to_string();
|
|
||||||
visitor.ctx.syms_mut().add(name);
|
|
||||||
}
|
|
||||||
BaseExprKind::Sym => {
|
|
||||||
let name = self.text_at(visitor.text).chars().skip(1).collect::<String>();
|
|
||||||
visitor.ctx.syms_mut().add(name);
|
|
||||||
}
|
|
||||||
BaseExprKind::List(l) | BaseExprKind::Tuple(l) => {
|
|
||||||
l.iter().for_each(|expr| visitor.visit(expr))
|
|
||||||
}
|
|
||||||
BaseExprKind::Object(o) => o.iter().for_each(|(k, v)| {
|
|
||||||
visitor.visit(k);
|
|
||||||
visitor.visit(v);
|
|
||||||
}),
|
|
||||||
BaseExprKind::Block(stmts) => {
|
|
||||||
stmts.iter().for_each(|stmt| visitor.visit(stmt));
|
|
||||||
}
|
|
||||||
_ => { /* no-op */ }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/main.rs
12
src/main.rs
@@ -1,7 +1,6 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![feature(unsize, coerce_unsized, new_uninit, box_into_pin)]
|
#![feature(unsize, coerce_unsized, new_uninit, box_into_pin)]
|
||||||
|
|
||||||
#[macro_use] mod visit;
|
|
||||||
mod compile;
|
mod compile;
|
||||||
mod mem;
|
mod mem;
|
||||||
mod obj;
|
mod obj;
|
||||||
@@ -38,16 +37,13 @@ fn main() -> Result<()> {
|
|||||||
//println!("{:#?}", ast);
|
//println!("{:#?}", ast);
|
||||||
|
|
||||||
let mut ctx = compile::ctx::Ctx::new();
|
let mut ctx = compile::ctx::Ctx::new();
|
||||||
{ compile::name::CollectSyms::new(&mut ctx, text.as_str()).collect(&ast); }
|
|
||||||
println!("{:#?}", ctx.syms());
|
|
||||||
|
|
||||||
ctx.name_stack_mut().push_default();
|
ctx.name_stack_mut().push_default();
|
||||||
{
|
{ compile::name::CollectLocalNames::new(&mut ctx, text.as_str()).collect(&ast); }
|
||||||
let mut collect_names = compile::name::CollectNames::new(&mut ctx, text.as_str());
|
|
||||||
collect_names.collect(&ast);
|
|
||||||
}
|
|
||||||
let _names = ctx.name_stack_mut().pop().unwrap();
|
let _names = ctx.name_stack_mut().pop().unwrap();
|
||||||
//println!("{:#?}", names);
|
//println!("{:#?}", names);
|
||||||
|
|
||||||
|
{ compile::name::CollectSyms::new(&mut ctx, text.as_str()).collect(&ast); }
|
||||||
|
println!("{:#?}", ctx.syms());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{syn::{op::*, span::*}, visit::*};
|
use crate::syn::{op::*, span::*, visit::*};
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@@ -174,51 +174,22 @@ impl Spanned for BaseExpr {
|
|||||||
// Acceptor (visitor) impls
|
// Acceptor (visitor) impls
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<V> DefaultAccept<V> for Expr
|
macro_rules! impl_accept {
|
||||||
where V: Visit,
|
($for:ty, $method:ident) => {
|
||||||
Self: Accept<V>,
|
impl<V: VisitAst> AcceptAst<V> for $for {
|
||||||
BinExpr: Accept<V>,
|
fn accept(&self, visitor: &mut V) {
|
||||||
UnExpr: Accept<V>,
|
visitor.$method(self)
|
||||||
FunCallExpr: Accept<V>,
|
|
||||||
IndexExpr: Accept<V>,
|
|
||||||
FunExpr: Accept<V>,
|
|
||||||
BaseExpr: Accept<V>,
|
|
||||||
{
|
|
||||||
fn default_accept(&self, visitor: &mut V) -> 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<V> DefaultAccept<V> for Stmt
|
impl_accept!(Stmt, visit_stmt);
|
||||||
where V: Visit,
|
impl_accept!(AssignStmt, visit_assign_stmt);
|
||||||
Self: Accept<V>,
|
impl_accept!(Expr, visit_expr);
|
||||||
Expr: Accept<V>,
|
impl_accept!(BinExpr, visit_bin_expr);
|
||||||
AssignStmt: Accept<V>,
|
impl_accept!(UnExpr, visit_un_expr);
|
||||||
{
|
impl_accept!(FunCallExpr, visit_fun_call_expr);
|
||||||
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
impl_accept!(IndexExpr, visit_index_expr);
|
||||||
match self {
|
impl_accept!(FunExpr, visit_fun_expr);
|
||||||
Stmt::Assign(a) => visitor.visit(a),
|
impl_accept!(BaseExpr, visit_base_expr);
|
||||||
Stmt::Expr(e) => visitor.visit(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
mpl_accept!(FunExpr);
|
|
||||||
impl_accept!(BaseExpr);
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ pub mod op;
|
|||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod span;
|
pub mod span;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
|
pub mod visit;
|
||||||
|
|||||||
104
src/syn/visit.rs
Normal file
104
src/syn/visit.rs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
use crate::syn::{ast::prelude::*, span::*};
|
||||||
|
|
||||||
|
pub trait VisitAst {
|
||||||
|
fn visit(&mut self, acceptor: &dyn AcceptAst<Self>) where Self: Sized {
|
||||||
|
acceptor.accept(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||||
|
match stmt {
|
||||||
|
Stmt::Assign(stmt) => self.visit_assign_stmt(stmt),
|
||||||
|
Stmt::Expr(expr) => self.visit_expr(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_assign_stmt(&mut self, stmt: &AssignStmt) {
|
||||||
|
self.visit_assign_lhs(&stmt.lhs);
|
||||||
|
self.visit_expr(&stmt.rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_assign_lhs(&mut self, expr: &Expr) {
|
||||||
|
self.visit_expr(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, expr: &Expr) {
|
||||||
|
match expr {
|
||||||
|
Expr::Bin(expr) => self.visit_bin_expr(expr),
|
||||||
|
Expr::Un(expr) => self.visit_un_expr(expr),
|
||||||
|
Expr::FunCall(expr) => self.visit_fun_call_expr(expr),
|
||||||
|
Expr::Index(expr) => self.visit_index_expr(expr),
|
||||||
|
Expr::Fun(expr) => self.visit_fun_expr(expr),
|
||||||
|
Expr::Base(expr) => self.visit_base_expr(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bin_expr(&mut self, expr: &BinExpr) {
|
||||||
|
self.visit_expr(&expr.lhs);
|
||||||
|
self.visit_expr(&expr.rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_un_expr(&mut self, expr: &UnExpr) {
|
||||||
|
self.visit_expr(&expr.expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_fun_call_expr(&mut self, expr: &FunCallExpr) {
|
||||||
|
self.visit_expr(&expr.expr);
|
||||||
|
expr.args
|
||||||
|
.iter()
|
||||||
|
.for_each(|arg| self.visit_expr(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_index_expr(&mut self, expr: &IndexExpr) {
|
||||||
|
self.visit_expr(&expr.expr);
|
||||||
|
self.visit_expr(&expr.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_fun_expr(&mut self, expr: &FunExpr) {
|
||||||
|
self.visit_expr(&expr.expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_base_expr(&mut self, expr: &BaseExpr) {
|
||||||
|
match &expr.kind {
|
||||||
|
BaseExprKind::Ident => self.visit_ident(expr.span()),
|
||||||
|
BaseExprKind::Num => self.visit_num(expr.span()),
|
||||||
|
BaseExprKind::Str => self.visit_str(expr.span()),
|
||||||
|
BaseExprKind::Sym => self.visit_sym(expr.span()),
|
||||||
|
BaseExprKind::List(list) => self.visit_list(list),
|
||||||
|
BaseExprKind::Object(obj) => self.visit_obj(obj),
|
||||||
|
BaseExprKind::Tuple(tuple) => self.visit_tuple(tuple),
|
||||||
|
BaseExprKind::Block(block) => self.visit_block(block),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_ident(&mut self, _span: Span) {}
|
||||||
|
fn visit_num(&mut self, _span: Span) {}
|
||||||
|
fn visit_str(&mut self, _span: Span) {}
|
||||||
|
fn visit_sym(&mut self, _span: Span) {}
|
||||||
|
|
||||||
|
fn visit_list(&mut self, list: &Vec<Expr>) {
|
||||||
|
list.iter()
|
||||||
|
.for_each(|expr| self.visit_expr(expr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_obj(&mut self, obj: &Vec<(Expr, Expr)>) {
|
||||||
|
obj.iter()
|
||||||
|
.for_each(|(k, v)| {
|
||||||
|
self.visit_expr(k);
|
||||||
|
self.visit_expr(v);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_tuple(&mut self, tuple: &Vec<Expr>) {
|
||||||
|
tuple.iter()
|
||||||
|
.for_each(|expr| self.visit_expr(expr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_block(&mut self, block: &Vec<Stmt>) {
|
||||||
|
block.iter()
|
||||||
|
.for_each(|stmt| self.visit_stmt(stmt))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AcceptAst<V: VisitAst> {
|
||||||
|
fn accept(&self, visitor: &mut V);
|
||||||
|
}
|
||||||
59
src/visit.rs
59
src/visit.rs
@@ -1,59 +0,0 @@
|
|||||||
pub trait Visit {
|
|
||||||
type Out;
|
|
||||||
fn visit(&mut self, acceptor: &dyn Accept<Self>) -> Self::Out where Self: Sized {
|
|
||||||
acceptor.accept(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Accept<V: Visit> {
|
|
||||||
fn accept(&self, visitor: &mut V) -> V::Out;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DefaultAccept<V: Visit>: Accept<V> + Sized {
|
|
||||||
fn default_accept(&self, visitor: &mut V) -> V::Out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! impl_default_accept {
|
|
||||||
($what:ident for $visitor:ty) => {
|
|
||||||
impl $crate::visit::Accept<$visitor> for $what
|
|
||||||
{
|
|
||||||
fn accept(&self, visitor: &mut $visitor) {
|
|
||||||
self.default_accept(visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! impl_empty_accept {
|
|
||||||
($default:ident for $visitor:ty) => {
|
|
||||||
impl $crate::visit::Accept<$visitor> for $default {
|
|
||||||
fn accept(&self, _: &mut $visitor) {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! impl_accept {
|
|
||||||
($what:ty) => {
|
|
||||||
impl<V: $crate::visit::Visit> $crate::visit::Accept<V> for $what {
|
|
||||||
fn accept(&self, visitor: &mut V) -> V::Out {
|
|
||||||
visitor.visit(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! impl_default_accept {
|
|
||||||
($what:ident : $($requires:ident),+ => $($tail:tt)+) => {
|
|
||||||
impl<V> $crate::visit::DefaultAccept<V> for $what
|
|
||||||
where V: $crate::visit::Visit $(+ $crate::visit::Visit<$requires>)+
|
|
||||||
{
|
|
||||||
$($tail)+
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Reference in New Issue
Block a user