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:
@@ -49,13 +49,13 @@ impl Specializer {
|
||||
fn visit_node(&self, node: TypedNode) -> TypedNode {
|
||||
let (new_kind, new_ty) = match node.kind {
|
||||
BoundKind::Call { callee, args } => {
|
||||
let (new_callee, new_args, ret_ty) = self.specialize_call_logic(*callee, args, node.ty.clone());
|
||||
(BoundKind::Call { callee: Box::new(new_callee), args: new_args }, ret_ty)
|
||||
let (new_callee, new_args, ret_ty) = self.specialize_call_logic(*callee, *args, node.ty.clone());
|
||||
(BoundKind::Call { callee: Box::new(new_callee), args: Box::new(new_args) }, ret_ty)
|
||||
},
|
||||
|
||||
BoundKind::TailCall { callee, args } => {
|
||||
let (new_callee, new_args, ret_ty) = self.specialize_call_logic(*callee, args, node.ty.clone());
|
||||
(BoundKind::TailCall { callee: Box::new(new_callee), args: new_args }, ret_ty)
|
||||
let (new_callee, new_args, ret_ty) = self.specialize_call_logic(*callee, *args, node.ty.clone());
|
||||
(BoundKind::TailCall { callee: Box::new(new_callee), args: Box::new(new_args) }, ret_ty)
|
||||
},
|
||||
|
||||
// Recursive traversal for other nodes
|
||||
@@ -69,9 +69,10 @@ impl Specializer {
|
||||
let exprs = exprs.into_iter().map(|e| self.visit_node(e)).collect();
|
||||
(BoundKind::Block { exprs }, node.ty)
|
||||
},
|
||||
BoundKind::Lambda { param_count, upvalues, body } => {
|
||||
BoundKind::Lambda { params, upvalues, body } => {
|
||||
let params = Box::new(self.visit_node(*params));
|
||||
let body = Rc::new(self.visit_node((*body).clone()));
|
||||
(BoundKind::Lambda { param_count, upvalues, body }, node.ty)
|
||||
(BoundKind::Lambda { params, upvalues, body }, node.ty)
|
||||
},
|
||||
BoundKind::DefLocal { name, slot, value, captured_by } => {
|
||||
let value = Box::new(self.visit_node(*value));
|
||||
@@ -109,10 +110,10 @@ impl Specializer {
|
||||
}
|
||||
}
|
||||
|
||||
fn specialize_call_logic(&self, callee: TypedNode, args: Vec<TypedNode>, original_ty: StaticType) -> (TypedNode, Vec<TypedNode>, StaticType) {
|
||||
fn specialize_call_logic(&self, callee: TypedNode, args: TypedNode, original_ty: StaticType) -> (TypedNode, TypedNode, StaticType) {
|
||||
// 1. Specialize children first
|
||||
let new_callee = self.visit_node(callee);
|
||||
let new_args: Vec<TypedNode> = args.into_iter().map(|a| self.visit_node(a)).collect();
|
||||
let new_args = self.visit_node(args);
|
||||
|
||||
// 2. Check if this call is a candidate (Callee is Get(Address))
|
||||
let address = if let BoundKind::Get { addr, .. } = &new_callee.kind {
|
||||
@@ -123,7 +124,12 @@ impl Specializer {
|
||||
};
|
||||
|
||||
// 3. Check if all argument types are statically known
|
||||
let arg_types: Vec<StaticType> = new_args.iter().map(|a| a.ty.clone()).collect();
|
||||
let arg_types: Vec<StaticType> = if let StaticType::Tuple(elements) = &new_args.ty {
|
||||
elements.clone()
|
||||
} else {
|
||||
vec![new_args.ty.clone()]
|
||||
};
|
||||
|
||||
if arg_types.iter().any(|t| matches!(t, StaticType::Any)) {
|
||||
// Cannot specialize with unknown types
|
||||
return (new_callee, new_args, original_ty);
|
||||
@@ -139,7 +145,7 @@ impl Specializer {
|
||||
identity: new_callee.identity.clone(),
|
||||
kind: BoundKind::Constant(val.clone()),
|
||||
ty: StaticType::Function(Box::new(Signature {
|
||||
params: arg_types,
|
||||
params: StaticType::Tuple(arg_types),
|
||||
ret: ret_ty.clone(),
|
||||
})),
|
||||
};
|
||||
@@ -158,7 +164,7 @@ impl Specializer {
|
||||
identity: new_callee.identity.clone(),
|
||||
kind: BoundKind::Constant(val.clone()),
|
||||
ty: StaticType::Function(Box::new(Signature {
|
||||
params: arg_types,
|
||||
params: StaticType::Tuple(arg_types),
|
||||
ret: ret_ty.clone(),
|
||||
})),
|
||||
};
|
||||
@@ -192,7 +198,7 @@ impl Specializer {
|
||||
identity: new_callee.identity.clone(),
|
||||
kind: BoundKind::Constant(res_val),
|
||||
ty: StaticType::Function(Box::new(Signature {
|
||||
params: arg_types,
|
||||
params: StaticType::Tuple(arg_types),
|
||||
ret: res_ty.clone(),
|
||||
})),
|
||||
};
|
||||
@@ -262,7 +268,19 @@ mod tests {
|
||||
let func_node = BoundNode {
|
||||
identity: make_identity(),
|
||||
kind: BoundKind::Lambda {
|
||||
param_count: 1,
|
||||
params: Box::new(BoundNode {
|
||||
identity: make_identity(),
|
||||
kind: BoundKind::Tuple {
|
||||
elements: vec![
|
||||
BoundNode {
|
||||
identity: make_identity(),
|
||||
kind: BoundKind::Parameter { name: name.clone(), slot: 0 },
|
||||
ty: ()
|
||||
}
|
||||
]
|
||||
},
|
||||
ty: ()
|
||||
}),
|
||||
upvalues: vec![],
|
||||
body: Rc::new(BoundNode { identity: make_identity(), kind: BoundKind::Nop, ty: () })
|
||||
},
|
||||
@@ -278,12 +296,13 @@ mod tests {
|
||||
|
||||
let spec = Specializer::new(Some(Rc::new(registry)), Some(compiler), None, None);
|
||||
|
||||
// Call(Get(Local(0)), [Arg(Int)])
|
||||
// Call(Get(Local(0)), Tuple([Arg(Int)]))
|
||||
let callee = make_typed_node(BoundKind::Get { addr, name: name.clone() }, StaticType::Any);
|
||||
let arg = make_typed_node(BoundKind::Constant(Value::Int(1)), StaticType::Int);
|
||||
let args_tuple = make_typed_node(BoundKind::Tuple { elements: vec![arg] }, StaticType::Tuple(vec![StaticType::Int]));
|
||||
|
||||
let call_node = make_typed_node(
|
||||
BoundKind::Call { callee: Box::new(callee), args: vec![arg] },
|
||||
BoundKind::Call { callee: Box::new(callee), args: Box::new(args_tuple) },
|
||||
StaticType::Any
|
||||
);
|
||||
|
||||
@@ -310,12 +329,13 @@ mod tests {
|
||||
let name0 = Symbol::from("f");
|
||||
let name1 = Symbol::from("x");
|
||||
|
||||
// Call(Get(Local(0)), [Get(Local(1))]) where arg is Any
|
||||
let callee = make_typed_node(BoundKind::Get { addr: Address::Local(0), name: name0 }, StaticType::Function(Box::new(Signature { params: vec![StaticType::Any], ret: StaticType::Void })));
|
||||
// Call(Get(Local(0)), Tuple([Get(Local(1))])) where arg is Any
|
||||
let callee = make_typed_node(BoundKind::Get { addr: Address::Local(0), name: name0 }, StaticType::Function(Box::new(Signature { params: StaticType::Tuple(vec![StaticType::Any]), ret: StaticType::Void })));
|
||||
let arg = make_typed_node(BoundKind::Get { addr: Address::Local(1), name: name1 }, StaticType::Any);
|
||||
let args_tuple = make_typed_node(BoundKind::Tuple { elements: vec![arg] }, StaticType::Tuple(vec![StaticType::Any]));
|
||||
|
||||
let call_node = make_typed_node(
|
||||
BoundKind::Call { callee: Box::new(callee), args: vec![arg] },
|
||||
BoundKind::Call { callee: Box::new(callee), args: Box::new(args_tuple) },
|
||||
StaticType::Void
|
||||
);
|
||||
|
||||
@@ -349,12 +369,13 @@ mod tests {
|
||||
|
||||
spec.cache.borrow_mut().insert(key, (specialized_val.clone(), ret_ty.clone()));
|
||||
|
||||
// Create the call node: Call(Get(0), [Arg(Int)])
|
||||
// Create the call node: Call(Get(0), Tuple([Arg(Int)]))
|
||||
let callee = make_typed_node(BoundKind::Get { addr, name }, StaticType::Any);
|
||||
let arg = make_typed_node(BoundKind::Constant(Value::Int(1)), StaticType::Int);
|
||||
let args_tuple = make_typed_node(BoundKind::Tuple { elements: vec![arg] }, StaticType::Tuple(vec![StaticType::Int]));
|
||||
|
||||
let call_node = make_typed_node(
|
||||
BoundKind::Call { callee: Box::new(callee), args: vec![arg] },
|
||||
BoundKind::Call { callee: Box::new(callee), args: Box::new(args_tuple) },
|
||||
StaticType::Any
|
||||
);
|
||||
|
||||
@@ -393,9 +414,10 @@ mod tests {
|
||||
|
||||
let callee = make_typed_node(BoundKind::Get { addr, name }, StaticType::Any);
|
||||
let arg = make_typed_node(BoundKind::Constant(Value::Int(1)), StaticType::Int);
|
||||
let args_tuple = make_typed_node(BoundKind::Tuple { elements: vec![arg] }, StaticType::Tuple(vec![StaticType::Int]));
|
||||
|
||||
let call_node = make_typed_node(
|
||||
BoundKind::Call { callee: Box::new(callee), args: vec![arg] },
|
||||
BoundKind::Call { callee: Box::new(callee), args: Box::new(args_tuple) },
|
||||
StaticType::Any
|
||||
);
|
||||
|
||||
@@ -431,10 +453,11 @@ mod tests {
|
||||
|
||||
let callee = make_typed_node(BoundKind::Get { addr, name }, StaticType::Any);
|
||||
let arg = make_typed_node(BoundKind::Constant(Value::Int(1)), StaticType::Int);
|
||||
let args_tuple = make_typed_node(BoundKind::Tuple { elements: vec![arg] }, StaticType::Tuple(vec![StaticType::Int]));
|
||||
|
||||
// Use TailCall here
|
||||
let call_node = make_typed_node(
|
||||
BoundKind::TailCall { callee: Box::new(callee), args: vec![arg] },
|
||||
BoundKind::TailCall { callee: Box::new(callee), args: Box::new(args_tuple) },
|
||||
StaticType::Any
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user