Refactor: Use root_purity instead of global_purity

This commit refactors the purity analysis from using a
`HashMap<GlobalIdx, Purity>` to a `Vec<Purity>` indexed by
`GlobalIdx.0`.

This change simplifies the data structure and makes purity lookups more
efficient. The `Binder`'s `globals` field has also been removed as it
was not being used.
This commit is contained in:
Michael Schimmel
2026-03-12 16:57:06 +01:00
parent dcb7685d29
commit bf86c76bb6
8 changed files with 123 additions and 131 deletions
+13 -12
View File
@@ -1,11 +1,10 @@
use crate::ast::compiler::bound_nodes::{
Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, GlobalIdx, UpvalueIdx,
Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, UpvalueIdx,
};
use crate::ast::nodes::Node;
use crate::ast::types::{Purity, Value};
use crate::ast::vm::Closure;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use super::folder::Folder;
@@ -17,7 +16,7 @@ pub struct Optimizer {
pub enabled: bool,
max_passes: usize,
pub globals: Option<Rc<RefCell<Vec<Value>>>>,
pub global_purity: Option<Rc<RefCell<HashMap<GlobalIdx, Purity>>>>,
pub root_purity: Option<Rc<RefCell<Vec<Purity>>>>,
pub lambda_registry: Option<Rc<RefCell<GlobalAnalyzedRegistry>>>,
}
@@ -27,7 +26,7 @@ impl Optimizer {
enabled,
max_passes: 5,
globals: None,
global_purity: None,
root_purity: None,
lambda_registry: None,
}
}
@@ -37,8 +36,8 @@ impl Optimizer {
self
}
pub fn with_purity(mut self, purity: Rc<RefCell<HashMap<GlobalIdx, Purity>>>) -> Self {
self.global_purity = Some(purity);
pub fn with_purity(mut self, purity: Rc<RefCell<Vec<Purity>>>) -> Self {
self.root_purity = Some(purity);
self
}
@@ -79,7 +78,7 @@ impl Optimizer {
path: &mut PathTracker,
base_sub: Option<SubstitutionMap>,
) -> Option<Rc<AnalyzedNode>> {
let inliner = Inliner::new(&self.globals, &self.global_purity);
let inliner = Inliner::new(&self.globals, &self.root_purity);
let mut inner_sub = base_sub.unwrap_or_else(|| sub.new_for_inlining());
if inliner.prepare_beta_reduction(params, arg_nodes, body, &mut inner_sub).is_some() {
@@ -105,7 +104,7 @@ impl Optimizer {
) -> Rc<AnalyzedNode> {
let node = &*node_rc;
let folder = Folder::new(&self.globals);
let inliner = Inliner::new(&self.globals, &self.global_purity);
let inliner = Inliner::new(&self.globals, &self.root_purity);
let (new_kind, metrics) = match &node.kind {
BoundKind::Get { addr, name } => {
@@ -215,11 +214,13 @@ impl Optimizer {
if let Address::Global(global_index) = addr
&& value_opt.ty.purity > Purity::Impure
&& let Some(purity_rc) = &self.global_purity
&& let Some(purity_rc) = &self.root_purity
{
purity_rc
.borrow_mut()
.insert(*global_index, value_opt.ty.purity);
let mut pr = purity_rc.borrow_mut();
let idx = global_index.0 as usize;
if idx < pr.len() {
pr[idx] = value_opt.ty.purity;
}
}
if Rc::ptr_eq(&value_opt, value) {