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:
2020-05-22 14:26:27 -04:00
parent 7de005b160
commit 86afce8686
10 changed files with 141 additions and 176 deletions

View File

@@ -10,6 +10,7 @@ pub enum Block {
Blocks(Vec<Block>), Blocks(Vec<Block>),
} }
/*
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// TranslateAst // TranslateAst
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -150,3 +151,4 @@ impl Visit<BaseExpr> for TranslateAst<'_, '_> {
Ok(base) Ok(base)
} }
} }
*/

View File

@@ -93,9 +93,12 @@ pub struct CollectNames<'c, 't> {
text: &'t str, text: &'t str,
} }
default_visitor!(Expr for CollectNames<'_, '_> where Out = ()); impl Visit for CollectNames<'_, '_> {
empty_visitor!(FunCallExpr for CollectNames<'_, '_>); type Out = ();
empty_visitor!(FunExpr for CollectNames<'_, '_>); }
impl_empty_accept!(FunCallExpr for CollectNames<'_, '_>);
impl_empty_accept!(FunExpr for CollectNames<'_, '_>);
impl<'c, 't> CollectNames<'c, 't> { 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 {
@@ -112,50 +115,46 @@ impl<'c, 't> CollectNames<'c, 't> {
} }
} }
impl Visit<AssignStmt> for CollectNames<'_, '_> { impl Accept<CollectNames<'_, '_>> for AssignStmt {
type Out = (); fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
visitor.visit(&self.lhs);
fn visit(&mut self, stmt: &AssignStmt) -> Self::Out {
self.visit(&stmt.lhs);
} }
} }
impl Visit<BinExpr> for CollectNames<'_, '_> { impl Accept<CollectNames<'_, '_>> for Expr {
type Out = (); fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
self.default_accept(visitor)
fn visit(&mut self, expr: &BinExpr) -> Self::Out {
self.visit(&expr.lhs);
} }
} }
impl Visit<UnExpr> for CollectNames<'_, '_> { impl Accept<CollectNames<'_, '_>> for BinExpr {
type Out = (); fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
visitor.visit(&self.lhs);
fn visit(&mut self, expr: &UnExpr) -> Self::Out {
self.visit(&expr.expr)
} }
} }
impl Visit<IndexExpr> for CollectNames<'_, '_> { impl Accept<CollectNames<'_, '_>> for UnExpr {
type Out = (); fn accept(&self, visitor: &mut CollectNames<'_, '_>) {
visitor.visit(&self.expr);
fn visit(&mut self, expr: &IndexExpr) -> Self::Out {
self.visit(&expr.expr);
} }
} }
impl Visit<BaseExpr> for CollectNames<'_, '_> { impl Accept<CollectNames<'_, '_>> for IndexExpr {
type Out = (); 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 // This is a LHS standalone expr
if let BaseExpr { if let BaseExpr {
kind: BaseExprKind::Ident, kind: BaseExprKind::Ident,
.. ..
} = expr } = self
{ {
let name = expr.text_at(self.text).to_string(); let name = self.text_at(visitor.text).to_string();
self.ctx.name_stack_mut().add(name); 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>) { pub fn collect(&mut self, stmts: &Vec<Stmt>) {
// Collect all LHS assignments // Collect all LHS assignments
for stmt in stmts.iter() { for stmt in stmts.iter() {
self.visit(stmt); stmt.accept(self);
} }
} }
} }
default_visitor!(Stmt for CollectSyms<'_, '_> where Out = ()); impl Visit for CollectSyms<'_, '_> {
default_visitor!(Expr for CollectSyms<'_, '_> where Out = ());
impl Visit<AssignStmt> for CollectSyms<'_, '_> {
type Out = (); type Out = ();
}
fn visit(&mut self, stmt: &AssignStmt) -> Self::Out { impl_default_accept!(Stmt for CollectSyms<'_, '_>);
self.visit(&stmt.lhs);
self.visit(&stmt.rhs); impl Accept<CollectSyms<'_, '_>> for AssignStmt {
fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
visitor.visit(&self.lhs);
visitor.visit(&self.rhs);
} }
} }
impl Visit<BinExpr> for CollectSyms<'_, '_> { impl_default_accept!(Expr for CollectSyms<'_, '_>);
type Out = ();
fn visit(&mut self, expr: &BinExpr) -> Self::Out { impl Accept<CollectSyms<'_, '_>> for BinExpr {
self.visit(&expr.lhs); fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
self.visit(&expr.rhs); visitor.visit(&self.lhs);
visitor.visit(&self.rhs);
} }
} }
impl Visit<UnExpr> for CollectSyms<'_, '_> { impl Accept<CollectSyms<'_, '_>> for UnExpr {
type Out = (); fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
visitor.visit(&self.expr);
fn visit(&mut self, expr: &UnExpr) -> Self::Out {
self.visit(&expr.expr);
} }
} }
impl Visit<FunCallExpr> for CollectSyms<'_, '_> { impl Accept<CollectSyms<'_, '_>> for FunCallExpr {
type Out = (); fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
visitor.visit(&self.expr);
fn visit(&mut self, expr: &FunCallExpr) -> Self::Out { self.args.iter().for_each(|expr| visitor.visit(expr));
self.visit(&expr.expr);
expr.args.iter().for_each(|expr| self.visit(expr));
} }
} }
impl Visit<IndexExpr> for CollectSyms<'_, '_> { impl Accept<CollectSyms<'_, '_>> for IndexExpr {
type Out = (); fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
visitor.visit(&self.expr);
fn visit(&mut self, expr: &IndexExpr) -> Self::Out { visitor.visit(&self.index);
self.visit(&expr.expr);
self.visit(&expr.index);
} }
} }
impl Visit<FunExpr> for CollectSyms<'_, '_> { impl Accept<CollectSyms<'_, '_>> for FunExpr {
type Out = (); fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
self.params.iter().for_each(|name| {
fn visit(&mut self, expr: &FunExpr) -> Self::Out { visitor.ctx.syms_mut().add(name.clone());
expr.params.iter().for_each(|name| {
self.ctx.syms_mut().add(name.clone());
}); });
self.visit(&expr.expr); visitor.visit(&self.expr)
} }
} }
impl Visit<BaseExpr> for CollectSyms<'_, '_> { impl Accept<CollectSyms<'_, '_>> for BaseExpr {
type Out = (); fn accept(&self, visitor: &mut CollectSyms<'_, '_>) {
match &self.kind {
fn visit(&mut self, expr: &BaseExpr) -> Self::Out {
match &expr.kind {
BaseExprKind::Ident => { BaseExprKind::Ident => {
let name = expr.text_at(self.text).to_string(); let name = self.text_at(visitor.text).to_string();
self.ctx.syms_mut().add(name); visitor.ctx.syms_mut().add(name);
} }
BaseExprKind::Sym => { BaseExprKind::Sym => {
let name = expr.text_at(self.text).chars().skip(1).collect::<String>(); let name = self.text_at(visitor.text).chars().skip(1).collect::<String>();
self.ctx.syms_mut().add(name); visitor.ctx.syms_mut().add(name);
} }
BaseExprKind::List(l) | BaseExprKind::Tuple(l) => { 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)| { BaseExprKind::Object(o) => o.iter().for_each(|(k, v)| {
self.visit(k); visitor.visit(k);
self.visit(v); visitor.visit(v);
}), }),
BaseExprKind::Block(stmts) => { BaseExprKind::Block(stmts) => {
stmts.iter().for_each(|stmt| self.visit(stmt)); stmts.iter().for_each(|stmt| visitor.visit(stmt));
} }
_ => { /* no-op */ } _ => { /* no-op */ }
} }

View File

@@ -9,12 +9,3 @@ pub trait Gc {
fn sweep(&mut self); 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)
}
}

View File

@@ -1,4 +1,4 @@
use crate::{obj::Obj, visit::{DynAccept, Accept, Visit}}; use crate::obj::Obj;
use std::{ use std::{
any, any,
cell::RefCell, 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 // Comparison impls
// //

View File

@@ -66,12 +66,15 @@ impl Obj for Attrs {
} }
} }
//impl_accept!(Attrs); /*
impl_accept!(Attrs);
impl<G: Gc> Visit<Attrs> for G { impl<G: Gc> Visit<Attrs> for G {
type Out = (); type Out = ();
fn visit(&mut self, _attrs: &Attrs) -> Self::Out { fn visit(&mut self, attrs: &Attrs) -> Self::Out {
todo!() attrs.attrs.values()
.for_each(|obj| obj.accept(self));
} }
} }
*/

