Skip to content

This site describes solve-engine as it is on main: 2.43.0, which npm does not have yet. npm installs 2.40.0, so a page may show an answer that version does not give yet.

ThreeTierEvaluator

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:180

Orchestrates three-tier evaluation over a persistent DocumentModel.

── Tier assignment ───────────────────────────────────────────────── | Tier | Condition | Action | |───────|────────────────────────────────────|───────────────────────────────| | 1 | Dirty, in or above the viewport | Full pipeline: lex→parse→compile→execute | | 2 | Visible + Cached (scroll into view)| Execute from cached bytecode | | 3 | Dirty, below the viewport | Compile-only; execute only variable defs | | Skip | Clean, empty, or non-evaluable | No action |

── Evaluation order ───────────────────────────────────────────────── Lines are always processed in ascending document order (line 1 → end) so that variable assignments flow correctly through the shared VM. Tier 2 relies on this: by the time a clean cached line is reached, the VM already contains all variables from preceding Tier-1 lines.

── Thread safety ──────────────────────────────────────────────────── Tier 1 (visible+dirty) compilation runs synchronously on the main thread for immediate rendering. Tier 3 (invisible+dirty) compilation can be dispatched to a Web Worker via dispatchBackgroundCompiles(). Worker- compiled bytecode is stored in the DocumentModel and validated via isBytecodeValid() to ensure the line text hasn’t changed between dispatch and response.

new ThreeTierEvaluator(
doc,
engine,
checkpointer?
): ThreeTierEvaluator;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:283

ParameterTypeDescription
docDocumentModelThe persistent document model.
engineEvaluatorHostThe expression engine (shared VM is accessed via engine.getVM()).
checkpointer?VMCheckpointerOptional VM state checkpointer. If provided, the evaluator will create checkpoints after variable-definition lines and support fast VM restoration via restoreTo(). If omitted, checkpointing is disabled.

ThreeTierEvaluator

applyTransaction(changes): {
edited: number[];
inserted: number[];
removed: number[];
};

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:831

Apply incremental line-level changes to the document model.

Phase 5.2f: Replaces the O(N) setDocument() + full re-evaluation with O(changed) incremental updates. Key benefits:

  1. Unchanged lines retain their persistent lineIds → bytecode survives
  2. Only changed + DAG-downstream lines are marked dirty → Tier 1 re-evaluation
  3. Clean lines in viewport use Tier 2 (cached bytecode execution)
  4. Clean lines outside viewport are skipped entirely

The DAG is fully cleared after propagation: shifted lines would have stale entries keyed by old line numbers, so the DAG is rebuilt from scratch during the subsequent evaluate() call.

Caller should follow up with evaluate(viewport) to re-evaluate dirty lines from line 1 and rebuild the DAG + checkpoints.

