Formula Engine
The evaluator is designed to match Excel semantics for scalar values, ranges, arrays, errors, references, and locale-sensitive behavior. The function catalog is registered at startup; bindings expose enough of it to evaluate any registered function.
Glossary: tree-walker vs bytecode VM
Formulon ships two evaluators. The tree-walker interprets the parsed AST directly; the bytecode VM lowers formulas to a compact instruction stream that runs faster on hot paths. Both must produce the same values — tests run them in parallel so the optimized path stays honest.
Glossary: value kind
The discriminator on every cell or formula result. The kinds are Blank, Number, Bool, Text, Error, Array, Ref, and Lambda. Each binding exposes them as an enum (e.g. WASM ValueKind.Number, Python ValueKind.NUMBER).
Function catalog
The catalog tracks 522 Excel functions across math, statistical, logical, text, date/time, lookup, financial, engineering, information, database, web, cube, and recent (LET / LAMBDA / dynamic array) families. The runtime registry currently reports 522 / 522 implemented. See Formula coverage for the category breakdown and validation guidance.
Evaluation modes
The tree-walker and bytecode VM can run in parallel for parity checks. That keeps optimization work honest: the faster path must produce the same values as the simpler path, on the same workbook, under the same profile.
Error behavior
Excel errors are values, not host-language exceptions:
| Excel error | Meaning |
|---|---|
#DIV/0! | Division by zero or empty divisor |
#VALUE! | Type mismatch in operands or arguments |
#REF! | Reference no longer resolvable (deleted sheet, broken range) |
#NAME? | Unrecognized function or defined name |
#NUM! | Numeric overflow or invalid numeric input |
#N/A | Value not available, typically from MATCH / VLOOKUP style functions |
#NULL! | Intersection produced an empty range |
#SPILL! | Dynamic array could not spill (collision or out-of-bounds) |
#CALC! | Engine could not produce a result (recursion, unfinished evaluation) |
#GETTING_DATA | Asynchronous external lookup in progress |
Cell error vs host error
A formula returning #DIV/0! is not an API failure. The host call succeeded; it produced an error value. Inspect value.kind === ValueKind.Error to handle it. Host-side failures (bad bytes, missing handle, IO error) flow through status envelopes / exceptions / non-zero exits instead.
Coordinates
Bindings use zero-based numeric coordinates to avoid locale-specific address parsing:
| Excel address | Binding tuple (sheet, row, col) |
|---|---|
Sheet1!A1 | (0, 0, 0) |
Sheet1!B4 | (0, 3, 1) |
Sheet2!C10 | (1, 9, 2) |
A1 text is accepted only where a CLI argument, formula string, or MCP tool input explicitly expects it.
Locale-sensitive behavior
Some functions (text formatting, date parsing, currency, list separators) read from the active compatibility profile. The default profile is win-365-ja_JP; alternative profiles are exposed only when matching oracle data exists. See Locale profiles.
Read next
- Recalculation — how the engine schedules formula evaluation.
- Formula coverage — registered functions by family.
- Error model — error values vs host failures in depth.