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:
+11
-6
@@ -200,7 +200,7 @@ macro_rules! dispatch_eval {
|
||||
|
||||
loop {
|
||||
match func_val {
|
||||
Value::Function(f) => return Ok(f(arg_vals)),
|
||||
Value::Function(f) => break Ok(f(arg_vals)),
|
||||
Value::Object(obj) => {
|
||||
if let Some(closure) = obj.as_any().downcast_ref::<Closure>() {
|
||||
let old_stack_top = $self.stack.len();
|
||||
@@ -225,14 +225,13 @@ macro_rules! dispatch_eval {
|
||||
arg_vals = next_args;
|
||||
continue;
|
||||
},
|
||||
Ok(val) => return Ok(val),
|
||||
Err(e) => return Err(e),
|
||||
res => break res,
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Object is not a closure: {}", obj.type_name()));
|
||||
break Err(format!("Object is not a closure: {}", obj.type_name()));
|
||||
}
|
||||
},
|
||||
_ => return Err(format!("Attempt to call non-function: {}", func_val)),
|
||||
_ => break Err(format!("Attempt to call non-function: {}", func_val)),
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -315,7 +314,13 @@ impl VM {
|
||||
/// The observed path for debugging.
|
||||
fn eval_observed<O: VMObserver>(&mut self, observer: &mut O, node: &Node<BoundKind, StaticType>) -> Result<Value, String> {
|
||||
observer.before_eval(self, node);
|
||||
let result = dispatch_eval!(self, node, eval_observed, observer);
|
||||
|
||||
// Wrap in a closure to ensure after_eval is called even on early returns (e.g. from ?)
|
||||
let wrapper = |vm: &mut Self, obs: &mut O| -> Result<Value, String> {
|
||||
dispatch_eval!(vm, node, eval_observed, obs)
|
||||
};
|
||||
|
||||
let result = wrapper(self, observer);
|
||||
observer.after_eval(self, node, &result);
|
||||
result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user