Remove is_tail field from Call node
The `is_tail` field on the `BoundKind::Call` node was an intermediate representation for tail-call optimization and is no longer needed as a distinct field. The TCO pass now embeds this information directly into the `RuntimeMetadata` of the `ExecNode`, which is the VM's internal AST. This simplifies the `BoundKind::Call` structure and removes redundant information.
This commit is contained in:
+10
-9
@@ -14,7 +14,7 @@ use crate::ast::compiler::lambda_collector::LambdaCollector;
|
||||
use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry};
|
||||
use crate::ast::compiler::optimizer::Optimizer;
|
||||
use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, Specializer};
|
||||
use crate::ast::compiler::tco::TCO;
|
||||
use crate::ast::compiler::tco::{TCO, ExecNode};
|
||||
use crate::ast::rtl;
|
||||
use crate::ast::rtl::intrinsics;
|
||||
|
||||
@@ -67,9 +67,10 @@ impl MacroEvaluator for RuntimeMacroEvaluator {
|
||||
|
||||
let checker = TypeChecker::new(self.global_types.clone());
|
||||
let typed_ast = checker.check(bound_ast, &[])?;
|
||||
let exec_ast = TCO::optimize(typed_ast);
|
||||
|
||||
let mut vm = VM::new(self.global_values.clone());
|
||||
vm.run(&typed_ast)
|
||||
vm.run(&exec_ast)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +177,7 @@ impl Environment {
|
||||
}
|
||||
|
||||
/// Backend: Optimization (TCO, etc.)
|
||||
pub fn link(&self, node: TypedNode) -> TypedNode {
|
||||
pub fn link(&self, node: TypedNode) -> ExecNode {
|
||||
// 1. Specialize (Always performed for correctness)
|
||||
let specialized = self.specialize_node(node);
|
||||
|
||||
@@ -184,7 +185,7 @@ impl Environment {
|
||||
let optimizer = Optimizer::new(self.optimization_level);
|
||||
let optimized = optimizer.optimize(specialized);
|
||||
|
||||
// 3. TCO (Always performed)
|
||||
// 3. TCO (Always performed, converts to ExecNode)
|
||||
TCO::optimize(optimized)
|
||||
}
|
||||
|
||||
@@ -229,7 +230,7 @@ impl Environment {
|
||||
let optimizer = Optimizer::new(opt_level);
|
||||
let optimized_ast = optimizer.optimize(specialized_ast);
|
||||
|
||||
// 4. TCO
|
||||
// 4. TCO (converts to ExecNode)
|
||||
let tco_ast = TCO::optimize(optimized_ast);
|
||||
|
||||
// 5. Compile to Value (VM)
|
||||
@@ -240,7 +241,7 @@ impl Environment {
|
||||
};
|
||||
|
||||
// 6. Determine correct return type from the newly inferred function signature
|
||||
let ret_type = if let StaticType::Function(sig) = &tco_ast.ty {
|
||||
let ret_type = if let StaticType::Function(sig) = &tco_ast.ty.ty {
|
||||
sig.ret.clone()
|
||||
} else {
|
||||
StaticType::Any
|
||||
@@ -261,7 +262,7 @@ impl Environment {
|
||||
}
|
||||
|
||||
/// Runtime: Execute the linked AST in the VM
|
||||
pub fn run(&self, node: &TypedNode) -> Result<Value, String> {
|
||||
pub fn run(&self, node: &ExecNode) -> Result<Value, String> {
|
||||
let mut vm = VM::new(self.global_values.clone());
|
||||
let mut result = vm.run(node)?;
|
||||
|
||||
@@ -269,7 +270,7 @@ impl Environment {
|
||||
if let Value::Object(obj) = &result
|
||||
&& let Some(closure) = obj.as_any().downcast_ref::<crate::ast::vm::Closure>()
|
||||
{
|
||||
result = vm.run(&closure.function_node)?;
|
||||
result = vm.run(&closure.exec_node)?;
|
||||
}
|
||||
|
||||
// IMPORTANT: Resolve any pending tail call requests from the top-level execution
|
||||
@@ -314,7 +315,7 @@ impl Environment {
|
||||
if let Ok(Value::Object(obj)) = &result
|
||||
&& let Some(closure) = obj.as_any().downcast_ref::<crate::ast::vm::Closure>()
|
||||
{
|
||||
result = vm.run_with_observer(&mut observer, &closure.function_node);
|
||||
result = vm.run_with_observer(&mut observer, &closure.exec_node);
|
||||
}
|
||||
|
||||
// Resolve top-level tail calls
|
||||
|
||||
Reference in New Issue
Block a user