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:
@@ -1,3 +1,4 @@
|
||||
/target
|
||||
Delphi
|
||||
*.snap.new
|
||||
repomix-output.xml
|
||||
|
||||
@@ -74,3 +74,7 @@ Options:
|
||||
* Dieses Dokument sollte aktuell gehalten werden.
|
||||
|
||||
@docs/BNF.md
|
||||
|
||||
# Repository
|
||||
|
||||
@repomix-output.xml
|
||||
|
||||
@@ -318,7 +318,7 @@ impl<'a> Analyzer<'a> {
|
||||
BoundKind::Error => (BoundKind::Error, Purity::Impure),
|
||||
};
|
||||
|
||||
crate::ast::nodes::Node {
|
||||
crate::ast::compiler::bound_nodes::Node {
|
||||
identity: node.identity.clone(),
|
||||
kind: new_kind,
|
||||
ty: NodeMetrics {
|
||||
|
||||
+22
-22
@@ -1,8 +1,8 @@
|
||||
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::nodes::{Node, Symbol, UntypedKind};
|
||||
use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
|
||||
use crate::ast::types::{Identity, StaticType, Purity};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@@ -114,7 +114,7 @@ pub enum ExprContext {
|
||||
}
|
||||
|
||||
pub type BindingResult = (
|
||||
BoundNode,
|
||||
Node,
|
||||
HashMap<Identity, Vec<Identity>>,
|
||||
Vec<CompilerScope>,
|
||||
u32,
|
||||
@@ -152,7 +152,7 @@ impl Binder {
|
||||
initial_scopes: Vec<CompilerScope>,
|
||||
initial_slot_count: u32,
|
||||
fixed_scope_idx: i32,
|
||||
node: &Node<UntypedKind>,
|
||||
node: &UntypedNode,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) -> Result<BindingResult, String> {
|
||||
let mut binder = Self::new(initial_scopes, initial_slot_count, fixed_scope_idx);
|
||||
@@ -208,10 +208,10 @@ impl Binder {
|
||||
|
||||
pub fn bind(
|
||||
&mut self,
|
||||
node: &Node<UntypedKind>,
|
||||
node: &UntypedNode,
|
||||
ctx: ExprContext,
|
||||
diag: &mut Diagnostics,
|
||||
) -> BoundNode {
|
||||
) -> Node {
|
||||
match &node.kind {
|
||||
UntypedKind::Nop => self.make_node(node.identity.clone(), BoundKind::Nop),
|
||||
UntypedKind::Constant(v) => {
|
||||
@@ -241,10 +241,10 @@ impl Binder {
|
||||
then_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();
|
||||
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();
|
||||
|
||||
let mut else_br_bound = None;
|
||||
@@ -296,7 +296,7 @@ impl Binder {
|
||||
}
|
||||
} else {
|
||||
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(
|
||||
node.identity.clone(),
|
||||
@@ -324,7 +324,7 @@ impl Binder {
|
||||
self.make_node(node.identity.clone(), BoundKind::Error)
|
||||
}
|
||||
} else {
|
||||
let target_node = self.bind_assign_pattern(target, diag);
|
||||
let target_node = self.bind_assign_pattern(target.as_ref(), diag);
|
||||
self.make_node(
|
||||
node.identity.clone(),
|
||||
BoundKind::Destructure {
|
||||
@@ -357,11 +357,11 @@ impl Binder {
|
||||
self.functions
|
||||
.push(FunctionCompiler::new(identity.clone(), vec![], 0));
|
||||
|
||||
let params_bound = self.bind_pattern(params, DeclarationKind::Parameter, diag);
|
||||
let body_bound = self.bind(body, ExprContext::Expression, diag);
|
||||
let params_bound = self.bind_pattern(params.as_ref(), DeclarationKind::Parameter, diag);
|
||||
let body_bound = self.bind(body.as_ref(), ExprContext::Expression, diag);
|
||||
let compiled_fn = self.functions.pop().unwrap();
|
||||
|
||||
fn count_params(node: &BoundNode) -> Option<u32> {
|
||||
fn count_params(node: &Node) -> Option<u32> {
|
||||
match &node.kind {
|
||||
BoundKind::Define {
|
||||
kind: DeclarationKind::Parameter,
|
||||
@@ -394,7 +394,7 @@ impl Binder {
|
||||
|
||||
UntypedKind::Call { callee, args } => {
|
||||
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(
|
||||
node.identity.clone(),
|
||||
@@ -413,7 +413,7 @@ impl Binder {
|
||||
);
|
||||
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(
|
||||
node.identity.clone(),
|
||||
BoundKind::Again {
|
||||
@@ -489,7 +489,7 @@ impl Binder {
|
||||
}
|
||||
|
||||
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(
|
||||
node.identity.clone(),
|
||||
BoundKind::Expansion {
|
||||
@@ -520,7 +520,7 @@ impl Binder {
|
||||
);
|
||||
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(),
|
||||
kind: crate::ast::compiler::bound_nodes::BoundKind::Error,
|
||||
ty: (),
|
||||
@@ -600,10 +600,10 @@ impl Binder {
|
||||
|
||||
fn bind_pattern(
|
||||
&mut self,
|
||||
node: &Node<UntypedKind>,
|
||||
node: &UntypedNode,
|
||||
kind: DeclarationKind,
|
||||
diag: &mut Diagnostics,
|
||||
) -> BoundNode {
|
||||
) -> Node {
|
||||
match &node.kind {
|
||||
UntypedKind::Identifier(sym) => {
|
||||
if let Some(addr) = self.declare_variable(sym, node.identity.clone(), kind, diag) {
|
||||
@@ -645,9 +645,9 @@ impl Binder {
|
||||
|
||||
fn bind_assign_pattern(
|
||||
&mut self,
|
||||
node: &Node<UntypedKind>,
|
||||
node: &UntypedNode,
|
||||
diag: &mut Diagnostics,
|
||||
) -> BoundNode {
|
||||
) -> Node {
|
||||
match &node.kind {
|
||||
UntypedKind::Identifier(sym) => {
|
||||
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 {
|
||||
identity,
|
||||
kind,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::ast::nodes::{Node, Symbol};
|
||||
use crate::ast::nodes::Symbol;
|
||||
use crate::ast::types::{Identity, StaticType, Value};
|
||||
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.
|
||||
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.
|
||||
pub type TypedNode = BoundNode<StaticType>;
|
||||
pub type TypedNode = Node<StaticType>;
|
||||
|
||||
/// 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.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -72,7 +77,7 @@ pub struct NodeMetrics {
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub type GlobalAnalyzedRegistry = std::collections::HashMap<GlobalIdx, Rc<AnalyzedNode>>;
|
||||
@@ -91,7 +96,7 @@ pub enum BoundKind<T = ()> {
|
||||
// Variable Update (Assignment)
|
||||
Set {
|
||||
addr: Address,
|
||||
value: Rc<BoundNode<T>>,
|
||||
value: Rc<Node<T>>,
|
||||
},
|
||||
|
||||
// Variable Declaration (Unified for Local/Global/Parameter)
|
||||
@@ -99,7 +104,7 @@ pub enum BoundKind<T = ()> {
|
||||
name: Symbol,
|
||||
addr: Address,
|
||||
kind: DeclarationKind,
|
||||
value: Rc<BoundNode<T>>,
|
||||
value: Rc<Node<T>>,
|
||||
captured_by: Vec<Identity>,
|
||||
},
|
||||
|
||||
@@ -108,64 +113,64 @@ pub enum BoundKind<T = ()> {
|
||||
|
||||
/// Specialized field access (O(1) via RecordLayout)
|
||||
GetField {
|
||||
rec: Rc<BoundNode<T>>,
|
||||
rec: Rc<Node<T>>,
|
||||
field: crate::ast::types::Keyword,
|
||||
},
|
||||
|
||||
If {
|
||||
cond: Rc<BoundNode<T>>,
|
||||
then_br: Rc<BoundNode<T>>,
|
||||
else_br: Option<Rc<BoundNode<T>>>,
|
||||
cond: Rc<Node<T>>,
|
||||
then_br: Rc<Node<T>>,
|
||||
else_br: Option<Rc<Node<T>>>,
|
||||
},
|
||||
|
||||
/// A destructuring operation (can be a definition or an assignment depending on the pattern)
|
||||
Destructure {
|
||||
pattern: Rc<BoundNode<T>>,
|
||||
value: Rc<BoundNode<T>>,
|
||||
pattern: Rc<Node<T>>,
|
||||
value: Rc<Node<T>>,
|
||||
},
|
||||
|
||||
Lambda {
|
||||
params: Rc<BoundNode<T>>,
|
||||
params: Rc<Node<T>>,
|
||||
// The list of variables captured from enclosing scopes
|
||||
upvalues: Vec<Address>,
|
||||
body: Rc<BoundNode<T>>,
|
||||
body: Rc<Node<T>>,
|
||||
/// Static optimization: number of positional parameters if the pattern is flat.
|
||||
positional_count: Option<u32>,
|
||||
},
|
||||
|
||||
Call {
|
||||
callee: Rc<BoundNode<T>>,
|
||||
args: Rc<BoundNode<T>>,
|
||||
callee: Rc<Node<T>>,
|
||||
args: Rc<Node<T>>,
|
||||
},
|
||||
|
||||
Again {
|
||||
args: Rc<BoundNode<T>>,
|
||||
args: Rc<Node<T>>,
|
||||
},
|
||||
|
||||
Pipe {
|
||||
inputs: Vec<Rc<BoundNode<T>>>,
|
||||
lambda: Rc<BoundNode<T>>,
|
||||
inputs: Vec<Rc<Node<T>>>,
|
||||
lambda: Rc<Node<T>>,
|
||||
out_type: crate::ast::types::StaticType,
|
||||
},
|
||||
Block {
|
||||
exprs: Vec<Rc<BoundNode<T>>>,
|
||||
exprs: Vec<Rc<Node<T>>>,
|
||||
},
|
||||
|
||||
Tuple {
|
||||
elements: Vec<Rc<BoundNode<T>>>,
|
||||
elements: Vec<Rc<Node<T>>>,
|
||||
},
|
||||
|
||||
Record {
|
||||
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.
|
||||
Expansion {
|
||||
/// 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.
|
||||
bound_expanded: Rc<BoundNode<T>>,
|
||||
bound_expanded: Rc<Node<T>>,
|
||||
},
|
||||
|
||||
/// 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)
|
||||
pub type RecordField<T> = (BoundNode<T>, BoundNode<T>);
|
||||
pub type RecordField<T> = (Node<T>, Node<T>);
|
||||
|
||||
impl<T> BoundKind<T> {
|
||||
pub fn display_name(&self) -> String {
|
||||
|
||||
@@ -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 std::collections::HashMap;
|
||||
|
||||
pub struct 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)
|
||||
}
|
||||
|
||||
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;
|
||||
match node.kind {
|
||||
BoundKind::Define {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::ast::compiler::bound_nodes::BoundKind;
|
||||
use crate::ast::nodes::Node;
|
||||
use crate::ast::compiler::bound_nodes::{BoundKind, Node};
|
||||
use crate::ast::types::Value;
|
||||
use crate::ast::vm::Closure;
|
||||
use std::fmt::Debug;
|
||||
@@ -12,7 +11,7 @@ pub struct Dumper {
|
||||
|
||||
impl Dumper {
|
||||
/// 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 {
|
||||
output: String::new(),
|
||||
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.output.push_str(label);
|
||||
self.output
|
||||
.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 {
|
||||
BoundKind::Nop => self.log("Nop", node),
|
||||
BoundKind::Constant(v) => {
|
||||
|
||||
@@ -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::rc::Rc;
|
||||
|
||||
/// 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.
|
||||
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> {
|
||||
/// 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 };
|
||||
collector.visit(node);
|
||||
}
|
||||
|
||||
fn visit(&mut self, node: &BoundNode<T>) {
|
||||
fn visit(&mut self, node: &Node<T>) {
|
||||
match &node.kind {
|
||||
BoundKind::Block { exprs } => {
|
||||
for expr in exprs {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
||||
use crate::ast::nodes::Node;
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, Node};
|
||||
use crate::ast::types::StaticType;
|
||||
use std::fmt::Debug;
|
||||
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.
|
||||
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;
|
||||
|
||||
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 {
|
||||
BoundKind::Get {
|
||||
addr: Address::Local(slot),
|
||||
|
||||
+81
-81
@@ -1,4 +1,4 @@
|
||||
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
||||
use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
|
||||
use crate::ast::types::{Identity, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@@ -7,19 +7,19 @@ use std::rc::Rc;
|
||||
pub trait MacroEvaluator {
|
||||
fn evaluate(
|
||||
&self,
|
||||
node: &Node<UntypedKind>,
|
||||
bindings: &HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
node: &UntypedNode,
|
||||
bindings: &HashMap<Rc<str>, UntypedNode>,
|
||||
) -> Result<Value, String>;
|
||||
}
|
||||
|
||||
/// Internal state for template expansion (Hygiene context + Parameter binding)
|
||||
struct ExpansionState<'a> {
|
||||
bindings: &'a HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
bindings: &'a HashMap<Rc<str>, UntypedNode>,
|
||||
/// The identity of the current expansion instance, used to "color" internal symbols.
|
||||
expansion_id: Identity,
|
||||
}
|
||||
|
||||
type MacroMap = HashMap<Rc<str>, (Vec<Rc<str>>, Node<UntypedKind>)>;
|
||||
type MacroMap = HashMap<Rc<str>, (Vec<Rc<str>>, UntypedNode)>;
|
||||
|
||||
/// A registry for macro declarations.
|
||||
#[derive(Clone)]
|
||||
@@ -50,7 +50,7 @@ impl MacroRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define(&mut self, name: Rc<str>, params: Vec<Rc<str>>, body: Node<UntypedKind>) {
|
||||
pub fn define(&mut self, name: Rc<str>, params: Vec<Rc<str>>, body: UntypedNode) {
|
||||
if let Some(current_rc) = self.scopes.last_mut() {
|
||||
// Copy-on-Write: If the Rc is shared, clone the map before modifying.
|
||||
let current = Rc::make_mut(current_rc);
|
||||
@@ -58,7 +58,7 @@ impl MacroRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(&self, name: &str) -> Option<(Vec<Rc<str>>, Node<UntypedKind>)> {
|
||||
pub fn lookup(&self, name: &str) -> Option<(Vec<Rc<str>>, UntypedNode)> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
if let Some(m) = scope.get(name) {
|
||||
return Some(m.clone());
|
||||
@@ -85,19 +85,19 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
self.registry
|
||||
}
|
||||
|
||||
pub fn expand(&mut self, node: Node<UntypedKind>) -> Result<Node<UntypedKind>, String> {
|
||||
pub fn expand(&mut self, node: UntypedNode) -> Result<UntypedNode, String> {
|
||||
self.expand_recursive(node)
|
||||
}
|
||||
|
||||
fn expand_recursive(&mut self, node: Node<UntypedKind>) -> Result<Node<UntypedKind>, String> {
|
||||
fn expand_recursive(&mut self, node: UntypedNode) -> Result<UntypedNode, String> {
|
||||
match node.kind {
|
||||
UntypedKind::MacroDecl { name, params, body } => {
|
||||
let p_names = self.extract_param_names(¶ms)?;
|
||||
self.registry.define(name.name, p_names, *body);
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Nop,
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -127,13 +127,13 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
let expanded_callee = self.expand_recursive(*callee)?;
|
||||
let expanded_args = self.expand_recursive(*args)?;
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(expanded_callee),
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -145,12 +145,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
}
|
||||
self.registry.pop();
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Block {
|
||||
exprs: expanded_exprs,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -160,29 +160,29 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
expanded_inputs.push(self.expand_recursive(input)?);
|
||||
}
|
||||
let expanded_lambda = Box::new(self.expand_recursive(*lambda)?);
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Pipe {
|
||||
inputs: expanded_inputs,
|
||||
lambda: expanded_lambda,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Lambda { params, body } => {
|
||||
self.registry.push();
|
||||
let expanded_params = self.expand_recursive(*params)?;
|
||||
let expanded_body = self.expand_recursive(Node::clone(&body))?;
|
||||
let expanded_body = self.expand_recursive((*body).clone())?;
|
||||
self.registry.pop();
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Lambda {
|
||||
params: Box::new(expanded_params),
|
||||
body: Rc::new(expanded_body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -198,40 +198,40 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::If {
|
||||
cond: Box::new(cond),
|
||||
then_br: Box::new(then_br),
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Def { target, value } => {
|
||||
let target = self.expand_recursive(*target)?;
|
||||
let value = self.expand_recursive(*value)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Def {
|
||||
target: Box::new(target),
|
||||
value: Box::new(value),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Assign { target, value } => {
|
||||
let target = self.expand_recursive(*target)?;
|
||||
let value = self.expand_recursive(*value)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Assign {
|
||||
target: Box::new(target),
|
||||
value: Box::new(value),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -240,12 +240,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
for e in elements {
|
||||
expanded_elements.push(self.expand_recursive(e)?);
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: expanded_elements,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -254,35 +254,35 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
for (k, v) in fields {
|
||||
expanded_fields.push((self.expand_recursive(k)?, self.expand_recursive(v)?));
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Record {
|
||||
fields: expanded_fields,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Expansion { call, expanded } => {
|
||||
let expanded = self.expand_recursive(*expanded)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Expansion {
|
||||
call,
|
||||
expanded: Box::new(expanded),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Again { args } => {
|
||||
let expanded_args = self.expand_recursive(*args)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Again {
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -295,9 +295,9 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
identity: Identity,
|
||||
name: &str,
|
||||
params: Vec<Rc<str>>,
|
||||
args: Vec<Node<UntypedKind>>,
|
||||
body: Node<UntypedKind>,
|
||||
) -> Result<Node<UntypedKind>, String> {
|
||||
args: Vec<UntypedNode>,
|
||||
body: UntypedNode,
|
||||
) -> Result<UntypedNode, String> {
|
||||
if params.len() != args.len() {
|
||||
return Err(format!(
|
||||
"Macro {} expects {} arguments, but got {}",
|
||||
@@ -324,36 +324,36 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
body
|
||||
};
|
||||
|
||||
let original_call = Node {
|
||||
let original_call = UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(Node {
|
||||
callee: Box::new(UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Identifier(Symbol::from(name)),
|
||||
ty: (),
|
||||
|
||||
}),
|
||||
args: Box::new(Node {
|
||||
args: Box::new(UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: bindings.into_values().collect(),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
};
|
||||
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Expansion {
|
||||
call: Box::new(original_call),
|
||||
expanded: Box::new(expanded_body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_param_names(&self, node: &Node<UntypedKind>) -> Result<Vec<Rc<str>>, String> {
|
||||
fn extract_param_names(&self, node: &UntypedNode) -> Result<Vec<Rc<str>>, String> {
|
||||
match &node.kind {
|
||||
UntypedKind::Identifier(sym) => Ok(vec![sym.name.clone()]),
|
||||
UntypedKind::Tuple { elements } => {
|
||||
@@ -369,17 +369,17 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
|
||||
fn expand_template(
|
||||
&self,
|
||||
node: Node<UntypedKind>,
|
||||
node: UntypedNode,
|
||||
state: &mut ExpansionState,
|
||||
) -> Result<Node<UntypedKind>, String> {
|
||||
) -> Result<UntypedNode, String> {
|
||||
match node.kind {
|
||||
UntypedKind::Identifier(mut sym) => {
|
||||
// Inside a template, all internal identifiers are colored.
|
||||
sym.context = Some(state.expansion_id.clone());
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Identifier(sym),
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -408,26 +408,26 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
UntypedKind::Def { target, value } => {
|
||||
let target = self.expand_template(*target, state)?;
|
||||
let val = self.expand_template(*value, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Def {
|
||||
target: Box::new(target),
|
||||
value: Box::new(val),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Assign { target, value } => {
|
||||
let target = self.expand_template(*target, state)?;
|
||||
let value = self.expand_template(*value, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Assign {
|
||||
target: Box::new(target),
|
||||
value: Box::new(value),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -441,12 +441,12 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
new_elements.push(self.expand_template(e, state)?);
|
||||
}
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: new_elements,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -460,10 +460,10 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
new_exprs.push(self.expand_template(e, state)?);
|
||||
}
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Block { exprs: new_exprs },
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -475,23 +475,23 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
self.expand_template(v, state)?,
|
||||
));
|
||||
}
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Record { fields: new_fields },
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Call { callee, args } => {
|
||||
let expanded_callee = self.expand_template(*callee, state)?;
|
||||
let expanded_args = self.expand_template(*args, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(expanded_callee),
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -507,14 +507,14 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::If {
|
||||
cond: Box::new(cond),
|
||||
then_br: Box::new(then_br),
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -524,37 +524,37 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
expanded_inputs.push(self.expand_template(input, state)?);
|
||||
}
|
||||
let expanded_lambda = Box::new(self.expand_template(*lambda, state)?);
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Pipe {
|
||||
inputs: expanded_inputs,
|
||||
lambda: expanded_lambda,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Lambda { params, body } => {
|
||||
let expanded_params = self.expand_template(*params, state)?;
|
||||
let body = self.expand_template(Node::clone(&body), state)?;
|
||||
Ok(Node {
|
||||
let body = self.expand_template((*body).clone(), state)?;
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Lambda {
|
||||
params: Box::new(expanded_params),
|
||||
body: Rc::new(body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
UntypedKind::Again { args } => {
|
||||
let expanded_args = self.expand_template(*args, state)?;
|
||||
Ok(Node {
|
||||
Ok(UntypedNode {
|
||||
identity: node.identity,
|
||||
kind: UntypedKind::Again {
|
||||
args: Box::new(expanded_args),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -566,11 +566,11 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
&self,
|
||||
val: Value,
|
||||
_identity: Identity,
|
||||
target: &mut Vec<Node<UntypedKind>>,
|
||||
target: &mut Vec<UntypedNode>,
|
||||
) -> Result<(), String> {
|
||||
match val {
|
||||
Value::Object(obj) => {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<Node<UntypedKind>>() {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<UntypedNode>() {
|
||||
match &node.kind {
|
||||
UntypedKind::Tuple { elements } => {
|
||||
for e in elements {
|
||||
@@ -599,22 +599,22 @@ impl<E: MacroEvaluator> MacroExpander<E> {
|
||||
}
|
||||
}
|
||||
|
||||
fn value_to_node(&self, val: Value, identity: Identity) -> Node<UntypedKind> {
|
||||
fn value_to_node(&self, val: Value, identity: Identity) -> UntypedNode {
|
||||
match val {
|
||||
Value::Object(obj) => {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<Node<UntypedKind>>() {
|
||||
if let Some(node) = obj.as_any().downcast_ref::<UntypedNode>() {
|
||||
return node.clone();
|
||||
}
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Constant(Value::Object(obj)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
_ => Node {
|
||||
_ => UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Constant(val),
|
||||
ty: (),
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -632,8 +632,8 @@ mod tests {
|
||||
impl MacroEvaluator for SimpleEvaluator {
|
||||
fn evaluate(
|
||||
&self,
|
||||
node: &Node<UntypedKind>,
|
||||
bindings: &HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
node: &UntypedNode,
|
||||
bindings: &HashMap<Rc<str>, UntypedNode>,
|
||||
) -> Result<Value, String> {
|
||||
if let UntypedKind::Identifier(ref sym) = node.kind
|
||||
&& let Some(arg) = bindings.get(&sym.name)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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::vm::Closure;
|
||||
use std::cell::RefCell;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, NodeMetrics};
|
||||
use crate::ast::nodes::Node;
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, Node, NodeMetrics};
|
||||
use crate::ast::types::{Purity, RecordLayout, StaticType, Value};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot, UpvalueIdx};
|
||||
use crate::ast::nodes::Node;
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot, Node, UpvalueIdx};
|
||||
use crate::ast::types::Value;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, BoundNode, NodeMetrics};
|
||||
use crate::ast::nodes::Node;
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, Node, NodeMetrics};
|
||||
use crate::ast::types::{Purity, Signature, StaticType, Value};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
@@ -11,11 +10,11 @@ pub struct MonoCacheKey {
|
||||
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 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>> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -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::nodes::Node;
|
||||
use crate::ast::types::StaticType;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -83,7 +82,7 @@ impl TypeChecker {
|
||||
|
||||
pub fn check(
|
||||
&self,
|
||||
node: &BoundNode,
|
||||
node: &Node,
|
||||
arg_types: &[StaticType],
|
||||
diag: &mut Diagnostics,
|
||||
) -> TypedNode {
|
||||
@@ -151,7 +150,7 @@ impl TypeChecker {
|
||||
|
||||
fn check_params(
|
||||
&self,
|
||||
node: &BoundNode,
|
||||
node: &Node,
|
||||
specialized_ty: &StaticType,
|
||||
ctx: &mut TypeContext,
|
||||
diag: &mut Diagnostics,
|
||||
@@ -272,7 +271,7 @@ impl TypeChecker {
|
||||
|
||||
fn check_node(
|
||||
&self,
|
||||
node: &BoundNode,
|
||||
node: &Node,
|
||||
ctx: &mut TypeContext,
|
||||
diag: &mut Diagnostics,
|
||||
) -> TypedNode {
|
||||
|
||||
+17
-16
@@ -1,7 +1,7 @@
|
||||
use crate::ast::compiler::analyzer::Analyzer;
|
||||
use crate::ast::compiler::binder::Binder;
|
||||
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::vm::{TracingObserver, VM};
|
||||
use std::cell::RefCell;
|
||||
@@ -10,8 +10,8 @@ use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::ast::compiler::bound_nodes::{
|
||||
Address, AnalyzedNode, BoundKind, BoundNode, GlobalAnalyzedRegistry, GlobalFunctionRegistry,
|
||||
GlobalIdx,
|
||||
Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, GlobalFunctionRegistry, GlobalIdx,
|
||||
Node,
|
||||
};
|
||||
use crate::ast::compiler::dumper::Dumper;
|
||||
use crate::ast::compiler::lambda_collector::LambdaCollector;
|
||||
@@ -94,7 +94,7 @@ struct 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 {
|
||||
self.registry.borrow().get(&idx).cloned()
|
||||
} else {
|
||||
@@ -122,8 +122,8 @@ struct RuntimeMacroEvaluator {
|
||||
impl MacroEvaluator for RuntimeMacroEvaluator {
|
||||
fn evaluate(
|
||||
&self,
|
||||
node: &Node<UntypedKind>,
|
||||
bindings: &HashMap<Rc<str>, Node<UntypedKind>>,
|
||||
node: &UntypedNode,
|
||||
bindings: &HashMap<Rc<str>, UntypedNode>,
|
||||
) -> Result<Value, String> {
|
||||
if let UntypedKind::Identifier(sym) = &node.kind
|
||||
&& let Some(arg_node) = bindings.get(&sym.name)
|
||||
@@ -290,7 +290,7 @@ impl Environment {
|
||||
&self,
|
||||
source: &str,
|
||||
base_path: &Path,
|
||||
all_files: &mut Vec<(PathBuf, Node<UntypedKind>)>,
|
||||
all_files: &mut Vec<(PathBuf, UntypedNode)>,
|
||||
) -> Result<(), String> {
|
||||
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.
|
||||
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 mut files = Vec::new();
|
||||
let mut files: Vec<(PathBuf, UntypedNode)> = Vec::new();
|
||||
|
||||
// 1. Always load the embedded system library first as a virtual module
|
||||
let system_path = PathBuf::from(SYSTEM_LIB_PATH);
|
||||
@@ -396,7 +396,7 @@ impl Environment {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn discover_globals(&self, node: &Node<UntypedKind>) {
|
||||
fn discover_globals(&self, node: &UntypedNode) {
|
||||
match &node.kind {
|
||||
UntypedKind::Def { target, .. } => {
|
||||
if let UntypedKind::Identifier(sym) = &target.kind {
|
||||
@@ -423,10 +423,11 @@ impl Environment {
|
||||
UntypedKind::MacroDecl { name, params, body } => {
|
||||
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 {
|
||||
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![],
|
||||
}
|
||||
@@ -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) {
|
||||
Ok(ast) => ast,
|
||||
Err(e) => {
|
||||
@@ -486,10 +487,10 @@ impl Environment {
|
||||
let wrapped_ast = if let crate::ast::compiler::bound_nodes::BoundKind::Lambda { .. } = bound_ast.kind {
|
||||
bound_ast
|
||||
} else {
|
||||
crate::ast::compiler::bound_nodes::BoundNode {
|
||||
crate::ast::compiler::bound_nodes::Node {
|
||||
identity: bound_ast.identity.clone(),
|
||||
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(),
|
||||
kind: crate::ast::compiler::bound_nodes::BoundKind::Tuple { elements: vec![] },
|
||||
ty: (),
|
||||
@@ -504,7 +505,7 @@ impl Environment {
|
||||
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 typed_ast_opt = self.compile_pipeline(untyped_ast, &mut diagnostics);
|
||||
@@ -744,7 +745,7 @@ impl Environment {
|
||||
let optimization = self.optimization;
|
||||
|
||||
let compiler = Rc::new(
|
||||
move |func_template: Rc<BoundNode>,
|
||||
move |func_template: Rc<Node>,
|
||||
arg_types: &[StaticType]|
|
||||
-> Result<(Value, StaticType), String> {
|
||||
let mut diag = Diagnostics::new();
|
||||
|
||||
+35
-30
@@ -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)]
|
||||
pub struct Node<K, T = ()> {
|
||||
pub struct UntypedNode {
|
||||
pub identity: Identity,
|
||||
pub kind: K,
|
||||
pub ty: T,
|
||||
pub kind: UntypedKind,
|
||||
}
|
||||
|
||||
impl Object for Node<UntypedKind> {
|
||||
impl Object for UntypedNode {
|
||||
fn type_name(&self) -> &'static str {
|
||||
"ast-node"
|
||||
}
|
||||
@@ -59,7 +58,7 @@ impl Clone for Box<dyn CustomNode> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum UntypedKind {
|
||||
Nop,
|
||||
Constant(Value),
|
||||
@@ -68,62 +67,68 @@ pub enum UntypedKind {
|
||||
/// A first-class field accessor (e.g. .name)
|
||||
FieldAccessor(crate::ast::types::Keyword),
|
||||
If {
|
||||
cond: Box<Node<UntypedKind>>,
|
||||
then_br: Box<Node<UntypedKind>>,
|
||||
else_br: Option<Box<Node<UntypedKind>>>,
|
||||
cond: Box<UntypedNode>,
|
||||
then_br: Box<UntypedNode>,
|
||||
else_br: Option<Box<UntypedNode>>,
|
||||
},
|
||||
Def {
|
||||
target: Box<Node<UntypedKind>>,
|
||||
value: Box<Node<UntypedKind>>,
|
||||
target: Box<UntypedNode>,
|
||||
value: Box<UntypedNode>,
|
||||
},
|
||||
Assign {
|
||||
target: Box<Node<UntypedKind>>,
|
||||
value: Box<Node<UntypedKind>>,
|
||||
target: Box<UntypedNode>,
|
||||
value: Box<UntypedNode>,
|
||||
},
|
||||
Lambda {
|
||||
params: Box<Node<UntypedKind>>,
|
||||
body: Rc<Node<UntypedKind>>,
|
||||
params: Box<UntypedNode>,
|
||||
body: Rc<UntypedNode>,
|
||||
},
|
||||
Call {
|
||||
callee: Box<Node<UntypedKind>>,
|
||||
args: Box<Node<UntypedKind>>,
|
||||
callee: Box<UntypedNode>,
|
||||
args: Box<UntypedNode>,
|
||||
},
|
||||
Again {
|
||||
args: Box<Node<UntypedKind>>,
|
||||
args: Box<UntypedNode>,
|
||||
},
|
||||
Pipe {
|
||||
inputs: Vec<Node<UntypedKind>>,
|
||||
lambda: Box<Node<UntypedKind>>,
|
||||
inputs: Vec<UntypedNode>,
|
||||
lambda: Box<UntypedNode>,
|
||||
},
|
||||
Block {
|
||||
exprs: Vec<Node<UntypedKind>>,
|
||||
exprs: Vec<UntypedNode>,
|
||||
},
|
||||
Tuple {
|
||||
elements: Vec<Node<UntypedKind>>,
|
||||
elements: Vec<UntypedNode>,
|
||||
},
|
||||
Record {
|
||||
fields: Vec<(Node<UntypedKind>, Node<UntypedKind>)>,
|
||||
fields: Vec<(UntypedNode, UntypedNode)>,
|
||||
},
|
||||
/// A macro declaration that can be expanded at compile time.
|
||||
MacroDecl {
|
||||
name: Symbol,
|
||||
params: Box<Node<UntypedKind>>,
|
||||
body: Box<Node<UntypedKind>>,
|
||||
params: Box<UntypedNode>,
|
||||
body: Box<UntypedNode>,
|
||||
},
|
||||
/// 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)
|
||||
Placeholder(Box<Node<UntypedKind>>),
|
||||
Placeholder(Box<UntypedNode>),
|
||||
/// 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.
|
||||
Expansion {
|
||||
/// The original call from the source AST.
|
||||
call: Box<Node<UntypedKind>>,
|
||||
call: Box<UntypedNode>,
|
||||
/// The resulting AST after macro expansion.
|
||||
expanded: Box<Node<UntypedKind>>,
|
||||
expanded: Box<UntypedNode>,
|
||||
},
|
||||
/// A diagnostic poison node, allowing compilation to continue after an error.
|
||||
Error,
|
||||
Extension(Box<dyn CustomNode>),
|
||||
}
|
||||
|
||||
impl PartialEq for Box<dyn CustomNode> {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
+71
-72
@@ -1,6 +1,6 @@
|
||||
use crate::ast::diagnostics::Diagnostics;
|
||||
use crate::ast::lexer::{Lexer, Token, TokenKind};
|
||||
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
||||
use crate::ast::nodes::{Symbol, UntypedKind, UntypedNode};
|
||||
use crate::ast::types::{Identity, Keyword, NodeIdentity, Value};
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -50,7 +50,7 @@ impl<'a> Parser<'a> {
|
||||
&self.current_token.kind
|
||||
}
|
||||
|
||||
pub fn parse_expression(&mut self) -> Node<UntypedKind> {
|
||||
pub fn parse_expression(&mut self) -> UntypedNode {
|
||||
let token_loc = self.current_token.location;
|
||||
let identity = NodeIdentity::new(token_loc);
|
||||
|
||||
@@ -61,28 +61,28 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::Quote => {
|
||||
self.advance(); // consume '
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(self.make_id_node("quote", identity.clone())),
|
||||
args: Box::new(Node {
|
||||
args: Box::new(UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Tuple {
|
||||
elements: vec![expr],
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::Backtick => {
|
||||
self.advance(); // consume `
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Template(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::Tilde => {
|
||||
@@ -90,17 +90,17 @@ impl<'a> Parser<'a> {
|
||||
if *self.peek() == TokenKind::At {
|
||||
self.advance(); // consume @
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Splice(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
} else {
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Placeholder(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_atom(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_atom(&mut self) -> UntypedNode {
|
||||
let token = self.advance();
|
||||
let identity = NodeIdentity::new(token.location);
|
||||
|
||||
@@ -152,14 +152,13 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind,
|
||||
ty: (),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_list(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_list(&mut self) -> UntypedNode {
|
||||
let start_loc = self.advance().location; // consume '('
|
||||
let identity = NodeIdentity::new(start_loc);
|
||||
|
||||
@@ -169,10 +168,10 @@ impl<'a> Parser<'a> {
|
||||
Some(identity.clone()),
|
||||
);
|
||||
self.advance(); // consume )
|
||||
return Node {
|
||||
return UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Error,
|
||||
ty: (),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -198,29 +197,29 @@ impl<'a> Parser<'a> {
|
||||
node
|
||||
}
|
||||
|
||||
fn parse_again(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_again(&mut self, identity: Identity) -> UntypedNode {
|
||||
let mut elements = Vec::new();
|
||||
|
||||
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
||||
elements.push(self.parse_expression());
|
||||
}
|
||||
|
||||
let args_node = Node {
|
||||
let args_node = UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
};
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Again {
|
||||
args: Box::new(args_node),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_if(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_if(&mut self, identity: Identity) -> UntypedNode {
|
||||
let cond = Box::new(self.parse_expression());
|
||||
let then_br = Box::new(self.parse_expression());
|
||||
let mut else_br = None;
|
||||
@@ -229,53 +228,53 @@ impl<'a> Parser<'a> {
|
||||
else_br = Some(Box::new(self.parse_expression()));
|
||||
}
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::If {
|
||||
cond,
|
||||
then_br,
|
||||
else_br,
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_def(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_def(&mut self, identity: Identity) -> UntypedNode {
|
||||
let target = Box::new(self.parse_pattern());
|
||||
let value = Box::new(self.parse_expression());
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Def { target, value },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_assign(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_assign(&mut self, identity: Identity) -> UntypedNode {
|
||||
// (assign target value)
|
||||
let target = Box::new(self.parse_expression());
|
||||
let value = Box::new(self.parse_expression());
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Assign { target, value },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_do(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_do(&mut self, identity: Identity) -> UntypedNode {
|
||||
let mut exprs = Vec::new();
|
||||
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
||||
exprs.push(self.parse_expression());
|
||||
}
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Block { exprs },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pipe(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_pipe(&mut self, identity: Identity) -> UntypedNode {
|
||||
let inputs_node = self.parse_expression();
|
||||
let inputs = match inputs_node.kind {
|
||||
UntypedKind::Tuple { elements } => elements,
|
||||
@@ -283,28 +282,28 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
let lambda = Box::new(self.parse_expression());
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Pipe { inputs, lambda },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_fn(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_fn(&mut self, identity: Identity) -> UntypedNode {
|
||||
let params = Box::new(self.parse_param_vector());
|
||||
let body = self.parse_expression();
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Lambda {
|
||||
params,
|
||||
body: Rc::new(body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_macro_decl(&mut self, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_macro_decl(&mut self, identity: Identity) -> UntypedNode {
|
||||
let name_node = self.parse_expression();
|
||||
let name = match name_node.kind {
|
||||
UntypedKind::Identifier(sym) => sym,
|
||||
@@ -318,18 +317,18 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
let params = Box::new(self.parse_param_vector());
|
||||
let body = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::MacroDecl {
|
||||
name,
|
||||
params,
|
||||
body: Box::new(body),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_param_vector(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_param_vector(&mut self) -> UntypedNode {
|
||||
if *self.peek() != TokenKind::LeftBracket {
|
||||
self.diagnostics.push_error(
|
||||
format!(
|
||||
@@ -338,16 +337,16 @@ impl<'a> Parser<'a> {
|
||||
),
|
||||
Some(NodeIdentity::new(self.current_token.location)),
|
||||
);
|
||||
return Node {
|
||||
return UntypedNode {
|
||||
identity: NodeIdentity::new(self.current_token.location),
|
||||
kind: UntypedKind::Error,
|
||||
ty: (),
|
||||
|
||||
};
|
||||
}
|
||||
self.parse_pattern()
|
||||
}
|
||||
|
||||
fn parse_pattern(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_pattern(&mut self) -> UntypedNode {
|
||||
let next = self.peek();
|
||||
match next {
|
||||
TokenKind::Identifier(_) => {
|
||||
@@ -356,10 +355,10 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::Identifier(s) => s.into(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Identifier(sym),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::LeftBracket => {
|
||||
@@ -372,10 +371,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.expect(TokenKind::RightBracket);
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
TokenKind::Tilde => {
|
||||
@@ -383,17 +382,17 @@ impl<'a> Parser<'a> {
|
||||
if *self.peek() == TokenKind::At {
|
||||
self.advance(); // consume @
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Splice(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
} else {
|
||||
let expr = self.parse_expression();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Placeholder(Box::new(expr)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,16 +405,16 @@ impl<'a> Parser<'a> {
|
||||
Some(NodeIdentity::new(self.current_token.location)),
|
||||
);
|
||||
self.advance();
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(self.current_token.location),
|
||||
kind: UntypedKind::Error,
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_call(&mut self, callee: Node<UntypedKind>, identity: Identity) -> Node<UntypedKind> {
|
||||
fn parse_call(&mut self, callee: UntypedNode, identity: Identity) -> UntypedNode {
|
||||
let mut elements = Vec::new();
|
||||
|
||||
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
|
||||
@@ -423,23 +422,23 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// The arguments are wrapped in a Tuple node, reusing the call's identity/location.
|
||||
let args_node = Node {
|
||||
let args_node = UntypedNode {
|
||||
identity: identity.clone(),
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
};
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Call {
|
||||
callee: Box::new(callee),
|
||||
args: Box::new(args_node),
|
||||
},
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_vector_literal(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_vector_literal(&mut self) -> UntypedNode {
|
||||
let token = self.advance();
|
||||
let mut elements = Vec::new();
|
||||
|
||||
@@ -450,14 +449,14 @@ impl<'a> Parser<'a> {
|
||||
|
||||
self.expect(TokenKind::RightBracket);
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_record_literal(&mut self) -> Node<UntypedKind> {
|
||||
fn parse_record_literal(&mut self) -> UntypedNode {
|
||||
let token = self.advance();
|
||||
let mut fields = Vec::new();
|
||||
|
||||
@@ -489,10 +488,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.expect(TokenKind::RightBrace);
|
||||
|
||||
Node {
|
||||
UntypedNode {
|
||||
identity: NodeIdentity::new(token.location),
|
||||
kind: UntypedKind::Record { fields },
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,11 +512,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_id_node(&self, name: &str, identity: Identity) -> Node<UntypedKind> {
|
||||
Node {
|
||||
fn make_id_node(&self, name: &str, identity: Identity) -> UntypedNode {
|
||||
UntypedNode {
|
||||
identity,
|
||||
kind: UntypedKind::Identifier(Symbol::from(name)),
|
||||
ty: (),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
||||
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 std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
@@ -166,7 +166,7 @@ impl VM {
|
||||
{
|
||||
self.stack.extend(next_args);
|
||||
} else {
|
||||
self.unpack(&closure.parameter_node, &next_args, &mut 0)?;
|
||||
self.unpack(closure.parameter_node.as_ref(), &next_args, &mut 0)?;
|
||||
}
|
||||
|
||||
// PRE-ALLOCATION
|
||||
@@ -240,7 +240,7 @@ impl VM {
|
||||
{
|
||||
self.stack.extend_from_slice(args);
|
||||
} 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
|
||||
@@ -346,9 +346,9 @@ impl VM {
|
||||
|
||||
// Destructuring works on tuples/vectors, or single values wrapped in a slice
|
||||
if let Some(vals) = val.as_slice() {
|
||||
self.unpack(pattern, vals, &mut offset)?;
|
||||
self.unpack(pattern.as_ref(), vals, &mut offset)?;
|
||||
} 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)
|
||||
}
|
||||
@@ -686,7 +686,7 @@ impl VM {
|
||||
let mut res = Ok(());
|
||||
for el in elements {
|
||||
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);
|
||||
break;
|
||||
@@ -694,7 +694,7 @@ impl VM {
|
||||
}
|
||||
res
|
||||
} 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>(
|
||||
&mut self,
|
||||
pattern: &Node<BoundKind<T>, T>,
|
||||
pattern: &Node<T>,
|
||||
values: &[Value],
|
||||
offset: &mut usize,
|
||||
) -> Result<(), String> {
|
||||
@@ -1048,12 +1048,12 @@ impl VM {
|
||||
*offset += 1;
|
||||
let mut sub_offset = 0;
|
||||
for el in elements {
|
||||
self.unpack(el, sub_values, &mut sub_offset)?;
|
||||
self.unpack(el.as_ref(), sub_values, &mut sub_offset)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
for el in elements {
|
||||
self.unpack(el, values, offset)?;
|
||||
self.unpack(el.as_ref(), values, offset)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user