Refactor lambda binding and parameter handling
Introduce `BoundKind::Parameter` to represent function parameters. Modify `Binder` to correctly handle parameters within lambda definitions, ensuring they are only defined within function scopes. Update `LambdaCollector` to register the body of lambdas as templates for global definitions. Adjust `Dumper` to accurately represent lambda parameters. Update `Specializer` and `TCO` to handle the new `BoundKind::Parameter`. Refactor `Call` and `TailCall` to use a single `args` node, often a tuple. Adjust type signatures in RTL to use `StaticType::Tuple` for function parameters.
This commit is contained in:
@@ -21,11 +21,23 @@ impl<T> Clone for Box<dyn BoundExtension<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Type alias for a node that has been bound. Defaults to untyped (T = ()).
|
||||
pub type BoundNode<T = ()> = Node<BoundKind<T>, T>;
|
||||
|
||||
/// Type alias for a node that has been fully type-checked.
|
||||
pub type TypedNode = BoundNode<StaticType>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BoundKind<T = ()> {
|
||||
Nop,
|
||||
Constant(Value),
|
||||
|
||||
/// A positional parameter in a Lambda's parameter list.
|
||||
Parameter {
|
||||
name: Symbol,
|
||||
slot: u32,
|
||||
},
|
||||
|
||||
// Variable Access (Resolved)
|
||||
Get {
|
||||
addr: Address,
|
||||
@@ -35,53 +47,53 @@ pub enum BoundKind<T = ()> {
|
||||
// Variable Update (Assignment)
|
||||
Set {
|
||||
addr: Address,
|
||||
value: Box<Node<BoundKind<T>, T>>,
|
||||
value: Box<BoundNode<T>>,
|
||||
},
|
||||
|
||||
// Variable Declaration (Local)
|
||||
DefLocal {
|
||||
name: Symbol,
|
||||
slot: u32,
|
||||
value: Box<Node<BoundKind<T>, T>>,
|
||||
value: Box<BoundNode<T>>,
|
||||
captured_by: Vec<Identity>,
|
||||
},
|
||||
|
||||
If {
|
||||
cond: Box<Node<BoundKind<T>, T>>,
|
||||
then_br: Box<Node<BoundKind<T>, T>>,
|
||||
else_br: Option<Box<Node<BoundKind<T>, T>>>,
|
||||
cond: Box<BoundNode<T>>,
|
||||
then_br: Box<BoundNode<T>>,
|
||||
else_br: Option<Box<BoundNode<T>>>,
|
||||
},
|
||||
|
||||
// Global Definition (Locals are implicit by stack position)
|
||||
DefGlobal {
|
||||
name: Symbol,
|
||||
global_index: u32,
|
||||
value: Box<Node<BoundKind<T>, T>>,
|
||||
value: Box<BoundNode<T>>,
|
||||
},
|
||||
|
||||
Lambda {
|
||||
param_count: u32,
|
||||
params: Box<BoundNode<T>>,
|
||||
// The list of variables captured from enclosing scopes
|
||||
upvalues: Vec<Address>,
|
||||
body: Rc<Node<BoundKind<T>, T>>,
|
||||
body: Rc<BoundNode<T>>,
|
||||
},
|
||||
|
||||
Call {
|
||||
callee: Box<Node<BoundKind<T>, T>>,
|
||||
args: Vec<Node<BoundKind<T>, T>>,
|
||||
callee: Box<BoundNode<T>>,
|
||||
args: Box<BoundNode<T>>,
|
||||
},
|
||||
|
||||
TailCall {
|
||||
callee: Box<Node<BoundKind<T>, T>>,
|
||||
args: Vec<Node<BoundKind<T>, T>>,
|
||||
callee: Box<BoundNode<T>>,
|
||||
args: Box<BoundNode<T>>,
|
||||
},
|
||||
|
||||
Block {
|
||||
exprs: Vec<Node<BoundKind<T>, T>>,
|
||||
exprs: Vec<BoundNode<T>>,
|
||||
},
|
||||
|
||||
Tuple {
|
||||
elements: Vec<Node<BoundKind<T>, T>>,
|
||||
elements: Vec<BoundNode<T>>,
|
||||
},
|
||||
|
||||
Map {
|
||||
@@ -93,7 +105,7 @@ pub enum BoundKind<T = ()> {
|
||||
/// 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<T>, T>>,
|
||||
bound_expanded: Box<BoundNode<T>>,
|
||||
},
|
||||
|
||||
/// DSL-specific extension slot
|
||||
@@ -101,25 +113,26 @@ pub enum BoundKind<T = ()> {
|
||||
}
|
||||
|
||||
/// A single entry in a Map literal (Key-Value pair)
|
||||
pub type MapEntry<T> = (Node<BoundKind<T>, T>, Node<BoundKind<T>, T>);
|
||||
|
||||
/// 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>;
|
||||
pub type MapEntry<T> = (BoundNode<T>, BoundNode<T>);
|
||||
|
||||
impl<T> BoundKind<T> {
|
||||
pub fn display_name(&self) -> String {
|
||||
match self {
|
||||
BoundKind::Nop => "NOP".to_string(),
|
||||
BoundKind::Constant(v) => format!("CONST({})", v),
|
||||
BoundKind::Parameter { name, slot } => format!("PARAM({}, Slot:{})", name.name, slot),
|
||||
BoundKind::Get { addr, name } => format!("GET({}, {:?})", name.name, addr),
|
||||
BoundKind::Set { addr, .. } => format!("SET({:?})", addr),
|
||||
BoundKind::DefLocal { name, slot, .. } => format!("DEF_LOCAL({}, Slot:{})", name.name, slot),
|
||||
BoundKind::If { .. } => "IF".to_string(),
|
||||
BoundKind::DefGlobal { name, global_index, .. } => format!("DEF_GLOBAL({}, Idx:{})", name.name, global_index),
|
||||
BoundKind::Lambda { upvalues, .. } => format!("LAMBDA(Captures:{})", upvalues.len()),
|
||||
BoundKind::Lambda { params, upvalues, .. } => {
|
||||
let p_str = match ¶ms.kind {
|
||||
BoundKind::Tuple { elements } => format!("p:{}", elements.len()),
|
||||
_ => "p:1".to_string(),
|
||||
};
|
||||
format!("LAMBDA({}, Captures:{})", p_str, upvalues.len())
|
||||
},
|
||||
BoundKind::Call { .. } => "CALL".to_string(),
|
||||
BoundKind::TailCall { .. } => "T-CALL".to_string(),
|
||||
BoundKind::Block { .. } => "BLOCK".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user