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.
Introduce generic `CompilerPhase` trait to unify different stages of the
bound AST. Rename `LocalSlot` to `VirtualId` and introduce `StackOffset`
for clearer distinction between compile-time and run-time addressing.
Update type aliases and implementations to reflect these changes.
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.
order
- Add new_for_inlining to SubstitutionMap to preserve the next_slot
counter, preventing local slot collisions when merging
scopes.
- Update Inliner to request fresh slots for parameters during beta
reduction instead of forcing identity mappings.
- Fix execution order in Optimizer::visit_node for closure inlining
to run prepare_beta_reduction before visiting the function
body, preventing corrupted upvalue captures.
- Fix CLI --no-opt flag to correctly disable the optimizer in the ast
binary.
- Add integration test to prevent future slot clash regressions.
This commit refactors various AST node types to use `Rc` (Reference
Counting) instead of `Box`. This change is primarily driven by the need
for shared ownership and more efficient handling of potentially
recursive or shared data structures within the AST.
The main benefits of this change include:
- **Reduced cloning:** `Rc` allows multiple parts of the AST to refer to
the same node without needing to clone the entire node. This is
particularly beneficial for optimization passes where nodes might be
visited multiple times.
- **Enabling sharing:** It makes it easier to represent scenarios where
a single AST node might be a child of multiple parent nodes.
- **Performance improvements:** By avoiding unnecessary deep copies of
AST nodes, this change can lead to performance gains, especially
during complex compilation phases.
The `SubstitutionMap::new_inner()` method provides a more robust way to
create nested substitution maps, ensuring that only global substitutions
are inherited. This prevents potential issues with overlapping local and
upvalue addresses in nested scopes, such as during lambda inlining.
This change also includes:
- A new `try_fold_record` method in `folder.rs` to optimize record
literals into constant values.
- Updates to `inliner.rs` to recognize `Value::Record` for inlining.
- Various test cases to verify record optimization and constant folding.
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.
Remove redundant tuple flattening logic in `map_params_to_args`. The
existing logic for iterating through tuple elements already correctly
handles nested tuples and records by recursively calling
`map_params_to_args`.
Introduces the `Inliner` struct to encapsulate logic related to value
and function inlining. This improves code organization and readability
within the optimizer engine.
Key changes include:
- Moving `is_inlinable_value` to the `Inliner` struct.
- Extracting beta-reduction preparation logic into
`Inliner::prepare_beta_reduction`.
- Moving parameter slot collection to
`Inliner::collect_parameter_slots`.
- Introducing `flatten_tuple` to a new `utils` module, used by both
`Folder` and `Inliner`.