refactor: separate parser and compiler AST node structures
Simplified the AST architecture by removing the overly complex Node<K,
T> structure and replacing it with specialized types for
each phase:
- Introduced UntypedNode in nodes.rs for the Parser and Macro system,
eliminating redundant ty: () initializations.
- Defined a new generic Node<T> in bound_nodes.rs for all compiler
stages, where T represents the phase-specific metadata.
- Updated the Binder to act as the bridge between UntypedNode and
Node<()>.
- Simplified type aliases: TypedNode, AnalyzedNode, and ExecNode now
leverage the streamlined Node<T> structure.
- Updated Parser, Macros, Type-Checker, Optimizer, and VM to reflect
the architectural changes.
- Fixed import chains and resolved needless borrows via clippy.
This change improves type safety, reduces boilerplate code in the
parser, and makes the compiler stages more idiomatic and
readable.
This commit is contained in:
+81
-81
@@ -1,4 +1,4 @@
|
||||
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
||||
use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
|
||||
use crate::ast::types::{Identity, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@@ -7,19 +7,19 @@ use std::rc::Rc;
|
||||
pub trait MacroEvaluator {
|
||||
fn evaluate(
|
||||
&self,
|
||||
node: &Node<UntypedKind>,
|
||||
bindings: &HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
node: &UntypedNode,
|
||||
bindings: &HashMap<Rc<str>, UntypedNode>,
|
||||
) -> Result<Value, String>;
|
||||
}
|
||||
|
||||
/// Internal state for template expansion (Hygiene context + Parameter binding)
|
||||
struct ExpansionState<'a> {
|
||||
bindings: &'a HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
bindings: &'a HashMap<Rc<str>, UntypedNode>,
|
||||
/// The identity of the current expansion instance, used to "color" internal symbols.
|
||||
expansion_id: Identity,
|
||||
}
|
||||
|
||||
type MacroMap = HashMap<Rc<str>, (Vec<Rc<str>>, Node<UntypedKind>)>;
|
||||
type MacroMap = HashMap<Rc<str>, (Vec<Rc<str>>, UntypedNode)>;
|
||||
|
||||
/// A registry for macro declarations.
|
||||
#[derive(Clone)]
|
||||
@@ -50,7 +50,7 @@ impl MacroRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define(&mut self, name: Rc<str>, params: Vec<Rc<str>>, body: Node<UntypedKind>) {
|
||||
pub fn define(&mut self, name: Rc<str>, params: Vec<Rc<str>>, body: UntypedNode) {
|
||||
if let Some(current_rc) = self.scopes.last_mut() {
|
||||
// Copy-on-Write: If the Rc is shared, clone the map before modifying.
|
||||
let current = Rc::make_mut(current_rc);
|
||||
@@ -58,7 +58,7 @@ impl MacroRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(&self, name: &str) -> Option<(Vec<Rc<str>>, Node<UntypedKind>)> {
|
||||
pub fn lookup(&self, name: &str) -> Option<(Vec<Rc<str>>, UntypedNode)> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
if let Some(m) = scope.get(name) {
|
||||
return Some(m.clone());
|
||||
@@ -85,19 +85,19 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
self.registry
|
||||
}
|
||||
|
||||
pub fn expand(&mut self, node: Node<UntypedKind>) -> Result<Node<UntypedKind>, String> {
|
||||
pub fn expand(&mut self, node: UntypedNode) -> Result<UntypedNode, String> {
|
||||
self.expand_recursive(node)
|
||||
}
|
||||
|
||||
fn expand_recursive(&mut self, node: Node<UntypedKind>) -> Result<Node<UntypedKind>, String> {
|
||||
fn expand_recursive(&mut self, node: UntypedNode) -> Result<UntypedNode, String> {
|
||||
match node.kind {
|
||||
UntypedKind::MacroDecl { name, params, body } => {
|
||||
let p_names = self.extract_param_names(¶ms)?;
|
||||
self.registry.define(name.name, p_names, *body);
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Nop,
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -127,13 +127,13 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let expanded_callee = self.expand_recursive(*callee)?;
|
||||
let expanded_args = self.expand_recursive(*args)?;
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(expanded_callee),
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -145,12 +145,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
}
|
||||
self.registry.pop();
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Block {
|
||||
exprs: expanded_exprs,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -160,29 +160,29 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
expanded_inputs.push(self.expand_recursive(input)?);
|
||||
}
|
||||
let expanded_lambda = Box::new(self.expand_recursive(*lambda)?);
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Pipe {
|
||||
inputs: expanded_inputs,
|
||||
lambda: expanded_lambda,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Lambda { params, body } => {
|
||||
self.registry.push();
|
||||
let expanded_params = self.expand_recursive(*params)?;
|
||||
let expanded_body = self.expand_recursive(Node::clone(&body))?;
|
||||
let expanded_body = self.expand_recursive((*body).clone())?;
|
||||
self.registry.pop();
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Lambda {
|
||||
params: Box::new(expanded_params),
|
||||
body: Rc::new(expanded_body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -198,40 +198,40 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::If {
|
||||
cond: Box::new(cond),
|
||||
then_br: Box::new(then_br),
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Def { target, value } => {
|
||||
let target = self.expand_recursive(*target)?;
|
||||
let value = self.expand_recursive(*value)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Def {
|
||||
target: Box::new(target),
|
||||
value: Box::new(value),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Assign { target, value } => {
|
||||
let target = self.expand_recursive(*target)?;
|
||||
let value = self.expand_recursive(*value)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Assign {
|
||||
target: Box::new(target),
|
||||
value: Box::new(value),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -240,12 +240,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
for e in elements {
|
||||
expanded_elements.push(self.expand_recursive(e)?);
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: expanded_elements,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -254,35 +254,35 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
for (k, v) in fields {
|
||||
expanded_fields.push((self.expand_recursive(k)?, self.expand_recursive(v)?));
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Record {
|
||||
fields: expanded_fields,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Expansion { call, expanded } => {
|
||||
let expanded = self.expand_recursive(*expanded)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Expansion {
|
||||
call,
|
||||
expanded: Box::new(expanded),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Again { args } => {
|
||||
let expanded_args = self.expand_recursive(*args)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Again {
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -295,9 +295,9 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
identity: Identity,
|
||||
name: &str,
|
||||
params: Vec<Rc<str>>,
|
||||
args: Vec<Node<UntypedKind>>,
|
||||
body: Node<UntypedKind>,
|
||||
) -> Result<Node<UntypedKind>, String> {
|
||||
args: Vec<UntypedNode>,
|
||||
body: UntypedNode,
|
||||
) -> Result<UntypedNode, String> {
|
||||
if params.len() != args.len() {
|
||||
return Err(format!(
|
||||
"Macro {} expects {} arguments, but got {}",
|
||||
@@ -324,36 +324,36 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
body
|
||||
};
|
||||
|
||||
let original_call = Node {
|
||||
let original_call = UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(Node {
|
||||
callee: Box::new(UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Identifier(Symbol::from(name)),
|
||||
ty: (),
|
||||
|
||||
}),
|
||||
args: Box::new(Node {
|
||||
args: Box::new(UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: bindings.into_values().collect(),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
};
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Expansion {
|
||||
call: Box::new(original_call),
|
||||
expanded: Box::new(expanded_body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_param_names(&self, node: &Node<UntypedKind>) -> Result<Vec<Rc<str>>, String> {
|
||||
fn extract_param_names(&self, node: &UntypedNode) -> Result<Vec<Rc<str>>, String> {
|
||||
match &node.kind {
|
||||
UntypedKind::Identifier(sym) => Ok(vec![sym.name.clone()]),
|
||||
UntypedKind::Tuple { elements } => {
|
||||
@@ -369,17 +369,17 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
|
||||
fn expand_template(
|
||||
&self,
|
||||
node: Node<UntypedKind>,
|
||||
node: UntypedNode,
|
||||
state: &mut ExpansionState,
|
||||
) -> Result<Node<UntypedKind>, String> {
|
||||
) -> Result<UntypedNode, String> {
|
||||
match node.kind {
|
||||
UntypedKind::Identifier(mut sym) => {
|
||||
// Inside a template, all internal identifiers are colored.
|
||||
sym.context = Some(state.expansion_id.clone());
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Identifier(sym),
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -408,26 +408,26 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
UntypedKind::Def { target, value } => {
|
||||
let target = self.expand_template(*target, state)?;
|
||||
let val = self.expand_template(*value, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Def {
|
||||
target: Box::new(target),
|
||||
value: Box::new(val),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Assign { target, value } => {
|
||||
let target = self.expand_template(*target, state)?;
|
||||
let value = self.expand_template(*value, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Assign {
|
||||
target: Box::new(target),
|
||||
value: Box::new(value),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -441,12 +441,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
new_elements.push(self.expand_template(e, state)?);
|
||||
}
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: new_elements,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -460,10 +460,10 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
new_exprs.push(self.expand_template(e, state)?);
|
||||
}
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Block { exprs: new_exprs },
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -475,23 +475,23 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
self.expand_template(v, state)?,
|
||||
));
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Record { fields: new_fields },
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Call { callee, args } => {
|
||||
let expanded_callee = self.expand_template(*callee, state)?;
|
||||
let expanded_args = self.expand_template(*args, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(expanded_callee),
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -507,14 +507,14 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::If {
|
||||
cond: Box::new(cond),
|
||||
then_br: Box::new(then_br),
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -524,37 +524,37 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
expanded_inputs.push(self.expand_template(input, state)?);
|
||||
}
|
||||
let expanded_lambda = Box::new(self.expand_template(*lambda, state)?);
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Pipe {
|
||||
inputs: expanded_inputs,
|
||||
lambda: expanded_lambda,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Lambda { params, body } => {
|
||||
let expanded_params = self.expand_template(*params, state)?;
|
||||
let body = self.expand_template(Node::clone(&body), state)?;
|
||||
Ok(Node {
|
||||
let body = self.expand_template((*body).clone(), state)?;
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Lambda {
|
||||
params: Box::new(expanded_params),
|
||||
body: Rc::new(body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Again { args } => {
|
||||
let expanded_args = self.expand_template(*args, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Again {
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -566,11 +566,11 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
&self,
|
||||
val: Value,
|
||||
_identity: Identity,
|
||||
target: &mut Vec<Node<UntypedKind>>,
|
||||
target: &mut Vec<UntypedNode>,
|
||||
) -> Result<(), String> {
|
||||
match val {
|
||||
Value::Object(obj) => {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<Node<UntypedKind>>() {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<UntypedNode>() {
|
||||
match &node.kind {
|
||||
UntypedKind::Tuple { elements } => {
|
||||
for e in elements {
|
||||
@@ -599,22 +599,22 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
}
|
||||
}
|
||||
|
||||
fn value_to_node(&self, val: Value, identity: Identity) -> Node<UntypedKind> {
|
||||
fn value_to_node(&self, val: Value, identity: Identity) -> UntypedNode {
|
||||
match val {
|
||||
Value::Object(obj) => {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<Node<UntypedKind>>() {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<UntypedNode>() {
|
||||
return node.clone();
|
||||
}
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Constant(Value::Object(obj)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
_ => Node {
|
||||
_ => UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Constant(val),
|
||||
ty: (),
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -632,8 +632,8 @@ mod tests {
|
||||
impl MacroEvaluator for SimpleEvaluator {
|
||||
fn evaluate(
|
||||
&self,
|
||||
node: &Node<UntypedKind>,
|
||||
bindings: &HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
node: &UntypedNode,
|
||||
bindings: &HashMap<Rc<str>, UntypedNode>,
|
||||
) -> Result<Value, String> {
|
||||
if let UntypedKind::Identifier(ref sym) = node.kind
|
||||
&& let Some(arg) = bindings.get(&sym.name)
|
||||
|
||||
Reference in New Issue
Block a user