Refactor optimizer utilities

Removes unused `flatten_tuple` function from optimizer utilities. The
functionality was moved to the `Folder` struct, making it more
contextually appropriate. This change streamlines the utility module and
improves code organization.
This commit is contained in:
Michael Schimmel
2026-02-25 21:26:12 +01:00
parent cf87bbeac5
commit 81c805f07e
6 changed files with 456 additions and 460 deletions
+26 -8
View File
@@ -1,6 +1,4 @@
use crate::ast::compiler::bound_nodes::{
Address, AnalyzedNode, BoundKind, GlobalIdx, UpvalueIdx,
};
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, GlobalIdx, UpvalueIdx};
use crate::ast::nodes::Node;
use crate::ast::types::{Purity, Value};
use crate::ast::vm::Closure;
@@ -8,9 +6,9 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use super::substitution_map::SubstitutionMap;
use super::folder::Folder;
use super::inliner::Inliner;
use super::substitution_map::SubstitutionMap;
use super::utils::{PathTracker, UsageInfo};
pub struct Optimizer {
@@ -177,6 +175,9 @@ impl Optimizer {
let args = self.visit_node(*args, sub, path);
if self.enabled {
let mut arg_nodes = Vec::new();
self.flatten_tuple(args.clone(), &mut arg_nodes);
if let BoundKind::Lambda {
params,
body,
@@ -192,7 +193,7 @@ impl Optimizer {
path.inlining_depth += 1;
let mut inner_sub = SubstitutionMap::new();
let collapsed = if inliner
.prepare_beta_reduction(params, &args, body, &mut inner_sub)
.prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub)
.is_some()
{
Some(self.visit_node((**body).clone(), &mut inner_sub, path))
@@ -231,7 +232,7 @@ impl Optimizer {
path.inlining_stack.insert(*idx);
path.inlining_depth += 1;
let collapsed = if inliner
.prepare_beta_reduction(params, &args, body, &mut inner_sub)
.prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub)
.is_some()
{
Some(self.visit_node((**body).clone(), &mut inner_sub, path))
@@ -273,7 +274,7 @@ impl Optimizer {
let collapsed = if inliner
.prepare_beta_reduction(
&closure.parameter_node,
&args,
&arg_nodes,
&inlined_body,
&mut closure_sub,
)
@@ -291,7 +292,7 @@ impl Optimizer {
}
}
if let Some(folded) = folder.try_fold_pure(&callee, &args) {
if let Some(folded) = folder.try_fold_pure(&callee, &arg_nodes) {
return folded;
}
}
@@ -533,4 +534,21 @@ impl Optimizer {
ty: metrics,
}
}
fn flatten_tuple(&self, node: AnalyzedNode, into: &mut Vec<AnalyzedNode>) {
match node.kind {
BoundKind::Tuple { elements } => {
for el in elements {
self.flatten_tuple(el, into);
}
}
BoundKind::Record { fields } => {
for (_, v) in fields {
self.flatten_tuple(v, into);
}
}
BoundKind::Nop => {}
_ => into.push(node),
}
}
}
+8 -9
View File
@@ -4,8 +4,6 @@ use crate::ast::types::{Purity, StaticType, Value};
use std::cell::RefCell;
use std::rc::Rc;
use super::utils::flatten_tuple;
pub struct Folder<'a> {
pub globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
}
@@ -50,17 +48,19 @@ impl<'a> Folder<'a> {
}
}
pub fn try_fold_pure(&self, callee: &AnalyzedNode, args: &AnalyzedNode) -> Option<AnalyzedNode> {
if callee.ty.purity < Purity::Pure || args.ty.purity < Purity::Pure {
pub fn try_fold_pure(
&self,
callee: &AnalyzedNode,
arg_nodes: &[AnalyzedNode],
) -> Option<AnalyzedNode> {
if callee.ty.purity < Purity::Pure {
return None;
}
let mut arg_nodes = Vec::new();
flatten_tuple(args.clone(), &mut arg_nodes);
let mut arg_values = Vec::with_capacity(arg_nodes.len());
for node in arg_nodes {
if let BoundKind::Constant(val) = node.kind {
arg_values.push(val);
if let BoundKind::Constant(val) = &node.kind {
arg_values.push(val.clone());
} else {
return None;
}
@@ -80,4 +80,3 @@ impl<'a> Folder<'a> {
Some(self.make_constant_node(result, callee))
}
}
+3 -6
View File
@@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use super::substitution_map::SubstitutionMap;
use super::utils::{flatten_tuple, UsageInfo};
use super::utils::UsageInfo;
pub struct Inliner<'a> {
pub globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
@@ -64,18 +64,15 @@ impl<'a> Inliner<'a> {
pub fn prepare_beta_reduction(
&self,
params: &AnalyzedNode,
args: &AnalyzedNode,
arg_vals: &[AnalyzedNode],
body: &AnalyzedNode,
sub: &mut SubstitutionMap,
) -> Option<()> {
let mut body_usage = UsageInfo::default();
body_usage.collect(body);
let mut arg_vals = Vec::new();
flatten_tuple(args.clone(), &mut arg_vals);
let mut slot_index = 0;
self.map_params_to_args(params, &arg_vals, &mut slot_index, sub, &body_usage);
self.map_params_to_args(params, arg_vals, &mut slot_index, sub, &body_usage);
if slot_index != arg_vals.len() {
return None;
+1 -1
View File
@@ -8,4 +8,4 @@ pub use engine::Optimizer;
pub use folder::Folder;
pub use inliner::Inliner;
pub use substitution_map::SubstitutionMap;
pub use utils::{PathTracker, UsageInfo, flatten_tuple};
pub use utils::{PathTracker, UsageInfo};
@@ -1,6 +1,6 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot, UpvalueIdx};
use crate::ast::nodes::Node;
use crate::ast::types::{Value};
use crate::ast::types::Value;
use std::collections::{HashMap, HashSet};
#[derive(Default)]
-18
View File
@@ -168,21 +168,3 @@ impl UsageInfo {
}
}
}
// --- Structural Helpers ---
pub fn flatten_tuple(node: AnalyzedNode, into: &mut Vec<AnalyzedNode>) {
match node.kind {
BoundKind::Tuple { elements } => {
for el in elements {
flatten_tuple(el, into);
}
}
BoundKind::Record { fields } => {
for (_, v) in fields {
flatten_tuple(v, into);
}
}
BoundKind::Nop => {}
_ => into.push(node),
}
}