Skip to content

Architecture

Formulon is organized around a single calculation core with thin packaging layers. Every host surface — WASM, Native Node, Python, CLI, MCP, formulon-cell — sits on top of the same C++17 core through the C ABI.

Glossary: C ABI layer

A flat C function interface that exposes the workbook model, evaluator, and IO to non-C++ hosts. It is the only stable boundary; bindings call into it, but only the core implements it. See Bindings.

Glossary: workbook model

The in-memory representation of an opened workbook — sheets, cells, styles, defined names, tables, dependency graph, dirty set, profile binding, and the workbook-level engine state needed to recalculate. Bindings hold a handle to the model, never the underlying bytes after parsing.

HostBoundaryCoreEvaluation & IOVerificationHost API (JS / Python / CLI / MCP / cell UI)C ABI / binding layerC++17 workbook modelFormula parser and tree-walker evaluatorOOXML / XLSB readersand writersOracle tests / optional VM parityHostBoundaryCoreEvaluation & IOVerificationHost API (JS / Python / CLI /MCP / cell UI)C ABI / binding layerC++17 workbook modelFormula parser and tree-walkerevaluatorOOXML / XLSB readers andwritersOracle tests / optional VM parity

What lives where

LayerOwns
Host APILanguage-specific surface (JS / Python / CLI / MCP tools / cell UI)
C ABI / bindingLifetime management, host value ↔ engine value translation
Workbook modelSheets, cells, styles, dependency graph, dirty state, profile
Parser / evaluatorFunction catalog, production tree-walker, error propagation; optional experimental bytecode VM in developer/test builds
File format layerOOXML, XLSB readers and writers, passthrough preservation
Oracle / parity testsCaptured Excel values, cross-surface agreement

The core owns workbook state, formula semantics, file parsing, dependency tracking, and recalculation. Bindings should translate host values and lifetime management without changing calculation behavior.

Release CLI, WASM, and binding binaries use the tree-walker and do not carry the experimental bytecode compiler, optimizer, or VM. Developer and test builds may compile it with FORMULON_BUILD_VM=ON; parity comparison is enabled only by an explicit FORMULON_VM_PARITY_CHECK=ON build.

Why the split

  • Determinism: a single calculation source means all surfaces produce the same values on the same profile.
  • Embedding: the core has no Node, Python, or browser assumptions, so the same binary serves all three.
  • Testing: oracle data is compared against the engine, not against per-binding logic.
  • C++ core — internal conventions of the calculation core.
  • Bindings — responsibilities and non-responsibilities.
  • Build from source — how the artifacts are produced.