Refactor closure instantiation and inlining
This commit makes several changes related to how closures are handled: - **Dumper:** Removes redundant introspection of closure ASTs, as this is no longer relevant. - **Optimizer:** Updates `try_inline` to accept `ExecNode` for parameters and adds a check to ensure the `function_node` is a `Lambda` before attempting inlining. - **Environment:** Simplifies closure creation by passing an `ExecNode` for parameters and ensuring the correct `stack_size` is used. - **VM:** Adjusts `Closure` to store an `ExecNode` for parameters and updates `VM::unpack` to accept an `ExecNode`.
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{BoundKind, Node};
|
use crate::ast::compiler::bound_nodes::{BoundKind, Node};
|
||||||
use crate::ast::types::Value;
|
|
||||||
use crate::ast::vm::Closure;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
/// Human-readable AST dumper for the bound AST.
|
/// Human-readable AST dumper for the bound AST.
|
||||||
@@ -38,28 +36,6 @@ impl Dumper {
|
|||||||
BoundKind::Nop => self.log("Nop", node),
|
BoundKind::Nop => self.log("Nop", node),
|
||||||
BoundKind::Constant(v) => {
|
BoundKind::Constant(v) => {
|
||||||
self.log(&format!("Constant: {}", v), node);
|
self.log(&format!("Constant: {}", v), node);
|
||||||
// Introspect Closure AST if possible
|
|
||||||
if let Value::Object(obj) = v
|
|
||||||
&& let Some(closure) = obj.as_any().downcast_ref::<Closure>()
|
|
||||||
{
|
|
||||||
self.indent += 1;
|
|
||||||
self.write_indent();
|
|
||||||
self.output.push_str("--- Specialized Body ---\n");
|
|
||||||
// We need to cast the inner TypedNode to the generic T required by visit.
|
|
||||||
// Since Dumper is generic over T, but Closure stores TypedNode (where T = StaticType),
|
|
||||||
// we can only fully dump if T is StaticType.
|
|
||||||
// However, we can hack it by creating a new Dumper for the inner AST string.
|
|
||||||
|
|
||||||
// We can't call self.visit because types mismatch if T != StaticType.
|
|
||||||
// So we just recursively dump to string and append.
|
|
||||||
let inner_dump = Dumper::dump(&closure.function_node);
|
|
||||||
for line in inner_dump.lines() {
|
|
||||||
self.write_indent();
|
|
||||||
self.output.push_str(line);
|
|
||||||
self.output.push('\n');
|
|
||||||
}
|
|
||||||
self.indent -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
BoundKind::Get { addr, name } => {
|
BoundKind::Get { addr, name } => {
|
||||||
self.log(&format!("Get: {} ({:?})", name.name, addr), node)
|
self.log(&format!("Get: {} ({:?})", name.name, addr), node)
|
||||||
|
|||||||
@@ -334,8 +334,9 @@ impl Optimizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
path.inlining_depth += 1;
|
path.inlining_depth += 1;
|
||||||
|
if let BoundKind::Lambda { params, .. } = &closure.function_node.kind {
|
||||||
let collapsed = self.try_inline(
|
let collapsed = self.try_inline(
|
||||||
&closure.parameter_node,
|
params,
|
||||||
&arg_nodes,
|
&arg_nodes,
|
||||||
&closure.function_node,
|
&closure.function_node,
|
||||||
sub,
|
sub,
|
||||||
@@ -348,6 +349,10 @@ impl Optimizer {
|
|||||||
if let Some(res) = collapsed {
|
if let Some(res) = collapsed {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
path.inlining_depth -= 1;
|
||||||
|
path.exit_lambda(&closure.function_node.identity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(folded) = folder.try_fold_pure(&callee_opt, &arg_nodes) {
|
if let Some(folded) = folder.try_fold_pure(&callee_opt, &arg_nodes) {
|
||||||
|
|||||||
@@ -666,14 +666,13 @@ impl Environment {
|
|||||||
} = &node.kind
|
} = &node.kind
|
||||||
&& upvalues.is_empty()
|
&& upvalues.is_empty()
|
||||||
{
|
{
|
||||||
let stack_size = node.ty.stack_size;
|
|
||||||
let closure = Rc::new(crate::ast::vm::Closure::new(
|
let closure = Rc::new(crate::ast::vm::Closure::new(
|
||||||
params.ty.original.clone(),
|
params.clone(),
|
||||||
body.ty.original.clone(),
|
body.ty.original.clone(),
|
||||||
body.clone(),
|
body.clone(),
|
||||||
vec![],
|
Vec::new(),
|
||||||
*positional_count,
|
*positional_count,
|
||||||
stack_size,
|
node.ty.stack_size,
|
||||||
));
|
));
|
||||||
let closure_obj: Rc<dyn crate::ast::types::Object> = closure;
|
let closure_obj: Rc<dyn crate::ast::types::Object> = closure;
|
||||||
|
|
||||||
|
|||||||
+6
-7
@@ -1,6 +1,5 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
||||||
use crate::ast::compiler::lowering::ExecNode;
|
use crate::ast::compiler::lowering::ExecNode;
|
||||||
use crate::ast::compiler::bound_nodes::Node;
|
|
||||||
use crate::ast::types::{Object, Value};
|
use crate::ast::types::{Object, Value};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@@ -8,8 +7,8 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Closure {
|
pub struct Closure {
|
||||||
/// The analyzed parameter pattern.
|
/// The executable parameter pattern.
|
||||||
pub parameter_node: Rc<AnalyzedNode>,
|
pub parameter_node: Rc<ExecNode>,
|
||||||
/// The analyzed body (before TCO).
|
/// The analyzed body (before TCO).
|
||||||
pub function_node: Rc<AnalyzedNode>,
|
pub function_node: Rc<AnalyzedNode>,
|
||||||
/// The executable node (after TCO).
|
/// The executable node (after TCO).
|
||||||
@@ -23,7 +22,7 @@ pub struct Closure {
|
|||||||
impl Closure {
|
impl Closure {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
params: Rc<AnalyzedNode>,
|
params: Rc<ExecNode>,
|
||||||
body: Rc<AnalyzedNode>,
|
body: Rc<AnalyzedNode>,
|
||||||
exec: Rc<ExecNode>,
|
exec: Rc<ExecNode>,
|
||||||
upvalues: Vec<Rc<RefCell<Value>>>,
|
upvalues: Vec<Rc<RefCell<Value>>>,
|
||||||
@@ -512,7 +511,7 @@ impl VM {
|
|||||||
}
|
}
|
||||||
let stack_size = node.ty.stack_size;
|
let stack_size = node.ty.stack_size;
|
||||||
let closure = Closure::new(
|
let closure = Closure::new(
|
||||||
params.ty.original.clone(),
|
params.clone(),
|
||||||
body.ty.original.clone(),
|
body.ty.original.clone(),
|
||||||
body.clone(),
|
body.clone(),
|
||||||
captured,
|
captured,
|
||||||
@@ -1026,9 +1025,9 @@ impl VM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unpack<T>(
|
fn unpack(
|
||||||
&mut self,
|
&mut self,
|
||||||
pattern: &Node<T>,
|
pattern: &ExecNode,
|
||||||
values: &[Value],
|
values: &[Value],
|
||||||
offset: &mut usize,
|
offset: &mut usize,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
|||||||
Reference in New Issue
Block a user