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:
+10
-42
@@ -188,48 +188,7 @@ macro_rules! dispatch_eval {
|
||||
Ok(Value::Object(Rc::new(closure)))
|
||||
},
|
||||
|
||||
BoundKind::TailCall { callee, args } => {
|
||||
let func_val = $self.$eval_method($($observer,)? callee)?;
|
||||
|
||||
let arg_vals = match &args.kind {
|
||||
BoundKind::Tuple { elements } => {
|
||||
// FAST-PATH: If it's a flat tuple, evaluate directly into Vec
|
||||
let mut vals = Vec::with_capacity(elements.len());
|
||||
let mut is_complex = false;
|
||||
for e in elements {
|
||||
if matches!(e.kind, BoundKind::Tuple { .. }) {
|
||||
is_complex = true;
|
||||
break;
|
||||
}
|
||||
vals.push($self.$eval_method($($observer,)? e)?);
|
||||
}
|
||||
if is_complex {
|
||||
macro_rules! get_args {
|
||||
($s:ident, $a:ident) => { $s.prepare_args($a)? };
|
||||
($s:ident, $o:ident, $a:ident) => { $s.prepare_args_observed($o, $a)? };
|
||||
}
|
||||
get_args!($self, $($observer,)? args)
|
||||
} else {
|
||||
vals
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
macro_rules! get_args {
|
||||
($s:ident, $a:ident) => { $s.prepare_args($a)? };
|
||||
($s:ident, $o:ident, $a:ident) => { $s.prepare_args_observed($o, $a)? };
|
||||
}
|
||||
get_args!($self, $($observer,)? args)
|
||||
}
|
||||
};
|
||||
|
||||
match func_val {
|
||||
Value::Object(obj) => Ok(Value::TailCallRequest(Box::new((obj, arg_vals)))),
|
||||
Value::Function(f) => Ok(f(arg_vals)),
|
||||
_ => Err(format!("Tail call target is not a function: {}", func_val)),
|
||||
}
|
||||
},
|
||||
|
||||
BoundKind::Call { callee, args } => {
|
||||
BoundKind::Call { callee, args, is_tail } => {
|
||||
let mut func_val = $self.$eval_method($($observer,)? callee)?;
|
||||
|
||||
let mut arg_vals = match &args.kind {
|
||||
@@ -262,6 +221,14 @@ macro_rules! dispatch_eval {
|
||||
}
|
||||
};
|
||||
|
||||
if *is_tail {
|
||||
match func_val {
|
||||
Value::Object(obj) => return Ok(Value::TailCallRequest(Box::new((obj, arg_vals)))),
|
||||
Value::Function(f) => return Ok(f(arg_vals)),
|
||||
_ => return Err(format!("Tail call target is not a function: {}", func_val)),
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match func_val {
|
||||
Value::Function(f) => break Ok(f(arg_vals)),
|
||||
@@ -792,6 +759,7 @@ mod tests {
|
||||
ty: StaticType::Tuple(vec![]),
|
||||
kind: BoundKind::Tuple { elements: vec![] },
|
||||
}),
|
||||
is_tail: false,
|
||||
},
|
||||
},
|
||||
// return x (Local 0)
|
||||
|
||||
Reference in New Issue
Block a user