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>),
}
/*
////////////////////////////////////////////////////////////////////////////////
// TranslateAst
////////////////////////////////////////////////////////////////////////////////
@@ -150,3 +151,4 @@ impl Visit<BaseExpr> for TranslateAst<'_, '_> {
Ok(base)
}
}
*/

View File

@@ -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 */ }
}

View File

@@ -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)
}
}

View File

@@ -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
//

View File

@@ -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));
}
}
*/

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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!()
}
}

View File

@@ -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);
*/

View File

@@ -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)+
}
};
}
*/