View File

@@ -28,16 +28,3 @@ impl Obj for Dict {
self 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);
}
}

View File

@@ -46,9 +46,11 @@ pub use self::{
sym::Sym, sym::Sym,
}; };
use crate::mem::ptr::ObjRef; use crate::mem::ptr::ObjRef;
use crate::visit::*;
use std::any::Any; use std::any::Any;
pub trait Obj { pub trait Obj {
fn attrs(&self) -> ObjRef<Attrs>; fn attrs(&self) -> ObjRef<Attrs>;
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
} }

View File

@@ -1,4 +1,4 @@
use crate::{obj::prelude::*, visit::{DynAccept, Visit}}; use crate::{obj::prelude::*, visit::Visit};
use derivative::Derivative; use derivative::Derivative;
use std::{any::Any, cell::Cell}; use std::{any::Any, cell::Cell};
@@ -39,21 +39,3 @@ impl Obj for Str {
self 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!()
}
}

View File

@@ -1,4 +1,4 @@
use crate::syn::{op::*, span::*}; use crate::{syn::{op::*, span::*}, visit::*};
use derivative::Derivative; use derivative::Derivative;
pub mod prelude { pub mod prelude {
@@ -174,20 +174,17 @@ impl Spanned for BaseExpr {
// Acceptor (visitor) impls // Acceptor (visitor) impls
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
impl_accept!(Stmt); impl<V> DefaultAccept<V> for Expr
impl_default_accept!(Stmt : AssignStmt, Expr => where V: Visit,
fn default_accept(&self, visitor: &mut V) -> Out { Self: Accept<V>,
match self { BinExpr: Accept<V>,
Stmt::Assign(a) => visitor.visit(a), UnExpr: Accept<V>,
Stmt::Expr(e) => visitor.visit(e), FunCallExpr: Accept<V>,
} IndexExpr: Accept<V>,
} FunExpr: Accept<V>,
); BaseExpr: Accept<V>,
impl_accept!(AssignStmt); {
impl_accept!(Expr); fn default_accept(&self, visitor: &mut V) -> V::Out {
impl_default_accept!(Expr: BinExpr, UnExpr, FunCallExpr, IndexExpr, FunExpr, BaseExpr =>
fn default_accept(&self, visitor: &mut V) -> Out {
match self { match self {
Expr::Bin(b) => visitor.visit(b.as_ref()), Expr::Bin(b) => visitor.visit(b.as_ref()),
Expr::Un(u) => visitor.visit(u.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), Expr::Base(b) => visitor.visit(b),
} }
} }
); }
impl_accept!(BinExpr); impl<V> DefaultAccept<V> for Stmt
impl_accept!(UnExpr); where V: Visit,
impl_accept!(FunCallExpr); Self: Accept<V>,
impl_accept!(IndexExpr); Expr: Accept<V>,
impl_accept!(FunExpr); 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); impl_accept!(BaseExpr);
*/

View File

@@ -1,47 +1,45 @@
pub trait Visit<A: ?Sized> { pub trait Visit {
type Out; 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 { pub trait Accept<V: Visit> {
fn accept<V: Visit<Self>>(&self, visitor: &mut V) -> V::Out; fn accept(&self, visitor: &mut V) -> V::Out;
} }
pub trait DynAccept<Out=()> { pub trait DefaultAccept<V: Visit>: Accept<V> + Sized {
fn accept(&self, visitor: &mut impl Visit<Self, Out=Out>);
}
pub trait DefaultAccept<V: Visit<Self>>: Accept + Sized {
fn default_accept(&self, visitor: &mut V) -> V::Out; fn default_accept(&self, visitor: &mut V) -> V::Out;
} }
#[macro_export] #[macro_export]
macro_rules! default_visitor { macro_rules! impl_default_accept {
($default:ident for $visitor:ty where Out = $out:ty) => { ($what:ident for $visitor:ty) => {
impl $crate::visit::Visit<$default> for $visitor { impl $crate::visit::Accept<$visitor> for $what
type Out = $out; {
fn visit(&mut self, acceptor: &$default) -> Self::Out { fn accept(&self, visitor: &mut $visitor) {
acceptor.default_accept(self) self.default_accept(visitor)
} }
} }
}; };
} }
#[macro_export] #[macro_export]
macro_rules! empty_visitor { macro_rules! impl_empty_accept {
($default:ident for $visitor:ty) => { ($default:ident for $visitor:ty) => {
impl $crate::visit::Visit<$default> for $visitor { impl $crate::visit::Accept<$visitor> for $default {
type Out = (); fn accept(&self, _: &mut $visitor) {}
fn visit(&mut self, _: &$default) -> Self::Out {}
} }
}; };
} }
/*
#[macro_export] #[macro_export]
macro_rules! impl_accept { macro_rules! impl_accept {
($what:ty) => { ($what:ty) => {
impl $crate::visit::Accept for $what { impl<V: $crate::visit::Visit> $crate::visit::Accept<V> for $what {
fn accept<V: $crate::visit::Visit<Self>>(&self, visitor: &mut V) -> V::Out { fn accept(&self, visitor: &mut V) -> V::Out {
visitor.visit(self) visitor.visit(self)
} }
} }
@@ -51,10 +49,11 @@ macro_rules! impl_accept {
#[macro_export] #[macro_export]
macro_rules! impl_default_accept { macro_rules! impl_default_accept {
($what:ident : $($requires:ident),+ => $($tail:tt)+) => { ($what:ident : $($requires:ident),+ => $($tail:tt)+) => {
impl<V, Out> $crate::visit::DefaultAccept<V> for $what impl<V> $crate::visit::DefaultAccept<V> for $what
where V: $crate::visit::Visit<Self, Out=Out> $(+ $crate::visit::Visit<$requires, Out=Out>)+ where V: $crate::visit::Visit $(+ $crate::visit::Visit<$requires>)+
{ {
$($tail)+ $($tail)+
} }
}; };
} }
*/