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:
@@ -2,7 +2,7 @@ use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use crate::ast::types::{Value, StaticType, Object};
|
||||
use crate::ast::nodes::{Node, UntypedKind};
|
||||
use crate::ast::nodes::{Node, UntypedKind, Symbol};
|
||||
use crate::ast::parser::Parser;
|
||||
use crate::ast::compiler::binder::Binder;
|
||||
use crate::ast::compiler::BoundKind;
|
||||
@@ -13,29 +13,26 @@ use crate::ast::compiler::dumper::Dumper;
|
||||
use crate::ast::compiler::macros::{MacroExpander, MacroRegistry, MacroEvaluator};
|
||||
|
||||
pub struct Environment {
|
||||
pub global_names: Rc<RefCell<HashMap<String, (u32, StaticType)>>>,
|
||||
pub global_names: Rc<RefCell<HashMap<Symbol, (u32, StaticType)>>>,
|
||||
pub global_values: Rc<RefCell<Vec<Value>>>,
|
||||
pub debug_mode: bool,
|
||||
}
|
||||
|
||||
/// Evaluator used during macro expansion to allow compile-time logic.
|
||||
struct RuntimeMacroEvaluator {
|
||||
global_names: Rc<RefCell<HashMap<String, (u32, StaticType)>>>,
|
||||
global_names: Rc<RefCell<HashMap<Symbol, (u32, StaticType)>>>,
|
||||
global_values: Rc<RefCell<Vec<Value>>>,
|
||||
}
|
||||
|
||||
impl MacroEvaluator for RuntimeMacroEvaluator {
|
||||
fn evaluate(&self, node: &Node<UntypedKind>, bindings: &HashMap<Rc<str>, Node<UntypedKind>>) -> Result<Value, String> {
|
||||
// 1. Check if it's a simple parameter substitution
|
||||
if let UntypedKind::Identifier(name) = &node.kind {
|
||||
if let Some(arg_node) = bindings.get(name) {
|
||||
if let UntypedKind::Identifier(sym) = &node.kind
|
||||
&& let Some(arg_node) = bindings.get(&sym.name) {
|
||||
return Ok(Value::Object(Rc::new(arg_node.clone()) as Rc<dyn Object>));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Full evaluation for complex compile-time expressions
|
||||
// Note: This evaluator currently doesn't see macro parameters in complex expressions
|
||||
// unless they are explicitly substituted. For now, we support global-only logic.
|
||||
let bound_ast = Binder::bind_root(self.global_names.clone(), node)?;
|
||||
let mut vm = VM::new(self.global_values.clone());
|
||||
vm.run(&bound_ast)
|
||||
@@ -76,7 +73,7 @@ impl Environment {
|
||||
let mut values = self.global_values.borrow_mut();
|
||||
|
||||
let idx = values.len() as u32;
|
||||
names.insert(name.to_string(), (idx, ty));
|
||||
names.insert(Symbol::from(name), (idx, ty));
|
||||
values.push(Value::Function(Rc::new(func)));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user