Continue working on overhauling Accept/Visit
* Accept requires a Visit parameter, so acceptor implementations are type-wide and not method-wide. This allows us to pass &dyn Trait references around to the visitor. * Additionally, visitors now take a &dyn Accept so that acceptors are dynamically dispatched(!) * Converted everything except for the WIP TranslateAst visitor. This might make things a little weird because return values can't vary per-acceptor anymore, and must instead be uniform. Maybe it would make most sense to do away with the Out parameters and expect acceptors to report their state to their visitor, instead of returning something. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -10,6 +10,7 @@ pub enum Block {
|
||||
Blocks(Vec<Block>),
|
||||
}
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TranslateAst
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -150,3 +151,4 @@ impl Visit<BaseExpr> for TranslateAst<'_, '_> {
|
||||
Ok(base)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -93,9 +93,12 @@ pub struct CollectNames<'c, 't> {
|
||||
text: &'t str,
|
||||
}
|
||||
|
||||
default_visitor!(Expr for CollectNames<'_, '_> where Out = ());
|
||||
empty_visitor!(FunCallExpr for CollectNames<'_, '_>);
|
||||
empty_visitor!(FunExpr for CollectNames<'_, '_>);
|
||||
impl Visit for CollectNames<'_, '_> {
|
||||
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 {
|
||||
@@ -112,50 +115,46 @@ impl<'c, 't> CollectNames<'c, 't> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<AssignStmt> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, stmt: &AssignStmt) -> Self::Out {
|
||||
self.visit(&stmt.lhs);
|
||||
impl Accept<CollectNames<'_, '_>> for AssignStmt {
|
||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
||||
visitor.visit(&self.lhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<BinExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &BinExpr) -> Self::Out {
|
||||
self.visit(&expr.lhs);
|
||||
impl Accept<CollectNames<'_, '_>> for Expr {
|
||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
||||
self.default_accept(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<UnExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &UnExpr) -> Self::Out {
|
||||
self.visit(&expr.expr)
|
||||
impl Accept<CollectNames<'_, '_>> for BinExpr {
|
||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
||||
visitor.visit(&self.lhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<IndexExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &IndexExpr) -> Self::Out {
|
||||
self.visit(&expr.expr);
|
||||
impl Accept<CollectNames<'_, '_>> for UnExpr {
|
||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
||||
visitor.visit(&self.expr);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<BaseExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
impl Accept<CollectNames<'_, '_>> for IndexExpr {
|
||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
||||
visitor.visit(&self.expr);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit(&mut self, expr: &BaseExpr) -> Self::Out {
|
||||
impl Accept<CollectNames<'_, '_>> for BaseExpr {
|
||||
fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
|
||||
// This is a LHS standalone expr
|
||||
if let BaseExpr {
|
||||
kind: BaseExprKind::Ident,
|
||||
..
|
||||
} = expr
|
||||
} = self
|
||||
{
|
||||
let name = expr.text_at(self.text).to_string();
|
||||
self.ctx.name_stack_mut().add(name);
|
||||
let name = self.text_at(visitor.text).to_string();
|
||||
visitor.ctx.name_stack_mut().add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,91 +179,82 @@ impl<'c, 't> CollectSyms<'c, 't> {
|
||||
pub fn collect(&mut self, stmts: &Vec<Stmt>) {
|
||||
// Collect all LHS assignments
|
||||
for stmt in stmts.iter() {
|
||||
self.visit(stmt);
|
||||
stmt.accept(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default_visitor!(Stmt for CollectSyms<'_, '_> where Out = ());
|
||||
default_visitor!(Expr for CollectSyms<'_, '_> where Out = ());
|
||||
|
||||
impl Visit<AssignStmt> for CollectSyms<'_, '_> {
|
||||
impl Visit for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
}
|
||||
|
||||
fn visit(&mut self, stmt: &AssignStmt) -> Self::Out {
|
||||
self.visit(&stmt.lhs);
|
||||
self.visit(&stmt.rhs);
|
||||
impl_default_accept!(Stmt for CollectSyms<'_, '_>);
|
||||
|
||||
impl Accept<CollectSyms<'_, '_>> for AssignStmt {
|
||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
||||
visitor.visit(&self.lhs);
|
||||
visitor.visit(&self.rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<BinExpr> for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
impl_default_accept!(Expr for CollectSyms<'_, '_>);
|
||||
|
||||
fn visit(&mut self, expr: &BinExpr) -> Self::Out {
|
||||
self.visit(&expr.lhs);
|
||||
self.visit(&expr.rhs);
|
||||
impl Accept<CollectSyms<'_, '_>> for BinExpr {
|
||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
||||
visitor.visit(&self.lhs);
|
||||
visitor.visit(&self.rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<UnExpr> for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &UnExpr) -> Self::Out {
|
||||
self.visit(&expr.expr);
|
||||
impl Accept<CollectSyms<'_, '_>> for UnExpr {
|
||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
||||
visitor.visit(&self.expr);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<FunCallExpr> for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &FunCallExpr) -> Self::Out {
|
||||
self.visit(&expr.expr);
|
||||
expr.args.iter().for_each(|expr| self.visit(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 Visit<IndexExpr> for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &IndexExpr) -> Self::Out {
|
||||
self.visit(&expr.expr);
|
||||
self.visit(&expr.index);
|
||||
impl Accept<CollectSyms<'_, '_>> for IndexExpr {
|
||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
||||
visitor.visit(&self.expr);
|
||||
visitor.visit(&self.index);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<FunExpr> for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &FunExpr) -> Self::Out {
|
||||
expr.params.iter().for_each(|name| {
|
||||
self.ctx.syms_mut().add(name.clone());
|
||||
impl Accept<CollectSyms<'_, '_>> for FunExpr {
|
||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
||||
self.params.iter().for_each(|name| {
|
||||
visitor.ctx.syms_mut().add(name.clone());
|
||||
});
|
||||
self.visit(&expr.expr);
|
||||
visitor.visit(&self.expr)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<BaseExpr> for CollectSyms<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &BaseExpr) -> Self::Out {
|
||||
match &expr.kind {
|
||||
impl Accept<CollectSyms<'_, '_>> for BaseExpr {
|
||||
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
|
||||
match &self.kind {
|
||||
BaseExprKind::Ident => {
|
||||
let name = expr.text_at(self.text).to_string();
|
||||
self.ctx.syms_mut().add(name);
|
||||
let name = self.text_at(visitor.text).to_string();
|
||||
visitor.ctx.syms_mut().add(name);
|
||||
}
|
||||
BaseExprKind::Sym => {
|
||||
let name = expr.text_at(self.text).chars().skip(1).collect::<String>();
|
||||
self.ctx.syms_mut().add(name);
|
||||
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| self.visit(expr))
|
||||
l.iter().for_each(|expr| visitor.visit(expr))
|
||||
}
|
||||
BaseExprKind::Object(o) => o.iter().for_each(|(k, v)| {
|
||||
self.visit(k);
|
||||
self.visit(v);
|
||||
visitor.visit(k);
|
||||
visitor.visit(v);
|
||||
}),
|
||||
BaseExprKind::Block(stmts) => {
|
||||
stmts.iter().for_each(|stmt| self.visit(stmt));
|
||||
stmts.iter().for_each(|stmt| visitor.visit(stmt));
|
||||
}
|
||||
_ => { /* no-op */ }
|
||||
}
|
||||
|
||||
@@ -9,12 +9,3 @@ pub trait Gc {
|
||||
|
||||
fn sweep(&mut self);
|
||||
}
|
||||
|
||||
impl<O> Visit<O> for O
|
||||
where O: Obj + Accept
|
||||
{
|
||||
type Out = ();
|
||||
fn visit(&mut self, obj: &O) -> Self::Out {
|
||||
obj.accept(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{obj::Obj, visit::{DynAccept, Accept, Visit}};
|
||||
use crate::obj::Obj;
|
||||
use std::{
|
||||
any,
|
||||
cell::RefCell,
|
||||
@@ -94,14 +94,6 @@ impl Debug for ObjRef<dyn Obj> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<O> DynAccept for ObjRef<O>
|
||||
where O: Obj + ?Sized + DynAccept
|
||||
{
|
||||
fn accept(&self, visitor: &mut impl Visit<Self, Out=()>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Comparison impls
|
||||
//
|
||||
|
||||
@@ -66,12 +66,15 @@ impl Obj for Attrs {
|
||||
}
|
||||
}
|
||||
|
||||
//impl_accept!(Attrs);
|
||||
/*
|
||||
impl_accept!(Attrs);
|
||||
|
||||
impl<G: Gc> Visit<Attrs> for G {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, _attrs: &Attrs) -> Self::Out {
|
||||
todo!()
|
||||
fn visit(&mut self, attrs: &Attrs) -> Self::Out {
|
||||
attrs.attrs.values()
|
||||
.for_each(|obj| obj.accept(self));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -28,16 +28,3 @@ impl Obj for Dict {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
//impl_accept!(Dict);
|
||||
|
||||
impl<G> Visit<Dict> for G
|
||||
where G: Gc + Visit<Attrs>,
|
||||
{
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, dict: &Dict) -> Self::Out {
|
||||
let attrs_ref: &Attrs = &dict.attrs.borrow();
|
||||
self.visit(attrs_ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,11 @@ pub use self::{
|
||||
sym::Sym,
|
||||
};
|
||||
use crate::mem::ptr::ObjRef;
|
||||
use crate::visit::*;
|
||||
use std::any::Any;
|
||||
|
||||
pub trait Obj {
|
||||
fn attrs(&self) -> ObjRef<Attrs>;
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{obj::prelude::*, visit::{DynAccept, Visit}};
|
||||
use crate::{obj::prelude::*, visit::Visit};
|
||||
use derivative::Derivative;
|
||||
use std::{any::Any, cell::Cell};
|
||||
|
||||
@@ -39,21 +39,3 @@ impl Obj for Str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
//impl_accept!(Str);
|
||||
|
||||
impl<O> DynAccept for O
|
||||
where O: Obj + ?Sized
|
||||
{
|
||||
fn accept(&self, visitor: &mut impl Visit<Self, Out=()>) {
|
||||
visitor.visit(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Gc> Visit<Str> for G {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, _s: &Str) -> Self::Out {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::syn::{op::*, span::*};
|
||||
use crate::{syn::{op::*, span::*}, visit::*};
|
||||
use derivative::Derivative;
|
||||
|
||||
pub mod prelude {
|
||||
@@ -174,20 +174,17 @@ impl Spanned for BaseExpr {
|
||||
// Acceptor (visitor) impls
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 {
|
||||
impl<V> DefaultAccept<V> for Expr
|
||||
where V: Visit,
|
||||
Self: Accept<V>,
|
||||
BinExpr: Accept<V>,
|
||||
UnExpr: Accept<V>,
|
||||
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()),
|
||||
@@ -197,11 +194,31 @@ impl_default_accept!(Expr: BinExpr, UnExpr, FunCallExpr, IndexExpr, FunExpr, Bas
|
||||
Expr::Base(b) => visitor.visit(b),
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl_accept!(BinExpr);
|
||||
impl_accept!(UnExpr);
|
||||
impl_accept!(FunCallExpr);
|
||||
impl_accept!(IndexExpr);
|
||||
impl_accept!(FunExpr);
|
||||
impl<V> DefaultAccept<V> for Stmt
|
||||
where V: Visit,
|
||||
Self: Accept<V>,
|
||||
Expr: Accept<V>,
|
||||
AssignStmt: Accept<V>,
|
||||
{
|
||||
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||
match self {
|
||||
Stmt::Assign(a) => visitor.visit(a),
|
||||
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);
|
||||
*/
|
||||
|
||||
45
src/visit.rs
45
src/visit.rs
@@ -1,47 +1,45 @@
|
||||
pub trait Visit<A: ?Sized> {
|
||||
pub trait Visit {
|
||||
type Out;
|
||||
fn visit(&mut self, acceptor: &A) -> Self::Out;
|
||||
fn visit(&mut self, acceptor: &dyn Accept<Self>) -> Self::Out where Self: Sized {
|
||||
acceptor.accept(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Accept {
|
||||
fn accept<V: Visit<Self>>(&self, visitor: &mut V) -> V::Out;
|
||||
pub trait Accept<V: Visit> {
|
||||
fn accept(&self, visitor: &mut V) -> V::Out;
|
||||
}
|
||||
|
||||
pub trait DynAccept<Out=()> {
|
||||
fn accept(&self, visitor: &mut impl Visit<Self, Out=Out>);
|
||||
}
|
||||
|
||||
pub trait DefaultAccept<V: Visit<Self>>: Accept + Sized {
|
||||
pub trait DefaultAccept<V: Visit>: Accept<V> + 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_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! empty_visitor {
|
||||
macro_rules! impl_empty_accept {
|
||||
($default:ident for $visitor:ty) => {
|
||||
impl $crate::visit::Visit<$default> for $visitor {
|
||||
type Out = ();
|
||||
fn visit(&mut self, _: &$default) -> Self::Out {}
|
||||
impl $crate::visit::Accept<$visitor> for $default {
|
||||
fn accept(&self, _: &mut $visitor) {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
#[macro_export]
|
||||
macro_rules! impl_accept {
|
||||
($what:ty) => {
|
||||
impl $crate::visit::Accept for $what {
|
||||
fn accept<V: $crate::visit::Visit<Self>>(&self, visitor: &mut V) -> V::Out {
|
||||
impl<V: $crate::visit::Visit> $crate::visit::Accept<V> for $what {
|
||||
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||
visitor.visit(self)
|
||||
}
|
||||
}
|
||||
@@ -51,10 +49,11 @@ macro_rules! impl_accept {
|
||||
#[macro_export]
|
||||
macro_rules! impl_default_accept {
|
||||
($what:ident : $($requires:ident),+ => $($tail:tt)+) => {
|
||||
impl<V, Out> $crate::visit::DefaultAccept<V> for $what
|
||||
where V: $crate::visit::Visit<Self, Out=Out> $(+ $crate::visit::Visit<$requires, Out=Out>)+
|
||||
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