# Calculate Module data flow

## What It Does
Calculate handles formula parsing, evaluation, and dependency-driven recalculation across sheets. It exposes a formula engine that: parses expressions, resolves named ranges and sheet tokens, computes built-in/custom functions, maintains dependency graphs, caches parsed formulas, and propagates value changes to dependent cells.

## Entry Points
- `computeFormula(formulaText: string, isFromComputeExpression?: boolean)` - Parse & compute single formula text.
- `computeExpression(formula: string, isFromComputeExpression?: boolean)` - Lower-level expression evaluator.
- `valueChanged(grid: string, changeArgs: ValueChangedArgs, ...)` - Triggered when a cell value/formula changes; kicks off refresh and dependent updates.
- `refresh(cellRef: string, ...)` - Recalculate dependent cells and refresh random/formula-driven values.
- `getCellValueFn(grid, actCell, sheetId, ...)` - Returns a callback that fetches a cell's computed value for formula evaluation.
- `defineFunction(formulaName, functionName|Function, description)` - Register custom formula implementations.
- `registerGridAsSheet(refName, model, sheetFamilyID)` / `unregisterGridAsSheet(...)` - Wire workbook/worksheet models into the engine.
- `getLibraryFormulas()` / `getFunction(libFormula)` - Access built-in formula implementations.
- `onFailure` (Event) - Emitted when calculation errors occur.

## ASCII Core Logic Flow

User Edit / Programmatic Change
         ↓
`valueChanged()` receives changeArgs
         ↓
validate input → `setValueRowCol()` → update cell model
         ↓
invalidate caches / update `storedData` & dependency tables
         ↓
`refresh()` called for changed cell
         ↓
compute path: `getCellValueFn()` used by `computeExpression()` / `computeFormula()`
         ↓
evaluate functions (library/custom) → `compute*` helpers
         ↓
write computed values back via `setValueRowCol()` (and undo record)
         ↓
propagate to dependents (recursive refresh) → UI render/update
         ↓
emit `onFailure` on errors

## Operations & Key Functions
- Parsing & Tokens
  - `computeExpression()` / `computeFormula()` — tokenize, handle parentheses, operators, references, strings, and errors.
  - `setTokensForSheets(text: string)` — map sheet names to internal tokens for multi-sheet parsing.
- Value Accessors
  - `getCellValueFn(grid, actCell, sheetId, ...)` — returns `row,col` -> value callback used during evaluation.
  - `getValueRowCol(grid,row,col)` — raw model read with formatting-awareness.
- Dependency Management
  - `updateDependentCell(cellRef)` — register a dependent formula cell.
  - `getDependentCells()` / `getDependentFormulaCells()` — read dependency maps.
  - `clearFormulaDependentCells(cell)` — remove dependencies on cell deletion/overwrite.
- Formula Computations (examples)
  - `computeSumIfAndAvgIf(range,isAvgIf)` — SUMIF/AVERAGEIF logic.
  - `computeLookup(range)` and `computeVHLookup(range,isVlookup)` — lookup family logic.
  - `computeIfsFormulas(...)` / `computeCountIfsFormulas(...)` — conditional aggregation.
  - `processLogical(stack, operator)` — logical operator resolution for AND/OR/NOT.
  - `computeStoreCells(sCell)` — evaluate stored cell formula sets.
  - Date/time helpers: `intToDate()`, `fromOADate()`, `toOADate()`, `parseDate()`.
- Caching & Tracking
  - `storedData: Map<string, FormulaInfo>` — parsed+value cache for formulas.
  - `FormulaInfo` objects store parsed formula, cached value, and calcID.
  - `randomValues`, `randCollection` — tracking for volatile/random functions.
- Registration & Extensibility
  - `defineFunction()` — register custom function handlers.
  - `registerGridAsSheet()` — link grid objects into the calculation family (`CalcSheetFamilyItem`).

## Validation & Safety
- Syntax & Parse Errors: extensive `formulaErrorStrings` detect invalid tokens, mismatched quotes/parentheses, unknown function names.
- Runtime Errors: `#DIV/0!`, `#SPILL!`, `#NAME?`, `#CIRCULARREF!`, `Calculation overflow` are surfaced via `onFailure` and error return values.
- Dependency Cycles: circular reference detection and `#CIRCULARREF!` handling; iteration guards for converging formulas.
- Bounds Checking: respects `maxRows`/`maxCols` and numeric limits (`minValue`/`maxValue`).
- Sheet/Range Validation: checks for missing sheets, invalid named ranges, and invalid references during tokenization.
- Protected/Read-only updates: engine expects external checks (grid APIs) to prevent writes to locked cells; valueChanged can be a no-op if caller enforces protection.
- Volatile Functions: `RAND`, `RANDBETWEEN` tracked via `randomValues` with controlled refresh to avoid unnecessary churn.

## Desired Outputs

User-Facing
- Visible cell value updates in grid after formula evaluation.
- Formula bar showing formula text and live computed result.
- Clear error markers/messages when formulas fail (e.g., `#DIV/0!`, `#NAME?`).
- Responsive recalculation: dependent cells update shortly after edits.

System-Level
- **Model Updates:** cell model values/formulas updated via `setValueRowCol()` and `valueChanged()`.
- **Caches & Tables:** `storedData: Map<string,FormulaInfo>` maintained; dependency maps updated (`sheetDependentFormulaCells`).
- **Events:** emits `onFailure` for calculation errors; `valueChanged()`/`refresh()` act as implicit event hooks for recalculation flow (integrations can listen to these lifecycle points).
- **Undo/Redo:** engine integration should create undo records when `setValueRowCol()` changes persisted cell values or formula text (consumer grid layer records history entries).
- **Registration Artifacts:** `CalcSheetFamilyItem` mapping between sheet tokens and parent objects for multi-sheet computations.
- **Render Integration:** engine produces final values which the UI layer renders into grid cells (update render pipeline / diff + repaint).
- **No Dedicated DOM Classes:** calculation is headless — UI classes remain the responsibility of the grid renderer; engine only supplies updated model values and error flags.

## Notes (Implementation-focused)
- Keep formula parsing and evaluation deterministic: separate tokenization/parsing from evaluation to enable caching of parsed ASTs in `FormulaInfo`.
- Use `getCellValueFn()` to decouple engine from grid internals; the callback isolates row/col access semantics and makes the compute path testable.
- Track `calcID` per formula to avoid re-evaluating unchanged parsed formulas across refresh cycles.
- Emit `onFailure` with rich `FormulaError` objects so UI can show helpful diagnostics and allow user correction.


---