Refactor AST substitution logic

This commit refactors the AST substitution logic to correctly handle
nested expansions and improve the inlining of lambda expressions.

The changes include:
- Extracting the core value from potentially expanded AST nodes before
  checking their kind.
- Ensuring that lambda expressions with empty upvalues are correctly
  substituted.
- Adding support for inlining global get expressions as AST
  substitutions.
- Improving the `UsageInfo` collection to correctly track assigned
  values.
This commit is contained in:
Michael Schimmel
2026-03-13 19:51:56 +01:00
parent e5d82ee2b6
commit 0dfcfac7b3
3 changed files with 41 additions and 17 deletions
+30 -10
View File
@@ -504,17 +504,29 @@ impl Optimizer {
} }
} }
let unmapped_addr = if let BoundKind::Define { addr, .. } = &e.kind {
Some(*addr)
} else {
None
};
let opt = self.visit_node(e.clone(), sub, path); let opt = self.visit_node(e.clone(), sub, path);
if let BoundKind::Define { addr, value, .. } = &opt.kind if let BoundKind::Define { value, .. } = &opt.kind
&& !info.assigned.contains(addr) && let Some(orig_addr) = unmapped_addr
&& !info.assigned.contains(&orig_addr)
{ {
if let BoundKind::Constant(val) = &value.kind { let mut core_value = value.as_ref();
sub.add_value(*addr, val.clone()); while let BoundKind::Expansion { bound_expanded, .. } = &core_value.kind {
} else if let BoundKind::Lambda { upvalues, .. } = &value.kind core_value = bound_expanded.as_ref();
}
if let BoundKind::Constant(val) = &core_value.kind {
sub.add_value(orig_addr, val.clone());
} else if let BoundKind::Lambda { upvalues, .. } = &core_value.kind
&& upvalues.is_empty() && upvalues.is_empty()
{ {
sub.add_ast_substitution(*addr, (**value).clone()); sub.add_ast_substitution(orig_addr, core_value.clone());
} }
} }
@@ -560,10 +572,13 @@ impl Optimizer {
for (old_idx, capture_addr) in upvalues.iter().enumerate() { for (old_idx, capture_addr) in upvalues.iter().enumerate() {
let mut inlined_val = None; let mut inlined_val = None;
if !sub.assigned.contains(capture_addr) let mut inlined_ast = None;
&& let Some(val) = sub.get_value(capture_addr) if !sub.assigned.contains(capture_addr) {
{ if let Some(val) = sub.get_value(capture_addr) {
inlined_val = Some(val.clone()); inlined_val = Some(val.clone());
} else if let Some(ast) = sub.ast_substitutions.get(capture_addr) {
inlined_ast = Some(Rc::clone(ast));
}
} }
if let Address::Local(slot) = capture_addr { if let Address::Local(slot) = capture_addr {
@@ -575,6 +590,11 @@ impl Optimizer {
.add_value(Address::Upvalue(UpvalueIdx(old_idx as u32)), val); .add_value(Address::Upvalue(UpvalueIdx(old_idx as u32)), val);
mapping.push(None); mapping.push(None);
upvalues_changed = true; upvalues_changed = true;
} else if let Some(ast) = inlined_ast {
next_inner_subs
.add_ast_substitution(Address::Upvalue(UpvalueIdx(old_idx as u32)), (*ast).clone());
mapping.push(None);
upvalues_changed = true;
} else { } else {
mapping.push(Some(new_upvalues.len() as u32)); mapping.push(Some(new_upvalues.len() as u32));
let mapped = sub.map_address(*capture_addr); let mapped = sub.map_address(*capture_addr);
+10 -5
View File
@@ -112,18 +112,23 @@ impl<'a> Inliner<'a> {
if let Some(arg) = args.get(*offset) if let Some(arg) = args.get(*offset)
&& !body_usage.is_assigned(addr) && !body_usage.is_assigned(addr)
{ {
if let BoundKind::Constant(val) = &arg.kind { let mut core_arg = arg.as_ref();
while let BoundKind::Expansion { bound_expanded, .. } = &core_arg.kind {
core_arg = bound_expanded.as_ref();
}
if let BoundKind::Constant(val) = &core_arg.kind {
sub.add_value(*addr, val.clone()); sub.add_value(*addr, val.clone());
} else if let BoundKind::Lambda { upvalues, .. } = &arg.kind } else if let BoundKind::Lambda { upvalues, .. } = &core_arg.kind
&& upvalues.is_empty() && upvalues.is_empty()
{ {
sub.add_ast_substitution(*addr, (**arg).clone()); sub.add_ast_substitution(*addr, core_arg.clone());
} else if let BoundKind::Get { } else if let BoundKind::Get {
addr: Address::Global(_), addr: Address::Global(_),
.. ..
} = &arg.kind } = &core_arg.kind
{ {
sub.add_ast_substitution(*addr, (**arg).clone()); sub.add_ast_substitution(*addr, core_arg.clone());
} }
} }
+1 -2
View File
@@ -143,8 +143,7 @@ impl UsageInfo {
self.collect(v); self.collect(v);
} }
} }
BoundKind::Define { addr, value, .. } => { BoundKind::Define { value, .. } => {
self.assigned.insert(*addr);
self.collect(value); self.collect(value);
} }
BoundKind::Expansion { bound_expanded, .. } => { BoundKind::Expansion { bound_expanded, .. } => {