Refactor Call to include is_tail flag
The `TailCall` variant has been merged into `Call` by adding an `is_tail` boolean field. This simplifies the AST by reducing the number of node variants and makes it easier to handle tail call optimization. The `tco.rs` module is responsible for setting this flag when a call occurs in tail position.
This commit is contained in:
@@ -34,7 +34,7 @@ impl Optimizer {
|
||||
|
||||
fn visit_node(&self, node: TypedNode) -> TypedNode {
|
||||
let (new_kind, new_ty) = match node.kind {
|
||||
BoundKind::Call { callee, args } | BoundKind::TailCall { callee, args } => {
|
||||
BoundKind::Call { callee, args, is_tail } => {
|
||||
let callee = self.visit_node(*callee);
|
||||
let args = self.visit_node(*args);
|
||||
|
||||
@@ -87,12 +87,12 @@ impl Optimizer {
|
||||
};
|
||||
return Node {
|
||||
identity: node.identity,
|
||||
kind: BoundKind::Call { callee: Box::new(cracked_lambda), args: Box::new(args) },
|
||||
kind: BoundKind::Call { callee: Box::new(cracked_lambda), args: Box::new(args), is_tail },
|
||||
ty: node.ty,
|
||||
};
|
||||
}
|
||||
|
||||
(BoundKind::Call { callee: Box::new(callee), args: Box::new(args) }, node.ty)
|
||||
(BoundKind::Call { callee: Box::new(callee), args: Box::new(args), is_tail }, node.ty)
|
||||
},
|
||||
|
||||
BoundKind::If { cond, then_br, else_br } => {
|
||||
@@ -269,7 +269,7 @@ impl Optimizer {
|
||||
self.contains_def_local(cond) || self.contains_def_local(then_br) || else_br.as_ref().is_some_and(|e| self.contains_def_local(e))
|
||||
}
|
||||
BoundKind::Block { exprs } => exprs.iter().any(|e| self.contains_def_local(e)),
|
||||
BoundKind::Call { callee, args } | BoundKind::TailCall { callee, args } => self.contains_def_local(callee) || self.contains_def_local(args),
|
||||
BoundKind::Call { callee, args, .. } => self.contains_def_local(callee) || self.contains_def_local(args),
|
||||
BoundKind::Lambda { .. } => false, // Nested lambda definitions are safe (they have their own frame)
|
||||
BoundKind::Tuple { elements } => elements.iter().any(|e| self.contains_def_local(e)),
|
||||
BoundKind::Record { fields } => fields.iter().any(|(k, v)| self.contains_def_local(k) || self.contains_def_local(v)),
|
||||
@@ -388,10 +388,10 @@ impl SubstitutionMap {
|
||||
let exprs = exprs.into_iter().map(|e| self.inline_recursive(e, depth, upvalue_subs)).collect();
|
||||
(BoundKind::Block { exprs }, node.ty)
|
||||
},
|
||||
BoundKind::Call { callee, args } | BoundKind::TailCall { callee, args } => {
|
||||
BoundKind::Call { callee, args, is_tail } => {
|
||||
let callee = Box::new(self.inline_recursive(*callee, depth, upvalue_subs));
|
||||
let args = Box::new(self.inline_recursive(*args, depth, upvalue_subs));
|
||||
(BoundKind::Call { callee, args }, node.ty)
|
||||
(BoundKind::Call { callee, args, is_tail }, node.ty)
|
||||
},
|
||||
BoundKind::DefLocal { name, slot, value, captured_by } => {
|
||||
let value = Box::new(self.inline_recursive(*value, depth, upvalue_subs));
|
||||
@@ -444,10 +444,10 @@ impl SubstitutionMap {
|
||||
let exprs = exprs.into_iter().map(|e| self.reindex_upvalues(e, mapping)).collect();
|
||||
(BoundKind::Block { exprs }, node.ty)
|
||||
},
|
||||
BoundKind::Call { callee, args } | BoundKind::TailCall { callee, args } => {
|
||||
BoundKind::Call { callee, args, is_tail } => {
|
||||
let callee = Box::new(self.reindex_upvalues(*callee, mapping));
|
||||
let args = Box::new(self.reindex_upvalues(*args, mapping));
|
||||
(BoundKind::Call { callee, args }, node.ty)
|
||||
(BoundKind::Call { callee, args, is_tail }, node.ty)
|
||||
},
|
||||
BoundKind::DefLocal { name, slot, value, captured_by } => {
|
||||
let value = Box::new(self.reindex_upvalues(*value, mapping));
|
||||
|
||||
Reference in New Issue
Block a user