doughlang: symbol interning and AST reparameterization

- intern: Add interners from cl-intern

- ast:
- Break AST into ternimals (AstTypes) and nonterminals (Expr, Pat, Bind, Make, Use)
- Make AST generic over terminals (except operators, for now)
This commit is contained in:
2026-01-06 04:57:15 -05:00
parent e4c008bd4b
commit 2be73d2660
17 changed files with 952 additions and 592 deletions

View File

@@ -5,11 +5,13 @@ use std::{convert::Infallible, error::Error};
use doughlang::{
ast::{
fold::{Fold, Foldable},
types::{Literal, Path, Symbol},
visit::{Visit, Walk},
*,
},
lexer::Lexer,
parser::{Parser, expr::Prec},
span::Span,
};
const CODE: &str = r#"
@@ -86,6 +88,7 @@ fn main() -> Result<(), Box<dyn Error>> {
#[derive(Clone, Debug, Default, PartialEq, Eq)]
struct CountNodes {
exprs: usize,
macro_ids: usize,
idents: usize,
paths: usize,
literals: usize,
@@ -102,50 +105,54 @@ impl CountNodes {
}
}
impl<'a> Visit<'a> for CountNodes {
impl<'a, A: AstTypes> Visit<'a, A> for CountNodes {
type Error = Infallible;
fn visit_expr<A: Annotation>(&mut self, expr: &'a Expr<A>) -> Result<(), Self::Error> {
fn visit_macro_id(&mut self, _name: &'a A::MacroId) -> Result<(), Self::Error> {
self.macro_ids += 1;
Ok(())
}
fn visit_symbol(&mut self, _name: &'a A::Symbol) -> Result<(), Self::Error> {
self.idents += 1;
Ok(())
}
fn visit_path(&mut self, _path: &'a A::Path) -> Result<(), Self::Error> {
self.paths += 1;
Ok(())
}
fn visit_literal(&mut self, _lit: &'a A::Literal) -> Result<(), Self::Error> {
self.literals += 1;
Ok(())
}
fn visit_use(&mut self, item: &'a Use<A>) -> Result<(), Self::Error> {
self.uses += 1;
item.children(self)
}
fn visit_expr(&mut self, expr: &'a Expr<A>) -> Result<(), Self::Error> {
self.exprs += 1;
expr.children(self)
}
fn visit_ident(&mut self, name: &'a str) -> Result<(), Self::Error> {
self.idents += 1;
name.children(self)
}
fn visit_path(&mut self, path: &'a Path) -> Result<(), Self::Error> {
self.paths += 1;
path.children(self)
}
fn visit_literal(&mut self, lit: &'a Literal) -> Result<(), Self::Error> {
self.literals += 1;
lit.children(self)
}
fn visit_use(&mut self, item: &'a Use) -> Result<(), Self::Error> {
self.uses += 1;
item.children(self)
}
fn visit_pat<A: Annotation>(&mut self, item: &'a Pat<A>) -> Result<(), Self::Error> {
fn visit_pat(&mut self, item: &'a Pat<A>) -> Result<(), Self::Error> {
self.patterns += 1;
item.children(self)
}
fn visit_bind<A: Annotation>(&mut self, item: &'a Bind<A>) -> Result<(), Self::Error> {
fn visit_bind(&mut self, item: &'a Bind<A>) -> Result<(), Self::Error> {
self.binds += 1;
item.children(self)
}
fn visit_make<A: Annotation>(&mut self, item: &'a Make<A>) -> Result<(), Self::Error> {
fn visit_make(&mut self, item: &'a Make<A>) -> Result<(), Self::Error> {
self.makes += 1;
item.children(self)
}
fn visit_makearm<A: Annotation>(&mut self, item: &'a MakeArm<A>) -> Result<(), Self::Error> {
fn visit_makearm(&mut self, item: &'a MakeArm<A>) -> Result<(), Self::Error> {
self.makearms += 1;
item.children(self)
}
@@ -153,10 +160,26 @@ impl<'a> Visit<'a> for CountNodes {
struct Sevenfold;
impl<A: Annotation> Fold<A> for Sevenfold {
impl Fold<DefaultTypes> for Sevenfold {
type Error = ();
fn fold_annotation(&mut self, anno: Span) -> Result<Span, Self::Error> {
Ok(anno)
}
fn fold_literal(&mut self, _lit: Literal) -> Result<Literal, Self::Error> {
Ok(Literal::Int(7, 10))
}
fn fold_macro_id(&mut self, name: Symbol) -> Result<Symbol, Self::Error> {
Ok(name)
}
fn fold_symbol(&mut self, name: Symbol) -> Result<Symbol, Self::Error> {
Ok(name)
}
fn fold_path(&mut self, path: Path) -> Result<Path, Self::Error> {
Ok(path)
}
}