Update how visitors work, add NameId type
* Visitors are now defined on a per-type level, allowing for greater flexibility in combining and re-using behavior * NameId is used for namespaces, which are used to index locally scoped variables. Syms are used for free namespaces, specifically in objects. All NameIDs are symbols, while not all symbols are NameIDs. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,22 +1,10 @@
|
||||
use crate::{
|
||||
compile::{visit::*, Ctx},
|
||||
syn::{ast::prelude::*, op::BinOp, span::*},
|
||||
obj::prelude::*,
|
||||
syn::{ast::prelude::*, span::*},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct NameId(usize);
|
||||
|
||||
impl NameId {
|
||||
pub fn new(id: usize) -> Self {
|
||||
NameId(id)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NameStack {
|
||||
next_sym: usize,
|
||||
stack: Vec<HashMap<String, NameId>>,
|
||||
@@ -84,78 +72,70 @@ impl NameStack {
|
||||
}
|
||||
|
||||
/// Collect local names and push them to the top layer of the name stack.
|
||||
pub struct CollectNames<'c, 't: 'c> {
|
||||
ctx: &'c mut Ctx<'t>,
|
||||
pub struct CollectNames<'c, 't> {
|
||||
ctx: &'c mut Ctx,
|
||||
text: &'t str,
|
||||
}
|
||||
|
||||
impl<'c, 't: 'c> CollectNames<'c, 't> {
|
||||
pub fn new(ctx: &'c mut Ctx<'t>) -> Self {
|
||||
CollectNames { ctx }
|
||||
default_visitor!(Expr for CollectNames<'_, '_> where Out = ());
|
||||
empty_visitor!(FunCallExpr for CollectNames<'_, '_>);
|
||||
empty_visitor!(FunExpr for CollectNames<'_, '_>);
|
||||
|
||||
impl<'c, 't> CollectNames<'c, 't> {
|
||||
pub fn new(ctx: &'c mut Ctx, text: &'t str) -> Self {
|
||||
CollectNames { ctx, text }
|
||||
}
|
||||
|
||||
pub fn collect(&mut self, stmts: &Vec<Stmt>) {
|
||||
// Collect all LHS assignments
|
||||
for stmt in stmts.iter() {
|
||||
self.visit_stmt(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_base_expr(&mut self, expr: &BaseExpr) {
|
||||
match &expr.kind {
|
||||
BaseExprKind::Ident => {
|
||||
let name = expr.text_at(self.ctx.text()).to_string();
|
||||
self.ctx.name_stack_mut().add(name);
|
||||
if let Stmt::Assign(stmt) = stmt {
|
||||
self.visit(stmt);
|
||||
}
|
||||
BaseExprKind::List(l) | BaseExprKind::Tuple(l) => {
|
||||
l.iter().for_each(|expr| self.visit_expr(expr));
|
||||
}
|
||||
BaseExprKind::Object(o) => {
|
||||
o.iter().for_each(|(key, value)| {
|
||||
self.visit_expr(key);
|
||||
self.visit_expr(value);
|
||||
});
|
||||
}
|
||||
_ => { /* no-op */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for CollectNames<'_, '_> {
|
||||
impl Visit<AssignStmt> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit_expr(&mut self, expr: &Expr) -> Self::Out {
|
||||
match expr {
|
||||
Expr::Bin(b) => {
|
||||
self.visit_expr(&b.lhs);
|
||||
// don't descend into dot-expressions - these are not names, but symbols
|
||||
if b.op != BinOp::Dot {
|
||||
self.visit_expr(&b.rhs);
|
||||
}
|
||||
}
|
||||
Expr::Un(u) => {
|
||||
self.visit_expr(&u.expr);
|
||||
}
|
||||
Expr::FunCall(f) => {
|
||||
self.visit_expr(&f.expr);
|
||||
f.args.iter().for_each(|expr| self.visit_expr(expr));
|
||||
}
|
||||
Expr::Index(i) => {
|
||||
self.visit_expr(&i.expr);
|
||||
self.visit_expr(&i.index);
|
||||
}
|
||||
Expr::Fun(_) => { /* no-op */ }
|
||||
Expr::Base(b) => self.visit_base_expr(b),
|
||||
}
|
||||
fn visit(&mut self, stmt: &AssignStmt) -> Self::Out {
|
||||
self.visit(&stmt.lhs);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, stmt: &Stmt) -> Self::Out {
|
||||
match stmt {
|
||||
Stmt::Assign(AssignStmt { lhs, rhs, .. }) => {
|
||||
self.visit_expr(lhs);
|
||||
self.visit_expr(rhs);
|
||||
}
|
||||
Stmt::Expr(expr) => {
|
||||
self.visit_expr(expr);
|
||||
}
|
||||
impl Visit<BinExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &BinExpr) -> Self::Out {
|
||||
self.visit(&expr.lhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<UnExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &UnExpr) -> Self::Out {
|
||||
self.visit(&expr.expr)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<IndexExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &IndexExpr) -> Self::Out {
|
||||
self.visit(&expr.expr);
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit<BaseExpr> for CollectNames<'_, '_> {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, expr: &BaseExpr) -> Self::Out {
|
||||
// This is a LHS standalone expr
|
||||
if let BaseExpr { kind: BaseExprKind::Ident, .. } = expr {
|
||||
let name = expr.text_at(self.text).to_string();
|
||||
self.ctx.name_stack_mut().add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user