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:
+71
-72
@@ -1,6 +1,6 @@
|
||||
use crate::ast::diagnostics::Diagnostics;
|
||||
use crate::ast::lexer::{Lexer, Token, TokenKind};
|
||||
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
||||
use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
|
||||
use crate::ast::types::{Identity, Keyword, NodeIdentity, Value};
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -50,7 +50,7 @@ impl<'a> Parser<'a> {
|
||||
&self.current_token.kind
|
||||
}
|
||||
|
||||
pub fn parse_expression(&mut self) -> Node<UntypedKind> {
|
||||
pub fn parse_expression(&mut self) -> UntypedNode {
|
||||
let token_loc = self.current_token.location;
|
||||
let identity = NodeIdentity::new(token_loc);
|
||||
|
||||
@@ -61,28 +61,28 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::Quote => {
|
||||
self.advance(); // consume '
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(self.make_id_node("quote", identity.clone())),
|
||||
args: Box::new(Node {
|
||||
args: Box::new(UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: vec![expr],
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::Backtick => {
|
||||
self.advance(); // consume `
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Template(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::Tilde => {
|
||||
@@ -90,17 +90,17 @@ impl<'a> Parser<'a> {
|
||||
if *self.peek() == TokenKind::At {
|
||||
self.advance(); // consume @
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Splice(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
} else {
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Placeholder(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_atom(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_atom(&mut self) -> UntypedNode {
|
||||
let token = self.advance();
|
||||
let identity = NodeIdentity::new(token.location);
|
||||
|
||||
@@ -152,14 +152,13 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind,
|
||||
ty: (),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_list(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_list(&mut self) -> UntypedNode {
|
||||
let start_loc = self.advance().location; // consume '('
|
||||
let identity = NodeIdentity::new(start_loc);
|
||||
|
||||
@@ -169,10 +168,10 @@ impl<'a> Parser<'a> {
|
||||
Some(identity.clone()),
|
||||
);
|
||||
self.advance(); // consume )
|
||||
return Node {
|
||||
return UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Error,
|
||||
ty: (),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -198,29 +197,29 @@ impl<'a> Parser<'a> {
|
||||
node
|
||||
}
|
||||
|
||||
fn parse_again(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_again(&mut self, identity: Identity) -> UntypedNode {
|
||||
let mut elements = Vec::new();
|
||||
|
||||
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
||||
elements.push(self.parse_expression());
|
||||
}
|
||||
|
||||
let args_node = Node {
|
||||
let args_node = UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
};
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Again {
|
||||
args: Box::new(args_node),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_if(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_if(&mut self, identity: Identity) -> UntypedNode {
|
||||
let cond = Box::new(self.parse_expression());
|
||||
let then_br = Box::new(self.parse_expression());
|
||||
let mut else_br = None;
|
||||
@@ -229,53 +228,53 @@ impl<'a> Parser<'a> {
|
||||
else_br = Some(Box::new(self.parse_expression()));
|
||||
}
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::If {
|
||||
cond,
|
||||
then_br,
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_def(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_def(&mut self, identity: Identity) -> UntypedNode {
|
||||
let target = Box::new(self.parse_pattern());
|
||||
let value = Box::new(self.parse_expression());
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Def { target, value },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_assign(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_assign(&mut self, identity: Identity) -> UntypedNode {
|
||||
// (assign target value)
|
||||
let target = Box::new(self.parse_expression());
|
||||
let value = Box::new(self.parse_expression());
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Assign { target, value },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_do(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_do(&mut self, identity: Identity) -> UntypedNode {
|
||||
let mut exprs = Vec::new();
|
||||
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
||||
exprs.push(self.parse_expression());
|
||||
}
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Block { exprs },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pipe(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_pipe(&mut self, identity: Identity) -> UntypedNode {
|
||||
let inputs_node = self.parse_expression();
|
||||
let inputs = match inputs_node.kind {
|
||||
UntypedKind::Tuple { elements } => elements,
|
||||
@@ -283,28 +282,28 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
let lambda = Box::new(self.parse_expression());
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Pipe { inputs, lambda },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_fn(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_fn(&mut self, identity: Identity) -> UntypedNode {
|
||||
let params = Box::new(self.parse_param_vector());
|
||||
let body = self.parse_expression();
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Lambda {
|
||||
params,
|
||||
body: Rc::new(body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_macro_decl(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_macro_decl(&mut self, identity: Identity) -> UntypedNode {
|
||||
let name_node = self.parse_expression();
|
||||
let name = match name_node.kind {
|
||||
UntypedKind::Identifier(sym) => sym,
|
||||
@@ -318,18 +317,18 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
let params = Box::new(self.parse_param_vector());
|
||||
let body = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::MacroDecl {
|
||||
name,
|
||||
params,
|
||||
body: Box::new(body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_param_vector(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_param_vector(&mut self) -> UntypedNode {
|
||||
if *self.peek() != TokenKind::LeftBracket {
|
||||
self.diagnostics.push_error(
|
||||
format!(
|
||||
@@ -338,16 +337,16 @@ impl<'a> Parser<'a> {
|
||||
),
|
||||
Some(NodeIdentity::new(self.current_token.location)),
|
||||
);
|
||||
return Node {
|
||||
return UntypedNode {
|
||||
identity: NodeIdentity::new(self.current_token.location),
|
||||
kind: UntypedKind::Error,
|
||||
ty: (),
|
||||
|
||||
};
|
||||
}
|
||||
self.parse_pattern()
|
||||
}
|
||||
|
||||
fn parse_pattern(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_pattern(&mut self) -> UntypedNode {
|
||||
let next = self.peek();
|
||||
match next {
|
||||
TokenKind::Identifier(_) => {
|
||||
@@ -356,10 +355,10 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::Identifier(s) => s.into(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Identifier(sym),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::LeftBracket => {
|
||||
@@ -372,10 +371,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.expect(TokenKind::RightBracket);
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::Tilde => {
|
||||
@@ -383,17 +382,17 @@ impl<'a> Parser<'a> {
|
||||
if *self.peek() == TokenKind::At {
|
||||
self.advance(); // consume @
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Splice(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
} else {
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Placeholder(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,16 +405,16 @@ impl<'a> Parser<'a> {
|
||||
Some(NodeIdentity::new(self.current_token.location)),
|
||||
);
|
||||
self.advance();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(self.current_token.location),
|
||||
kind: UntypedKind::Error,
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_call(&mut self, callee: Node<UntypedKind>, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_call(&mut self, callee: UntypedNode, identity: Identity) -> UntypedNode {
|
||||
let mut elements = Vec::new();
|
||||
|
||||
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
||||
@@ -423,23 +422,23 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// The arguments are wrapped in a Tuple node, reusing the call's identity/location.
|
||||
let args_node = Node {
|
||||
let args_node = UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
};
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(callee),
|
||||
args: Box::new(args_node),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_vector_literal(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_vector_literal(&mut self) -> UntypedNode {
|
||||
let token = self.advance();
|
||||
let mut elements = Vec::new();
|
||||
|
||||
@@ -450,14 +449,14 @@ impl<'a> Parser<'a> {
|
||||
|
||||
self.expect(TokenKind::RightBracket);
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_record_literal(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_record_literal(&mut self) -> UntypedNode {
|
||||
let token = self.advance();
|
||||
let mut fields = Vec::new();
|
||||
|
||||
@@ -489,10 +488,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.expect(TokenKind::RightBrace);
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Record { fields },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,11 +512,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_id_node(&self, name: &str, identity: Identity) -> Node<UntypedKind> {
|
||||
Node {
|
||||
fn make_id_node(&self, name: &str, identity: Identity) -> UntypedNode {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Identifier(Symbol::from(name)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user