diff --git a/cl-frontend/examples/collect-identifiers.rs b/cl-frontend/examples/collect-identifiers.rs new file mode 100644 index 0000000..55dc8af --- /dev/null +++ b/cl-frontend/examples/collect-identifiers.rs @@ -0,0 +1,523 @@ +//! Collects identifiers into a list + +use cl_frontend::repline::Repline; +use conlang::{common::Loc, lexer::Lexer, parser::Parser}; +use std::{ + collections::HashMap, + error::Error, + fmt::Display, + ops::{Deref, DerefMut}, +}; + +fn main() -> Result<(), Box> { + let mut rl = Repline::new("\x1b[33m", "cl>", "? >"); + while let Ok(line) = rl.read() { + let mut parser = Parser::new(Lexer::new(&line)); + let code = match parser.stmt() { + Ok(code) => { + rl.accept(); + code + } + Err(_) => { + continue; + } + }; + let c = Collector::from(&code); + print!("\x1b[G\x1b[J{c}"); + } + Ok(()) +} + +/// Ties the [Collector] location stack to the program stack +pub struct CollectorLoc<'loc, 'code> { + inner: &'loc mut Collector<'code>, +} +impl<'l, 'c> CollectorLoc<'l, 'c> { + pub fn new(c: &'l mut Collector<'c>, loc: Loc) -> Self { + c.location.push(loc); + Self { inner: c } + } +} +impl<'l, 'c> Deref for CollectorLoc<'l, 'c> { + type Target = Collector<'c>; + fn deref(&self) -> &Self::Target { + self.inner + } +} +impl<'l, 'c> DerefMut for CollectorLoc<'l, 'c> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.inner + } +} +impl<'l, 'c> Drop for CollectorLoc<'l, 'c> { + fn drop(&mut self) { + let Self { inner: c } = self; + c.location.pop(); + } +} + +#[derive(Clone, Debug, Default)] +pub struct Collector<'code> { + location: Vec, + defs: HashMap<&'code str, Vec>, + refs: HashMap<&'code str, Vec>, +} + +impl<'c> Collector<'c> { + pub fn new() -> Self { + Self::default() + } + pub fn location<'loc>(&'loc mut self, loc: Loc) -> CollectorLoc<'loc, 'c> { + CollectorLoc::new(self, loc) + } + pub fn collect(&mut self, collectible: &'c impl Collectible<'c>) -> &mut Self { + collectible.collect(self); + self + } + pub fn define(&mut self, name: &'c str) -> &mut Self { + // println!("Inserted definition of {name}"); + let loc = self.location.last().copied().unwrap_or(Loc(0, 0)); + self.defs + .entry(name) + .and_modify(|c| c.push(loc)) + .or_insert_with(|| vec![loc]); + self + } + pub fn reference(&mut self, name: &'c str) -> &mut Self { + // println!("Inserted usage of {name}"); + let loc = self.location.last().copied().unwrap_or(Loc(0, 0)); + self.refs + .entry(name) + .and_modify(|c| c.push(loc)) + .or_insert_with(|| vec![loc]); + self + } +} +impl<'c> Display for Collector<'c> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { location: _, defs, refs } = self; + writeln!(f, "Definitions:")?; + for (name, locs) in defs { + for loc in locs { + writeln!(f, "{loc} {name}")?; + } + } + writeln!(f, "Usages:")?; + for (name, locs) in refs { + for loc in locs { + writeln!(f, "{loc} {name}")?; + } + } + Ok(()) + } +} + +impl<'c, C: Collectible<'c>> From<&'c C> for Collector<'c> { + fn from(value: &'c C) -> Self { + let mut c = Self::new(); + c.collect(value); + c + } +} + +use collectible::Collectible; +pub mod collectible { + + use super::Collector; + use conlang::ast::*; + pub trait Collectible<'code> { + fn collect(&'code self, c: &mut Collector<'code>); + } + + impl<'c> Collectible<'c> for File { + fn collect(&'c self, c: &mut Collector<'c>) { + let File { items } = self; + for item in items { + item.collect(c) + } + } + } + impl<'c> Collectible<'c> for Item { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { extents, attrs: _, vis: _, kind } = self; + kind.collect(&mut c.location(extents.head)); + } + } + impl<'c> Collectible<'c> for ItemKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + ItemKind::Alias(f) => f.collect(c), + ItemKind::Const(f) => f.collect(c), + ItemKind::Static(f) => f.collect(c), + ItemKind::Module(f) => f.collect(c), + ItemKind::Function(f) => f.collect(c), + ItemKind::Struct(f) => f.collect(c), + ItemKind::Enum(f) => f.collect(c), + ItemKind::Impl(f) => f.collect(c), + } + } + } + impl<'c> Collectible<'c> for Alias { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { to, from } = self; + c.collect(to).collect(from); + } + } + impl<'c> Collectible<'c> for Const { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { name: Identifier(name), ty, init } = self; + c.define(name).collect(init).collect(ty); + } + } + impl<'c> Collectible<'c> for Static { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { mutable: _, name: Identifier(name), ty, init } = self; + c.define(name).collect(init).collect(ty); + } + } + impl<'c> Collectible<'c> for Module { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { name: Identifier(name), kind } = self; + c.define(name).collect(kind); + } + } + impl<'c> Collectible<'c> for ModuleKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + ModuleKind::Inline(f) => f.collect(c), + ModuleKind::Outline => {} + } + } + } + impl<'c> Collectible<'c> for Function { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { name: Identifier(name), args, body, rety } = self; + c.define(name).collect(args).collect(body).collect(rety); + } + } + impl<'c> Collectible<'c> for Struct { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { name: Identifier(name), kind } = self; + c.define(name).collect(kind); + } + } + impl<'c> Collectible<'c> for StructKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + StructKind::Empty => {} + StructKind::Tuple(k) => k.collect(c), + StructKind::Struct(k) => k.collect(c), + } + } + } + impl<'c> Collectible<'c> for StructMember { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { vis: _, name: Identifier(name), ty } = self; + c.define(name).collect(ty); + } + } + impl<'c> Collectible<'c> for Enum { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { name: Identifier(name), kind } = self; + c.define(name).collect(kind); + } + } + impl<'c> Collectible<'c> for EnumKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + EnumKind::NoVariants => {} + EnumKind::Variants(v) => v.collect(c), + } + } + } + impl<'c> Collectible<'c> for Variant { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { name: Identifier(name), kind } = self; + c.define(name).collect(kind); + } + } + impl<'c> Collectible<'c> for VariantKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + VariantKind::Plain => {} + VariantKind::CLike(_) => {} + VariantKind::Tuple(v) => v.collect(c), + VariantKind::Struct(v) => v.collect(c), + } + } + } + impl<'c> Collectible<'c> for Impl { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { target, body } = self; + c.collect(target).collect(body); + } + } + impl<'c> Collectible<'c> for Block { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { stmts } = self; + for stmt in stmts { + stmt.collect(c); + } + } + } + impl<'c> Collectible<'c> for Stmt { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { extents, kind, semi: _ } = self; + c.location(extents.head).collect(kind); + } + } + impl<'c> Collectible<'c> for StmtKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + StmtKind::Empty => {} + StmtKind::Local(s) => s.collect(c), + StmtKind::Item(s) => s.collect(c), + StmtKind::Expr(s) => s.collect(c), + } + } + } + impl<'c> Collectible<'c> for Let { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { mutable: _, name: Identifier(name), ty, init } = self; + c.collect(init).collect(ty).define(name); + } + } + impl<'c> Collectible<'c> for Expr { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { extents, kind } = self; + c.location(extents.head).collect(kind); + } + } + impl<'c> Collectible<'c> for ExprKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + ExprKind::Assign(k) => k.collect(c), + ExprKind::Binary(k) => k.collect(c), + ExprKind::Unary(k) => k.collect(c), + ExprKind::Member(k) => k.collect(c), + ExprKind::Call(k) => k.collect(c), + ExprKind::Index(k) => k.collect(c), + ExprKind::Path(k) => k.collect(c), + ExprKind::Literal(k) => k.collect(c), + ExprKind::Array(k) => k.collect(c), + ExprKind::ArrayRep(k) => k.collect(c), + ExprKind::AddrOf(k) => k.collect(c), + ExprKind::Block(k) => k.collect(c), + ExprKind::Empty => {} + ExprKind::Group(k) => k.collect(c), + ExprKind::Tuple(k) => k.collect(c), + ExprKind::While(k) => k.collect(c), + ExprKind::If(k) => k.collect(c), + ExprKind::For(k) => k.collect(c), + ExprKind::Break(k) => k.collect(c), + ExprKind::Return(k) => k.collect(c), + ExprKind::Continue(k) => k.collect(c), + } + } + } + impl<'c> Collectible<'c> for Assign { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { head, op: _, tail } = self; + c.collect(head).collect(tail); + } + } + impl<'c> Collectible<'c> for Binary { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { head, tail } = self; + c.collect(head); + for (_, tail) in tail { + c.collect(tail); + } + } + } + impl<'c> Collectible<'c> for Unary { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { ops: _, tail } = self; + c.collect(tail); + } + } + impl<'c> Collectible<'c> for Member { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { head, tail } = self; + c.collect(head).collect(tail); + } + } + impl<'c> Collectible<'c> for Call { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { callee, args } = self; + c.collect(callee).collect(args); + } + } + impl<'c> Collectible<'c> for Tuple { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { exprs } = self; + c.collect(exprs); + } + } + impl<'c> Collectible<'c> for Index { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { head, indices } = self; + c.collect(head).collect(indices); + } + } + impl<'c> Collectible<'c> for Indices { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { exprs } = self; + c.collect(exprs); + } + } + impl<'c> Collectible<'c> for Array { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { values } = self; + c.collect(values); + } + } + impl<'c> Collectible<'c> for ArrayRep { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { value, repeat } = self; + c.collect(value).collect(repeat); + } + } + impl<'c> Collectible<'c> for AddrOf { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { count: _, mutable: _, expr } = self; + c.collect(expr); + } + } + impl<'c> Collectible<'c> for Group { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { expr } = self; + c.collect(expr); + } + } + impl<'c> Collectible<'c> for While { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { cond, pass, fail } = self; + c.collect(cond).collect(pass).collect(fail); + } + } + impl<'c> Collectible<'c> for Else { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { body } = self; + c.collect(body); + } + } + impl<'c> Collectible<'c> for If { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { cond, pass, fail } = self; + c.collect(cond).collect(pass).collect(fail); + } + } + impl<'c> Collectible<'c> for For { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { bind: Identifier(name), cond, pass, fail } = self; + c.collect(cond).define(name).collect(pass).collect(fail); + } + } + impl<'c> Collectible<'c> for Break { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { body } = self; + c.collect(body); + } + } + impl<'c> Collectible<'c> for Return { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { body } = self; + c.collect(body); + } + } + impl<'c> Collectible<'c> for Continue { + fn collect(&'c self, _c: &mut Collector<'c>) {} + } + impl<'c> Collectible<'c> for Literal { + fn collect(&'c self, _c: &mut Collector<'c>) {} + } + impl<'c> Collectible<'c> for Identifier { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self(name) = self; + c.reference(name); + } + } + impl<'c> Collectible<'c> for Param { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { mutability: _, name, ty } = self; + c.collect(name).collect(ty); + } + } + impl<'c> Collectible<'c> for Ty { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { extents, kind } = self; + c.location(extents.head).collect(kind); + } + } + impl<'c> Collectible<'c> for TyKind { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + TyKind::Never => {} + TyKind::Empty => {} + TyKind::SelfTy => {} + TyKind::Path(t) => t.collect(c), + TyKind::Tuple(t) => t.collect(c), + TyKind::Ref(t) => t.collect(c), + TyKind::Fn(t) => t.collect(c), + } + } + } + impl<'c> Collectible<'c> for Path { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { absolute: _, parts } = self; + for part in parts { + c.collect(part); + } + } + } + impl<'c> Collectible<'c> for PathPart { + fn collect(&'c self, c: &mut Collector<'c>) { + match self { + PathPart::SuperKw => {} + PathPart::SelfKw => {} + PathPart::Ident(i) => i.collect(c), + } + } + } + impl<'c> Collectible<'c> for TyTuple { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { types } = self; + for ty in types { + c.collect(ty); + } + } + } + impl<'c> Collectible<'c> for TyRef { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { count: _, to } = self; + c.collect(to); + } + } + impl<'c> Collectible<'c> for TyFn { + fn collect(&'c self, c: &mut Collector<'c>) { + let Self { args, rety } = self; + c.collect(args).collect(rety); + } + } + + impl<'c, C: Collectible<'c> + Sized> Collectible<'c> for Vec { + fn collect(&'c self, c: &mut Collector<'c>) { + for i in self { + c.collect(i); + } + } + } + impl<'c, C: Collectible<'c> + Sized> Collectible<'c> for Option { + fn collect(&'c self, c: &mut Collector<'c>) { + if let Some(i) = self { + c.collect(i); + } + } + } + impl<'c, C: Collectible<'c>> Collectible<'c> for Box { + fn collect(&'c self, c: &mut Collector<'c>) { + c.collect(self.as_ref()); + } + } +}