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:
+9
-9
@@ -1,7 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
use crate::ast::lexer::{Lexer, Token, TokenKind};
|
||||
use crate::ast::types::{Identity, NodeIdentity, Value, Keyword};
|
||||
use crate::ast::nodes::{Node, UntypedKind};
|
||||
use crate::ast::nodes::{Node, UntypedKind, Symbol};
|
||||
|
||||
pub struct Parser<'a> {
|
||||
lexer: Lexer<'a>,
|
||||
@@ -95,7 +95,7 @@ impl<'a> Parser<'a> {
|
||||
"true" => UntypedKind::Constant(Value::Bool(true)),
|
||||
"false" => UntypedKind::Constant(Value::Bool(false)),
|
||||
"void" => UntypedKind::Constant(Value::Void),
|
||||
_ => UntypedKind::Identifier(id),
|
||||
_ => UntypedKind::Identifier(id.into()),
|
||||
}
|
||||
}
|
||||
_ => return Err(format!("Unexpected token in atom: {:?} at {:?}", token.kind, token.location)),
|
||||
@@ -114,8 +114,8 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let head = self.parse_expression()?;
|
||||
|
||||
let result = if let UntypedKind::Identifier(name) = &head.kind {
|
||||
match name.as_ref() {
|
||||
let result = if let UntypedKind::Identifier(ref sym) = head.kind {
|
||||
match sym.name.as_ref() {
|
||||
"if" => self.parse_if(identity),
|
||||
"fn" => self.parse_fn(identity),
|
||||
"def" => self.parse_def(identity),
|
||||
@@ -151,7 +151,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_def(&mut self, identity: Identity) -> Result<Node<UntypedKind>, String> {
|
||||
let name_node = self.parse_expression()?;
|
||||
let name = match name_node.kind {
|
||||
UntypedKind::Identifier(s) => s,
|
||||
UntypedKind::Identifier(sym) => sym,
|
||||
_ => return Err("Expected identifier for def name".to_string()),
|
||||
};
|
||||
|
||||
@@ -205,7 +205,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_macro_decl(&mut self, identity: Identity) -> Result<Node<UntypedKind>, String> {
|
||||
let name_node = self.parse_expression()?;
|
||||
let name = match name_node.kind {
|
||||
UntypedKind::Identifier(s) => s,
|
||||
UntypedKind::Identifier(sym) => sym,
|
||||
_ => return Err("Expected identifier for macro name".to_string()),
|
||||
};
|
||||
let params = self.parse_param_vector()?;
|
||||
@@ -217,7 +217,7 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_param_vector(&mut self) -> Result<Vec<Rc<str>>, String> {
|
||||
fn parse_param_vector(&mut self) -> Result<Vec<Symbol>, String> {
|
||||
if *self.peek() != TokenKind::LeftBracket {
|
||||
return Err(format!("Expected parameter vector [...] for fn, found {:?}", self.peek()));
|
||||
}
|
||||
@@ -227,7 +227,7 @@ impl<'a> Parser<'a> {
|
||||
while *self.peek() != TokenKind::RightBracket {
|
||||
let token = self.advance()?;
|
||||
match token.kind {
|
||||
TokenKind::Identifier(name) => params.push(name),
|
||||
TokenKind::Identifier(name) => params.push(name.into()),
|
||||
_ => return Err(format!("Expected identifier in param vector, found {:?}", token.kind)),
|
||||
}
|
||||
}
|
||||
@@ -313,7 +313,7 @@ impl<'a> Parser<'a> {
|
||||
fn make_id_node(&self, name: &str, identity: Identity) -> Node<UntypedKind> {
|
||||
Node {
|
||||
identity,
|
||||
kind: UntypedKind::Identifier(Rc::from(name)),
|
||||
kind: UntypedKind::Identifier(Symbol::from(name)),
|
||||
ty: (),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user