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.
VMCheckpointer
Defined in: packages/engine/src/vm/VMCheckpoints.ts:88
Manages VM state checkpoints for the three-tier evaluation strategy.
Checkpoint creation: After a variable-definition line executes
(Tier 1 or Tier 3), snapshot() records the current values of the
written variables. The checkpoint is linked via prototypal inheritance
to the previous checkpoint, so only changed variables consume memory.
Checkpoint restoration: Before evaluating a viewport whose start line
is not line 1, restoreTo(lineNumber) resets the VM and replays all
variable definitions up to and including that line. This avoids
re-evaluating the entire document from line 1 on every scroll.
Thread safety: Checkpoints are created synchronously on the main thread during evaluation. They are immutable after creation (Value is an immutable type), so no synchronization is needed.
Integration with Phase 5.2e: setViewport() will use getNearestCheckpoint()
to find the checkpoint just before the new viewport start, then call
restoreTo() to set up the VM before evaluating only the visible lines.
This is the key to O(visible lines) scrolling instead of O(document).
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new VMCheckpointer(vm): VMCheckpointer;Defined in: packages/engine/src/vm/VMCheckpoints.ts:107
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
vm | VM |
Returns
Section titled “Returns”VMCheckpointer
Accessors
Section titled “Accessors”Get Signature
Section titled “Get Signature”get count(): number;Defined in: packages/engine/src/vm/VMCheckpoints.ts:747
Number of checkpoints stored.
Returns
Section titled “Returns”number
isEmpty
Section titled “isEmpty”Get Signature
Section titled “Get Signature”get isEmpty(): boolean;Defined in: packages/engine/src/vm/VMCheckpoints.ts:752
Returns true if no checkpoints have been created.
Returns
Section titled “Returns”boolean
syncedLine
Section titled “syncedLine”Get Signature
Section titled “Get Signature”get syncedLine(): number | null;Defined in: packages/engine/src/vm/VMCheckpoints.ts:713
The line syncTo last put the VM at, or null when that is not known. A diagnostic for tests.
Returns
Section titled “Returns”number | null
vmInstance
Section titled “vmInstance”Get Signature
Section titled “Get Signature”get vmInstance(): VM;Defined in: packages/engine/src/vm/VMCheckpoints.ts:757
The associated VM instance.
Returns
Section titled “Returns”Methods
Section titled “Methods”applyCheckpointAt()
Section titled “applyCheckpointAt()”applyCheckpointAt(lineNumber): boolean;Defined in: packages/engine/src/vm/VMCheckpoints.ts:364
Apply the bindings recorded AT lineNumber, leaving the rest of the VM
alone.
restoreTo rebuilds the whole prefix, which costs the chain every time it is called. A caller moving forward through the document already holds the prefix up to the line before, and needs only what this line added: restoring once and then applying each line in turn as it is passed costs the chain once rather than once per line.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | 1-based line whose own bindings are applied. |
Returns
Section titled “Returns”boolean
Whether a checkpoint existed at that line.
clear()
Section titled “clear()”clear(): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:609
Clear all checkpoints. The underlying VM is NOT reset, call
vm.reset() separately if needed.
Returns
Section titled “Returns”void
desync()
Section titled “desync()”desync(): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:705
Forget which line the VM is at, after something outside the chain changed it wholesale (another document ran on the same engine). The next syncTo sets every name the chain records.
Returns
Section titled “Returns”void
dropCheckpointAt()
Section titled “dropCheckpointAt()”dropCheckpointAt(lineNumber): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:402
Drop the entry a line holds, because the line no longer writes anything.
A line’s entry is replaced when the line writes again and left alone
otherwise, so a definition edited into an expression with no definition in
it (:v3 = 44 edited to 7 + 7) kept saying v3 = 44 in the chain. The
lines below it that asked what the prefix holds were told 44, where a pass
from scratch has nothing there. The entry after it is re-parented to the
one before, the same way snapshot keeps the links straight.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | 1-based line whose entry, if any, goes. |
Returns
Section titled “Returns”void
forget()
Section titled “forget()”forget(names): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:443
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
names | readonly string[] |
Returns
Section titled “Returns”void
getAllCheckpoints()
Section titled “getAllCheckpoints()”getAllCheckpoints(): readonly VMCheckpoint[];Defined in: packages/engine/src/vm/VMCheckpoints.ts:490
Get the entire checkpoint chain from root to the last checkpoint. Useful for debugging and serialization.
Returns
Section titled “Returns”readonly VMCheckpoint[]
getCheckpointAt()
Section titled “getCheckpointAt()”getCheckpointAt(lineNumber): | VMCheckpoint | undefined;Defined in: packages/engine/src/vm/VMCheckpoints.ts:477
Get a specific checkpoint by its line number.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
lineNumber | number |
Returns
Section titled “Returns”| VMCheckpoint
| undefined
The checkpoint, or undefined if not found.
getNearestCheckpoint()
Section titled “getNearestCheckpoint()”getNearestCheckpoint(lineNumber): VMCheckpoint | null;Defined in: packages/engine/src/vm/VMCheckpoints.ts:468
Find the nearest checkpoint at or before the given line number.
Uses linear scan (checkpoints are sorted by lineNumber and the list is short, typically < 20 for Obsidian documents). Can be upgraded to binary search if needed for documents with 1000+ variable defs.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
lineNumber | number |
Returns
Section titled “Returns”VMCheckpoint | null
The nearest checkpoint, or null if none exists before the line.
indexAgreesWithChain()
Section titled “indexAgreesWithChain()”indexAgreesWithChain(): boolean;Defined in: packages/engine/src/vm/VMCheckpoints.ts:583
Whether the per-name index says exactly what the chain says: for every name, the checkpoints holding it in their own bags, in document order. A diagnostic for tests; linear in the chain.
Returns
Section titled “Returns”boolean
lookupFunctionBefore()
Section titled “lookupFunctionBefore()”lookupFunctionBefore(name, lineNumber): UserFunctionDef | undefined;Defined in: packages/engine/src/vm/VMCheckpoints.ts:506
The function a name was bound to at the end of the line before
lineNumber, or undefined if no line above it had defined one.
lookupVariableBefore, for the functions bag: a function definition is a definition, and one edited away or failed leaves the name as the lines above left it just as a variable does.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
name | string | The function name. |
lineNumber | number | The 1-based line whose own entry is to be excluded. |
Returns
Section titled “Returns”UserFunctionDef | undefined
The definition the lines above made, or undefined.
lookupVariable()
Section titled “lookupVariable()”lookupVariable(name): Value | undefined;Defined in: packages/engine/src/vm/VMCheckpoints.ts:549
The value a name holds at the end of the chain, or undefined if no checkpoint holds it. Read from the index, as lookupVariableBefore.
Note: This queries the checkpointer’s snapshot, not the VM. The VM may have been modified since the last snapshot (e.g., by Tier 2 execution of non-variable-def lines that don’t create checkpoints).
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
name | string |
Returns
Section titled “Returns”Value | undefined
lookupVariableBefore()
Section titled “lookupVariableBefore()”lookupVariableBefore(name, lineNumber): Value | undefined;Defined in: packages/engine/src/vm/VMCheckpoints.ts:537
The value a name held at the end of the line before lineNumber, or
undefined if no line above it had set one.
What a definition that failed leaves behind. A pass from scratch skips
the store when the right-hand side errors, so the name keeps whatever the
lines above it had put there: :x = 1 then :x = zz leaves x at 1,
and :x = zz on its own leaves it undefined. The incremental path holds
the value from the previous pass instead, which for the line that failed
is its own old answer, so the evaluator asks here what the prefix holds
and puts that back.
Read from the per-name index, not by following parent. The chain from
the nearest checkpoint back to the root visits exactly the entries of
the array before it, in reverse, so the first one found holding the name
is the last entry at or before the line whose own bag holds it. The
index lists those entries per name in document order, and a binary
search finds that one directly: O(log k) in the number of lines that
wrote the name. Following the links cost the distance to the root for a
name no line above defines, which is every name in an ordinary list of
assignments, so a repeat pass over bare assignments was quadratic in the
document (#712).
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
name | string | The variable. |
lineNumber | number | The 1-based line whose own entry is to be excluded. |
Returns
Section titled “Returns”Value | undefined
The value the lines above set, or undefined.
noteLineRan()
Section titled “noteLineRan()”noteLineRan(lineNumber): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:682
Record that lineNumber has just run on a VM syncTo had put at
the line before it, and recorded what it wrote, so the VM now holds the
state at the end of lineNumber. Any other order leaves the line
unknown, and the next syncTo sets every name.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | The 1-based line that ran. |
Returns
Section titled “Returns”void
renumber()
Section titled “renumber()”renumber(positionOf): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:424
Follow every line to its new position after a structural edit.
An insert or a delete moves every line below it, and the chain is read
by position. It used to be cleared instead and rebuilt as lines ran, but
a clean line above the viewport never runs, so its entry was gone for
good and a line below asking what the prefix held was told nothing:
:a = 5 above the viewport was reported as undefined by :b = a + c
under it. Each entry follows its line by id, the entry of a deleted
line goes, and the parents are linked again in the new order.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
positionOf | (lineId) => number | The 1-based position a line id has now, or -1 for a line that is gone. |
Returns
Section titled “Returns”void
restoreTo()
Section titled “restoreTo()”restoreTo(lineNumber): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:240
Restore the VM to the state at or just after the given line number.
Finds the nearest checkpoint whose lineNumber <= targetLineNumber,
then replays all variable definitions from root → that checkpoint
into the VM via setVar(). The VM’s stack is also reset.
If no checkpoint exists at or before the target line, the VM is fully reset (empty scope, empty stack).
Performance: O(total variable definitions before the line), since each checkpoint in the chain contributes only the names its own line wrote.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | Target 1-based line number. The VM will have the state that existed AFTER evaluating lines up to lineNumber. |
Returns
Section titled “Returns”void
resync()
Section titled “resync()”resync(names): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:694
Put names back to what the chain holds for them at the line the VM is
at, after something outside the chain changed them (the evaluator
clearing running totals at the start of a pass). Nothing to do while
that line is not known: the next syncTo sets every name.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
names | Iterable<string> | The names changed. |
Returns
Section titled “Returns”void
snapshot()
Section titled “snapshot()”snapshot( lineNumber, lineId, variableNames, functionNames?): VMCheckpoint | null;Defined in: packages/engine/src/vm/VMCheckpoints.ts:134
Create a checkpoint at the current line, recording the VM values of the specified variables.
Records only what this line wrote; the rest is reached through the parent link rather than copied.
A line that is snapshotted again drops every checkpoint at or after it first, so the list stays in document order and the new checkpoint inherits from the line before it rather than from one after it. See the body for what went wrong without that.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | 1-based line position. |
lineId | number | Persistent line ID from DocumentModel. |
variableNames | string[] | Names of variables that were written at this line. |
functionNames? | ReadonlySet<string> | Which of those names the line defined as functions, from the bytecode it ran. Without it the VM is asked, which cannot tell a line that defined f from one that set the variable f under a function of that name defined above. |
Returns
Section titled “Returns”VMCheckpoint | null
The new checkpoint, or null if no variable names provided.
syncTo()
Section titled “syncTo()”syncTo(lineNumber): void;Defined in: packages/engine/src/vm/VMCheckpoints.ts:643
Put the VM into the state the document has at the end of lineNumber,
for every name the chain records, by moving from the line it was last
put at rather than rebuilding it.
The evaluator runs a line against the VM, and the VM holds whatever the
lines that ran last wrote. A pass that skips the clean lines above the
viewport, or runs only the viewport, therefore handed a line the values
of lines below it: x * 2 above x = 5 answered 10 from the second
pass on, and x + 100 between :x = 1 and :x = 99 answered 199 once
the viewport started below line 1, where a pass from scratch answers
x is undefined and 101.
Moving down applies the entries passed on the way, in document order;
moving up sets each name an entry passed on the way wrote back to what
the lines above lineNumber left it, or removes it. Either costs the
entries between the two lines, so an edit or a scroll costs the distance
it moves rather than the length of the document. When the line is not
known (the first call, after renumber, or after another caller
applied entries of its own) every name the chain records is set from it
instead. A name the chain does not record, a host’s own for example, is
left as it is, and so is anything else the VM holds (a stored equation).
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | The 1-based line, 0 for the state before line 1. |
Returns
Section titled “Returns”void
updateCheckpointAt()
Section titled “updateCheckpointAt()”updateCheckpointAt(lineNumber, variableNames): boolean;Defined in: packages/engine/src/vm/VMCheckpoints.ts:330
Record what lineNumber has just written, without disturbing the chain
after it.
snapshot drops every checkpoint at or after the line, which is right for a pass running forward in document order: it re-takes them as it goes. A caller re-running a few lines out of a document does not, and dropping the entries for lines it will never visit would lose the very bindings it is sweeping through them to collect. So this overwrites in place instead.
Safe against the prototype chain, because it replaces only the checkpoint’s OWN bindings: a later checkpoint that also writes the name holds its own copy and goes on shadowing this one.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
lineNumber | number | 1-based line whose recorded bindings are refreshed. |
variableNames | string[] | The names it wrote. |
Returns
Section titled “Returns”boolean
Whether a checkpoint existed at that line to update.