# LazilyTransformingAstService

Manages lazy application of formula AST transformations.

## Problem
Structural operations (adding/removing rows/columns, moving cells, renaming sheets)
require updating every formula that references the affected area. Applying these
transformations eagerly to all formulas after every operation is expensive, especially
for large spreadsheets with many formulas.

## Solution: Lazy Transformation
Instead of transforming all formulas immediately, this service stores transformations
in a queue. Each formula vertex (FormulaVertex) and column index entry (ValueIndex)
tracks its own version number. When a consumer needs up-to-date data, it calls
`applyTransformations()` with its current version and receives all transformations
accumulated since that version.

## Compaction
Over time, the transformations array grows unboundedly. To prevent this memory leak,
the engine periodically triggers compaction when the number of accumulated
transformations reaches the configurable `maxPendingLazyTransformations`:

1. All FormulaVertex instances are forced to apply pending transformations
   (via `DependencyGraph.forceApplyPostponedTransformations()`).
2. All ColumnIndex entries are forced to apply pending transformations
   (via `ColumnSearchStrategy.forceApplyPostponedTransformations()`).
3. `compact()` is called, which advances `versionOffset` and clears the
   transformations array.
4. `UndoRedo.cleanupOrphanedOldData()` removes any oldData entries that were
   written during forced application but belong to already-evicted undo entries.

The `versionOffset` ensures that version numbers remain globally consistent
after compaction: `version() = versionOffset + transformations.length`.

## Constructors

### constructor 

\+ **new LazilyTransformingAstService**(`stats`: [Statistics](statistics.md), `maxPendingLazyTransformations`: number): *[LazilyTransformingAstService](lazilytransformingastservice.md)*

*Defined in [src/LazilyTransformingAstService.ts:61](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L61)*

**Parameters:**

Name | Type |
------ | ------ |
`stats` | [Statistics](statistics.md) |
`maxPendingLazyTransformations` | number |

**Returns:** *[LazilyTransformingAstService](lazilytransformingastservice.md)*

## Properties

### parser

• **parser**? : *ParserWithCaching*

*Defined in [src/LazilyTransformingAstService.ts:56](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L56)*

___

### undoRedo

• **undoRedo**? : *[UndoRedo](undoredo.md)*

*Defined in [src/LazilyTransformingAstService.ts:57](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L57)*

## Methods

### addTransformation 

▸ **addTransformation**(`transformation`: FormulaTransformer): *number*

*Defined in [src/LazilyTransformingAstService.ts:73](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L73)*

**Parameters:**

Name | Type |
------ | ------ |
`transformation` | FormulaTransformer |

**Returns:** *number*

___

### applyTransformations 

▸ **applyTransformations**(`ast`: Ast, `address`: [SimpleCellAddress](../interfaces/simplecelladdress.md), `version`: number): *[Ast, [SimpleCellAddress](../interfaces/simplecelladdress.md), number]*

*Defined in [src/LazilyTransformingAstService.ts:95](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L95)*

**Parameters:**

Name | Type |
------ | ------ |
`ast` | Ast |
`address` | [SimpleCellAddress](../interfaces/simplecelladdress.md) |
`version` | number |

**Returns:** *[Ast, [SimpleCellAddress](../interfaces/simplecelladdress.md), number]*

___

### applyTransformationsToAddress 

▸ **applyTransformationsToAddress**(`address`: [SimpleCellAddress](../interfaces/simplecelladdress.md), `version`: number): *[Maybe](../globals.md#maybe)‹[SimpleCellAddress](../interfaces/simplecelladdress.md)›*

*Defined in [src/LazilyTransformingAstService.ts:136](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L136)*

Replays stored transformations over a bare address that carries no formula.

`applyTransformations` above does the same walk for a formula vertex, which owns an AST and so
also records undo data as it goes. A value has no AST to record, and the vertex that owns the
formula still writes its own undo entry when it catches up, so this walk deliberately records
nothing. It reuses each transformation's own `transformSingleAst` with an empty node rather
than reaching for `fixNodeAddress`, because two transformers do more than shift coordinates:
`MoveCellsTransformer` only moves an address that lies inside the range being moved, and that
decision lives in `transformSingleAst`, not in `fixNodeAddress`.

Returns `undefined` when the stamp predates the last compaction. Compaction brings every
vertex up to date before it discards transformations, but a `CellError` cached inside a
vertex's value is not a vertex and is never brought up to date, so its version can fall behind
`versionOffset`. The transformations needed to move the address are gone by then, and naming
some other cell is worse than naming none.

**Parameters:**

Name | Type | Description |
------ | ------ | ------ |
`address` | [SimpleCellAddress](../interfaces/simplecelladdress.md) | the address as it was at `version` |
`version` | number | the version the address was current at  |

**Returns:** *[Maybe](../globals.md#maybe)‹[SimpleCellAddress](../interfaces/simplecelladdress.md)›*

___

### beginCombinedMode 

▸ **beginCombinedMode**(`sheet`: number): *void*

*Defined in [src/LazilyTransformingAstService.ts:82](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L82)*

**Parameters:**

Name | Type |
------ | ------ |
`sheet` | number |

**Returns:** *void*

___

### commitCombinedMode 

▸ **commitCombinedMode**(): *number*

*Defined in [src/LazilyTransformingAstService.ts:86](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L86)*

**Returns:** *number*

___

### compact 

▸ **compact**(): *void*

*Defined in [src/LazilyTransformingAstService.ts:175](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L175)*

Compacts the transformations array by discarding all entries that have already
been applied by every consumer. Safe to call only after all FormulaVertex and
ColumnIndex consumers have been brought up to the current version.
After calling, UndoRedo.cleanupOrphanedOldData() must be invoked to remove
oldData entries written during forceApplyPostponedTransformations for
already-evicted undo entries.

**Returns:** *void*

___

### getTransformationsFrom 

▸ **getTransformationsFrom**(`version`: number, `filter?`: undefined | function): *IterableIterator‹FormulaTransformer›*

*Defined in [src/LazilyTransformingAstService.ts:149](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L149)*

**Parameters:**

Name | Type |
------ | ------ |
`version` | number |
`filter?` | undefined &#124; function |

**Returns:** *IterableIterator‹FormulaTransformer›*

___

### needsCompaction 

▸ **needsCompaction**(): *boolean*

*Defined in [src/LazilyTransformingAstService.ts:163](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L163)*

Returns true when enough transformations have accumulated to justify the cost
of forcing all consumers (FormulaVertex, ColumnIndex) to apply pending changes.

**Returns:** *boolean*

___

### version 

▸ **version**(): *number*

*Defined in [src/LazilyTransformingAstService.ts:69](https://github.com/handsontable/hyperformula/blob/e2ced02/src/LazilyTransformingAstService.ts#L69)*

**Returns:** *number*