From 86afce868641ab101ee3e264d0bea07c07a4eea3 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Fri, 22 May 2020 14:26:27 -0400 Subject: [PATCH] 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 --- src/compile/block.rs | 2 + src/compile/name.rs | 148 ++++++++++++++++++++----------------------- src/mem/gc.rs | 9 --- src/mem/ptr.rs | 10 +-- src/obj/attrs.rs | 9 ++- src/obj/dict.rs | 13 ---- src/obj/mod.rs | 2 + src/obj/str.rs | 20 +----- src/syn/ast.rs | 59 +++++++++++------ src/visit.rs | 45 +++++++------ 10 files changed, 141 insertions(+), 176 deletions(-) diff --git a/src/compile/block.rs b/src/compile/block.rs index 672cc92..1250b46 100644 --- a/src/compile/block.rs +++ b/src/compile/block.rs @@ -10,6 +10,7 @@ pub enum Block { Blocks(Vec), } +/* //////////////////////////////////////////////////////////////////////////////// // TranslateAst //////////////////////////////////////////////////////////////////////////////// @@ -150,3 +151,4 @@ impl Visit for TranslateAst<'_, '_> { Ok(base) } } +*/ diff --git a/src/compile/name.rs b/src/compile/name.rs index b7fbc02..4fdbb3f 100644 --- a/src/compile/name.rs +++ b/src/compile/name.rs @@ -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 for CollectNames<'_, '_> { - type Out = (); - - fn visit(&mut self, stmt: &AssignStmt) -> Self::Out { - self.visit(&stmt.lhs); +impl Accept> for AssignStmt { + fn accept(&self, visitor: &mut CollectNames<'_, '_>) { + visitor.visit(&self.lhs); } } -impl Visit for CollectNames<'_, '_> { - type Out = (); - - fn visit(&mut self, expr: &BinExpr) -> Self::Out { - self.visit(&expr.lhs); +impl Accept> for Expr { + fn accept(&self, visitor: &mut CollectNames<'_, '_>) { + self.default_accept(visitor) } } -impl Visit for CollectNames<'_, '_> { - type Out = (); - - fn visit(&mut self, expr: &UnExpr) -> Self::Out { - self.visit(&expr.expr) +impl Accept> for BinExpr { + fn accept(&self, visitor: &mut CollectNames<'_, '_>) { + visitor.visit(&self.lhs); } } -impl Visit for CollectNames<'_, '_> { - type Out = (); - - fn visit(&mut self, expr: &IndexExpr) -> Self::Out { - self.visit(&expr.expr); +impl Accept> for UnExpr { + fn accept(&self, visitor: &mut CollectNames<'_, '_>) { + visitor.visit(&self.expr); } } -impl Visit for CollectNames<'_, '_> { - type Out = (); +impl Accept> for IndexExpr { + fn accept(&self, visitor: &mut CollectNames<'_, '_>) { + visitor.visit(&self.expr); + } +} - fn visit(&mut self, expr: &BaseExpr) -> Self::Out { +impl Accept> 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) { // 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 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> for AssignStmt { + fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { + visitor.visit(&self.lhs); + visitor.visit(&self.rhs); } } -impl Visit 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> for BinExpr { + fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { + visitor.visit(&self.lhs); + visitor.visit(&self.rhs); } } -impl Visit for CollectSyms<'_, '_> { - type Out = (); - - fn visit(&mut self, expr: &UnExpr) -> Self::Out { - self.visit(&expr.expr); +impl Accept> for UnExpr { + fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { + visitor.visit(&self.expr); } } -impl Visit 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> for FunCallExpr { + fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { + visitor.visit(&self.expr); + self.args.iter().for_each(|expr| visitor.visit(expr)); } } -impl Visit for CollectSyms<'_, '_> { - type Out = (); - - fn visit(&mut self, expr: &IndexExpr) -> Self::Out { - self.visit(&expr.expr); - self.visit(&expr.index); +impl Accept> for IndexExpr { + fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { + visitor.visit(&self.expr); + visitor.visit(&self.index); } } -impl Visit 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> 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 for CollectSyms<'_, '_> { - type Out = (); - - fn visit(&mut self, expr: &BaseExpr) -> Self::Out { - match &expr.kind { +impl Accept> 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::(); - self.ctx.syms_mut().add(name); + let name = self.text_at(visitor.text).chars().skip(1).collect::(); + 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 */ } } diff --git a/src/mem/gc.rs b/src/mem/gc.rs index 4ba5e59..de52e17 100644 --- a/src/mem/gc.rs +++ b/src/mem/gc.rs @@ -9,12 +9,3 @@ pub trait Gc { fn sweep(&mut self); } - -impl Visit for O - where O: Obj + Accept -{ - type Out = (); - fn visit(&mut self, obj: &O) -> Self::Out { - obj.accept(self) - } -} diff --git a/src/mem/ptr.rs b/src/mem/ptr.rs index 2441c2c..32957b9 100644 --- a/src/mem/ptr.rs +++ b/src/mem/ptr.rs @@ -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 { } } -impl DynAccept for ObjRef - where O: Obj + ?Sized + DynAccept -{ - fn accept(&self, visitor: &mut impl Visit) { - todo!() - } -} - // // Comparison impls // diff --git a/src/obj/attrs.rs b/src/obj/attrs.rs index 8825910..c3272d4 100644 --- a/src/obj/attrs.rs +++ b/src/obj/attrs.rs @@ -66,12 +66,15 @@ impl Obj for Attrs { } } -//impl_accept!(Attrs); +/* +impl_accept!(Attrs); impl Visit 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)); } } +*/ diff --git a/src/obj/dict.rs b/src/obj/dict.rs index ecb6052..f3d6716 100644 --- a/src/obj/dict.rs +++ b/src/obj/dict.rs @@ -28,16 +28,3 @@ impl Obj for Dict { self } } - -//impl_accept!(Dict); - -impl Visit for G - where G: Gc + Visit, -{ - type Out = (); - - fn visit(&mut self, dict: &Dict) -> Self::Out { - let attrs_ref: &Attrs = &dict.attrs.borrow(); - self.visit(attrs_ref); - } -} diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 1b018a4..e431c29 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -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; fn as_any(&self) -> &dyn Any; } + diff --git a/src/obj/str.rs b/src/obj/str.rs index c4b2ff5..77647fb 100644 --- a/src/obj/str.rs +++ b/src/obj/str.rs @@ -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 DynAccept for O - where O: Obj + ?Sized -{ - fn accept(&self, visitor: &mut impl Visit) { - visitor.visit(self) - } -} - -impl Visit for G { - type Out = (); - - fn visit(&mut self, _s: &Str) -> Self::Out { - todo!() - } -} diff --git a/src/syn/ast.rs b/src/syn/ast.rs index 8c55d18..975fdc0 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -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 DefaultAccept for Expr + where V: Visit, + Self: Accept, + BinExpr: Accept, + UnExpr: Accept, + FunCallExpr: Accept, + IndexExpr: Accept, + FunExpr: Accept, + BaseExpr: Accept, +{ + 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 DefaultAccept for Stmt + where V: Visit, + Self: Accept, + Expr: Accept, + AssignStmt: Accept, +{ + 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); +*/ diff --git a/src/visit.rs b/src/visit.rs index 68cdd90..73c25ef 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -1,47 +1,45 @@ -pub trait Visit { +pub trait Visit { type Out; - fn visit(&mut self, acceptor: &A) -> Self::Out; + fn visit(&mut self, acceptor: &dyn Accept) -> Self::Out where Self: Sized { + acceptor.accept(self) + } } -pub trait Accept { - fn accept>(&self, visitor: &mut V) -> V::Out; +pub trait Accept { + fn accept(&self, visitor: &mut V) -> V::Out; } -pub trait DynAccept { - fn accept(&self, visitor: &mut impl Visit); -} - -pub trait DefaultAccept>: Accept + Sized { +pub trait DefaultAccept: 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_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>(&self, visitor: &mut V) -> V::Out { + impl $crate::visit::Accept 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 $crate::visit::DefaultAccept for $what - where V: $crate::visit::Visit $(+ $crate::visit::Visit<$requires, Out=Out>)+ + impl $crate::visit::DefaultAccept for $what + where V: $crate::visit::Visit $(+ $crate::visit::Visit<$requires>)+ { $($tail)+ } }; } +*/