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:
Michael Schimmel
2026-03-13 13:16:03 +01:00
parent bf86c76bb6
commit 7d72a99fa1
19 changed files with 2574 additions and 2566 deletions
+1
View File
@@ -1,3 +1,4 @@
/target /target
Delphi Delphi
*.snap.new *.snap.new
repomix-output.xml
+4
View File
@@ -74,3 +74,7 @@ Options:
* Dieses Dokument sollte aktuell gehalten werden. * Dieses Dokument sollte aktuell gehalten werden.
@docs/BNF.md @docs/BNF.md
# Repository
@repomix-output.xml
+386 -386
View File
@@ -1,386 +1,386 @@
use crate::ast::compiler::bound_nodes::{ use crate::ast::compiler::bound_nodes::{
Address, AnalyzedNode, BoundKind, GlobalIdx, NodeMetrics, TypedNode, Address, AnalyzedNode, BoundKind, GlobalIdx, NodeMetrics, TypedNode,
}; };
use crate::ast::types::Purity; use crate::ast::types::Purity;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::rc::Rc; use std::rc::Rc;
pub struct Analyzer<'a> { pub struct Analyzer<'a> {
root_purity: &'a [Purity], root_purity: &'a [Purity],
/// Stack of currently visiting lambdas to detect direct recursion. /// Stack of currently visiting lambdas to detect direct recursion.
lambda_stack: Vec<crate::ast::types::Identity>, lambda_stack: Vec<crate::ast::types::Identity>,
/// Map of global index to its Lambda identity if known. /// Map of global index to its Lambda identity if known.
globals_to_lambdas: HashMap<GlobalIdx, crate::ast::types::Identity>, globals_to_lambdas: HashMap<GlobalIdx, crate::ast::types::Identity>,
/// Set of identities that were found to be recursive. /// Set of identities that were found to be recursive.
recursive_identities: HashSet<crate::ast::types::Identity>, recursive_identities: HashSet<crate::ast::types::Identity>,
} }
impl<'a> Analyzer<'a> { impl<'a> Analyzer<'a> {
pub fn analyze( pub fn analyze(
node: &TypedNode, node: &TypedNode,
root_purity: &'a [Purity], root_purity: &'a [Purity],
) -> AnalyzedNode { ) -> AnalyzedNode {
let mut analyzer = Self { let mut analyzer = Self {
root_purity, root_purity,
lambda_stack: Vec::new(), lambda_stack: Vec::new(),
globals_to_lambdas: HashMap::new(), globals_to_lambdas: HashMap::new(),
recursive_identities: HashSet::new(), recursive_identities: HashSet::new(),
}; };
// First pass: map globals to their lambda identities // First pass: map globals to their lambda identities
analyzer.collect_globals(node); analyzer.collect_globals(node);
// Second pass: full analysis (decorating TypedNode into AnalyzedNode) // Second pass: full analysis (decorating TypedNode into AnalyzedNode)
analyzer.visit(Rc::new(node.clone())) analyzer.visit(Rc::new(node.clone()))
} }
fn collect_globals(&mut self, node: &TypedNode) { fn collect_globals(&mut self, node: &TypedNode) {
match &node.kind { match &node.kind {
BoundKind::Define { BoundKind::Define {
addr: Address::Global(global_index), addr: Address::Global(global_index),
value, value,
.. ..
} => { } => {
if let BoundKind::Lambda { .. } = &value.kind { if let BoundKind::Lambda { .. } = &value.kind {
self.globals_to_lambdas self.globals_to_lambdas
.insert(*global_index, value.identity.clone()); .insert(*global_index, value.identity.clone());
} }
self.collect_globals(value); self.collect_globals(value);
} }
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
for e in exprs { for e in exprs {
self.collect_globals(e); self.collect_globals(e);
} }
} }
_ => { _ => {
node.kind node.kind
.for_each_child(|child| self.collect_globals(child)); .for_each_child(|child| self.collect_globals(child));
} }
} }
} }
fn visit(&mut self, node_rc: Rc<TypedNode>) -> AnalyzedNode { fn visit(&mut self, node_rc: Rc<TypedNode>) -> AnalyzedNode {
let node = &*node_rc; let node = &*node_rc;
let mut is_recursive = false; let mut is_recursive = false;
let (new_kind, purity) = match &node.kind { let (new_kind, purity) = match &node.kind {
BoundKind::Constant(v) => (BoundKind::Constant(v.clone()), Purity::Pure), BoundKind::Constant(v) => (BoundKind::Constant(v.clone()), Purity::Pure),
BoundKind::Nop => (BoundKind::Nop, Purity::Pure), BoundKind::Nop => (BoundKind::Nop, Purity::Pure),
BoundKind::Get { addr, name } => { BoundKind::Get { addr, name } => {
let p = match addr { let p = match addr {
Address::Global(idx) => { Address::Global(idx) => {
self.root_purity.get(idx.0 as usize).cloned().unwrap_or(Purity::Pure) self.root_purity.get(idx.0 as usize).cloned().unwrap_or(Purity::Pure)
} }
_ => Purity::Pure, _ => Purity::Pure,
}; };
( (
BoundKind::Get { BoundKind::Get {
addr: *addr, addr: *addr,
name: name.clone(), name: name.clone(),
}, },
p, p,
) )
} }
BoundKind::FieldAccessor(k) => (BoundKind::FieldAccessor(*k), Purity::Pure), BoundKind::FieldAccessor(k) => (BoundKind::FieldAccessor(*k), Purity::Pure),
BoundKind::GetField { rec, field } => { BoundKind::GetField { rec, field } => {
let rec_m = self.visit(rec.clone()); let rec_m = self.visit(rec.clone());
let p = rec_m.ty.purity; let p = rec_m.ty.purity;
( (
BoundKind::GetField { BoundKind::GetField {
rec: Rc::new(rec_m), rec: Rc::new(rec_m),
field: *field, field: *field,
}, },
p, p,
) )
} }
BoundKind::Set { addr, value } => { BoundKind::Set { addr, value } => {
let val_m = self.visit(value.clone()); let val_m = self.visit(value.clone());
( (
BoundKind::Set { BoundKind::Set {
addr: *addr, addr: *addr,
value: Rc::new(val_m), value: Rc::new(val_m),
}, },
Purity::Impure, Purity::Impure,
) )
} }
BoundKind::Define { BoundKind::Define {
name, name,
addr, addr,
kind, kind,
value, value,
captured_by, captured_by,
} => { } => {
let val_m = self.visit(value.clone()); let val_m = self.visit(value.clone());
( (
BoundKind::Define { BoundKind::Define {
name: name.clone(), name: name.clone(),
addr: *addr, addr: *addr,
kind: *kind, kind: *kind,
value: Rc::new(val_m), value: Rc::new(val_m),
captured_by: captured_by.clone(), captured_by: captured_by.clone(),
}, },
Purity::Impure, Purity::Impure,
) )
} }
BoundKind::If { BoundKind::If {
cond, cond,
then_br, then_br,
else_br, else_br,
} => { } => {
let cond_m = self.visit(cond.clone()); let cond_m = self.visit(cond.clone());
let then_m = self.visit(then_br.clone()); let then_m = self.visit(then_br.clone());
let else_m = else_br.as_ref().map(|e| self.visit(e.clone())); let else_m = else_br.as_ref().map(|e| self.visit(e.clone()));
let mut p = cond_m.ty.purity.min(then_m.ty.purity); let mut p = cond_m.ty.purity.min(then_m.ty.purity);
if let Some(ref em) = else_m { if let Some(ref em) = else_m {
p = p.min(em.ty.purity); p = p.min(em.ty.purity);
} }
( (
BoundKind::If { BoundKind::If {
cond: Rc::new(cond_m), cond: Rc::new(cond_m),
then_br: Rc::new(then_m), then_br: Rc::new(then_m),
else_br: else_m.map(Rc::new), else_br: else_m.map(Rc::new),
}, },
p, p,
) )
} }
BoundKind::Lambda { BoundKind::Lambda {
params, params,
upvalues, upvalues,
body, body,
positional_count, positional_count,
} => { } => {
self.lambda_stack.push(node.identity.clone()); self.lambda_stack.push(node.identity.clone());
let params_m = self.visit(params.clone()); let params_m = self.visit(params.clone());
let body_m = self.visit(body.clone()); let body_m = self.visit(body.clone());
self.lambda_stack.pop(); self.lambda_stack.pop();
is_recursive = self.recursive_identities.contains(&node.identity); is_recursive = self.recursive_identities.contains(&node.identity);
( (
BoundKind::Lambda { BoundKind::Lambda {
params: Rc::new(params_m), params: Rc::new(params_m),
upvalues: upvalues.clone(), upvalues: upvalues.clone(),
body: Rc::new(body_m), body: Rc::new(body_m),
positional_count: *positional_count, positional_count: *positional_count,
}, },
Purity::Pure, Purity::Pure,
) )
} }
BoundKind::Destructure { pattern, value } => { BoundKind::Destructure { pattern, value } => {
let pat_m = self.visit(pattern.clone()); let pat_m = self.visit(pattern.clone());
let val_m = self.visit(value.clone()); let val_m = self.visit(value.clone());
( (
BoundKind::Destructure { BoundKind::Destructure {
pattern: Rc::new(pat_m), pattern: Rc::new(pat_m),
value: Rc::new(val_m), value: Rc::new(val_m),
}, },
Purity::Impure, Purity::Impure,
) )
} }
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
let callee_m = self.visit(callee.clone()); let callee_m = self.visit(callee.clone());
let args_m = self.visit(args.clone()); let args_m = self.visit(args.clone());
if let BoundKind::Get { if let BoundKind::Get {
addr: Address::Global(idx), addr: Address::Global(idx),
.. ..
} = &callee.kind } = &callee.kind
&& let Some(lambda_id) = self.globals_to_lambdas.get(idx) && let Some(lambda_id) = self.globals_to_lambdas.get(idx)
&& self.lambda_stack.contains(lambda_id) && self.lambda_stack.contains(lambda_id)
{ {
self.recursive_identities.insert(lambda_id.clone()); self.recursive_identities.insert(lambda_id.clone());
is_recursive = true; is_recursive = true;
} }
let p_func = if let BoundKind::Get { let p_func = if let BoundKind::Get {
addr: Address::Global(idx), addr: Address::Global(idx),
.. ..
} = &callee.kind } = &callee.kind
{ {
self.root_purity self.root_purity
.get(idx.0 as usize) .get(idx.0 as usize)
.cloned() .cloned()
.unwrap_or(Purity::Impure) .unwrap_or(Purity::Impure)
} else { } else {
Purity::Impure Purity::Impure
}; };
let p = callee_m.ty.purity.min(args_m.ty.purity).min(p_func); let p = callee_m.ty.purity.min(args_m.ty.purity).min(p_func);
( (
BoundKind::Call { BoundKind::Call {
callee: Rc::new(callee_m), callee: Rc::new(callee_m),
args: Rc::new(args_m), args: Rc::new(args_m),
}, },
p, p,
) )
} }
BoundKind::Again { args } => { BoundKind::Again { args } => {
let args_m = self.visit(args.clone()); let args_m = self.visit(args.clone());
if let Some(lambda_id) = self.lambda_stack.last() { if let Some(lambda_id) = self.lambda_stack.last() {
self.recursive_identities.insert(lambda_id.clone()); self.recursive_identities.insert(lambda_id.clone());
is_recursive = true; is_recursive = true;
} }
( (
BoundKind::Again { BoundKind::Again {
args: Rc::new(args_m), args: Rc::new(args_m),
}, },
Purity::Impure, Purity::Impure,
) )
} }
BoundKind::Pipe { BoundKind::Pipe {
inputs, inputs,
lambda, lambda,
out_type, out_type,
} => { } => {
let mut analyzed_inputs = Vec::with_capacity(inputs.len()); let mut analyzed_inputs = Vec::with_capacity(inputs.len());
for input in inputs { for input in inputs {
analyzed_inputs.push(Rc::new(self.visit(input.clone()))); analyzed_inputs.push(Rc::new(self.visit(input.clone())));
} }
let a_lambda = Rc::new(self.visit(lambda.clone())); let a_lambda = Rc::new(self.visit(lambda.clone()));
( (
BoundKind::Pipe { BoundKind::Pipe {
inputs: analyzed_inputs, inputs: analyzed_inputs,
lambda: a_lambda, lambda: a_lambda,
out_type: out_type.clone(), out_type: out_type.clone(),
}, },
Purity::Impure, Purity::Impure,
) )
} }
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
let mut new_exprs = Vec::with_capacity(exprs.len()); let mut new_exprs = Vec::with_capacity(exprs.len());
let mut p = Purity::Pure; let mut p = Purity::Pure;
for e in exprs { for e in exprs {
let em = self.visit(e.clone()); let em = self.visit(e.clone());
p = p.min(em.ty.purity); p = p.min(em.ty.purity);
new_exprs.push(Rc::new(em)); new_exprs.push(Rc::new(em));
} }
(BoundKind::Block { exprs: new_exprs }, p) (BoundKind::Block { exprs: new_exprs }, p)
} }
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
let mut new_elements = Vec::with_capacity(elements.len()); let mut new_elements = Vec::with_capacity(elements.len());
let mut p = Purity::Pure; let mut p = Purity::Pure;
for e in elements { for e in elements {
let em = self.visit(e.clone()); let em = self.visit(e.clone());
p = p.min(em.ty.purity); p = p.min(em.ty.purity);
new_elements.push(Rc::new(em)); new_elements.push(Rc::new(em));
} }
( (
BoundKind::Tuple { BoundKind::Tuple {
elements: new_elements, elements: new_elements,
}, },
p, p,
) )
} }
BoundKind::Record { layout, values } => { BoundKind::Record { layout, values } => {
let mut new_values = Vec::with_capacity(values.len()); let mut new_values = Vec::with_capacity(values.len());
let mut p = Purity::Pure; let mut p = Purity::Pure;
for v in values { for v in values {
let vm = self.visit(v.clone()); let vm = self.visit(v.clone());
p = p.min(vm.ty.purity); p = p.min(vm.ty.purity);
new_values.push(Rc::new(vm)); new_values.push(Rc::new(vm));
} }
( (
BoundKind::Record { BoundKind::Record {
layout: layout.clone(), layout: layout.clone(),
values: new_values, values: new_values,
}, },
p, p,
) )
} }
BoundKind::Expansion { BoundKind::Expansion {
original_call, original_call,
bound_expanded, bound_expanded,
} => { } => {
let expanded_m = self.visit(bound_expanded.clone()); let expanded_m = self.visit(bound_expanded.clone());
( (
BoundKind::Expansion { BoundKind::Expansion {
original_call: original_call.clone(), original_call: original_call.clone(),
bound_expanded: Rc::new(expanded_m.clone()), bound_expanded: Rc::new(expanded_m.clone()),
}, },
expanded_m.ty.purity, expanded_m.ty.purity,
) )
} }
BoundKind::Extension(_) => (BoundKind::Nop, Purity::Impure), BoundKind::Extension(_) => (BoundKind::Nop, Purity::Impure),
BoundKind::Error => (BoundKind::Error, Purity::Impure), BoundKind::Error => (BoundKind::Error, Purity::Impure),
}; };
crate::ast::nodes::Node { crate::ast::compiler::bound_nodes::Node {
identity: node.identity.clone(), identity: node.identity.clone(),
kind: new_kind, kind: new_kind,
ty: NodeMetrics { ty: NodeMetrics {
original: node_rc, original: node_rc,
purity, purity,
is_recursive, is_recursive,
}, },
} }
} }
} }
trait NodeExt { trait NodeExt {
fn for_each_child<F: FnMut(&TypedNode)>(&self, f: F); fn for_each_child<F: FnMut(&TypedNode)>(&self, f: F);
} }
impl NodeExt for BoundKind<crate::ast::types::StaticType> { impl NodeExt for BoundKind<crate::ast::types::StaticType> {
fn for_each_child<F: FnMut(&TypedNode)>(&self, mut f: F) { fn for_each_child<F: FnMut(&TypedNode)>(&self, mut f: F) {
match self { match self {
BoundKind::If { BoundKind::If {
cond, cond,
then_br, then_br,
else_br, else_br,
} => { } => {
f(cond); f(cond);
f(then_br); f(then_br);
if let Some(e) = else_br { if let Some(e) = else_br {
f(e); f(e);
} }
} }
BoundKind::Define { value, .. } | BoundKind::Set { value, .. } => { BoundKind::Define { value, .. } | BoundKind::Set { value, .. } => {
f(value); f(value);
} }
BoundKind::GetField { rec, .. } => { BoundKind::GetField { rec, .. } => {
f(rec); f(rec);
} }
BoundKind::Lambda { params, body, .. } => { BoundKind::Lambda { params, body, .. } => {
f(params); f(params);
f(body); f(body);
} }
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
f(callee); f(callee);
f(args); f(args);
} }
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
for e in exprs { for e in exprs {
f(e); f(e);
} }
} }
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
for e in elements { for e in elements {
f(e); f(e);
} }
} }
BoundKind::Record { values, .. } => { BoundKind::Record { values, .. } => {
for v in values { for v in values {
f(v); f(v);
} }
} }
BoundKind::Expansion { bound_expanded, .. } => { BoundKind::Expansion { bound_expanded, .. } => {
f(bound_expanded); f(bound_expanded);
} }
_ => {} _ => {}
} }
} }
} }
+22 -22
View File
@@ -1,8 +1,8 @@
use crate::ast::compiler::bound_nodes::{ use crate::ast::compiler::bound_nodes::{
Address, BoundKind, BoundNode, DeclarationKind, GlobalIdx, LocalSlot, UpvalueIdx, Address, BoundKind, DeclarationKind, GlobalIdx, LocalSlot, Node, UpvalueIdx,
}; };
use crate::ast::diagnostics::Diagnostics; use crate::ast::diagnostics::Diagnostics;
use crate::ast::nodes::{Node, Symbol, UntypedKind}; use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
use crate::ast::types::{Identity, StaticType, Purity}; use crate::ast::types::{Identity, StaticType, Purity};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@@ -114,7 +114,7 @@ pub enum ExprContext {
} }
pub type BindingResult = ( pub type BindingResult = (
BoundNode, Node,
HashMap<Identity, Vec<Identity>>, HashMap<Identity, Vec<Identity>>,
Vec<CompilerScope>, Vec<CompilerScope>,
u32, u32,
@@ -152,7 +152,7 @@ impl Binder {
initial_scopes: Vec<CompilerScope>, initial_scopes: Vec<CompilerScope>,
initial_slot_count: u32, initial_slot_count: u32,
fixed_scope_idx: i32, fixed_scope_idx: i32,
node: &Node<UntypedKind>, node: &UntypedNode,
diagnostics: &mut Diagnostics, diagnostics: &mut Diagnostics,
) -> Result<BindingResult, String> { ) -> Result<BindingResult, String> {
let mut binder = Self::new(initial_scopes, initial_slot_count, fixed_scope_idx); let mut binder = Self::new(initial_scopes, initial_slot_count, fixed_scope_idx);
@@ -208,10 +208,10 @@ impl Binder {
pub fn bind( pub fn bind(
&mut self, &mut self,
node: &Node<UntypedKind>, node: &UntypedNode,
ctx: ExprContext, ctx: ExprContext,
diag: &mut Diagnostics, diag: &mut Diagnostics,
) -> BoundNode { ) -> Node {
match &node.kind { match &node.kind {
UntypedKind::Nop => self.make_node(node.identity.clone(), BoundKind::Nop), UntypedKind::Nop => self.make_node(node.identity.clone(), BoundKind::Nop),
UntypedKind::Constant(v) => { UntypedKind::Constant(v) => {
@@ -241,10 +241,10 @@ impl Binder {
then_br, then_br,
else_br, else_br,
} => { } => {
let cond = self.bind(cond, ExprContext::Expression, diag); let cond = self.bind(cond.as_ref(), ExprContext::Expression, diag);
self.functions.last_mut().unwrap().push_scope(); self.functions.last_mut().unwrap().push_scope();
let then_br = self.bind(then_br, ctx, diag); let then_br = self.bind(then_br.as_ref(), ctx, diag);
self.functions.last_mut().unwrap().pop_scope(); self.functions.last_mut().unwrap().pop_scope();
let mut else_br_bound = None; let mut else_br_bound = None;
@@ -296,7 +296,7 @@ impl Binder {
} }
} else { } else {
let val_node = self.bind(value, ExprContext::Expression, diag); let val_node = self.bind(value, ExprContext::Expression, diag);
let target_node = self.bind_pattern(target, DeclarationKind::Variable, diag); let target_node = self.bind_pattern(target.as_ref(), DeclarationKind::Variable, diag);
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
@@ -324,7 +324,7 @@ impl Binder {
self.make_node(node.identity.clone(), BoundKind::Error) self.make_node(node.identity.clone(), BoundKind::Error)
} }
} else { } else {
let target_node = self.bind_assign_pattern(target, diag); let target_node = self.bind_assign_pattern(target.as_ref(), diag);
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Destructure { BoundKind::Destructure {
@@ -357,11 +357,11 @@ impl Binder {
self.functions self.functions
.push(FunctionCompiler::new(identity.clone(), vec![], 0)); .push(FunctionCompiler::new(identity.clone(), vec![], 0));
let params_bound = self.bind_pattern(params, DeclarationKind::Parameter, diag); let params_bound = self.bind_pattern(params.as_ref(), DeclarationKind::Parameter, diag);
let body_bound = self.bind(body, ExprContext::Expression, diag); let body_bound = self.bind(body.as_ref(), ExprContext::Expression, diag);
let compiled_fn = self.functions.pop().unwrap(); let compiled_fn = self.functions.pop().unwrap();
fn count_params(node: &BoundNode) -> Option<u32> { fn count_params(node: &Node) -> Option<u32> {
match &node.kind { match &node.kind {
BoundKind::Define { BoundKind::Define {
kind: DeclarationKind::Parameter, kind: DeclarationKind::Parameter,
@@ -394,7 +394,7 @@ impl Binder {
UntypedKind::Call { callee, args } => { UntypedKind::Call { callee, args } => {
let callee = self.bind(callee, ExprContext::Expression, diag); let callee = self.bind(callee, ExprContext::Expression, diag);
let args = self.bind(args, ExprContext::Expression, diag); let args = self.bind(args.as_ref(), ExprContext::Expression, diag);
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
@@ -413,7 +413,7 @@ impl Binder {
); );
return self.make_node(node.identity.clone(), BoundKind::Error); return self.make_node(node.identity.clone(), BoundKind::Error);
} }
let args = self.bind(args, ExprContext::Expression, diag); let args = self.bind(args.as_ref(), ExprContext::Expression, diag);
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Again { BoundKind::Again {
@@ -489,7 +489,7 @@ impl Binder {
} }
UntypedKind::Expansion { call, expanded } => { UntypedKind::Expansion { call, expanded } => {
let bound_expanded = self.bind(expanded, ctx, diag); let bound_expanded = self.bind(expanded.as_ref(), ctx, diag);
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Expansion { BoundKind::Expansion {
@@ -520,7 +520,7 @@ impl Binder {
); );
self.make_node(node.identity.clone(), BoundKind::Error) self.make_node(node.identity.clone(), BoundKind::Error)
} }
UntypedKind::Error => crate::ast::compiler::bound_nodes::BoundNode { UntypedKind::Error => crate::ast::compiler::bound_nodes::Node {
identity: node.identity.clone(), identity: node.identity.clone(),
kind: crate::ast::compiler::bound_nodes::BoundKind::Error, kind: crate::ast::compiler::bound_nodes::BoundKind::Error,
ty: (), ty: (),
@@ -600,10 +600,10 @@ impl Binder {
fn bind_pattern( fn bind_pattern(
&mut self, &mut self,
node: &Node<UntypedKind>, node: &UntypedNode,
kind: DeclarationKind, kind: DeclarationKind,
diag: &mut Diagnostics, diag: &mut Diagnostics,
) -> BoundNode { ) -> Node {
match &node.kind { match &node.kind {
UntypedKind::Identifier(sym) => { UntypedKind::Identifier(sym) => {
if let Some(addr) = self.declare_variable(sym, node.identity.clone(), kind, diag) { if let Some(addr) = self.declare_variable(sym, node.identity.clone(), kind, diag) {
@@ -645,9 +645,9 @@ impl Binder {
fn bind_assign_pattern( fn bind_assign_pattern(
&mut self, &mut self,
node: &Node<UntypedKind>, node: &UntypedNode,
diag: &mut Diagnostics, diag: &mut Diagnostics,
) -> BoundNode { ) -> Node {
match &node.kind { match &node.kind {
UntypedKind::Identifier(sym) => { UntypedKind::Identifier(sym) => {
if let Some(addr) = self.resolve_variable(sym, diag, &node.identity) { if let Some(addr) = self.resolve_variable(sym, diag, &node.identity) {
@@ -684,7 +684,7 @@ impl Binder {
} }
} }
fn make_node(&self, identity: Identity, kind: BoundKind<()>) -> BoundNode { fn make_node(&self, identity: Identity, kind: BoundKind<()>) -> Node {
Node { Node {
identity, identity,
kind, kind,
+31 -26
View File
@@ -1,4 +1,4 @@
use crate::ast::nodes::{Node, Symbol}; use crate::ast::nodes::Symbol;
use crate::ast::types::{Identity, StaticType, Value}; use crate::ast::types::{Identity, StaticType, Value};
use std::rc::Rc; use std::rc::Rc;
@@ -55,13 +55,18 @@ impl<T> Clone for Box<dyn BoundExtension<T>> {
} }
/// A bound AST node, decorated with type or metric information T. /// A bound AST node, decorated with type or metric information T.
pub type BoundNode<T = ()> = Node<BoundKind<T>, T>; #[derive(Debug, Clone, PartialEq)]
pub struct Node<T = ()> {
pub identity: Identity,
pub kind: BoundKind<T>,
pub ty: T,
}
/// Type alias for a node that has been fully type-checked. /// Type alias for a node that has been fully type-checked.
pub type TypedNode = BoundNode<StaticType>; pub type TypedNode = Node<StaticType>;
/// Type alias for the global function registry. /// Type alias for the global function registry.
pub type GlobalFunctionRegistry = std::collections::HashMap<GlobalIdx, Rc<BoundNode>>; pub type GlobalFunctionRegistry = std::collections::HashMap<GlobalIdx, Rc<Node>>;
/// Metrics collected during the analysis phase. /// Metrics collected during the analysis phase.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@@ -72,7 +77,7 @@ pub struct NodeMetrics {
} }
/// Type alias for a node that has been analyzed. /// Type alias for a node that has been analyzed.
pub type AnalyzedNode = BoundNode<NodeMetrics>; pub type AnalyzedNode = Node<NodeMetrics>;
/// Type alias for the global analyzed function registry. /// Type alias for the global analyzed function registry.
pub type GlobalAnalyzedRegistry = std::collections::HashMap<GlobalIdx, Rc<AnalyzedNode>>; pub type GlobalAnalyzedRegistry = std::collections::HashMap<GlobalIdx, Rc<AnalyzedNode>>;
@@ -91,7 +96,7 @@ pub enum BoundKind<T = ()> {
// Variable Update (Assignment) // Variable Update (Assignment)
Set { Set {
addr: Address, addr: Address,
value: Rc<BoundNode<T>>, value: Rc<Node<T>>,
}, },
// Variable Declaration (Unified for Local/Global/Parameter) // Variable Declaration (Unified for Local/Global/Parameter)
@@ -99,7 +104,7 @@ pub enum BoundKind<T = ()> {
name: Symbol, name: Symbol,
addr: Address, addr: Address,
kind: DeclarationKind, kind: DeclarationKind,
value: Rc<BoundNode<T>>, value: Rc<Node<T>>,
captured_by: Vec<Identity>, captured_by: Vec<Identity>,
}, },
@@ -108,64 +113,64 @@ pub enum BoundKind<T = ()> {
/// Specialized field access (O(1) via RecordLayout) /// Specialized field access (O(1) via RecordLayout)
GetField { GetField {
rec: Rc<BoundNode<T>>, rec: Rc<Node<T>>,
field: crate::ast::types::Keyword, field: crate::ast::types::Keyword,
}, },
If { If {
cond: Rc<BoundNode<T>>, cond: Rc<Node<T>>,
then_br: Rc<BoundNode<T>>, then_br: Rc<Node<T>>,
else_br: Option<Rc<BoundNode<T>>>, else_br: Option<Rc<Node<T>>>,
}, },
/// A destructuring operation (can be a definition or an assignment depending on the pattern) /// A destructuring operation (can be a definition or an assignment depending on the pattern)
Destructure { Destructure {
pattern: Rc<BoundNode<T>>, pattern: Rc<Node<T>>,
value: Rc<BoundNode<T>>, value: Rc<Node<T>>,
}, },
Lambda { Lambda {
params: Rc<BoundNode<T>>, params: Rc<Node<T>>,
// The list of variables captured from enclosing scopes // The list of variables captured from enclosing scopes
upvalues: Vec<Address>, upvalues: Vec<Address>,
body: Rc<BoundNode<T>>, body: Rc<Node<T>>,
/// Static optimization: number of positional parameters if the pattern is flat. /// Static optimization: number of positional parameters if the pattern is flat.
positional_count: Option<u32>, positional_count: Option<u32>,
}, },
Call { Call {
callee: Rc<BoundNode<T>>, callee: Rc<Node<T>>,
args: Rc<BoundNode<T>>, args: Rc<Node<T>>,
}, },
Again { Again {
args: Rc<BoundNode<T>>, args: Rc<Node<T>>,
}, },
Pipe { Pipe {
inputs: Vec<Rc<BoundNode<T>>>, inputs: Vec<Rc<Node<T>>>,
lambda: Rc<BoundNode<T>>, lambda: Rc<Node<T>>,
out_type: crate::ast::types::StaticType, out_type: crate::ast::types::StaticType,
}, },
Block { Block {
exprs: Vec<Rc<BoundNode<T>>>, exprs: Vec<Rc<Node<T>>>,
}, },
Tuple { Tuple {
elements: Vec<Rc<BoundNode<T>>>, elements: Vec<Rc<Node<T>>>,
}, },
Record { Record {
layout: std::sync::Arc<crate::ast::types::RecordLayout>, layout: std::sync::Arc<crate::ast::types::RecordLayout>,
values: Vec<Rc<BoundNode<T>>>, values: Vec<Rc<Node<T>>>,
}, },
/// An expanded macro call, preserving the original call for debugging and UI. /// An expanded macro call, preserving the original call for debugging and UI.
Expansion { Expansion {
/// The original call from the untyped AST. /// The original call from the untyped AST.
original_call: Rc<Node<crate::ast::nodes::UntypedKind>>, original_call: Rc<crate::ast::nodes::UntypedNode>,
/// The result of binding the expanded AST. /// The result of binding the expanded AST.
bound_expanded: Rc<BoundNode<T>>, bound_expanded: Rc<Node<T>>,
}, },
/// A diagnostic poison node, allowing compilation to continue after an error. /// A diagnostic poison node, allowing compilation to continue after an error.
@@ -302,7 +307,7 @@ where
} }
/// A single field in a Record literal (Key-Value pair) /// A single field in a Record literal (Key-Value pair)
pub type RecordField<T> = (BoundNode<T>, BoundNode<T>); pub type RecordField<T> = (Node<T>, Node<T>);
impl<T> BoundKind<T> { impl<T> BoundKind<T> {
pub fn display_name(&self) -> String { pub fn display_name(&self) -> String {
+3 -3
View File
@@ -1,15 +1,15 @@
use crate::ast::compiler::bound_nodes::{BoundKind, BoundNode}; use crate::ast::compiler::bound_nodes::{BoundKind, Node};
use crate::ast::types::Identity; use crate::ast::types::Identity;
use std::collections::HashMap; use std::collections::HashMap;
pub struct CapturePass; pub struct CapturePass;
impl CapturePass { impl CapturePass {
pub fn apply(node: BoundNode, capture_map: &HashMap<Identity, Vec<Identity>>) -> BoundNode { pub fn apply<T: Clone>(node: Node<T>, capture_map: &HashMap<Identity, Vec<Identity>>) -> Node<T> {
Self::transform(node, capture_map) Self::transform(node, capture_map)
} }
fn transform(mut node: BoundNode, capture_map: &HashMap<Identity, Vec<Identity>>) -> BoundNode { fn transform<T: Clone>(mut node: Node<T>, capture_map: &HashMap<Identity, Vec<Identity>>) -> Node<T> {
use std::rc::Rc; use std::rc::Rc;
match node.kind { match node.kind {
BoundKind::Define { BoundKind::Define {
+4 -5
View File
@@ -1,5 +1,4 @@
use crate::ast::compiler::bound_nodes::BoundKind; use crate::ast::compiler::bound_nodes::{BoundKind, Node};
use crate::ast::nodes::Node;
use crate::ast::types::Value; use crate::ast::types::Value;
use crate::ast::vm::Closure; use crate::ast::vm::Closure;
use std::fmt::Debug; use std::fmt::Debug;
@@ -12,7 +11,7 @@ pub struct Dumper {
impl Dumper { impl Dumper {
/// Produces a formatted string representation of the given bound AST node and its children. /// Produces a formatted string representation of the given bound AST node and its children.
pub fn dump<T: Debug>(node: &Node<BoundKind<T>, T>) -> String { pub fn dump<T: Debug>(node: &Node<T>) -> String {
let mut dumper = Self { let mut dumper = Self {
output: String::new(), output: String::new(),
indent: 0, indent: 0,
@@ -27,14 +26,14 @@ impl Dumper {
} }
} }
fn log<T: Debug>(&mut self, label: &str, node: &Node<BoundKind<T>, T>) { fn log<T: Debug>(&mut self, label: &str, node: &Node<T>) {
self.write_indent(); self.write_indent();
self.output.push_str(label); self.output.push_str(label);
self.output self.output
.push_str(&format!(" <Metadata: {:?}>\n", node.ty)); .push_str(&format!(" <Metadata: {:?}>\n", node.ty));
} }
fn visit<T: Debug>(&mut self, node: &Node<BoundKind<T>, T>) { fn visit<T: Debug>(&mut self, node: &Node<T>) {
match &node.kind { match &node.kind {
BoundKind::Nop => self.log("Nop", node), BoundKind::Nop => self.log("Nop", node),
BoundKind::Constant(v) => { BoundKind::Constant(v) => {
+4 -4
View File
@@ -1,21 +1,21 @@
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode, GlobalIdx}; use crate::ast::compiler::bound_nodes::{Address, BoundKind, GlobalIdx, Node};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
/// A pass that collects all global function definitions (lambdas) into a registry. /// A pass that collects all global function definitions (lambdas) into a registry.
/// This allows the Specializer to retrieve the original AST of a function for monomorphization. /// This allows the Specializer to retrieve the original AST of a function for monomorphization.
pub struct LambdaCollector<'a, T> { pub struct LambdaCollector<'a, T> {
registry: &'a mut HashMap<GlobalIdx, Rc<BoundNode<T>>>, registry: &'a mut HashMap<GlobalIdx, Rc<Node<T>>>,
} }
impl<'a, T: Clone> LambdaCollector<'a, T> { impl<'a, T: Clone> LambdaCollector<'a, T> {
/// Performs a full traversal of the AST and populates the provided registry. /// Performs a full traversal of the AST and populates the provided registry.
pub fn collect(node: &BoundNode<T>, registry: &'a mut HashMap<GlobalIdx, Rc<BoundNode<T>>>) { pub fn collect(node: &Node<T>, registry: &'a mut HashMap<GlobalIdx, Rc<Node<T>>>) {
let mut collector = Self { registry }; let mut collector = Self { registry };
collector.visit(node); collector.visit(node);
} }
fn visit(&mut self, node: &BoundNode<T>) { fn visit(&mut self, node: &Node<T>) {
match &node.kind { match &node.kind {
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
for expr in exprs { for expr in exprs {
+4 -5
View File
@@ -1,5 +1,4 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind}; use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, Node};
use crate::ast::nodes::Node;
use crate::ast::types::StaticType; use crate::ast::types::StaticType;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;
@@ -24,12 +23,12 @@ impl Debug for RuntimeMetadata {
} }
/// The ExecNode is the AST used by the VM. It carries TCO flags and links to metrics. /// The ExecNode is the AST used by the VM. It carries TCO flags and links to metrics.
pub type ExecNode = Node<BoundKind<RuntimeMetadata>, RuntimeMetadata>; pub type ExecNode = Node<RuntimeMetadata>;
fn calc_stack_size<T>(root_node: &Node<BoundKind<T>, T>) -> u32 { fn calc_stack_size<T>(root_node: &Node<T>) -> u32 {
let mut max_slot = -1i32; let mut max_slot = -1i32;
fn visit<T>(node: &Node<BoundKind<T>, T>, max_slot: &mut i32) { fn visit<T>(node: &Node<T>, max_slot: &mut i32) {
match &node.kind { match &node.kind {
BoundKind::Get { BoundKind::Get {
addr: Address::Local(slot), addr: Address::Local(slot),
+81 -81
View File
@@ -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 crate::ast::types::{Identity, Value};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@@ -7,19 +7,19 @@ use std::rc::Rc;
pub trait MacroEvaluator { pub trait MacroEvaluator {
fn evaluate( fn evaluate(
&self, &self,
node: &Node<UntypedKind>, node: &UntypedNode,
bindings: &HashMap<Rc<str>, Node<UntypedKind>>, bindings: &HashMap<Rc<str>, UntypedNode>,
) -> Result<Value, String>; ) -> Result<Value, String>;
} }
/// Internal state for template expansion (Hygiene context + Parameter binding) /// Internal state for template expansion (Hygiene context + Parameter binding)
struct ExpansionState<'a> { 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. /// The identity of the current expansion instance, used to "color" internal symbols.
expansion_id: Identity, 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. /// A registry for macro declarations.
#[derive(Clone)] #[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() { if let Some(current_rc) = self.scopes.last_mut() {
// Copy-on-Write: If the Rc is shared, clone the map before modifying. // Copy-on-Write: If the Rc is shared, clone the map before modifying.
let current = Rc::make_mut(current_rc); 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() { for scope in self.scopes.iter().rev() {
if let Some(m) = scope.get(name) { if let Some(m) = scope.get(name) {
return Some(m.clone()); return Some(m.clone());
@@ -85,19 +85,19 @@ impl<E: MacroEvaluator> MacroExpander<E> {
self.registry 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) 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 { match node.kind {
UntypedKind::MacroDecl { name, params, body } => { UntypedKind::MacroDecl { name, params, body } => {
let p_names = self.extract_param_names(&params)?; let p_names = self.extract_param_names(&params)?;
self.registry.define(name.name, p_names, *body); self.registry.define(name.name, p_names, *body);
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Nop, kind: UntypedKind::Nop,
ty: (),
}) })
} }
@@ -127,13 +127,13 @@ impl<E: MacroEvaluator> MacroExpander<E> {
let expanded_callee = self.expand_recursive(*callee)?; let expanded_callee = self.expand_recursive(*callee)?;
let expanded_args = self.expand_recursive(*args)?; let expanded_args = self.expand_recursive(*args)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Call { kind: UntypedKind::Call {
callee: Box::new(expanded_callee), callee: Box::new(expanded_callee),
args: Box::new(expanded_args), args: Box::new(expanded_args),
}, },
ty: (),
}) })
} }
@@ -145,12 +145,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
} }
self.registry.pop(); self.registry.pop();
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Block { kind: UntypedKind::Block {
exprs: expanded_exprs, exprs: expanded_exprs,
}, },
ty: (),
}) })
} }
@@ -160,29 +160,29 @@ impl<E: MacroEvaluator> MacroExpander<E> {
expanded_inputs.push(self.expand_recursive(input)?); expanded_inputs.push(self.expand_recursive(input)?);
} }
let expanded_lambda = Box::new(self.expand_recursive(*lambda)?); let expanded_lambda = Box::new(self.expand_recursive(*lambda)?);
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Pipe { kind: UntypedKind::Pipe {
inputs: expanded_inputs, inputs: expanded_inputs,
lambda: expanded_lambda, lambda: expanded_lambda,
}, },
ty: (),
}) })
} }
UntypedKind::Lambda { params, body } => { UntypedKind::Lambda { params, body } => {
self.registry.push(); self.registry.push();
let expanded_params = self.expand_recursive(*params)?; 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(); self.registry.pop();
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Lambda { kind: UntypedKind::Lambda {
params: Box::new(expanded_params), params: Box::new(expanded_params),
body: Rc::new(expanded_body), body: Rc::new(expanded_body),
}, },
ty: (),
}) })
} }
@@ -198,40 +198,40 @@ impl<E: MacroEvaluator> MacroExpander<E> {
} else { } else {
None None
}; };
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::If { kind: UntypedKind::If {
cond: Box::new(cond), cond: Box::new(cond),
then_br: Box::new(then_br), then_br: Box::new(then_br),
else_br, else_br,
}, },
ty: (),
}) })
} }
UntypedKind::Def { target, value } => { UntypedKind::Def { target, value } => {
let target = self.expand_recursive(*target)?; let target = self.expand_recursive(*target)?;
let value = self.expand_recursive(*value)?; let value = self.expand_recursive(*value)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Def { kind: UntypedKind::Def {
target: Box::new(target), target: Box::new(target),
value: Box::new(value), value: Box::new(value),
}, },
ty: (),
}) })
} }
UntypedKind::Assign { target, value } => { UntypedKind::Assign { target, value } => {
let target = self.expand_recursive(*target)?; let target = self.expand_recursive(*target)?;
let value = self.expand_recursive(*value)?; let value = self.expand_recursive(*value)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Assign { kind: UntypedKind::Assign {
target: Box::new(target), target: Box::new(target),
value: Box::new(value), value: Box::new(value),
}, },
ty: (),
}) })
} }
@@ -240,12 +240,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
for e in elements { for e in elements {
expanded_elements.push(self.expand_recursive(e)?); expanded_elements.push(self.expand_recursive(e)?);
} }
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Tuple { kind: UntypedKind::Tuple {
elements: expanded_elements, elements: expanded_elements,
}, },
ty: (),
}) })
} }
@@ -254,35 +254,35 @@ impl<E: MacroEvaluator> MacroExpander<E> {
for (k, v) in fields { for (k, v) in fields {
expanded_fields.push((self.expand_recursive(k)?, self.expand_recursive(v)?)); expanded_fields.push((self.expand_recursive(k)?, self.expand_recursive(v)?));
} }
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Record { kind: UntypedKind::Record {
fields: expanded_fields, fields: expanded_fields,
}, },
ty: (),
}) })
} }
UntypedKind::Expansion { call, expanded } => { UntypedKind::Expansion { call, expanded } => {
let expanded = self.expand_recursive(*expanded)?; let expanded = self.expand_recursive(*expanded)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Expansion { kind: UntypedKind::Expansion {
call, call,
expanded: Box::new(expanded), expanded: Box::new(expanded),
}, },
ty: (),
}) })
} }
UntypedKind::Again { args } => { UntypedKind::Again { args } => {
let expanded_args = self.expand_recursive(*args)?; let expanded_args = self.expand_recursive(*args)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Again { kind: UntypedKind::Again {
args: Box::new(expanded_args), args: Box::new(expanded_args),
}, },
ty: (),
}) })
} }
@@ -295,9 +295,9 @@ impl<E: MacroEvaluator> MacroExpander<E> {
identity: Identity, identity: Identity,
name: &str, name: &str,
params: Vec<Rc<str>>, params: Vec<Rc<str>>,
args: Vec<Node<UntypedKind>>, args: Vec<UntypedNode>,
body: Node<UntypedKind>, body: UntypedNode,
) -> Result<Node<UntypedKind>, String> { ) -> Result<UntypedNode, String> {
if params.len() != args.len() { if params.len() != args.len() {
return Err(format!( return Err(format!(
"Macro {} expects {} arguments, but got {}", "Macro {} expects {} arguments, but got {}",
@@ -324,36 +324,36 @@ impl<E: MacroEvaluator> MacroExpander<E> {
body body
}; };
let original_call = Node { let original_call = UntypedNode {
identity: identity.clone(), identity: identity.clone(),
kind: UntypedKind::Call { kind: UntypedKind::Call {
callee: Box::new(Node { callee: Box::new(UntypedNode {
identity: identity.clone(), identity: identity.clone(),
kind: UntypedKind::Identifier(Symbol::from(name)), kind: UntypedKind::Identifier(Symbol::from(name)),
ty: (),
}), }),
args: Box::new(Node { args: Box::new(UntypedNode {
identity: identity.clone(), identity: identity.clone(),
kind: UntypedKind::Tuple { kind: UntypedKind::Tuple {
elements: bindings.into_values().collect(), elements: bindings.into_values().collect(),
}, },
ty: (),
}), }),
}, },
ty: (),
}; };
Ok(Node { Ok(UntypedNode {
identity, identity,
kind: UntypedKind::Expansion { kind: UntypedKind::Expansion {
call: Box::new(original_call), call: Box::new(original_call),
expanded: Box::new(expanded_body), 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 { match &node.kind {
UntypedKind::Identifier(sym) => Ok(vec![sym.name.clone()]), UntypedKind::Identifier(sym) => Ok(vec![sym.name.clone()]),
UntypedKind::Tuple { elements } => { UntypedKind::Tuple { elements } => {
@@ -369,17 +369,17 @@ impl<E: MacroEvaluator> MacroExpander<E> {
fn expand_template( fn expand_template(
&self, &self,
node: Node<UntypedKind>, node: UntypedNode,
state: &mut ExpansionState, state: &mut ExpansionState,
) -> Result<Node<UntypedKind>, String> { ) -> Result<UntypedNode, String> {
match node.kind { match node.kind {
UntypedKind::Identifier(mut sym) => { UntypedKind::Identifier(mut sym) => {
// Inside a template, all internal identifiers are colored. // Inside a template, all internal identifiers are colored.
sym.context = Some(state.expansion_id.clone()); sym.context = Some(state.expansion_id.clone());
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Identifier(sym), kind: UntypedKind::Identifier(sym),
ty: (),
}) })
} }
@@ -408,26 +408,26 @@ impl<E: MacroEvaluator> MacroExpander<E> {
UntypedKind::Def { target, value } => { UntypedKind::Def { target, value } => {
let target = self.expand_template(*target, state)?; let target = self.expand_template(*target, state)?;
let val = self.expand_template(*value, state)?; let val = self.expand_template(*value, state)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Def { kind: UntypedKind::Def {
target: Box::new(target), target: Box::new(target),
value: Box::new(val), value: Box::new(val),
}, },
ty: (),
}) })
} }
UntypedKind::Assign { target, value } => { UntypedKind::Assign { target, value } => {
let target = self.expand_template(*target, state)?; let target = self.expand_template(*target, state)?;
let value = self.expand_template(*value, state)?; let value = self.expand_template(*value, state)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Assign { kind: UntypedKind::Assign {
target: Box::new(target), target: Box::new(target),
value: Box::new(value), value: Box::new(value),
}, },
ty: (),
}) })
} }
@@ -441,12 +441,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
new_elements.push(self.expand_template(e, state)?); new_elements.push(self.expand_template(e, state)?);
} }
} }
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Tuple { kind: UntypedKind::Tuple {
elements: new_elements, elements: new_elements,
}, },
ty: (),
}) })
} }
@@ -460,10 +460,10 @@ impl<E: MacroEvaluator> MacroExpander<E> {
new_exprs.push(self.expand_template(e, state)?); new_exprs.push(self.expand_template(e, state)?);
} }
} }
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Block { exprs: new_exprs }, kind: UntypedKind::Block { exprs: new_exprs },
ty: (),
}) })
} }
@@ -475,23 +475,23 @@ impl<E: MacroEvaluator> MacroExpander<E> {
self.expand_template(v, state)?, self.expand_template(v, state)?,
)); ));
} }
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Record { fields: new_fields }, kind: UntypedKind::Record { fields: new_fields },
ty: (),
}) })
} }
UntypedKind::Call { callee, args } => { UntypedKind::Call { callee, args } => {
let expanded_callee = self.expand_template(*callee, state)?; let expanded_callee = self.expand_template(*callee, state)?;
let expanded_args = self.expand_template(*args, state)?; let expanded_args = self.expand_template(*args, state)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Call { kind: UntypedKind::Call {
callee: Box::new(expanded_callee), callee: Box::new(expanded_callee),
args: Box::new(expanded_args), args: Box::new(expanded_args),
}, },
ty: (),
}) })
} }
@@ -507,14 +507,14 @@ impl<E: MacroEvaluator> MacroExpander<E> {
} else { } else {
None None
}; };
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::If { kind: UntypedKind::If {
cond: Box::new(cond), cond: Box::new(cond),
then_br: Box::new(then_br), then_br: Box::new(then_br),
else_br, else_br,
}, },
ty: (),
}) })
} }
@@ -524,37 +524,37 @@ impl<E: MacroEvaluator> MacroExpander<E> {
expanded_inputs.push(self.expand_template(input, state)?); expanded_inputs.push(self.expand_template(input, state)?);
} }
let expanded_lambda = Box::new(self.expand_template(*lambda, state)?); let expanded_lambda = Box::new(self.expand_template(*lambda, state)?);
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Pipe { kind: UntypedKind::Pipe {
inputs: expanded_inputs, inputs: expanded_inputs,
lambda: expanded_lambda, lambda: expanded_lambda,
}, },
ty: (),
}) })
} }
UntypedKind::Lambda { params, body } => { UntypedKind::Lambda { params, body } => {
let expanded_params = self.expand_template(*params, state)?; let expanded_params = self.expand_template(*params, state)?;
let body = self.expand_template(Node::clone(&body), state)?; let body = self.expand_template((*body).clone(), state)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Lambda { kind: UntypedKind::Lambda {
params: Box::new(expanded_params), params: Box::new(expanded_params),
body: Rc::new(body), body: Rc::new(body),
}, },
ty: (),
}) })
} }
UntypedKind::Again { args } => { UntypedKind::Again { args } => {
let expanded_args = self.expand_template(*args, state)?; let expanded_args = self.expand_template(*args, state)?;
Ok(Node { Ok(UntypedNode {
identity: node.identity, identity: node.identity,
kind: UntypedKind::Again { kind: UntypedKind::Again {
args: Box::new(expanded_args), args: Box::new(expanded_args),
}, },
ty: (),
}) })
} }
@@ -566,11 +566,11 @@ impl<E: MacroEvaluator> MacroExpander<E> {
&self, &self,
val: Value, val: Value,
_identity: Identity, _identity: Identity,
target: &mut Vec<Node<UntypedKind>>, target: &mut Vec<UntypedNode>,
) -> Result<(), String> { ) -> Result<(), String> {
match val { match val {
Value::Object(obj) => { 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 { match &node.kind {
UntypedKind::Tuple { elements } => { UntypedKind::Tuple { elements } => {
for e in 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 { match val {
Value::Object(obj) => { 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(); return node.clone();
} }
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Constant(Value::Object(obj)), kind: UntypedKind::Constant(Value::Object(obj)),
ty: (),
} }
} }
_ => Node { _ => UntypedNode {
identity, identity,
kind: UntypedKind::Constant(val), kind: UntypedKind::Constant(val),
ty: (),
}, },
} }
} }
@@ -632,8 +632,8 @@ mod tests {
impl MacroEvaluator for SimpleEvaluator { impl MacroEvaluator for SimpleEvaluator {
fn evaluate( fn evaluate(
&self, &self,
node: &Node<UntypedKind>, node: &UntypedNode,
bindings: &HashMap<Rc<str>, Node<UntypedKind>>, bindings: &HashMap<Rc<str>, UntypedNode>,
) -> Result<Value, String> { ) -> Result<Value, String> {
if let UntypedKind::Identifier(ref sym) = node.kind if let UntypedKind::Identifier(ref sym) = node.kind
&& let Some(arg) = bindings.get(&sym.name) && let Some(arg) = bindings.get(&sym.name)
+1 -2
View File
@@ -1,7 +1,6 @@
use crate::ast::compiler::bound_nodes::{ use crate::ast::compiler::bound_nodes::{
Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, UpvalueIdx, Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, Node, UpvalueIdx,
}; };
use crate::ast::nodes::Node;
use crate::ast::types::{Purity, Value}; use crate::ast::types::{Purity, Value};
use crate::ast::vm::Closure; use crate::ast::vm::Closure;
use std::cell::RefCell; use std::cell::RefCell;
+1 -2
View File
@@ -1,5 +1,4 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, NodeMetrics}; use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, Node, NodeMetrics};
use crate::ast::nodes::Node;
use crate::ast::types::{Purity, RecordLayout, StaticType, Value}; use crate::ast::types::{Purity, RecordLayout, StaticType, Value};
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
@@ -1,5 +1,4 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot, UpvalueIdx}; use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot, Node, UpvalueIdx};
use crate::ast::nodes::Node;
use crate::ast::types::Value; use crate::ast::types::Value;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::rc::Rc; use std::rc::Rc;
+3 -4
View File
@@ -1,5 +1,4 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, BoundNode, NodeMetrics}; use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, Node, NodeMetrics};
use crate::ast::nodes::Node;
use crate::ast::types::{Purity, Signature, StaticType, Value}; use crate::ast::types::{Purity, Signature, StaticType, Value};
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
@@ -11,11 +10,11 @@ pub struct MonoCacheKey {
pub arg_types: Vec<StaticType>, pub arg_types: Vec<StaticType>,
} }
pub type CompileFunc = Rc<dyn Fn(Rc<BoundNode>, &[StaticType]) -> Result<(Value, StaticType), String>>; pub type CompileFunc = Rc<dyn Fn(Rc<Node>, &[StaticType]) -> Result<(Value, StaticType), String>>;
pub type RtlLookupFunc = Rc<dyn Fn(&str, &[StaticType]) -> Option<(Value, StaticType)>>; pub type RtlLookupFunc = Rc<dyn Fn(&str, &[StaticType]) -> Option<(Value, StaticType)>>;
pub trait FunctionRegistry { pub trait FunctionRegistry {
fn resolve(&self, addr: Address) -> Option<Rc<BoundNode>>; fn resolve(&self, addr: Address) -> Option<Rc<Node>>;
fn resolve_analyzed(&self, _addr: Address) -> Option<Rc<AnalyzedNode>> { fn resolve_analyzed(&self, _addr: Address) -> Option<Rc<AnalyzedNode>> {
None None
} }
+4 -5
View File
@@ -1,6 +1,5 @@
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode, TypedNode}; use crate::ast::compiler::bound_nodes::{Address, BoundKind, Node, TypedNode};
use crate::ast::diagnostics::Diagnostics; use crate::ast::diagnostics::Diagnostics;
use crate::ast::nodes::Node;
use crate::ast::types::StaticType; use crate::ast::types::StaticType;
use std::rc::Rc; use std::rc::Rc;
@@ -83,7 +82,7 @@ impl TypeChecker {
pub fn check( pub fn check(
&self, &self,
node: &BoundNode, node: &Node,
arg_types: &[StaticType], arg_types: &[StaticType],
diag: &mut Diagnostics, diag: &mut Diagnostics,
) -> TypedNode { ) -> TypedNode {
@@ -151,7 +150,7 @@ impl TypeChecker {
fn check_params( fn check_params(
&self, &self,
node: &BoundNode, node: &Node,
specialized_ty: &StaticType, specialized_ty: &StaticType,
ctx: &mut TypeContext, ctx: &mut TypeContext,
diag: &mut Diagnostics, diag: &mut Diagnostics,
@@ -272,7 +271,7 @@ impl TypeChecker {
fn check_node( fn check_node(
&self, &self,
node: &BoundNode, node: &Node,
ctx: &mut TypeContext, ctx: &mut TypeContext,
diag: &mut Diagnostics, diag: &mut Diagnostics,
) -> TypedNode { ) -> TypedNode {
+855 -854
View File
File diff suppressed because it is too large Load Diff
+35 -30
View File
@@ -30,15 +30,14 @@ impl From<&str> for Symbol {
} }
} }
/// A generic AST Node wrapper to preserve identity and metadata /// A parser AST Node wrapper to preserve identity and metadata
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Node<K, T = ()> { pub struct UntypedNode {
pub identity: Identity, pub identity: Identity,
pub kind: K, pub kind: UntypedKind,
pub ty: T,
} }
impl Object for Node<UntypedKind> { impl Object for UntypedNode {
fn type_name(&self) -> &'static str { fn type_name(&self) -> &'static str {
"ast-node" "ast-node"
} }
@@ -59,7 +58,7 @@ impl Clone for Box<dyn CustomNode> {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
pub enum UntypedKind { pub enum UntypedKind {
Nop, Nop,
Constant(Value), Constant(Value),
@@ -68,62 +67,68 @@ pub enum UntypedKind {
/// A first-class field accessor (e.g. .name) /// A first-class field accessor (e.g. .name)
FieldAccessor(crate::ast::types::Keyword), FieldAccessor(crate::ast::types::Keyword),
If { If {
cond: Box<Node<UntypedKind>>, cond: Box<UntypedNode>,
then_br: Box<Node<UntypedKind>>, then_br: Box<UntypedNode>,
else_br: Option<Box<Node<UntypedKind>>>, else_br: Option<Box<UntypedNode>>,
}, },
Def { Def {
target: Box<Node<UntypedKind>>, target: Box<UntypedNode>,
value: Box<Node<UntypedKind>>, value: Box<UntypedNode>,
}, },
Assign { Assign {
target: Box<Node<UntypedKind>>, target: Box<UntypedNode>,
value: Box<Node<UntypedKind>>, value: Box<UntypedNode>,
}, },
Lambda { Lambda {
params: Box<Node<UntypedKind>>, params: Box<UntypedNode>,
body: Rc<Node<UntypedKind>>, body: Rc<UntypedNode>,
}, },
Call { Call {
callee: Box<Node<UntypedKind>>, callee: Box<UntypedNode>,
args: Box<Node<UntypedKind>>, args: Box<UntypedNode>,
}, },
Again { Again {
args: Box<Node<UntypedKind>>, args: Box<UntypedNode>,
}, },
Pipe { Pipe {
inputs: Vec<Node<UntypedKind>>, inputs: Vec<UntypedNode>,
lambda: Box<Node<UntypedKind>>, lambda: Box<UntypedNode>,
}, },
Block { Block {
exprs: Vec<Node<UntypedKind>>, exprs: Vec<UntypedNode>,
}, },
Tuple { Tuple {
elements: Vec<Node<UntypedKind>>, elements: Vec<UntypedNode>,
}, },
Record { Record {
fields: Vec<(Node<UntypedKind>, Node<UntypedKind>)>, fields: Vec<(UntypedNode, UntypedNode)>,
}, },
/// A macro declaration that can be expanded at compile time. /// A macro declaration that can be expanded at compile time.
MacroDecl { MacroDecl {
name: Symbol, name: Symbol,
params: Box<Node<UntypedKind>>, params: Box<UntypedNode>,
body: Box<Node<UntypedKind>>, body: Box<UntypedNode>,
}, },
/// A template for AST nodes, allowing for substitutions. (Quasiquote) /// A template for AST nodes, allowing for substitutions. (Quasiquote)
Template(Box<Node<UntypedKind>>), Template(Box<UntypedNode>),
/// A placeholder inside a template to be replaced by a node or value. (Unquote) /// A placeholder inside a template to be replaced by a node or value. (Unquote)
Placeholder(Box<Node<UntypedKind>>), Placeholder(Box<UntypedNode>),
/// A placeholder that flattens a sequence or merges a record into its surroundings. (Splice) /// A placeholder that flattens a sequence or merges a record into its surroundings. (Splice)
Splice(Box<Node<UntypedKind>>), Splice(Box<UntypedNode>),
/// Represents an expanded macro call, preserving the original call for debugging. /// Represents an expanded macro call, preserving the original call for debugging.
Expansion { Expansion {
/// The original call from the source AST. /// The original call from the source AST.
call: Box<Node<UntypedKind>>, call: Box<UntypedNode>,
/// The resulting AST after macro expansion. /// The resulting AST after macro expansion.
expanded: Box<Node<UntypedKind>>, expanded: Box<UntypedNode>,
}, },
/// A diagnostic poison node, allowing compilation to continue after an error. /// A diagnostic poison node, allowing compilation to continue after an error.
Error, Error,
Extension(Box<dyn CustomNode>), Extension(Box<dyn CustomNode>),
} }
impl PartialEq for Box<dyn CustomNode> {
fn eq(&self, _other: &Self) -> bool {
false
}
}
+71 -72
View File
@@ -1,6 +1,6 @@
use crate::ast::diagnostics::Diagnostics; use crate::ast::diagnostics::Diagnostics;
use crate::ast::lexer::{Lexer, Token, TokenKind}; 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 crate::ast::types::{Identity, Keyword, NodeIdentity, Value};
use std::rc::Rc; use std::rc::Rc;
@@ -50,7 +50,7 @@ impl<'a> Parser<'a> {
&self.current_token.kind &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 token_loc = self.current_token.location;
let identity = NodeIdentity::new(token_loc); let identity = NodeIdentity::new(token_loc);
@@ -61,28 +61,28 @@ impl<'a> Parser<'a> {
TokenKind::Quote => { TokenKind::Quote => {
self.advance(); // consume ' self.advance(); // consume '
let expr = self.parse_expression(); let expr = self.parse_expression();
Node { UntypedNode {
identity: identity.clone(), identity: identity.clone(),
kind: UntypedKind::Call { kind: UntypedKind::Call {
callee: Box::new(self.make_id_node("quote", identity.clone())), callee: Box::new(self.make_id_node("quote", identity.clone())),
args: Box::new(Node { args: Box::new(UntypedNode {
identity, identity,
kind: UntypedKind::Tuple { kind: UntypedKind::Tuple {
elements: vec![expr], elements: vec![expr],
}, },
ty: (),
}), }),
}, },
ty: (),
} }
} }
TokenKind::Backtick => { TokenKind::Backtick => {
self.advance(); // consume ` self.advance(); // consume `
let expr = self.parse_expression(); let expr = self.parse_expression();
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Template(Box::new(expr)), kind: UntypedKind::Template(Box::new(expr)),
ty: (),
} }
} }
TokenKind::Tilde => { TokenKind::Tilde => {
@@ -90,17 +90,17 @@ impl<'a> Parser<'a> {
if *self.peek() == TokenKind::At { if *self.peek() == TokenKind::At {
self.advance(); // consume @ self.advance(); // consume @
let expr = self.parse_expression(); let expr = self.parse_expression();
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Splice(Box::new(expr)), kind: UntypedKind::Splice(Box::new(expr)),
ty: (),
} }
} else { } else {
let expr = self.parse_expression(); let expr = self.parse_expression();
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Placeholder(Box::new(expr)), 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 token = self.advance();
let identity = NodeIdentity::new(token.location); let identity = NodeIdentity::new(token.location);
@@ -152,14 +152,13 @@ impl<'a> Parser<'a> {
} }
}; };
Node { UntypedNode {
identity, identity,
kind, kind,
ty: (),
} }
} }
fn parse_list(&mut self) -> Node<UntypedKind> { fn parse_list(&mut self) -> UntypedNode {
let start_loc = self.advance().location; // consume '(' let start_loc = self.advance().location; // consume '('
let identity = NodeIdentity::new(start_loc); let identity = NodeIdentity::new(start_loc);
@@ -169,10 +168,10 @@ impl<'a> Parser<'a> {
Some(identity.clone()), Some(identity.clone()),
); );
self.advance(); // consume ) self.advance(); // consume )
return Node { return UntypedNode {
identity, identity,
kind: UntypedKind::Error, kind: UntypedKind::Error,
ty: (),
}; };
} }
@@ -198,29 +197,29 @@ impl<'a> Parser<'a> {
node node
} }
fn parse_again(&mut self, identity: Identity) -> Node<UntypedKind> { fn parse_again(&mut self, identity: Identity) -> UntypedNode {
let mut elements = Vec::new(); let mut elements = Vec::new();
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF { while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
elements.push(self.parse_expression()); elements.push(self.parse_expression());
} }
let args_node = Node { let args_node = UntypedNode {
identity: identity.clone(), identity: identity.clone(),
kind: UntypedKind::Tuple { elements }, kind: UntypedKind::Tuple { elements },
ty: (),
}; };
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Again { kind: UntypedKind::Again {
args: Box::new(args_node), 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 cond = Box::new(self.parse_expression());
let then_br = Box::new(self.parse_expression()); let then_br = Box::new(self.parse_expression());
let mut else_br = None; let mut else_br = None;
@@ -229,53 +228,53 @@ impl<'a> Parser<'a> {
else_br = Some(Box::new(self.parse_expression())); else_br = Some(Box::new(self.parse_expression()));
} }
Node { UntypedNode {
identity, identity,
kind: UntypedKind::If { kind: UntypedKind::If {
cond, cond,
then_br, then_br,
else_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 target = Box::new(self.parse_pattern());
let value = Box::new(self.parse_expression()); let value = Box::new(self.parse_expression());
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Def { target, value }, 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) // (assign target value)
let target = Box::new(self.parse_expression()); let target = Box::new(self.parse_expression());
let value = Box::new(self.parse_expression()); let value = Box::new(self.parse_expression());
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Assign { target, value }, 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(); let mut exprs = Vec::new();
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF { while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
exprs.push(self.parse_expression()); exprs.push(self.parse_expression());
} }
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Block { exprs }, 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_node = self.parse_expression();
let inputs = match inputs_node.kind { let inputs = match inputs_node.kind {
UntypedKind::Tuple { elements } => elements, UntypedKind::Tuple { elements } => elements,
@@ -283,28 +282,28 @@ impl<'a> Parser<'a> {
}; };
let lambda = Box::new(self.parse_expression()); let lambda = Box::new(self.parse_expression());
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Pipe { inputs, lambda }, 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 params = Box::new(self.parse_param_vector());
let body = self.parse_expression(); let body = self.parse_expression();
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Lambda { kind: UntypedKind::Lambda {
params, params,
body: Rc::new(body), 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_node = self.parse_expression();
let name = match name_node.kind { let name = match name_node.kind {
UntypedKind::Identifier(sym) => sym, UntypedKind::Identifier(sym) => sym,
@@ -318,18 +317,18 @@ impl<'a> Parser<'a> {
}; };
let params = Box::new(self.parse_param_vector()); let params = Box::new(self.parse_param_vector());
let body = self.parse_expression(); let body = self.parse_expression();
Node { UntypedNode {
identity, identity,
kind: UntypedKind::MacroDecl { kind: UntypedKind::MacroDecl {
name, name,
params, params,
body: Box::new(body), 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 { if *self.peek() != TokenKind::LeftBracket {
self.diagnostics.push_error( self.diagnostics.push_error(
format!( format!(
@@ -338,16 +337,16 @@ impl<'a> Parser<'a> {
), ),
Some(NodeIdentity::new(self.current_token.location)), Some(NodeIdentity::new(self.current_token.location)),
); );
return Node { return UntypedNode {
identity: NodeIdentity::new(self.current_token.location), identity: NodeIdentity::new(self.current_token.location),
kind: UntypedKind::Error, kind: UntypedKind::Error,
ty: (),
}; };
} }
self.parse_pattern() self.parse_pattern()
} }
fn parse_pattern(&mut self) -> Node<UntypedKind> { fn parse_pattern(&mut self) -> UntypedNode {
let next = self.peek(); let next = self.peek();
match next { match next {
TokenKind::Identifier(_) => { TokenKind::Identifier(_) => {
@@ -356,10 +355,10 @@ impl<'a> Parser<'a> {
TokenKind::Identifier(s) => s.into(), TokenKind::Identifier(s) => s.into(),
_ => unreachable!(), _ => unreachable!(),
}; };
Node { UntypedNode {
identity: NodeIdentity::new(token.location), identity: NodeIdentity::new(token.location),
kind: UntypedKind::Identifier(sym), kind: UntypedKind::Identifier(sym),
ty: (),
} }
} }
TokenKind::LeftBracket => { TokenKind::LeftBracket => {
@@ -372,10 +371,10 @@ impl<'a> Parser<'a> {
} }
self.expect(TokenKind::RightBracket); self.expect(TokenKind::RightBracket);
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Tuple { elements }, kind: UntypedKind::Tuple { elements },
ty: (),
} }
} }
TokenKind::Tilde => { TokenKind::Tilde => {
@@ -383,17 +382,17 @@ impl<'a> Parser<'a> {
if *self.peek() == TokenKind::At { if *self.peek() == TokenKind::At {
self.advance(); // consume @ self.advance(); // consume @
let expr = self.parse_expression(); let expr = self.parse_expression();
Node { UntypedNode {
identity: NodeIdentity::new(token.location), identity: NodeIdentity::new(token.location),
kind: UntypedKind::Splice(Box::new(expr)), kind: UntypedKind::Splice(Box::new(expr)),
ty: (),
} }
} else { } else {
let expr = self.parse_expression(); let expr = self.parse_expression();
Node { UntypedNode {
identity: NodeIdentity::new(token.location), identity: NodeIdentity::new(token.location),
kind: UntypedKind::Placeholder(Box::new(expr)), kind: UntypedKind::Placeholder(Box::new(expr)),
ty: (),
} }
} }
} }
@@ -406,16 +405,16 @@ impl<'a> Parser<'a> {
Some(NodeIdentity::new(self.current_token.location)), Some(NodeIdentity::new(self.current_token.location)),
); );
self.advance(); self.advance();
Node { UntypedNode {
identity: NodeIdentity::new(self.current_token.location), identity: NodeIdentity::new(self.current_token.location),
kind: UntypedKind::Error, 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(); let mut elements = Vec::new();
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF { 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. // 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(), identity: identity.clone(),
kind: UntypedKind::Tuple { elements }, kind: UntypedKind::Tuple { elements },
ty: (),
}; };
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Call { kind: UntypedKind::Call {
callee: Box::new(callee), callee: Box::new(callee),
args: Box::new(args_node), 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 token = self.advance();
let mut elements = Vec::new(); let mut elements = Vec::new();
@@ -450,14 +449,14 @@ impl<'a> Parser<'a> {
self.expect(TokenKind::RightBracket); self.expect(TokenKind::RightBracket);
Node { UntypedNode {
identity: NodeIdentity::new(token.location), identity: NodeIdentity::new(token.location),
kind: UntypedKind::Tuple { elements }, 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 token = self.advance();
let mut fields = Vec::new(); let mut fields = Vec::new();
@@ -489,10 +488,10 @@ impl<'a> Parser<'a> {
} }
self.expect(TokenKind::RightBrace); self.expect(TokenKind::RightBrace);
Node { UntypedNode {
identity: NodeIdentity::new(token.location), identity: NodeIdentity::new(token.location),
kind: UntypedKind::Record { fields }, kind: UntypedKind::Record { fields },
ty: (),
} }
} }
@@ -513,11 +512,11 @@ impl<'a> Parser<'a> {
} }
} }
fn make_id_node(&self, name: &str, identity: Identity) -> Node<UntypedKind> { fn make_id_node(&self, name: &str, identity: Identity) -> UntypedNode {
Node { UntypedNode {
identity, identity,
kind: UntypedKind::Identifier(Symbol::from(name)), kind: UntypedKind::Identifier(Symbol::from(name)),
ty: (),
} }
} }
} }
+1063 -1063
View File
File diff suppressed because it is too large Load Diff