Update visitor pattern for AST

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-05-26 18:58:27 -04:00
parent 93c99e65df
commit a2a70a8604
6 changed files with 160 additions and 257 deletions

View File

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

View File

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

View File

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

View File

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

View File

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