A transaction in which every change replaces as many lines as it deletes (a keystroke inside a line, sent as delete-one-insert-one) moves no line, and is applied in place through DocumentModel.editLine instead: the lines keep their ids, nothing is renumbered or cleared, and the ids of the lines whose text changed come back in edited, with inserted and removed empty. A transaction with any change that alters the line count takes the structural path for all of it (#713).

ParameterTypeDescription
changesLineChange[]Line-level changes to apply. Must be non-overlapping.
{
edited: number[];
inserted: number[];
removed: number[];
}

Metadata about the applied changes.

edited: number[];
inserted: number[];
removed: number[];

backgroundCompile(viewport): EvalLineResult[];

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:501

Background-compile invisible dirty lines beyond the viewport (Tier 3 only).

Compiles expressions to discover reads/writes for the dependency graph without executing display-only expressions. Variable definitions are executed to maintain VM state for future Tier-2 executions.

This is intended to be called after evaluate() so visible lines are rendered first, then background work fills in the dependency graph.

Phase 5.2h: This synchronous method is retained for environments without Worker support. Prefer dispatchBackgroundCompiles() which offloads compilation to a Web Worker with Transferable bytecode.

ParameterType
viewportViewportRange

EvalLineResult[]


dispatchBackgroundCompiles(viewport): void;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:554

Dispatch background compilation to a Web Worker (Phase 5.2h).

Collects invisible dirty lines beyond the viewport that need compilation, sends them to the compilation worker, and asynchronously stores the transferred bytecode in the DocumentModel when the worker responds.

This is the non-blocking alternative to backgroundCompile(). The worker compiles expressions with Transferable ArrayBuffers (zero-copy postMessage), so bytecode appears on the main thread without serialization overhead.

Lines that already have cached bytecode (from a previous worker pass or synchronous compile) are skipped, only truly uncompiled dirty lines are sent to the worker.

Usage: Call after evaluate() so visible lines render first, then this fills the bytecode cache for future Tier-2 scrolls.

ParameterTypeDescription
viewportViewportRangeThe current visible range. Lines beyond viewport.endLine that are dirty and don’t have bytecode are dispatched.

void


dispose(): void;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:650

Retire this evaluator: the call a host makes when the document it serves is closed or replaced by another.

It stops the background compilation worker, if one was started, and drops the evaluator’s subscription to the shared global :name store. Until then the store holds a reference to the evaluator, so one that is never retired stays reachable (and keeps marking its lines dirty) after the host has let go of it.

It also detaches the evaluator from the engine, where the engine still points at it: the engine’s document model and its async batcher’s checkpoint chain are cleared if they are this evaluator’s own. Left in place, the engine went on answering from the retired document, so a later evaluateLine("line 1 * 2") read a line of a note the host had closed rather than refusing for want of a document. An engine an evaluator built since has taken over is left alone.

terminateWorker is the first half of this and keeps working as it did. dispose is safe to make more than once. The document model and the engine themselves are left intact: the host owns both, and may build a new evaluator over them.

void


evaluate(viewport, signal?): EvalResult;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:362

Evaluate all lines needed to render the given viewport.

Processes lines from 1 to viewport.endLine in document order. Dirty lines in the viewport, and above it, get the Tier-1 full pipeline; clean cached lines in it get Tier-2 bytecode execution; clean lines above it are skipped. Each line that runs reads the VM as a pass from line 1 leaves it at that line (see runAt). Lines after the viewport are not visited; backgroundCompile gives them Tier-3 compile-only.

ParameterType
viewportViewportRange
signal?AbortSignal

EvalResult

Results for all processed lines, including tier metadata.


evaluateAll(signal?): EvalResult;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:688

Evaluate all dirty lines in the document, regardless of viewport. Used for full re-evaluation after plugin register/unregister.

ParameterType
signal?AbortSignal

EvalResult


getCheckpointer(): VMCheckpointer | null;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:2419

Get the VM checkpointer, or null if checkpointing is disabled.

VMCheckpointer | null


getDoc(): DocumentModel;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:680

Get the DocumentModel (read-only access for decoration building).

DocumentModel


getPageManager(): PageManager;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:2427

Get the PageManager (Phase 5.2g). Exposed for testing.

PageManager


restoreTo(lineNumber): void;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:2410

Restore the VM to the state at or just after the given line number.

Finds the nearest checkpoint at or before lineNumber and replays all variable definitions from the checkpoint chain into the VM. After calling this, the VM is ready to evaluate lines starting at lineNumber + 1 without re-evaluating all preceding lines.

Usage: Phase 5.2e’s setViewport() calls restoreTo(viewport.startLine - 1) before evaluating only the newly visible lines. This is the key to O(visible lines) scrolling.

ParameterTypeDescription
lineNumbernumberThe line number to restore to. Variables defined at lines ≤ this number will be available in the VM.

void


setViewport(viewport, signal?): EvalResult;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:723

Zero-allocation viewport evaluation, the Phase 5.2e “holy grail.”

Key insight: When the user scrolls (viewport-only change, no edits), we don’t need to re-evaluate from line 1. Instead:

  1. Restore the VM to just before the viewport via the nearest checkpoint.
  2. Evaluate ONLY the visible lines (Tier 2 for clean cached, Tier 1 for dirty).
  3. Lines before the viewport are completely skipped, their state lives in the VM checkpointer’s prototypal chain.

Correctness guard: If any variable-definition line before the viewport is dirty (e.g., the user edited a variable def that hasn’t been re-evaluated yet), we clear stale checkpoints and fall back to evaluate() which processes from line 1 and rebuilds fresh checkpoints. This guarantees that stale checkpoints are never used as restoration targets. Only variable-def lines matter here, VMCheckpointer.snapshot() only records state for lines that write a variable, so a dirty plain-expression line before the viewport has no checkpoint to invalidate (see DocumentModel.hasAnyDirtyVariableDefLineBefore()).

Performance: O(visible lines) instead of O(document length). Target: < 1ms for a typical ~30-line viewport, independent of document size.

ParameterTypeDescription
viewportViewportRangeThe visible line range.
signal?AbortSignal-

EvalResult

Results for visible lines only. Lines before the viewport are not included in lines[] or resultMap.


terminateWorker(): void;

Defined in: packages/engine/src/engine/ThreeTierEvaluator.ts:616

Terminate the compilation worker if active, and unsubscribe from sharedGlobalVariableStore. Call this when the evaluator is no longer needed to clean up resources, every call site that retires a ThreeTierEvaluator (document switch, pane destroy()) already calls this unconditionally, so folding the global-store unsubscribe in here needs no new call sites anywhere.

void