Commit Graph

17 Commits

Author SHA1 Message Date
Michael Schimmel bd506b1b17 feat: Track optimization path to prevent infinite recursion
Introduce a `PathTracker` to manage recursion depth and detect cycles
during optimization. This prevents infinite inlining of recursive
functions.
2026-02-22 10:05:56 +01:00
Michael Schimmel e3bfc01027 Fix: Correctly determine lambda purity
The purity of a lambda definition should always be `Pure`. The purity of
the lambda's body is only relevant when the lambda is called. This
change ensures that defining a lambda does not incorrectly mark the
parent scope as impure.
2026-02-22 09:20:44 +01:00
Michael Schimmel f35606616b Introduce Purity enum for optimizer
Refactor the optimizer to use a Purity enum instead of a boolean for
tracking function purity. This allows for a more granular representation
of purity:

- `Impure`: Functions with side effects.
- `SideEffectFree`: Functions without side effects but may not be
  deterministic (e.g., `now()`, `random()`).
- `Pure`: Functions without side effects and are deterministic.

This change enhances the optimizer's ability to perform more aggressive
optimizations by accurately determining function purity.
2026-02-22 08:42:22 +01:00
Michael Schimmel 329b885c4b Formatting 2026-02-22 02:35:06 +01:00
Michael Schimmel 2123f1d279 feat: Add typed lambda registry to Optimizer
The Optimizer now accepts a typed lambda registry, allowing it to
perform more aggressive inlining and beta-reduction on globally defined
functions. This is a significant step towards optimizing recursive and
globally defined lambdas more effectively.
2026-02-22 02:31:55 +01:00
Michael Schimmel e5841976c4 Refactor: Collect global usage in optimizer
Introduce `collect_usage` to gather both local and global variable
usage. This enables dead code elimination for unused global definitions.
2026-02-22 02:07:00 +01:00
Michael Schimmel 7c997ca841 Refactor: Replace optimization level with boolean flag
The optimizer now uses a simple boolean flag (`optimization`) instead of
an `optimization_level` (u32). This simplifies the optimizer's logic and
makes it easier to enable or disable optimizations.

The command-line interface and internal testing have been updated to
reflect this change.
2026-02-22 01:50:14 +01:00
Michael Schimmel e87f7232e6 Refactor: Improve optimizer and DCE
This commit introduces several improvements to the AST optimizer and
dead code elimination (DCE) logic:

- **Address Mapping:** The `Get` and `Set` operations now correctly map
  local slots and global indices using the substitution map, ensuring
  that remapped variables are handled properly.
- **Parameter Slot Mapping:** Parameters are now explicitly mapped to
  their correct slots within the `Lambda` node, preventing potential
  slot reassignments in the function body.
- **Pure Function Analysis:** The `is_pure` function has been refined to
  accurately identify pure expressions, including calls to pure
  functions and stateless closures.
- **Dead Code Elimination:** DCE logic in `BoundKind::Block` has been
  enhanced to remove unused local definitions and pure, non-essential
  expressions more effectively. Global DCE is also improved.
- **Constant Folding:** `try_fold_pure` is now more robust in folding
  pure function calls with constant arguments, reducing redundant
  computations.
- **Beta Reduction:** `try_beta_reduce` has been updated to avoid
  reducing if the body contains `DefLocal`, ensuring correctness.
- **Global Purity Tracking:** A `global_purity` map is introduced to
  track the purity of global values, enabling better optimization of
  global accesses.
- **Inlinable Value Check:** The `is_inlinable_value` check now
  correctly identifies stateless closures for inlining.
- **Optimization Level:** The default `optimization_level` is set to 2
  to enable more aggressive optimizations.
2026-02-22 00:41:02 +01:00
Michael Schimmel 0107264026 feat: Implement purity inference for optimization
This commit introduces purity inference to the compiler's optimizer.
This allows for more aggressive constant folding and dead code
elimination by tracking which functions and global variables
are free of side effects.

Key changes include:

- Added `global_purity` field to `Optimizer` and `Environment`.
- Modified `Optimizer::is_pure` to recursively determine if an
  AST node represents a pure computation.
- Introduced `Optimizer::try_fold_pure` to replace the old
  `try_fold_intrinsic`, enabling folding of pure function calls
  with constant arguments.
- Updated `Environment::register_native` and
  `Environment::register_constant`
  to optionally record purity.
- Added purity flags to several built-in functions in `core.rs` and
  `datetime.rs`.
