Refactor: Use Symbol for identifiers and macro hygiene

Introduces a `Symbol` struct to represent identifiers, incorporating
macro hygiene context. Updates various parts of the AST compiler and
environment to use `Symbol` instead of raw `Rc<str>` for identifiers,
improving robustness for macro expansions.

Also includes:
- Adds a new example `macro_hygiene.myc`.
- Updates `.gitignore`.
- Refactors `MacroExpander` to use `ExpansionState` for cleaner template
  expansion.
- Adjusts `VM::eval_observed` to ensure `after_eval` is called
  correctly.
- Resets `Environment` for each test run and compilation/dumping in
  `main.rs`.
This commit is contained in:
Michael Schimmel
2026-02-18 14:32:09 +01:00
parent 73ddd644c1
commit 76586c0903
12 changed files with 363 additions and 123 deletions
+26 -5
View File
@@ -3,6 +3,27 @@ use std::fmt::Debug;
use std::any::Any;
use crate::ast::types::{Identity, Value, Object};
/// A name with an optional context for macro hygiene.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Symbol {
pub name: Rc<str>,
/// Points to the identity of the Expansion node if this symbol
/// was created/referenced inside a macro expansion.
pub context: Option<Identity>,
}
impl From<Rc<str>> for Symbol {
fn from(name: Rc<str>) -> Self {
Self { name, context: None }
}
}
impl From<&str> for Symbol {
fn from(name: &str) -> Self {
Self { name: Rc::from(name), context: None }
}
}
/// A generic AST Node wrapper to preserve identity and metadata
#[derive(Debug, Clone)]
pub struct Node<K, T = ()> {
@@ -36,14 +57,14 @@ impl Clone for Box<dyn CustomNode> {
pub enum UntypedKind {
Nop,
Constant(Value),
Identifier(Rc<str>),
Identifier(Symbol),
If {
cond: Box<Node<UntypedKind>>,
then_br: Box<Node<UntypedKind>>,
else_br: Option<Box<Node<UntypedKind>>>,
},
Def {
name: Rc<str>,
name: Symbol,
value: Box<Node<UntypedKind>>,
},
Assign {
@@ -51,7 +72,7 @@ pub enum UntypedKind {
value: Box<Node<UntypedKind>>,
},
Lambda {
params: Vec<Rc<str>>,
params: Vec<Symbol>,
body: Rc<Node<UntypedKind>>,
},
Call {
@@ -69,8 +90,8 @@ pub enum UntypedKind {
},
/// A macro declaration that can be expanded at compile time.
MacroDecl {
name: Rc<str>,
params: Vec<Rc<str>>,
name: Symbol,
params: Vec<Symbol>,
body: Box<Node<UntypedKind>>,
},
/// A template for AST nodes, allowing for substitutions. (Quasiquote)