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
+13 -11
View File
@@ -87,6 +87,9 @@ impl CompilerApp {
let start_total = std::time::Instant::now();
self.trace_logs.clear();
// Reset environment for a fresh run
self.env = Environment::new();
let res = (|| -> Result<(myc::ast::types::Value, std::time::Duration, std::time::Duration, std::time::Duration), String> {
let start_compile = std::time::Instant::now();
let compiled = self.env.compile(&self.source_code)?;
@@ -110,11 +113,10 @@ impl CompilerApp {
}
for line in &mut logs {
if line.len() > 255 {
if let Some((idx, _)) = line.char_indices().nth(255) {
if line.len() > 255
&& let Some((idx, _)) = line.char_indices().nth(255) {
line.truncate(idx);
line.push_str("...");
}
}
}
@@ -154,6 +156,7 @@ impl CompilerApp {
}
fn dump_ast(&mut self) {
self.env = Environment::new();
match self.env.dump_ast(&self.source_code) {
Ok(dump) => {
self.output_log = format!(
@@ -367,6 +370,7 @@ impl eframe::App for CompilerApp {
// Log Output Area
egui::ScrollArea::vertical()
.id_salt("output_log_scroll")
.auto_shrink([false, true]) // Don't shrink horizontally, fill width
.show(ui, |ui| {
match self.active_tab {
AppTab::Output => {
@@ -379,14 +383,12 @@ impl eframe::App for CompilerApp {
);
},
AppTab::Trace => {
egui::ScrollArea::vertical()
.id_salt("trace_log_scroll")
.show(ui, |ui| {
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
for line in &self.trace_logs {
ui.label(line);
}
});
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
ui.with_layout(egui::Layout::top_down_justified(egui::Align::LEFT), |ui| {
for line in &self.trace_logs {
ui.label(line);
}
});
}
}
});