- A new example `optimizer_purity.myc` demonstrates the new feature.
2026-02-22 00:16:04 +01:00
Michael Schimmel ac73aaf59e Feat: Add global inlining and DCE
Introduce global inlining by allowing the Optimizer to access the
environment's global values. This enables replacing global variable
accesses with their constant values when appropriate.

Additionally, implement Dead Code Elimination (DCE) for global
definitions. A global definition can be removed if it was only used for
inlining within the current script and has no side effects.

Update the Optimizer struct to hold an optional reference to the global
values and modify the `Optimizer::new` constructor to accept this. The
`Environment::specialize` and `Environment::compile_script` methods are
updated to pass the global values to the optimizer.

The `SubstitutionMap` is also updated to track script-local global
substitutions and used global indices, supporting both global inlining
and global DCE.
2026-02-21 23:29:24 +01:00
Michael Schimmel 1aa844db22 feat: Add dead code elimination and improve optimization
Integrates dead code elimination (DCE) into the optimizer.
This phase removes expressions that have no side effects and are not the
result of the block.

Also includes several improvements to the existing optimization passes:
- DCE now correctly handles assignments to variables that are never used
  or captured.
- Explicitly tracks captured slots in the `SubstitutionMap` to prevent
  premature inlining.
- Introduces a `is_side_effect_free` helper function for more robust
  purity checks.
- Updates dependencies to include `insta` for snapshot testing.
2026-02-21 22:51:53 +01:00
Michael Schimmel b2e010e755 Add example and refine local inlining
Add a new example file `examples/def_local_inlining.myc` to demonstrate
and test local inlining.

Refine the optimizer to handle local inlining more robustly by:
- Passing a `SubstitutionMap` to `visit_node` to track local variable
  substitutions.
- Enabling constant propagation for local variables by checking
  `sub.locals` in `BoundKind::Get`.
- Updating `BoundKind::DefLocal` and `BoundKind::Set` to maintain the
  substitution map for local variables.
- Adjusting `try_beta_reduce` to use the optimizer's `visit_node` with
  the substitution map for inlining.
- Re-indexing upvalues correctly when inlining captured variables into
  lambdas.
2026-02-21 22:35:04 +01:00
Michael Schimmel ff1024ee49 Remove is_tail field from Call node
The `is_tail` field on the `BoundKind::Call` node was an intermediate
representation for tail-call optimization and is no longer needed as a
distinct field. The TCO pass now embeds this information directly into
the `RuntimeMetadata` of the `ExecNode`, which is the VM's internal AST.
This simplifies the `BoundKind::Call` structure and removes redundant
information.
2026-02-21 22:01:03 +01:00
Michael Schimmel 78dff07930 Refactor Call to include is_tail flag
The `TailCall` variant has been merged into `Call` by adding an
`is_tail` boolean field. This simplifies the AST by reducing the number
of node variants and makes it easier to handle tail call optimization.
The `tco.rs` module is responsible for setting this flag when a call
occurs in tail position.
2026-02-21 21:12:20 +01:00
Michael Schimmel f980d9befc Add PartialEq to BoundKind and Value
Implement PartialEq for BoundKind to allow for structural equality
checks during optimization. This enables the optimizer to terminate
early when a node no longer changes.

Also, implement PartialEq for Value to facilitate comparisons between
different Value variants.
2026-02-21 20:01:58 +01:00
Michael Schimmel 56b8e8389b Refactor optimizer with aggressive collapsing
The optimizer has been refactored to separate its phases and introduce
more aggressive collapsing capabilities.

Phase 2 (Cracking) now focuses on stateless transformations, making it
easier to reason about and potentially parallelize.

Phase 2.5 (Aggressive Collapsing) has been introduced, enabling
optimizations like:
- Beta-reduction for lambda literals.
- Cracking and inlining for constant closures.
- Folding intrinsics for constant arithmetic.
- Short-circuiting conditional expressions.

These changes aim to improve performance by reducing redundant
computations and code bloat. The maximum number of optimization passes
has also been increased to 5 to allow for more complex transformations.
2026-02-21 19:42:09 +01:00
Michael Schimmel 0bbe35eeec feat: Implement closure cracking and inlining
Introduces a new optimizer pass that can "crack" closures, allowing for
more aggressive specialization. It also enables inlining of upvalues
that point to immutable global variables. This removes overhead for
higher-order functions and currying when arguments are statically
resolvable.
2026-02-21 18:49:55 +01:00