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:
+56
-9
@@ -102,6 +102,8 @@ macro_rules! dispatch_eval {
|
||||
BoundKind::Nop => Ok(Value::Void),
|
||||
BoundKind::Constant(v) => Ok(v.clone()),
|
||||
|
||||
BoundKind::Parameter { .. } => Ok(Value::Void),
|
||||
|
||||
BoundKind::DefGlobal { global_index, value, .. } => {
|
||||
let val = $self.$eval_method($($observer,)? value)?;
|
||||
let idx = *global_index as usize;
|
||||
@@ -161,7 +163,10 @@ macro_rules! dispatch_eval {
|
||||
Ok(last)
|
||||
},
|
||||
|
||||
BoundKind::Lambda { param_count: _, upvalues, body } => {
|
||||
BoundKind::Lambda { params: _, upvalues, body } => {
|
||||
// PERFORMANCE: Creating a closure captures upvalues.
|
||||
// The actual execution of the lambda (in Call branch) now skips
|
||||
// the Lambda node itself and jumps directly to the body.
|
||||
let mut captured = Vec::with_capacity(upvalues.len());
|
||||
for addr in upvalues {
|
||||
captured.push($self.capture_upvalue(*addr)?);
|
||||
@@ -177,9 +182,28 @@ macro_rules! dispatch_eval {
|
||||
|
||||
BoundKind::TailCall { callee, args } => {
|
||||
let func_val = $self.$eval_method($($observer,)? callee)?;
|
||||
let mut arg_vals = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
arg_vals.push($self.$eval_method($($observer,)? arg)?);
|
||||
|
||||
// PERFORMANCE OPTIMIZATION: "Everything is a Tuple" Unification
|
||||
// To avoid heap-allocating a Value::List (Rc<Vec<Value>>) for every function call,
|
||||
// we check if the arguments are a literal tuple. If so, we evaluate them
|
||||
// directly into our stack-ready vector.
|
||||
let mut arg_vals = Vec::new();
|
||||
match &args.kind {
|
||||
BoundKind::Tuple { elements } => {
|
||||
arg_vals.reserve(elements.len());
|
||||
for e in elements {
|
||||
arg_vals.push($self.$eval_method($($observer,)? e)?);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Fallback for dynamic tuples (e.g. arguments passed as a variable)
|
||||
let v = $self.$eval_method($($observer,)? args)?;
|
||||
if let Value::List(l) = v {
|
||||
arg_vals = (*l).clone();
|
||||
} else {
|
||||
arg_vals.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match func_val {
|
||||
@@ -192,9 +216,24 @@ macro_rules! dispatch_eval {
|
||||
BoundKind::Call { callee, args } => {
|
||||
let mut func_val = $self.$eval_method($($observer,)? callee)?;
|
||||
|
||||
let mut arg_vals = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
arg_vals.push($self.$eval_method($($observer,)? arg)?);
|
||||
// PERFORMANCE OPTIMIZATION: Same as in TailCall above.
|
||||
// Short-circuiting the Tuple -> Value::List -> Vec conversion to save heap cycles.
|
||||
let mut arg_vals = Vec::new();
|
||||
match &args.kind {
|
||||
BoundKind::Tuple { elements } => {
|
||||
arg_vals.reserve(elements.len());
|
||||
for e in elements {
|
||||
arg_vals.push($self.$eval_method($($observer,)? e)?);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let v = $self.$eval_method($($observer,)? args)?;
|
||||
if let Value::List(l) = v {
|
||||
arg_vals = (*l).clone();
|
||||
} else {
|
||||
arg_vals.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
@@ -542,7 +581,11 @@ mod tests {
|
||||
identity: id.clone(),
|
||||
ty: StaticType::Any,
|
||||
kind: BoundKind::Lambda {
|
||||
param_count: 0,
|
||||
params: Box::new(Node {
|
||||
identity: id.clone(),
|
||||
ty: StaticType::Tuple(vec![]),
|
||||
kind: BoundKind::Tuple { elements: vec![] },
|
||||
}),
|
||||
upvalues: vec![Address::Local(0)], // Capture x
|
||||
body: Rc::new(lambda_body),
|
||||
},
|
||||
@@ -559,7 +602,11 @@ mod tests {
|
||||
ty: StaticType::Any,
|
||||
kind: BoundKind::Get { addr: Address::Local(1), name: Symbol::from("f") },
|
||||
}),
|
||||
args: vec![],
|
||||
args: Box::new(Node {
|
||||
identity: id.clone(),
|
||||
ty: StaticType::Tuple(vec![]),
|
||||
kind: BoundKind::Tuple { elements: vec![] },
|
||||
}),
|
||||
},
|
||||
},
|
||||
// return x (Local 0)
|
||||
|
||||
Reference in New Issue
Block a user