diff --git a/src/compile/name.rs b/src/compile/name.rs index cd6e84c..d2b8cf8 100644 --- a/src/compile/name.rs +++ b/src/compile/name.rs @@ -1,8 +1,7 @@ use crate::{ compile::ctx::Ctx, obj::prelude::*, - syn::{ast::prelude::*, span::*}, - visit::*, + syn::{ast::prelude::*, span::*, visit::*}, }; use std::collections::HashMap; @@ -87,85 +86,39 @@ impl NameStack { // CollectNames //////////////////////////////////////////////////////////////////////////////// - - -// 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> { +pub struct CollectLocalNames<'c, 't> { ctx: &'c mut Ctx, text: &'t str, } -impl Visit for CollectNames<'_, '_> { - type Out = (); -} - -impl_empty_accept!(FunCallExpr for CollectNames<'_, '_>); -impl_empty_accept!(FunExpr for CollectNames<'_, '_>); - -impl<'c, 't> CollectNames<'c, 't> { +impl<'c, 't> CollectLocalNames<'c, 't> { pub fn new(ctx: &'c mut Ctx, text: &'t str) -> Self { - CollectNames { ctx, text } + CollectLocalNames { ctx, text } } - pub fn collect(&mut self, stmts: &Vec) { - // Collect all LHS assignments - for stmt in stmts.iter() { - if let Stmt::Assign(stmt) = stmt { - self.visit(stmt); - } + pub fn collect(&mut self, ast: &Vec) { + ast.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 { + self.visit_assign_stmt(stmt); } } -} -impl Accept> for AssignStmt { - fn accept(&self, visitor: &mut CollectNames<'_, '_>) { - visitor.visit(&self.lhs); + 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> for Expr { - fn accept(&self, visitor: &mut CollectNames<'_, '_>) { - self.default_accept(visitor) - } -} - -impl Accept> for BinExpr { - fn accept(&self, visitor: &mut CollectNames<'_, '_>) { - visitor.visit(&self.lhs); - } -} - -impl Accept> for UnExpr { - fn accept(&self, visitor: &mut CollectNames<'_, '_>) { - visitor.visit(&self.expr); - } -} - -impl Accept> for IndexExpr { - fn accept(&self, visitor: &mut CollectNames<'_, '_>) { - visitor.visit(&self.expr); - } -} - -impl Accept> 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 @@ -186,85 +139,22 @@ impl<'c, 't> CollectSyms<'c, 't> { pub fn collect(&mut self, stmts: &Vec) { // Collect all LHS assignments - for stmt in stmts.iter() { - stmt.accept(self); - } + stmts.iter() + .for_each(|stmt| self.visit(stmt)) } } -impl Visit for CollectSyms<'_, '_> { - type Out = (); -} +impl VisitAst for CollectSyms<'_, '_> { + 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<'_, '_>); - -impl Accept> for AssignStmt { - fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { - visitor.visit(&self.lhs); - visitor.visit(&self.rhs); - } -} - -impl_default_accept!(Expr for CollectSyms<'_, '_>); - -impl Accept> for BinExpr { - fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { - visitor.visit(&self.lhs); - visitor.visit(&self.rhs); - } -} - -impl Accept> for UnExpr { - fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { - visitor.visit(&self.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 Accept> for IndexExpr { - fn accept(&self, visitor: &mut CollectSyms<'_, '_>) { - visitor.visit(&self.expr); - visitor.visit(&self.index); - } -} - -impl Accept> 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> 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::(); - 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 */ } - } + fn visit_sym(&mut self, span: Span) { + let name = span.text_at(self.text) + .chars() + .skip(1) + .collect::(); + self.ctx.syms_mut().add(name); } } diff --git a/src/main.rs b/src/main.rs index ff9ffd8..5ad5135 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ #![allow(dead_code)] #![feature(unsize, coerce_unsized, new_uninit, box_into_pin)] -#[macro_use] mod visit; mod compile; mod mem; mod obj; @@ -38,16 +37,13 @@ fn main() -> Result<()> { //println!("{:#?}", ast); 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(); - { - let mut collect_names = compile::name::CollectNames::new(&mut ctx, text.as_str()); - collect_names.collect(&ast); - } + { compile::name::CollectLocalNames::new(&mut ctx, text.as_str()).collect(&ast); } let _names = ctx.name_stack_mut().pop().unwrap(); //println!("{:#?}", names); + { compile::name::CollectSyms::new(&mut ctx, text.as_str()).collect(&ast); } + println!("{:#?}", ctx.syms()); + Ok(()) } diff --git a/src/syn/ast.rs b/src/syn/ast.rs index 975fdc0..d3cb28c 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -1,4 +1,4 @@ -use crate::{syn::{op::*, span::*}, visit::*}; +use crate::syn::{op::*, span::*, visit::*}; use derivative::Derivative; pub mod prelude { @@ -174,51 +174,22 @@ impl Spanned for BaseExpr { // Acceptor (visitor) impls //////////////////////////////////////////////////////////////////////////////// -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()), - 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), +macro_rules! impl_accept { + ($for:ty, $method:ident) => { + impl AcceptAst for $for { + fn accept(&self, visitor: &mut V) { + visitor.$method(self) + } } - } + }; } -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); -*/ +impl_accept!(Stmt, visit_stmt); +impl_accept!(AssignStmt, visit_assign_stmt); +impl_accept!(Expr, visit_expr); +impl_accept!(BinExpr, visit_bin_expr); +impl_accept!(UnExpr, visit_un_expr); +impl_accept!(FunCallExpr, visit_fun_call_expr); +impl_accept!(IndexExpr, visit_index_expr); +impl_accept!(FunExpr, visit_fun_expr); +impl_accept!(BaseExpr, visit_base_expr); diff --git a/src/syn/mod.rs b/src/syn/mod.rs index 97f51c5..63afd19 100644 --- a/src/syn/mod.rs +++ b/src/syn/mod.rs @@ -5,3 +5,4 @@ pub mod op; pub mod parser; pub mod span; pub mod token; +pub mod visit; diff --git a/src/syn/visit.rs b/src/syn/visit.rs new file mode 100644 index 0000000..9facca6 --- /dev/null +++ b/src/syn/visit.rs @@ -0,0 +1,104 @@ +use crate::syn::{ast::prelude::*, span::*}; + +pub trait VisitAst { + fn visit(&mut self, acceptor: &dyn AcceptAst) 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) { + 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) { + tuple.iter() + .for_each(|expr| self.visit_expr(expr)) + } + + fn visit_block(&mut self, block: &Vec) { + block.iter() + .for_each(|stmt| self.visit_stmt(stmt)) + } +} + +pub trait AcceptAst { + fn accept(&self, visitor: &mut V); +} diff --git a/src/visit.rs b/src/visit.rs deleted file mode 100644 index 73c25ef..0000000 --- a/src/visit.rs +++ /dev/null @@ -1,59 +0,0 @@ -pub trait Visit { - type 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 DefaultAccept: Accept + 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 $crate::visit::Accept 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 $crate::visit::DefaultAccept for $what - where V: $crate::visit::Visit $(+ $crate::visit::Visit<$requires>)+ - { - $($tail)+ - } - }; -} -*/