Refactor Binder to use simpler types

The Binder has been refactored to simplify its internal types and reduce
redundancy.
Key changes include:
- Removed StaticType from LocalInfo, as it's not strictly needed for the
  binder.
- Simplified `define` in CompilerScope to not take a StaticType.
- Removed StaticType from upvalues in FunctionCompiler.
- Adjusted global mappings to store only the index, not the type.
- Updated BoundKind to use a generic type parameter `T` for metadata,
  defaulting to `()` for untyped bound nodes.
- Introduced `BoundNode` and `TypedNode` type aliases for clarity.
- Minor adjustments to dumper and VM to accommodate the new generic
  BoundKind.
This commit is contained in:
Michael Schimmel
2026-02-19 12:07:28 +01:00
parent c49561255e
commit 4673ea78b9
7 changed files with 130 additions and 176 deletions
+42 -19
View File
@@ -2,15 +2,27 @@ use std::rc::Rc;
use crate::ast::types::{Value, StaticType, Identity};
use crate::ast::nodes::Node;
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Address {
Local(u32), // Stack-Slot index (relative to frame base)
Upvalue(u32), // Index in the closure's upvalue array
Global(u32), // Index in the global environment vector
}
/// Trait for DSL-specific AST extensions (like Pipe, Series-Access, etc.)
pub trait BoundExtension<T>: std::fmt::Debug {
fn clone_box(&self) -> Box<dyn BoundExtension<T>>;
fn display_name(&self) -> String;
}
impl<T> Clone for Box<dyn BoundExtension<T>> {
fn clone(&self) -> Self {
self.clone_box()
}
}
#[derive(Debug, Clone)]
pub enum BoundKind {
pub enum BoundKind<T = ()> {
Nop,
Constant(Value),
@@ -20,66 +32,76 @@ pub enum BoundKind {
// Variable Update (Assignment)
Set {
addr: Address,
value: Box<Node<BoundKind, StaticType>>,
value: Box<Node<BoundKind<T>, T>>,
},
// Variable Declaration (Local)
DefLocal {
slot: u32,
value: Box<Node<BoundKind, StaticType>>,
value: Box<Node<BoundKind<T>, T>>,
captured_by: Vec<Identity>,
},
If {
cond: Box<Node<BoundKind, StaticType>>,
then_br: Box<Node<BoundKind, StaticType>>,
else_br: Option<Box<Node<BoundKind, StaticType>>>,
cond: Box<Node<BoundKind<T>, T>>,
then_br: Box<Node<BoundKind<T>, T>>,
else_br: Option<Box<Node<BoundKind<T>, T>>>,
},
// Global Definition (Locals are implicit by stack position)
DefGlobal {
global_index: u32,
value: Box<Node<BoundKind, StaticType>>,
value: Box<Node<BoundKind<T>, T>>,
},
Lambda {
param_count: u32,
// The list of variables captured from enclosing scopes
upvalues: Vec<Address>,
body: Rc<Node<BoundKind, StaticType>>,
body: Rc<Node<BoundKind<T>, T>>,
},
Call {
callee: Box<Node<BoundKind, StaticType>>,
args: Vec<Node<BoundKind, StaticType>>,
callee: Box<Node<BoundKind<T>, T>>,
args: Vec<Node<BoundKind<T>, T>>,
},
TailCall {
callee: Box<Node<BoundKind, StaticType>>,
args: Vec<Node<BoundKind, StaticType>>,
callee: Box<Node<BoundKind<T>, T>>,
args: Vec<Node<BoundKind<T>, T>>,
},
Block {
exprs: Vec<Node<BoundKind, StaticType>>,
exprs: Vec<Node<BoundKind<T>, T>>,
},
// NEW
Tuple {
elements: Vec<Node<BoundKind, StaticType>>,
elements: Vec<Node<BoundKind<T>, T>>,
},
Map {
entries: Vec<(Node<BoundKind, StaticType>, Node<BoundKind, StaticType>)>,
entries: Vec<(Node<BoundKind<T>, T>, Node<BoundKind<T>, 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>>,
/// The result of binding the expanded AST.
bound_expanded: Box<Node<BoundKind, StaticType>>,
bound_expanded: Box<Node<BoundKind<T>, T>>,
},
/// DSL-specific extension slot
Extension(Box<dyn BoundExtension<T>>),
}
impl BoundKind {
/// Type alias for a node that has been bound (addresses resolved) but not yet type-checked.
pub type BoundNode = Node<BoundKind<()>, ()>;
/// Type alias for a node that has been fully type-checked and is ready for execution.
pub type TypedNode = Node<BoundKind<StaticType>, StaticType>;
impl<T> BoundKind<T> {
pub fn display_name(&self) -> String {
match self {
BoundKind::Nop => "NOP".to_string(),
@@ -96,6 +118,7 @@ impl BoundKind {
BoundKind::Tuple { elements } => format!("TUPLE({})", elements.len()),
BoundKind::Map { entries } => format!("MAP({})", entries.len()),
BoundKind::Expansion { .. } => "EXPANSION".to_string(),
BoundKind::Extension(ext) => ext.display_name(),
}
}
}