Refactor: Move utils to separate module

Moves `PathTracker` and `UsageInfo` to the `utils` module to improve
code organization.
This commit is contained in:
Michael Schimmel
2026-02-25 20:35:12 +01:00
parent cad0c03973
commit 04f2203900
5 changed files with 179 additions and 175 deletions
+3 -30
View File
@@ -5,12 +5,13 @@ use crate::ast::nodes::Node;
use crate::ast::types::{Purity, Value};
use crate::ast::vm::Closure;
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::rc::Rc;
use super::substitution_map::{SubstitutionMap, UsageInfo};
use super::substitution_map::SubstitutionMap;
use super::folder::Folder;
use super::inliner::Inliner;
use super::utils::{PathTracker, UsageInfo};
pub struct Optimizer {
pub enabled: bool,
@@ -20,34 +21,6 @@ pub struct Optimizer {
pub lambda_registry: Option<Rc<RefCell<HashMap<GlobalIdx, AnalyzedNode>>>>,
}
struct PathTracker {
inlining_depth: usize,
inlining_stack: HashSet<GlobalIdx>,
identity_stack: HashSet<crate::ast::types::Identity>,
}
impl PathTracker {
fn new() -> Self {
Self {
inlining_depth: 0,
inlining_stack: HashSet::new(),
identity_stack: HashSet::new(),
}
}
fn enter_lambda(&mut self, identity: &crate::ast::types::Identity) -> bool {
if self.identity_stack.contains(identity) {
return false;
}
self.identity_stack.insert(identity.clone());
true
}
fn exit_lambda(&mut self, identity: &crate::ast::types::Identity) {
self.identity_stack.remove(identity);
}
}
impl Optimizer {
pub fn new(enabled: bool) -> Self {
Self {
+2 -2
View File
@@ -5,8 +5,8 @@ use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use super::substitution_map::{SubstitutionMap, UsageInfo};
use super::utils::flatten_tuple;
use super::substitution_map::SubstitutionMap;
use super::utils::{flatten_tuple, UsageInfo};
pub struct Inliner<'a> {
pub globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
+2 -1
View File
@@ -7,4 +7,5 @@ pub mod utils;
pub use engine::Optimizer;
pub use folder::Folder;
pub use inliner::Inliner;
pub use substitution_map::{SubstitutionMap, UsageInfo};
pub use substitution_map::SubstitutionMap;
pub use utils::{PathTracker, UsageInfo, flatten_tuple};
+1 -141
View File
@@ -1,148 +1,8 @@
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot, UpvalueIdx};
use crate::ast::nodes::Node;
use crate::ast::types::{Identity, Value};
use crate::ast::vm::Closure;
use crate::ast::types::{Value};
use std::collections::{HashMap, HashSet};
#[derive(Default)]
pub struct UsageInfo {
pub used: HashSet<Address>,
pub assigned: HashSet<Address>,
pub used_identities: HashSet<Identity>,
}
impl UsageInfo {
pub fn is_assigned(&self, addr: &Address) -> bool {
self.assigned.contains(addr)
}
pub fn is_used(&self, addr: &Address) -> bool {
self.used.contains(addr)
}
pub fn collect(&mut self, node: &AnalyzedNode) {
match &node.kind {
BoundKind::Destructure { pattern, value } => {
self.collect_pattern(pattern);
self.collect(value);
}
BoundKind::Constant(v) => {
if let Value::Object(obj) = v
&& let Some(closure) = obj.as_any().downcast_ref::<Closure>()
{
self.used_identities
.insert(closure.function_node.identity.clone());
self.collect(&closure.function_node);
}
}
BoundKind::Get { addr, .. } => {
self.used.insert(*addr);
}
BoundKind::Set { addr, value } => {
self.assigned.insert(*addr);
self.collect(value);
}
BoundKind::Lambda {
params,
body,
upvalues,
..
} => {
self.used_identities.insert(node.identity.clone());
let mut inner_info = UsageInfo::default();
inner_info.collect(params);
inner_info.collect(body);
// Propagate globals and identities
for addr in &inner_info.used {
if let Address::Global(_) = addr {
self.used.insert(*addr);
}
}
for addr in &inner_info.assigned {
if let Address::Global(_) = addr {
self.assigned.insert(*addr);
}
}
self.used_identities.extend(inner_info.used_identities);
// Map used upvalues to parent scope
for addr in &inner_info.used {
if let Address::Upvalue(idx) = addr
&& let Some(parent_addr) = upvalues.get(idx.0 as usize)
{
self.used.insert(*parent_addr);
}
}
// Map assigned upvalues to parent scope
for addr in &inner_info.assigned {
if let Address::Upvalue(idx) = addr
&& let Some(parent_addr) = upvalues.get(idx.0 as usize)
{
self.assigned.insert(*parent_addr);
}
}
}
BoundKind::Block { exprs } => {
for e in exprs {
self.collect(e);
}
}
BoundKind::If {
cond,
then_br,
else_br,
} => {
self.collect(cond);
self.collect(then_br);
if let Some(e) = else_br {
self.collect(e);
}
}
BoundKind::Call { callee, args } => {
self.collect(callee);
self.collect(args);
}
BoundKind::Tuple { elements } => {
for e in elements {
self.collect(e);
}
}
BoundKind::Record { fields } => {
for (k, v) in fields {
self.collect(k);
self.collect(v);
}
}
BoundKind::Define { value, .. } => {
self.collect(value);
}
BoundKind::Expansion { bound_expanded, .. } => {
self.collect(bound_expanded);
}
_ => {}
}
}
pub fn collect_pattern(&mut self, node: &AnalyzedNode) {
match &node.kind {
BoundKind::Define { addr, .. } => {
self.assigned.insert(*addr);
}
BoundKind::Set { addr, .. } => {
self.assigned.insert(*addr);
}
BoundKind::Tuple { elements } => {
for el in elements {
self.collect_pattern(el);
}
}
_ => {}
}
}
}
#[derive(Default)]
pub struct SubstitutionMap {
pub values: HashMap<Address, Value>,
+171 -1
View File
@@ -1,5 +1,175 @@
use crate::ast::compiler::bound_nodes::{AnalyzedNode, BoundKind};
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, GlobalIdx};
use crate::ast::types::{Identity, Value};
use crate::ast::vm::Closure;
use std::collections::HashSet;
// --- PathTracker ---
#[derive(Default)]
pub struct PathTracker {
pub inlining_depth: usize,
pub inlining_stack: HashSet<GlobalIdx>,
pub identity_stack: HashSet<Identity>,
}
impl PathTracker {
pub fn new() -> Self {
Self::default()
}
pub fn enter_lambda(&mut self, identity: &Identity) -> bool {
if self.identity_stack.contains(identity) {
return false;
}
self.identity_stack.insert(identity.clone());
true
}
pub fn exit_lambda(&mut self, identity: &Identity) {
self.identity_stack.remove(identity);
}
}
// --- UsageInfo ---
#[derive(Default)]
pub struct UsageInfo {
pub used: HashSet<Address>,
pub assigned: HashSet<Address>,
pub used_identities: HashSet<Identity>,
}
impl UsageInfo {
pub fn is_assigned(&self, addr: &Address) -> bool {
self.assigned.contains(addr)
}
pub fn is_used(&self, addr: &Address) -> bool {
self.used.contains(addr)
}
pub fn collect(&mut self, node: &AnalyzedNode) {
match &node.kind {
BoundKind::Destructure { pattern, value } => {
self.collect_pattern(pattern);
self.collect(value);
}
BoundKind::Constant(v) => {
if let Value::Object(obj) = v
&& let Some(closure) = obj.as_any().downcast_ref::<Closure>()
{
self.used_identities
.insert(closure.function_node.identity.clone());
self.collect(&closure.function_node);
}
}
BoundKind::Get { addr, .. } => {
self.used.insert(*addr);
}
BoundKind::Set { addr, value } => {
self.assigned.insert(*addr);
self.collect(value);
}
BoundKind::Lambda {
params,
body,
upvalues,
..
} => {
self.used_identities.insert(node.identity.clone());
let mut inner_info = UsageInfo::default();
inner_info.collect(params);
inner_info.collect(body);
// Propagate globals and identities
for addr in &inner_info.used {
if let Address::Global(_) = addr {
self.used.insert(*addr);
}
}
for addr in &inner_info.assigned {
if let Address::Global(_) = addr {
self.assigned.insert(*addr);
}
}
self.used_identities.extend(inner_info.used_identities);
// Map used upvalues to parent scope
for addr in &inner_info.used {
if let Address::Upvalue(idx) = addr
&& let Some(parent_addr) = upvalues.get(idx.0 as usize)
{
self.used.insert(*parent_addr);
}
}
// Map assigned upvalues to parent scope
for addr in &inner_info.assigned {
if let Address::Upvalue(idx) = addr
&& let Some(parent_addr) = upvalues.get(idx.0 as usize)
{
self.assigned.insert(*parent_addr);
}
}
}
BoundKind::Block { exprs } => {
for e in exprs {
self.collect(e);
}
}
BoundKind::If {
cond,
then_br,
else_br,
} => {
self.collect(cond);
self.collect(then_br);
if let Some(e) = else_br {
self.collect(e);
}
}
BoundKind::Call { callee, args } => {
self.collect(callee);
self.collect(args);
}
BoundKind::Tuple { elements } => {
for e in elements {
self.collect(e);
}
}
BoundKind::Record { fields } => {
for (k, v) in fields {
self.collect(k);
self.collect(v);
}
}
BoundKind::Define { value, .. } => {
self.collect(value);
}
BoundKind::Expansion { bound_expanded, .. } => {
self.collect(bound_expanded);
}
_ => {}
}
}
pub fn collect_pattern(&mut self, node: &AnalyzedNode) {
match &node.kind {
BoundKind::Define { addr, .. } => {
self.assigned.insert(*addr);
}
BoundKind::Set { addr, .. } => {
self.assigned.insert(*addr);
}
BoundKind::Tuple { elements } => {
for el in elements {
self.collect_pattern(el);
}
}
_ => {}
}
}
}
// --- Structural Helpers ---
pub fn flatten_tuple(node: AnalyzedNode, into: &mut Vec<AnalyzedNode>) {
match node.kind {
BoundKind::Tuple { elements } => {