cl-typeck: Reimplement NameCollectable in terms of an AST visitor
This commit is contained in:
parent
a877c0d726
commit
b9085551e1
@ -5,7 +5,8 @@ use crate::{
|
|||||||
module::Module as Mod,
|
module::Module as Mod,
|
||||||
project::Project as Prj,
|
project::Project as Prj,
|
||||||
};
|
};
|
||||||
use cl_ast::*;
|
use cl_ast::{ast_visitor::Visit, *};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
pub trait NameCollectable<'a> {
|
pub trait NameCollectable<'a> {
|
||||||
/// Collects the identifiers within this node,
|
/// Collects the identifiers within this node,
|
||||||
@ -19,227 +20,149 @@ pub trait NameCollectable<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NameCollectable<'a> for File {
|
impl<'a> NameCollectable<'a> for File {
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
fn collect(&'a self, prj: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
||||||
for item in &self.items {
|
NameCollector::with_root(prj, parent).visit_file(self);
|
||||||
item.collect(c, parent)?;
|
|
||||||
}
|
|
||||||
Ok(parent)
|
Ok(parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> NameCollectable<'a> for Item {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Item { attrs: Attrs { meta }, vis, kind, .. } = self;
|
|
||||||
let id = match kind {
|
|
||||||
ItemKind::Impl(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Module(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Alias(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Enum(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Struct(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Const(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Static(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Function(i) => i.collect(c, parent),
|
|
||||||
ItemKind::Use(i) => i.collect(c, parent),
|
|
||||||
}?;
|
|
||||||
c[id].set_meta(meta).set_vis(*vis).set_source(self);
|
|
||||||
|
|
||||||
Ok(id)
|
#[derive(Debug)]
|
||||||
|
pub struct NameCollector<'prj, 'a> {
|
||||||
|
prj: &'prj mut Prj<'a>,
|
||||||
|
parent: DefID,
|
||||||
|
retval: Option<DefID>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'prj, 'a> NameCollector<'prj, 'a> {
|
||||||
|
pub fn new(prj: &'prj mut Prj<'a>) -> Self {
|
||||||
|
Self { parent: prj.root, prj, retval: None }
|
||||||
|
}
|
||||||
|
pub fn with_root(prj: &'prj mut Prj<'a>, parent: DefID) -> Self {
|
||||||
|
Self { prj, parent, retval: None }
|
||||||
|
}
|
||||||
|
/// Runs the provided function with the given parent
|
||||||
|
pub fn with_parent<F, N>(&mut self, parent: DefID, node: N, f: F)
|
||||||
|
where F: FnOnce(&mut Self, N) {
|
||||||
|
let parent = mem::replace(&mut self.parent, parent);
|
||||||
|
f(self, node);
|
||||||
|
self.parent = parent;
|
||||||
|
}
|
||||||
|
/// Extracts the return value from the provided function
|
||||||
|
pub fn returns<F, N>(&mut self, node: N, f: F) -> Option<DefID>
|
||||||
|
where F: FnOnce(&mut Self, N) {
|
||||||
|
let out = self.retval.take();
|
||||||
|
f(self, node);
|
||||||
|
mem::replace(&mut self.retval, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> NameCollectable<'a> for Module {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Self { name: Identifier(name), kind } = self;
|
|
||||||
let module =
|
|
||||||
c.pool
|
|
||||||
.insert(Def { name: *name, module: Mod::new(parent), ..Default::default() });
|
|
||||||
c[parent].module.types.insert(*name, module);
|
|
||||||
|
|
||||||
match kind {
|
impl<'prj, 'a> ast_visitor::Visit<'a> for NameCollector<'prj, 'a> {
|
||||||
ModuleKind::Inline(file) => file.collect(c, module)?,
|
fn visit_item(&mut self, i: &'a Item) {
|
||||||
ModuleKind::Outline => todo!("Out of line modules: {name}"),
|
let Item { extents: _, attrs, vis, kind } = i;
|
||||||
};
|
if let Some(def) = self.returns(kind, Self::visit_item_kind) {
|
||||||
Ok(module)
|
self.prj[def]
|
||||||
|
.set_meta(&attrs.meta)
|
||||||
|
.set_vis(*vis)
|
||||||
|
.set_source(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> NameCollectable<'a> for Impl {
|
fn visit_module(&mut self, m: &'a Module) {
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
let Self { prj, parent, retval: _ } = self;
|
||||||
let Self { target: _, body } = self;
|
let Module { name: Identifier(name), kind } = m;
|
||||||
let def = Def { module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.types.insert(*name, id);
|
||||||
|
|
||||||
|
self.with_parent(id, kind, Self::visit_module_kind);
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_alias(&mut self, a: &'a Alias) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Alias { to: Identifier(name), from: _ } = a;
|
||||||
|
|
||||||
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.types.insert(*name, id);
|
||||||
|
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_enum(&mut self, e: &'a Enum) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Enum { name: Identifier(name), kind } = e;
|
||||||
|
|
||||||
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.types.insert(*name, id);
|
||||||
|
|
||||||
|
self.with_parent(id, kind, Self::visit_enum_kind);
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_struct(&mut self, s: &'a Struct) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Struct { name: Identifier(name), kind } = s;
|
||||||
|
|
||||||
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.types.insert(*name, id);
|
||||||
|
|
||||||
|
self.with_parent(id, kind, Self::visit_struct_kind);
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_const(&mut self, c: &'a Const) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Const { name: Identifier(name), ty: _, init } = c;
|
||||||
|
|
||||||
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.values.insert(*name, id);
|
||||||
|
|
||||||
|
self.with_parent(id, &**init, Self::visit_expr);
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_static(&mut self, s: &'a Static) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Static { name: Identifier(name), mutable: _, ty: _, init } = s;
|
||||||
|
|
||||||
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.values.insert(*name, id);
|
||||||
|
|
||||||
|
self.with_parent(id, &**init, Self::visit_expr);
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_function(&mut self, f: &'a Function) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Function { name: Identifier(name), body, .. } = f;
|
||||||
|
|
||||||
|
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
prj[*parent].module.values.insert(*name, id);
|
||||||
|
|
||||||
|
if let Some(body) = body {
|
||||||
|
self.with_parent(id, body, Self::visit_block);
|
||||||
|
}
|
||||||
|
self.retval = Some(id);
|
||||||
|
}
|
||||||
|
fn visit_impl(&mut self, i: &'a Impl) {
|
||||||
|
let Self { prj, parent, retval: _ } = self;
|
||||||
|
let Impl { target: _, body } = i;
|
||||||
|
let def = Def { module: Mod::new(*parent), ..Default::default() };
|
||||||
|
let id = prj.pool.insert(def);
|
||||||
|
|
||||||
// items will get reparented after name collection, when target is available
|
// items will get reparented after name collection, when target is available
|
||||||
body.collect(c, id)?;
|
self.with_parent(id, body, Self::visit_file);
|
||||||
|
|
||||||
Ok(id)
|
self.retval = Some(id);
|
||||||
}
|
}
|
||||||
}
|
fn visit_use(&mut self, _u: &'a Use) {
|
||||||
impl<'a> NameCollectable<'a> for Use {
|
let Self { prj, parent, retval } = self;
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let def =
|
let def =
|
||||||
Def { module: Mod::new(parent), kind: DefKind::Use(parent), ..Default::default() };
|
Def { module: Mod::new(*parent), kind: DefKind::Use(*parent), ..Default::default() };
|
||||||
|
|
||||||
let id = c.pool.insert(def);
|
let id = prj.pool.insert(def);
|
||||||
c[parent].module.imports.push(id);
|
prj[*parent].module.imports.push(id);
|
||||||
|
|
||||||
Ok(id)
|
*retval = Some(id);
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Alias {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Alias { to: Identifier(name), .. } = self;
|
|
||||||
|
|
||||||
let def = Def { name: *name, module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
|
||||||
|
|
||||||
c[parent].module.types.insert(*name, id);
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Enum {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Enum { name: Identifier(name), .. } = self;
|
|
||||||
|
|
||||||
let def = Def { name: *name, module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
|
||||||
|
|
||||||
c[parent].module.types.insert(*name, id);
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Struct {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Struct { name: Identifier(name), .. } = self;
|
|
||||||
|
|
||||||
let def = Def { name: *name, module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
|
||||||
|
|
||||||
c[parent].module.types.insert(*name, id);
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Const {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Self { name: Identifier(name), init, .. } = self;
|
|
||||||
|
|
||||||
let kind = DefKind::Undecided;
|
|
||||||
|
|
||||||
let def = Def { name: *name, kind, module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
|
||||||
|
|
||||||
c[parent].module.values.insert(*name, id);
|
|
||||||
init.collect(c, id)?;
|
|
||||||
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Static {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Self { name: Identifier(name), init, .. } = self;
|
|
||||||
|
|
||||||
let kind = DefKind::Undecided;
|
|
||||||
|
|
||||||
let def = Def { name: *name, kind, module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
|
||||||
|
|
||||||
c[parent].module.values.insert(*name, id);
|
|
||||||
init.collect(c, id)?;
|
|
||||||
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Function {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let Self { name: Identifier(name), body, .. } = self;
|
|
||||||
|
|
||||||
let kind = DefKind::Undecided;
|
|
||||||
|
|
||||||
let def = Def { name: *name, kind, module: Mod::new(parent), ..Default::default() };
|
|
||||||
let id = c.pool.insert(def);
|
|
||||||
|
|
||||||
c[parent].module.values.insert(*name, id);
|
|
||||||
body.collect(c, id)?;
|
|
||||||
|
|
||||||
Ok(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Block {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
self.stmts.as_slice().collect(c, parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Stmt {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
self.kind.collect(c, parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for StmtKind {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
match self {
|
|
||||||
StmtKind::Empty => Ok(parent),
|
|
||||||
StmtKind::Local(Let { init, .. }) => init.collect(c, parent),
|
|
||||||
StmtKind::Item(item) => item.collect(c, parent),
|
|
||||||
StmtKind::Expr(expr) => expr.collect(c, parent),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for Expr {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
self.kind.collect(c, parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> NameCollectable<'a> for ExprKind {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
match self {
|
|
||||||
ExprKind::Assign(Assign { parts, .. }) | ExprKind::Binary(Binary { parts, .. }) => {
|
|
||||||
parts.0.collect(c, parent)?;
|
|
||||||
parts.1.collect(c, parent)
|
|
||||||
}
|
|
||||||
ExprKind::Unary(Unary { tail, .. }) => tail.collect(c, parent),
|
|
||||||
ExprKind::Index(Index { head, indices }) => {
|
|
||||||
indices.collect(c, parent)?;
|
|
||||||
head.collect(c, parent)
|
|
||||||
}
|
|
||||||
ExprKind::Array(Array { values }) => values.collect(c, parent),
|
|
||||||
ExprKind::ArrayRep(ArrayRep { value, repeat }) => {
|
|
||||||
value.collect(c, parent)?;
|
|
||||||
repeat.collect(c, parent)
|
|
||||||
}
|
|
||||||
ExprKind::AddrOf(AddrOf { expr, .. }) => expr.collect(c, parent),
|
|
||||||
ExprKind::Block(block) => block.collect(c, parent),
|
|
||||||
ExprKind::Group(Group { expr }) => expr.collect(c, parent),
|
|
||||||
ExprKind::Tuple(Tuple { exprs }) => exprs.collect(c, parent),
|
|
||||||
ExprKind::While(While { cond, pass, fail })
|
|
||||||
| ExprKind::If(If { cond, pass, fail })
|
|
||||||
| ExprKind::For(For { cond, pass, fail, .. }) => {
|
|
||||||
cond.collect(c, parent)?;
|
|
||||||
pass.collect(c, parent)?;
|
|
||||||
fail.body.collect(c, parent)
|
|
||||||
}
|
|
||||||
ExprKind::Break(Break { body }) | ExprKind::Return(Return { body }) => {
|
|
||||||
body.collect(c, parent)
|
|
||||||
}
|
|
||||||
_ => Ok(parent),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a, T: NameCollectable<'a>> NameCollectable<'a> for [T] {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
let mut last = parent;
|
|
||||||
for expr in self {
|
|
||||||
last = expr.collect(c, parent)?;
|
|
||||||
}
|
|
||||||
Ok(last)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a, T: NameCollectable<'a>> NameCollectable<'a> for Option<T> {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
match self {
|
|
||||||
Some(body) => body.collect(c, parent),
|
|
||||||
None => Ok(parent),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a, T: NameCollectable<'a>> NameCollectable<'a> for Box<T> {
|
|
||||||
fn collect(&'a self, c: &mut Prj<'a>, parent: DefID) -> Result<DefID, &'static str> {
|
|
||||||
(**self).collect(c, parent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user