Extract calculate_stack_size to a standalone function

The `calculate_stack_size` method was duplicated in `bound_nodes.rs` and
`tco.rs`. This commit extracts it into a single standalone function in
`tco.rs` to avoid duplication. The stack size is now calculated and
stored in the `ExecNode`'s `ty` field during the TCO optimization phase.
This commit is contained in:
Michael Schimmel
2026-03-11 10:35:18 +01:00
parent 3657f19047
commit db26719cad
4 changed files with 106 additions and 119 deletions
+7 -14
View File
@@ -144,8 +144,7 @@ impl MacroEvaluator for RuntimeMacroEvaluator {
let exec_ast = TCO::optimize(Analyzer::analyze(&typed_ast, &HashMap::new())); // Minimal analysis for macro eval
let mut vm = VM::new(self.global_values.clone());
let stack_size = exec_ast.calculate_stack_size();
vm.run(&exec_ast, stack_size)
vm.run(&exec_ast)
}
}
@@ -601,7 +600,7 @@ impl Environment {
} = &node.kind
&& upvalues.is_empty()
{
let stack_size = node.calculate_stack_size();
let stack_size = node.ty.stack_size;
let closure = Rc::new(crate::ast::vm::Closure::new(
params.ty.original.clone(),
body.ty.original.clone(),
@@ -629,7 +628,7 @@ impl Environment {
purity: Purity::Impure,
func: Rc::new(move |args| {
let mut vm = VM::new(global_values.clone());
let res = match vm.run(&exec_node, 0) { // Root call, use 0 if node is not a lambda
let res = match vm.run(&exec_node) {
Ok(v) => v,
Err(e) => panic!("Myc Runtime Error: {}", e),
};
@@ -708,8 +707,7 @@ impl Environment {
let tco_ast = TCO::optimize(optimized_ast);
let mut vm = VM::new(global_values.clone());
let stack_size = tco_ast.calculate_stack_size();
let compiled_val = match vm.run(&tco_ast, stack_size) {
let compiled_val = match vm.run(&tco_ast) {
Ok(v) => v,
Err(e) => return Err(format!("VM Error during specialization: {}", e)),
};
@@ -746,7 +744,6 @@ impl Environment {
pub fn run_script_compiled(&self, compiled: TypedNode) -> Result<Value, String> {
let linked = self.link(compiled);
let _stack_size = linked.calculate_stack_size();
let func = self.instantiate(linked);
let res = (func.func)(&[]);
self.run_pipeline();
@@ -757,16 +754,12 @@ impl Environment {
self.preload_dependencies(source, None)?;
let compiled = self.compile(source).into_result()?;
let linked = self.link(compiled);
// Late Counting: Determine stack size after all optimizations are finished.
// This keeps AST nodes clean and ensures the VM always has enough space.
let stack_size = linked.calculate_stack_size();
let mut vm = VM::new(self.global_values.clone());
let mut observer = TracingObserver::new();
// 1. Run the script wrapper (returns a closure representing the script)
let result = vm.run_with_observer(&mut observer, &linked, stack_size);
// 1. Run the script wrapper (returns a closure representing the script)
let result = vm.run_with_observer(&mut observer, &linked);
// 2. Execute the root closure immediately to get the actual script result.
// All Myc scripts are wrapped in a parameterless lambda for consistency.
let mut final_result = result;