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
+1 -1
View File
@@ -318,7 +318,7 @@ impl<'a> Analyzer<'a> {
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 {
+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 {
+17 -16
View File
@@ -1,7 +1,7 @@
use crate::ast::compiler::analyzer::Analyzer; use crate::ast::compiler::analyzer::Analyzer;
use crate::ast::compiler::binder::Binder; use crate::ast::compiler::binder::Binder;
use crate::ast::compiler::{TypeChecker, TypedNode}; use crate::ast::compiler::{TypeChecker, TypedNode};
use crate::ast::nodes::{Node, Symbol, UntypedKind}; use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
use crate::ast::parser::Parser; use crate::ast::parser::Parser;
use crate::ast::vm::{TracingObserver, VM}; use crate::ast::vm::{TracingObserver, VM};
use std::cell::RefCell; use std::cell::RefCell;
@@ -10,8 +10,8 @@ use std::path::{Path, PathBuf};
use std::rc::Rc; use std::rc::Rc;
use crate::ast::compiler::bound_nodes::{ use crate::ast::compiler::bound_nodes::{
Address, AnalyzedNode, BoundKind, BoundNode, GlobalAnalyzedRegistry, GlobalFunctionRegistry, Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, GlobalFunctionRegistry, GlobalIdx,
GlobalIdx, Node,
}; };
use crate::ast::compiler::dumper::Dumper; use crate::ast::compiler::dumper::Dumper;
use crate::ast::compiler::lambda_collector::LambdaCollector; use crate::ast::compiler::lambda_collector::LambdaCollector;
@@ -94,7 +94,7 @@ struct EnvFunctionRegistry {
} }
impl FunctionRegistry for EnvFunctionRegistry { impl FunctionRegistry for EnvFunctionRegistry {
fn resolve(&self, addr: Address) -> Option<Rc<BoundNode>> { fn resolve(&self, addr: Address) -> Option<Rc<Node>> {
if let Address::Global(idx) = addr { if let Address::Global(idx) = addr {
self.registry.borrow().get(&idx).cloned() self.registry.borrow().get(&idx).cloned()
} else { } else {
@@ -122,8 +122,8 @@ struct RuntimeMacroEvaluator {
impl MacroEvaluator for RuntimeMacroEvaluator { impl MacroEvaluator for RuntimeMacroEvaluator {
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(sym) = &node.kind if let UntypedKind::Identifier(sym) = &node.kind
&& let Some(arg_node) = bindings.get(&sym.name) && let Some(arg_node) = bindings.get(&sym.name)
@@ -290,7 +290,7 @@ impl Environment {
&self, &self,
source: &str, source: &str,
base_path: &Path, base_path: &Path,
all_files: &mut Vec<(PathBuf, Node<UntypedKind>)>, all_files: &mut Vec<(PathBuf, UntypedNode)>,
) -> Result<(), String> { ) -> Result<(), String> {
let directives = self.extract_use_directives(source); let directives = self.extract_use_directives(source);
@@ -358,7 +358,7 @@ impl Environment {
/// It returns the base path which can be used to resolve further things if necessary. /// It returns the base path which can be used to resolve further things if necessary.
pub fn preload_dependencies(&self, source: &str, file_path: Option<&Path>) -> Result<(), String> { pub fn preload_dependencies(&self, source: &str, file_path: Option<&Path>) -> Result<(), String> {
let base_path = file_path.and_then(|p| p.parent()).unwrap_or_else(|| Path::new(".")); let base_path = file_path.and_then(|p| p.parent()).unwrap_or_else(|| Path::new("."));
let mut files = Vec::new(); let mut files: Vec<(PathBuf, UntypedNode)> = Vec::new();
// 1. Always load the embedded system library first as a virtual module // 1. Always load the embedded system library first as a virtual module
let system_path = PathBuf::from(SYSTEM_LIB_PATH); let system_path = PathBuf::from(SYSTEM_LIB_PATH);
@@ -396,7 +396,7 @@ impl Environment {
Ok(()) Ok(())
} }
fn discover_globals(&self, node: &Node<UntypedKind>) { fn discover_globals(&self, node: &UntypedNode) {
match &node.kind { match &node.kind {
UntypedKind::Def { target, .. } => { UntypedKind::Def { target, .. } => {
if let UntypedKind::Identifier(sym) = &target.kind { if let UntypedKind::Identifier(sym) = &target.kind {
@@ -423,10 +423,11 @@ impl Environment {
UntypedKind::MacroDecl { name, params, body } => { UntypedKind::MacroDecl { name, params, body } => {
let mut registry = self.macro_registry.borrow_mut(); let mut registry = self.macro_registry.borrow_mut();
fn extract_names(node: &Node<UntypedKind>) -> Vec<Rc<str>> { fn extract_names(node: &UntypedNode) -> Vec<Rc<str>> {
match &node.kind { match &node.kind {
UntypedKind::Identifier(sym) => vec![sym.name.clone()], UntypedKind::Identifier(sym) => vec![sym.name.clone()],
UntypedKind::Tuple { elements } => { elements.iter().flat_map(extract_names).collect() UntypedKind::Tuple { elements } => {
elements.iter().flat_map(extract_names).collect()
} }
_ => vec![], _ => vec![],
} }
@@ -444,7 +445,7 @@ impl Environment {
} }
} }
fn compile_pipeline(&self, untyped_ast: Node<UntypedKind>, diagnostics: &mut Diagnostics) -> Option<TypedNode> { fn compile_pipeline(&self, untyped_ast: UntypedNode, diagnostics: &mut Diagnostics) -> Option<TypedNode> {
let expanded_ast = match self.get_expander().expand(untyped_ast) { let expanded_ast = match self.get_expander().expand(untyped_ast) {
Ok(ast) => ast, Ok(ast) => ast,
Err(e) => { Err(e) => {
@@ -486,10 +487,10 @@ impl Environment {
let wrapped_ast = if let crate::ast::compiler::bound_nodes::BoundKind::Lambda { .. } = bound_ast.kind { let wrapped_ast = if let crate::ast::compiler::bound_nodes::BoundKind::Lambda { .. } = bound_ast.kind {
bound_ast bound_ast
} else { } else {
crate::ast::compiler::bound_nodes::BoundNode { crate::ast::compiler::bound_nodes::Node {
identity: bound_ast.identity.clone(), identity: bound_ast.identity.clone(),
kind: crate::ast::compiler::bound_nodes::BoundKind::Lambda { kind: crate::ast::compiler::bound_nodes::BoundKind::Lambda {
params: std::rc::Rc::new(crate::ast::nodes::Node { params: std::rc::Rc::new(crate::ast::compiler::bound_nodes::Node {
identity: bound_ast.identity.clone(), identity: bound_ast.identity.clone(),
kind: crate::ast::compiler::bound_nodes::BoundKind::Tuple { elements: vec![] }, kind: crate::ast::compiler::bound_nodes::BoundKind::Tuple { elements: vec![] },
ty: (), ty: (),
@@ -504,7 +505,7 @@ impl Environment {
Some(checker.check(&wrapped_ast, &[], diagnostics)) Some(checker.check(&wrapped_ast, &[], diagnostics))
} }
fn compile_untyped(&self, untyped_ast: Node<UntypedKind>) -> Result<TypedNode, String> { fn compile_untyped(&self, untyped_ast: UntypedNode) -> Result<TypedNode, String> {
let mut diagnostics = Diagnostics::new(); let mut diagnostics = Diagnostics::new();
let typed_ast_opt = self.compile_pipeline(untyped_ast, &mut diagnostics); let typed_ast_opt = self.compile_pipeline(untyped_ast, &mut diagnostics);
@@ -744,7 +745,7 @@ impl Environment {
let optimization = self.optimization; let optimization = self.optimization;
let compiler = Rc::new( let compiler = Rc::new(
move |func_template: Rc<BoundNode>, move |func_template: Rc<Node>,
arg_types: &[StaticType]| arg_types: &[StaticType]|
-> Result<(Value, StaticType), String> { -> Result<(Value, StaticType), String> {
let mut diag = Diagnostics::new(); let mut diag = Diagnostics::new();
+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: (),
} }
} }
} }
+10 -10
View File
@@ -1,6 +1,6 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind}; use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
use crate::ast::compiler::lowering::ExecNode; use crate::ast::compiler::lowering::ExecNode;
use crate::ast::nodes::Node; use crate::ast::compiler::bound_nodes::Node;
use crate::ast::types::{Object, Value}; use crate::ast::types::{Object, Value};
use std::any::Any; use std::any::Any;
use std::cell::RefCell; use std::cell::RefCell;
@@ -166,7 +166,7 @@ impl VM {
{ {
self.stack.extend(next_args); self.stack.extend(next_args);
} else { } else {
self.unpack(&closure.parameter_node, &next_args, &mut 0)?; self.unpack(closure.parameter_node.as_ref(), &next_args, &mut 0)?;
} }
// PRE-ALLOCATION // PRE-ALLOCATION
@@ -240,7 +240,7 @@ impl VM {
{ {
self.stack.extend_from_slice(args); self.stack.extend_from_slice(args);
} else { } else {
self.unpack(&closure.parameter_node, args, &mut 0)?; self.unpack(closure.parameter_node.as_ref(), args, &mut 0)?;
} }
// Fill remaining stack slots with Void // Fill remaining stack slots with Void
@@ -346,9 +346,9 @@ impl VM {
// Destructuring works on tuples/vectors, or single values wrapped in a slice // Destructuring works on tuples/vectors, or single values wrapped in a slice
if let Some(vals) = val.as_slice() { if let Some(vals) = val.as_slice() {
self.unpack(pattern, vals, &mut offset)?; self.unpack(pattern.as_ref(), vals, &mut offset)?;
} else { } else {
self.unpack(pattern, std::slice::from_ref(&val), &mut offset)?; self.unpack(pattern.as_ref(), std::slice::from_ref(&val), &mut offset)?;
} }
Ok(val) Ok(val)
} }
@@ -686,7 +686,7 @@ impl VM {
let mut res = Ok(()); let mut res = Ok(());
for el in elements { for el in elements {
if let Err(e) = if let Err(e) =
self.unpack(el, &args_for_unpack, &mut offset) self.unpack(el.as_ref(), &args_for_unpack, &mut offset)
{ {
res = Err(e); res = Err(e);
break; break;
@@ -694,7 +694,7 @@ impl VM {
} }
res res
} else { } else {
self.unpack(&closure.parameter_node, &args_for_unpack, &mut 0) self.unpack(closure.parameter_node.as_ref(), &args_for_unpack, &mut 0)
} }
}; };
@@ -1028,7 +1028,7 @@ impl VM {
fn unpack<T>( fn unpack<T>(
&mut self, &mut self,
pattern: &Node<BoundKind<T>, T>, pattern: &Node<T>,
values: &[Value], values: &[Value],
offset: &mut usize, offset: &mut usize,
) -> Result<(), String> { ) -> Result<(), String> {
@@ -1048,12 +1048,12 @@ impl VM {
*offset += 1; *offset += 1;
let mut sub_offset = 0; let mut sub_offset = 0;
for el in elements { for el in elements {
self.unpack(el, sub_values, &mut sub_offset)?; self.unpack(el.as_ref(), sub_values, &mut sub_offset)?;
} }
return Ok(()); return Ok(());
} }
for el in elements { for el in elements {
self.unpack(el, values, offset)?; self.unpack(el.as_ref(), values, offset)?;
} }
Ok(()) Ok(())
} }