solve-engine 2.38.21 → 2.38.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PackageCompatibility-ZCZVGHws.d.ts → PackageCompatibility-C7ILySsH.d.ts} +1 -1
- package/dist/{PackageCompatibility-Bv42nEm2.d.cts → PackageCompatibility-CzDzOIg9.d.cts} +1 -1
- package/dist/{PackageRegistry-7dFbaAZp.d.cts → PackageRegistry-Bd8ErpwZ.d.cts} +78 -1
- package/dist/{PackageRegistry-B6s8LGCu.d.ts → PackageRegistry-D7_B0mxv.d.ts} +78 -1
- package/dist/{VMBuiltins-0C4z3yDS.d.cts → VMBuiltins-Baa90D2v.d.cts} +232 -1
- package/dist/{VMBuiltins-Bu6qaKi0.d.ts → VMBuiltins-BqkoJtHt.d.ts} +232 -1
- package/dist/chunk-54QMY2VL.cjs +2 -0
- package/dist/chunk-54QMY2VL.cjs.map +1 -0
- package/dist/{chunk-7PUNL5CJ.cjs → chunk-6FBXJYWO.cjs} +3 -3
- package/dist/{chunk-H4G3UXJV.js.map → chunk-6FBXJYWO.cjs.map} +1 -1
- package/dist/chunk-AEGR3GFA.js +3 -0
- package/dist/chunk-AEGR3GFA.js.map +1 -0
- package/dist/chunk-CR7IHPA2.cjs +2 -0
- package/dist/chunk-CR7IHPA2.cjs.map +1 -0
- package/dist/{chunk-NFASELLK.js → chunk-FBXQUQCY.js} +2 -2
- package/dist/{chunk-NFASELLK.js.map → chunk-FBXQUQCY.js.map} +1 -1
- package/dist/chunk-GITRBCSD.cjs +5 -0
- package/dist/chunk-GITRBCSD.cjs.map +1 -0
- package/dist/chunk-JVHRND2N.js +5 -0
- package/dist/chunk-JVHRND2N.js.map +1 -0
- package/dist/{chunk-H4G3UXJV.js → chunk-KSOB5FCI.js} +3 -3
- package/dist/chunk-KSOB5FCI.js.map +1 -0
- package/dist/chunk-OBQC7KDY.cjs +2 -0
- package/dist/chunk-OBQC7KDY.cjs.map +1 -0
- package/dist/{chunk-VLFP6IAY.cjs → chunk-OGBLSNQE.cjs} +2 -2
- package/dist/{chunk-VLFP6IAY.cjs.map → chunk-OGBLSNQE.cjs.map} +1 -1
- package/dist/chunk-QP4VIEXZ.js +2 -0
- package/dist/chunk-QP4VIEXZ.js.map +1 -0
- package/dist/chunk-RMBUP4XA.js +2 -0
- package/dist/chunk-RMBUP4XA.js.map +1 -0
- package/dist/chunk-UITBYTCD.cjs +3 -0
- package/dist/chunk-UITBYTCD.cjs.map +1 -0
- package/dist/chunk-X2QJE3SV.js +2 -0
- package/dist/chunk-X2QJE3SV.js.map +1 -0
- package/dist/chunk-Y5ZY6DPX.cjs +2 -0
- package/dist/chunk-Y5ZY6DPX.cjs.map +1 -0
- package/dist/chunk-ZISAN7NW.js +2 -0
- package/dist/chunk-ZISAN7NW.js.map +1 -0
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/engine.cjs +1 -1
- package/dist/engine.d.cts +128 -5
- package/dist/engine.d.ts +128 -5
- package/dist/engine.js +1 -1
- package/dist/engine.worker.cjs +1 -1
- package/dist/engine.worker.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/language.d.cts +3 -3
- package/dist/language.d.ts +3 -3
- package/dist/packages.cjs +1 -1
- package/dist/packages.d.cts +2 -2
- package/dist/packages.d.ts +2 -2
- package/dist/packages.js +1 -1
- package/dist/testing.cjs +2 -2
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +1 -1
- package/dist/vm.cjs +1 -1
- package/dist/vm.d.cts +1 -1
- package/dist/vm.d.ts +1 -1
- package/dist/vm.js +1 -1
- package/dist/worker.cjs +2 -2
- package/dist/worker.d.cts +2 -2
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2YHOWQ43.js +0 -2
- package/dist/chunk-2YHOWQ43.js.map +0 -1
- package/dist/chunk-3JSXJSMT.js +0 -2
- package/dist/chunk-3JSXJSMT.js.map +0 -1
- package/dist/chunk-432HHLSB.cjs +0 -5
- package/dist/chunk-432HHLSB.cjs.map +0 -1
- package/dist/chunk-5QA3BI4V.js +0 -3
- package/dist/chunk-5QA3BI4V.js.map +0 -1
- package/dist/chunk-6W3JFXPQ.cjs +0 -2
- package/dist/chunk-6W3JFXPQ.cjs.map +0 -1
- package/dist/chunk-7PUNL5CJ.cjs.map +0 -1
- package/dist/chunk-EPLOL7WC.cjs +0 -2
- package/dist/chunk-EPLOL7WC.cjs.map +0 -1
- package/dist/chunk-HNXV35Q2.cjs +0 -2
- package/dist/chunk-HNXV35Q2.cjs.map +0 -1
- package/dist/chunk-JM7BIFF4.js +0 -5
- package/dist/chunk-JM7BIFF4.js.map +0 -1
- package/dist/chunk-JZQRUOO6.js +0 -2
- package/dist/chunk-JZQRUOO6.js.map +0 -1
- package/dist/chunk-K2OUNZZG.cjs +0 -2
- package/dist/chunk-K2OUNZZG.cjs.map +0 -1
- package/dist/chunk-LJIR7MLG.cjs +0 -3
- package/dist/chunk-LJIR7MLG.cjs.map +0 -1
- package/dist/chunk-SIUHB77U.js +0 -2
- package/dist/chunk-SIUHB77U.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { a as PrecedenceParser, b as PrefixParselet, I as InfixParselet } from '
|
|
|
2
2
|
import { M as MarkdownLineType, L as Lexer, e as TokenCategory, c as LexerVocabulary } from './Lexer-DaWkCu84.cjs';
|
|
3
3
|
import { IAsyncResolver } from './resolvers.cjs';
|
|
4
4
|
import { T as TokenFusion, c as TokenNormalizer, a as NormalizerRule } from './TokenNormalizer-D382VSYh.cjs';
|
|
5
|
-
import { b as VMCheckpointer, D as DependencyGraph, V as VM, h as DagSnapshot, i as EngineContext, S as ScopeManager, P as PluginFunctionHandler, A as AsConverter } from './VMBuiltins-
|
|
5
|
+
import { b as VMCheckpointer, D as DependencyGraph, V as VM, h as DagSnapshot, i as EngineContext, S as ScopeManager, P as PluginFunctionHandler, A as AsConverter } from './VMBuiltins-Baa90D2v.cjs';
|
|
6
6
|
import { V as Value, b as ValueType, D as DatetimeGrain } from './Value-B55Hvn3e.cjs';
|
|
7
7
|
import { a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.cjs';
|
|
8
8
|
import { C as CalendarBackend } from './CalendarBackend-MdS3Bb4P.cjs';
|
|
@@ -2410,6 +2410,8 @@ declare class ExpressionEngine {
|
|
|
2410
2410
|
private builderPool;
|
|
2411
2411
|
private builderPoolIndex;
|
|
2412
2412
|
private lastTelemetry;
|
|
2413
|
+
/** Whether the line being evaluated sits on a cycle; see {@link setLineOnCycle}. */
|
|
2414
|
+
private lineOnCycle;
|
|
2413
2415
|
constructor(options?: EngineOptions);
|
|
2414
2416
|
/**
|
|
2415
2417
|
* Get the native event stream from the batcher for stream-based consumers.
|
|
@@ -2434,6 +2436,81 @@ declare class ExpressionEngine {
|
|
|
2434
2436
|
* Tests use this to access `batcher._testCaptures` for synchronous
|
|
2435
2437
|
* event observation without async stream reader timing issues.
|
|
2436
2438
|
*/
|
|
2439
|
+
/**
|
|
2440
|
+
* Put a name back to what the lines above `lineNumber` left it holding.
|
|
2441
|
+
*
|
|
2442
|
+
* The invariant a pass from scratch keeps without trying: when it reaches a
|
|
2443
|
+
* line, every name holds what the lines above defined, because those lines
|
|
2444
|
+
* have just run in order and stored. The incremental path keeps the VM
|
|
2445
|
+
* between passes, so a line that writes a name can find the name holding
|
|
2446
|
+
* its own previous answer instead. That is invisible for `:x = 5`, which
|
|
2447
|
+
* stores over it, and wrong twice over for a definition that reads what it
|
|
2448
|
+
* writes or fails to store:
|
|
2449
|
+
*
|
|
2450
|
+
* - `:v3 = 44` above `:v3 = v3 + 3` is 47 on every pass from scratch, since
|
|
2451
|
+
* line 1 puts 44 back each time. Edit line 1 away and nothing puts
|
|
2452
|
+
* anything back, so line 2 reads its own 47 and climbs by three a pass,
|
|
2453
|
+
* where a pass from scratch says `v3` is undefined.
|
|
2454
|
+
* - `:x = 5` edited to `:x = zz + 1` skips the store, on both paths, and
|
|
2455
|
+
* the incremental one is left holding the 5 the same line stored before
|
|
2456
|
+
* the edit, where a pass from scratch has nothing.
|
|
2457
|
+
*
|
|
2458
|
+
* The checkpoint chain records what each line wrote in document order, so
|
|
2459
|
+
* the value the prefix holds is the one it holds just before this line,
|
|
2460
|
+
* and this puts the VM there: the value if there is one, absent if not.
|
|
2461
|
+
* The evaluator calls it before a definition runs and again if it fails,
|
|
2462
|
+
* both times before the line's own checkpoint is taken, so the checkpoint
|
|
2463
|
+
* records the corrected state.
|
|
2464
|
+
*
|
|
2465
|
+
* A function is a definition too, and was the one kind nothing could
|
|
2466
|
+
* undo: `f(x) = x + 4` edited into a blank left `f(9)` answering 13 for
|
|
2467
|
+
* the rest of the session. The prefix is consulted for a function binding
|
|
2468
|
+
* as well as a variable one, and each is put back on its own, since a
|
|
2469
|
+
* name can be bound in both bags at once (`f(x) = x + 1` above `:f = 4`).
|
|
2470
|
+
* A name bound to neither above is unbound from both.
|
|
2471
|
+
*
|
|
2472
|
+
* An accumulator is left alone. Every pass resets each running total to
|
|
2473
|
+
* its seed and re-runs every line that steps it, in order, so by the time
|
|
2474
|
+
* any step runs the VM already holds what the steps above built, seed
|
|
2475
|
+
* included, and putting the prefix back would only undo a step.
|
|
2476
|
+
*
|
|
2477
|
+
* @param name - The name the line writes.
|
|
2478
|
+
* @param lineNumber - The 1-based line it sits on.
|
|
2479
|
+
*/
|
|
2480
|
+
restoreToPrefix(name: string, lineNumber: number): void;
|
|
2481
|
+
/**
|
|
2482
|
+
* Whether `name` is a running total, stepped by `+=` or `-=` somewhere.
|
|
2483
|
+
*
|
|
2484
|
+
* The evaluator's cycle walk asks, because a total's steppers depend on one
|
|
2485
|
+
* another through the total in a way the graph deliberately does not
|
|
2486
|
+
* record: a line is kept out of the consumers of a name it writes, which
|
|
2487
|
+
* is right for `:x = 5` and hides the fold for `spent += 5`.
|
|
2488
|
+
*
|
|
2489
|
+
* @param name - A variable name.
|
|
2490
|
+
* @returns True when a line has stepped it.
|
|
2491
|
+
*/
|
|
2492
|
+
/**
|
|
2493
|
+
* Tell the engine whether the line about to run sits on a cycle.
|
|
2494
|
+
*
|
|
2495
|
+
* A line that depends on itself, through positions or names or both, has
|
|
2496
|
+
* no answer of its own: each value it could hold is computed from that same
|
|
2497
|
+
* value a pass earlier. A single fresh pass reports that, because some
|
|
2498
|
+
* member reads a line below it that has not run, and the error travels all
|
|
2499
|
+
* the way round. The incremental path carries the VM between passes, so a
|
|
2500
|
+
* member could find a number to start from, and the pair then chased it.
|
|
2501
|
+
*
|
|
2502
|
+
* While this is set, a positional read of a line below the one running
|
|
2503
|
+
* answers as an unevaluated line does, which is what makes a member report
|
|
2504
|
+
* the cycle rather than the number it read last pass. The evaluator sets it
|
|
2505
|
+
* per line from the cycle membership it keeps, and puts the names such a
|
|
2506
|
+
* line reads back to the prefix before it runs, for the same reason. A line
|
|
2507
|
+
* not on a cycle keeps the incremental path's tolerance of a plain forward
|
|
2508
|
+
* reference, which resolves by running the document again.
|
|
2509
|
+
*
|
|
2510
|
+
* @param onCycle - Whether the line about to run is on a cycle.
|
|
2511
|
+
*/
|
|
2512
|
+
setLineOnCycle(onCycle: boolean): void;
|
|
2513
|
+
isAccumulatorName(name: string): boolean;
|
|
2437
2514
|
/** The names of every user-defined unit in scope, for detecting a removal. */
|
|
2438
2515
|
userUnitNames(): string[];
|
|
2439
2516
|
/**
|
|
@@ -2,7 +2,7 @@ import { a as PrecedenceParser, b as PrefixParselet, I as InfixParselet } from '
|
|
|
2
2
|
import { M as MarkdownLineType, L as Lexer, e as TokenCategory, c as LexerVocabulary } from './Lexer-DPn5dfCH.js';
|
|
3
3
|
import { IAsyncResolver } from './resolvers.js';
|
|
4
4
|
import { T as TokenFusion, c as TokenNormalizer, a as NormalizerRule } from './TokenNormalizer-DAzPp-j1.js';
|
|
5
|
-
import { b as VMCheckpointer, D as DependencyGraph, V as VM, h as DagSnapshot, i as EngineContext, S as ScopeManager, P as PluginFunctionHandler, A as AsConverter } from './VMBuiltins-
|
|
5
|
+
import { b as VMCheckpointer, D as DependencyGraph, V as VM, h as DagSnapshot, i as EngineContext, S as ScopeManager, P as PluginFunctionHandler, A as AsConverter } from './VMBuiltins-BqkoJtHt.js';
|
|
6
6
|
import { V as Value, b as ValueType, D as DatetimeGrain } from './Value-B55Hvn3e.js';
|
|
7
7
|
import { a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.js';
|
|
8
8
|
import { C as CalendarBackend } from './CalendarBackend-MdS3Bb4P.js';
|
|
@@ -2410,6 +2410,8 @@ declare class ExpressionEngine {
|
|
|
2410
2410
|
private builderPool;
|
|
2411
2411
|
private builderPoolIndex;
|
|
2412
2412
|
private lastTelemetry;
|
|
2413
|
+
/** Whether the line being evaluated sits on a cycle; see {@link setLineOnCycle}. */
|
|
2414
|
+
private lineOnCycle;
|
|
2413
2415
|
constructor(options?: EngineOptions);
|
|
2414
2416
|
/**
|
|
2415
2417
|
* Get the native event stream from the batcher for stream-based consumers.
|
|
@@ -2434,6 +2436,81 @@ declare class ExpressionEngine {
|
|
|
2434
2436
|
* Tests use this to access `batcher._testCaptures` for synchronous
|
|
2435
2437
|
* event observation without async stream reader timing issues.
|
|
2436
2438
|
*/
|
|
2439
|
+
/**
|
|
2440
|
+
* Put a name back to what the lines above `lineNumber` left it holding.
|
|
2441
|
+
*
|
|
2442
|
+
* The invariant a pass from scratch keeps without trying: when it reaches a
|
|
2443
|
+
* line, every name holds what the lines above defined, because those lines
|
|
2444
|
+
* have just run in order and stored. The incremental path keeps the VM
|
|
2445
|
+
* between passes, so a line that writes a name can find the name holding
|
|
2446
|
+
* its own previous answer instead. That is invisible for `:x = 5`, which
|
|
2447
|
+
* stores over it, and wrong twice over for a definition that reads what it
|
|
2448
|
+
* writes or fails to store:
|
|
2449
|
+
*
|
|
2450
|
+
* - `:v3 = 44` above `:v3 = v3 + 3` is 47 on every pass from scratch, since
|
|
2451
|
+
* line 1 puts 44 back each time. Edit line 1 away and nothing puts
|
|
2452
|
+
* anything back, so line 2 reads its own 47 and climbs by three a pass,
|
|
2453
|
+
* where a pass from scratch says `v3` is undefined.
|
|
2454
|
+
* - `:x = 5` edited to `:x = zz + 1` skips the store, on both paths, and
|
|
2455
|
+
* the incremental one is left holding the 5 the same line stored before
|
|
2456
|
+
* the edit, where a pass from scratch has nothing.
|
|
2457
|
+
*
|
|
2458
|
+
* The checkpoint chain records what each line wrote in document order, so
|
|
2459
|
+
* the value the prefix holds is the one it holds just before this line,
|
|
2460
|
+
* and this puts the VM there: the value if there is one, absent if not.
|
|
2461
|
+
* The evaluator calls it before a definition runs and again if it fails,
|
|
2462
|
+
* both times before the line's own checkpoint is taken, so the checkpoint
|
|
2463
|
+
* records the corrected state.
|
|
2464
|
+
*
|
|
2465
|
+
* A function is a definition too, and was the one kind nothing could
|
|
2466
|
+
* undo: `f(x) = x + 4` edited into a blank left `f(9)` answering 13 for
|
|
2467
|
+
* the rest of the session. The prefix is consulted for a function binding
|
|
2468
|
+
* as well as a variable one, and each is put back on its own, since a
|
|
2469
|
+
* name can be bound in both bags at once (`f(x) = x + 1` above `:f = 4`).
|
|
2470
|
+
* A name bound to neither above is unbound from both.
|
|
2471
|
+
*
|
|
2472
|
+
* An accumulator is left alone. Every pass resets each running total to
|
|
2473
|
+
* its seed and re-runs every line that steps it, in order, so by the time
|
|
2474
|
+
* any step runs the VM already holds what the steps above built, seed
|
|
2475
|
+
* included, and putting the prefix back would only undo a step.
|
|
2476
|
+
*
|
|
2477
|
+
* @param name - The name the line writes.
|
|
2478
|
+
* @param lineNumber - The 1-based line it sits on.
|
|
2479
|
+
*/
|
|
2480
|
+
restoreToPrefix(name: string, lineNumber: number): void;
|
|
2481
|
+
/**
|
|
2482
|
+
* Whether `name` is a running total, stepped by `+=` or `-=` somewhere.
|
|
2483
|
+
*
|
|
2484
|
+
* The evaluator's cycle walk asks, because a total's steppers depend on one
|
|
2485
|
+
* another through the total in a way the graph deliberately does not
|
|
2486
|
+
* record: a line is kept out of the consumers of a name it writes, which
|
|
2487
|
+
* is right for `:x = 5` and hides the fold for `spent += 5`.
|
|
2488
|
+
*
|
|
2489
|
+
* @param name - A variable name.
|
|
2490
|
+
* @returns True when a line has stepped it.
|
|
2491
|
+
*/
|
|
2492
|
+
/**
|
|
2493
|
+
* Tell the engine whether the line about to run sits on a cycle.
|
|
2494
|
+
*
|
|
2495
|
+
* A line that depends on itself, through positions or names or both, has
|
|
2496
|
+
* no answer of its own: each value it could hold is computed from that same
|
|
2497
|
+
* value a pass earlier. A single fresh pass reports that, because some
|
|
2498
|
+
* member reads a line below it that has not run, and the error travels all
|
|
2499
|
+
* the way round. The incremental path carries the VM between passes, so a
|
|
2500
|
+
* member could find a number to start from, and the pair then chased it.
|
|
2501
|
+
*
|
|
2502
|
+
* While this is set, a positional read of a line below the one running
|
|
2503
|
+
* answers as an unevaluated line does, which is what makes a member report
|
|
2504
|
+
* the cycle rather than the number it read last pass. The evaluator sets it
|
|
2505
|
+
* per line from the cycle membership it keeps, and puts the names such a
|
|
2506
|
+
* line reads back to the prefix before it runs, for the same reason. A line
|
|
2507
|
+
* not on a cycle keeps the incremental path's tolerance of a plain forward
|
|
2508
|
+
* reference, which resolves by running the document again.
|
|
2509
|
+
*
|
|
2510
|
+
* @param onCycle - Whether the line about to run is on a cycle.
|
|
2511
|
+
*/
|
|
2512
|
+
setLineOnCycle(onCycle: boolean): void;
|
|
2513
|
+
isAccumulatorName(name: string): boolean;
|
|
2437
2514
|
/** The names of every user-defined unit in scope, for detecting a removal. */
|
|
2438
2515
|
userUnitNames(): string[];
|
|
2439
2516
|
/**
|
|
@@ -81,6 +81,21 @@ interface Bytecode {
|
|
|
81
81
|
interface LineExecutionContext {
|
|
82
82
|
/** 1-based current line number, or -1 when there is no real document (see class doc above). */
|
|
83
83
|
lineIndex: number;
|
|
84
|
+
/**
|
|
85
|
+
* How many lines the document has now; absent when there is no document.
|
|
86
|
+
*
|
|
87
|
+
* A form that declares a span before reading it (see `noteLineRead`) needs
|
|
88
|
+
* to know where the document ends: a range written as `line 1 : line
|
|
89
|
+
* 3000000` has no line to read past the last one, and declaring three
|
|
90
|
+
* million positions that exist nowhere cost the heap for nothing. The
|
|
91
|
+
* walk that reads the span already stops at the first line it cannot use.
|
|
92
|
+
*
|
|
93
|
+
* Asked for rather than copied, because one context serves a document for
|
|
94
|
+
* as long as it is open: a count taken when the context was built was the
|
|
95
|
+
* count before the last insert, and a range declared under it stopped a
|
|
96
|
+
* line short.
|
|
97
|
+
*/
|
|
98
|
+
getLineCount?: () => number;
|
|
84
99
|
/**
|
|
85
100
|
* Whether this engine may fetch live data (`network.enabled`). A plugin
|
|
86
101
|
* function that reads a resolver's cache uses it to say "live data is
|
|
@@ -98,6 +113,19 @@ interface LineExecutionContext {
|
|
|
98
113
|
calendar?: CalendarBackend;
|
|
99
114
|
/** Look up another line's cached result by 1-based line number. `undefined` = not evaluated yet (or out of range), distinct from a line that evaluated to an actual `undefined`-like Value, which can't happen (every Value type has a concrete representation). */
|
|
100
115
|
getLineResult?: (lineNumber: number) => Value | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Say that this line is about to read `lineNumber`, before reading it.
|
|
118
|
+
*
|
|
119
|
+
* A form that reads several lines stops at the first it cannot use, so the
|
|
120
|
+
* lines after that one are never read and, if reading were the only way
|
|
121
|
+
* the dependency graph learned of a read, never recorded. A cycle that
|
|
122
|
+
* closes through one of those lines was then invisible from scratch and
|
|
123
|
+
* visible from a history that had once read the whole span, and the two
|
|
124
|
+
* paths disagreed about whether the line was on a cycle at all. A form
|
|
125
|
+
* declares its whole span through this first, so what the graph knows does
|
|
126
|
+
* not depend on how far the form got. Absent where there is no document.
|
|
127
|
+
*/
|
|
128
|
+
noteLineRead?: (lineNumber: number) => void;
|
|
101
129
|
/**
|
|
102
130
|
* The 1-based positions of the lines carrying `#tag`, ascending, or
|
|
103
131
|
* `undefined` when this path keeps no index and the caller should walk the
|
|
@@ -519,6 +547,8 @@ interface VM {
|
|
|
519
547
|
defineUserFunction(name: string, params: string[], program: BytecodeProgram): void;
|
|
520
548
|
getUserFunction(name: string): UserFunctionDef | undefined;
|
|
521
549
|
hasUserFunction(name: string): boolean;
|
|
550
|
+
/** Unbind a user function, for a definition edited away, deleted, or failed. */
|
|
551
|
+
deleteUserFunction(name: string): void;
|
|
522
552
|
/**
|
|
523
553
|
* Every session-scoped variable currently defined, as `[name, value]` pairs,
|
|
524
554
|
* for snapshotting the VM's state (see `engine/EngineSnapshot.ts`). The
|
|
@@ -662,6 +692,46 @@ declare class DependencyGraph {
|
|
|
662
692
|
*/
|
|
663
693
|
private lastPositionReader;
|
|
664
694
|
private lastPositionReads;
|
|
695
|
+
/**
|
|
696
|
+
* Readers that recorded a position they had not been recorded reading,
|
|
697
|
+
* since the evaluator last took the list.
|
|
698
|
+
*
|
|
699
|
+
* A positional edge can close a cycle, and the moment it is recorded is the
|
|
700
|
+
* one moment that is knowable: the reader has just run its current text,
|
|
701
|
+
* so the edge is real, and every other edge in the graph describes the
|
|
702
|
+
* last run of the line that holds it. The evaluator takes the list at the
|
|
703
|
+
* end of each pass and looks for a cycle through each reader on it; see
|
|
704
|
+
* `ThreeTierEvaluator.settleCycles`. A line that only
|
|
705
|
+
* re-recorded edges it already had is not on it, which is every line of
|
|
706
|
+
* every pass once a document has settled.
|
|
707
|
+
*/
|
|
708
|
+
private readersThatGainedAPosition;
|
|
709
|
+
/**
|
|
710
|
+
* How many recorded positional edges point downwards, from a reader to a
|
|
711
|
+
* line below it.
|
|
712
|
+
*
|
|
713
|
+
* A cycle needs one. Every edge in a document of `prev` and `above` points
|
|
714
|
+
* upwards, positions fall strictly along any path, and no path can come
|
|
715
|
+
* back to where it started. So the evaluator asks this before walking
|
|
716
|
+
* anything, and a document with no forward reference never pays for the
|
|
717
|
+
* walk at all, which is nearly every document and every pass after the one
|
|
718
|
+
* that closed a cycle.
|
|
719
|
+
*/
|
|
720
|
+
private downwardPositionReads;
|
|
721
|
+
/**
|
|
722
|
+
* Lines that registered a different edge set since the evaluator last
|
|
723
|
+
* asked, and the keys whose producer set changed.
|
|
724
|
+
*
|
|
725
|
+
* The roots of the end-of-pass cycle walk. A cycle is closed, or a name that
|
|
726
|
+
* pinned one is withdrawn, by a change in the graph; nothing else creates
|
|
727
|
+
* one. A line that re-registers the edges it had is not on the list, which
|
|
728
|
+
* is every line of a settled pass, and it is also a line that is dirty
|
|
729
|
+
* because it threw, which stays dirty and re-runs every pass: rooting the
|
|
730
|
+
* walk on "ran" rather than "changed" made such a line reset its cycle on
|
|
731
|
+
* alternate passes for ever. Taken and cleared by {@link takeEdgeChanges}.
|
|
732
|
+
*/
|
|
733
|
+
private edgesChangedThisPass;
|
|
734
|
+
private producersChangedThisPass;
|
|
665
735
|
/**
|
|
666
736
|
* Whether this line already carries exactly these edges.
|
|
667
737
|
*
|
|
@@ -729,6 +799,90 @@ declare class DependencyGraph {
|
|
|
729
799
|
* @param dependsOnLine - 1-based line whose result it read
|
|
730
800
|
*/
|
|
731
801
|
registerLinePositionDependency(lineNumber: number, dependsOnLine: number): void;
|
|
802
|
+
/**
|
|
803
|
+
* Cut a line's recorded positions back to the ones its last run read.
|
|
804
|
+
*
|
|
805
|
+
* For the evaluator to call once a line has executed. A positional read is
|
|
806
|
+
* discovered while the line runs, and a position the line has stopped
|
|
807
|
+
* reading cannot be discovered that way, so without this the recorded set
|
|
808
|
+
* only ever grew: `prev + 1` edited to `7` went on reading line 1 in the
|
|
809
|
+
* graph for the rest of the session, and `total above` kept its edges to
|
|
810
|
+
* the lines above a heading that had cut its block short. Anything asking
|
|
811
|
+
* the graph what a line reads was told what it used to read, and a cycle
|
|
812
|
+
* that the heading had broken was still a cycle to the graph, while a cycle
|
|
813
|
+
* that its removal re-closed was not new to it and so was never noticed.
|
|
814
|
+
*
|
|
815
|
+
* A run that read no position at all leaves the line with none. A line
|
|
816
|
+
* that did not execute (compiled only, or skipped) must not be reconciled,
|
|
817
|
+
* since it read nothing for a reason that says nothing about its text.
|
|
818
|
+
*
|
|
819
|
+
* @param lineNumber - 1-based line that has just executed
|
|
820
|
+
*/
|
|
821
|
+
reconcilePositionReads(lineNumber: number): void;
|
|
822
|
+
/**
|
|
823
|
+
* Forget every position this line was recorded reading.
|
|
824
|
+
*
|
|
825
|
+
* For a line whose text has just changed, before it runs: whatever the old
|
|
826
|
+
* text read is not evidence about the new one, and a rule consulting the
|
|
827
|
+
* graph between the edit and the run would otherwise be told the old
|
|
828
|
+
* edges. The next run records what the new text reads. Only the `line:`
|
|
829
|
+
* keys go; a data-source pin is discovered the same way but is not about
|
|
830
|
+
* the text, and stays until the line is removed.
|
|
831
|
+
*
|
|
832
|
+
* @param lineNumber - 1-based line whose positions are to go
|
|
833
|
+
*/
|
|
834
|
+
forgetPositionReads(lineNumber: number): void;
|
|
835
|
+
/**
|
|
836
|
+
* The positions a line has been recorded reading, as line numbers.
|
|
837
|
+
*
|
|
838
|
+
* The forward direction of {@link getAffectedLinesByPosition}: that answers
|
|
839
|
+
* "who reads this position", this answers "which positions does this line
|
|
840
|
+
* read". Both directions are what finding a cycle takes.
|
|
841
|
+
*
|
|
842
|
+
* @param lineNumber - 1-based line doing the reading
|
|
843
|
+
* @returns The positions it has read, in no particular order; empty if none
|
|
844
|
+
*/
|
|
845
|
+
positionsReadBy(lineNumber: number): number[];
|
|
846
|
+
/**
|
|
847
|
+
* The readers that recorded a new position since this was last called, and
|
|
848
|
+
* an empty list until one does.
|
|
849
|
+
*
|
|
850
|
+
* Taking the list clears it. See {@link readersThatGainedAPosition}.
|
|
851
|
+
*
|
|
852
|
+
* @returns The 1-based readers, in the order they recorded
|
|
853
|
+
*/
|
|
854
|
+
/**
|
|
855
|
+
* What changed in the graph since this was last called: the lines whose
|
|
856
|
+
* edge set changed, and the keys whose producer set changed. Taking it
|
|
857
|
+
* clears it. See {@link edgesChangedThisPass}.
|
|
858
|
+
*
|
|
859
|
+
* @returns The changed lines and keys, each possibly empty.
|
|
860
|
+
*/
|
|
861
|
+
takeEdgeChanges(): {
|
|
862
|
+
lines: readonly number[];
|
|
863
|
+
keys: readonly string[];
|
|
864
|
+
};
|
|
865
|
+
takeReadersThatGainedAPosition(): readonly number[];
|
|
866
|
+
/**
|
|
867
|
+
* Whether any recorded positional edge points from a reader to a line
|
|
868
|
+
* below it.
|
|
869
|
+
*
|
|
870
|
+
* The precondition for a positional cycle, and so for the walk that looks
|
|
871
|
+
* for one; see {@link downwardPositionReads}.
|
|
872
|
+
*
|
|
873
|
+
* @returns True while at least one such edge is recorded
|
|
874
|
+
*/
|
|
875
|
+
hasDownwardPositionRead(): boolean;
|
|
876
|
+
/** The positions an entry records, in the recorded half; the same walk {@link positionsReadBy} makes. */
|
|
877
|
+
private positionsReadFrom;
|
|
878
|
+
/**
|
|
879
|
+
* Drop one positional edge from every index that holds it.
|
|
880
|
+
*
|
|
881
|
+
* The consumer index is what says whether the edge exists, so a position the
|
|
882
|
+
* entry lists twice (in the set, and later inside the span that grew over
|
|
883
|
+
* it) is dropped once and counted once.
|
|
884
|
+
*/
|
|
885
|
+
private dropPositionRead;
|
|
732
886
|
/**
|
|
733
887
|
* Every line that read some position's result, whichever position it was.
|
|
734
888
|
*
|
|
@@ -796,6 +950,20 @@ declare class DependencyGraph {
|
|
|
796
950
|
* @param key - The key, from {@link edgeKey}
|
|
797
951
|
* @returns Set of line numbers that write this key, or empty set if none
|
|
798
952
|
*/
|
|
953
|
+
/**
|
|
954
|
+
* The lines that read `key`, one edge away.
|
|
955
|
+
*
|
|
956
|
+
* The consumer index, which {@link registerLine} keeps clear of the line
|
|
957
|
+
* that writes the key: a definition's read of its own name is a convention
|
|
958
|
+
* for the graph's benefit, not a dependency, and `x += 1` reads its total
|
|
959
|
+
* to step it, not to depend on another line. That is what makes this index
|
|
960
|
+
* the right one for finding a cycle, where the raw reads would make every
|
|
961
|
+
* definition a self-loop and every twice-defined name a two-cycle.
|
|
962
|
+
*
|
|
963
|
+
* @param key - An edge key.
|
|
964
|
+
* @returns The 1-based readers, or an empty set.
|
|
965
|
+
*/
|
|
966
|
+
directConsumersOf(key: string): ReadonlySet<number>;
|
|
799
967
|
getProducers(key: string): ReadonlySet<number>;
|
|
800
968
|
/**
|
|
801
969
|
* The keys a line that WRITES something reads.
|
|
@@ -1010,9 +1178,13 @@ declare class VMCheckpointer {
|
|
|
1010
1178
|
* @param lineNumber 1-based line position.
|
|
1011
1179
|
* @param lineId Persistent line ID from DocumentModel.
|
|
1012
1180
|
* @param variableNames Names of variables that were written at this line.
|
|
1181
|
+
* @param functionNames Which of those names the line defined as functions,
|
|
1182
|
+
* from the bytecode it ran. Without it the VM is asked, which cannot tell
|
|
1183
|
+
* a line that defined `f` from one that set the variable `f` under a
|
|
1184
|
+
* function of that name defined above.
|
|
1013
1185
|
* @returns The new checkpoint, or null if no variable names provided.
|
|
1014
1186
|
*/
|
|
1015
|
-
snapshot(lineNumber: number, lineId: number, variableNames: string[]): VMCheckpoint | null;
|
|
1187
|
+
snapshot(lineNumber: number, lineId: number, variableNames: string[], functionNames?: ReadonlySet<string>): VMCheckpoint | null;
|
|
1016
1188
|
/**
|
|
1017
1189
|
* Restore the VM to the state at or just after the given line number.
|
|
1018
1190
|
*
|
|
@@ -1087,6 +1259,33 @@ declare class VMCheckpointer {
|
|
|
1087
1259
|
*
|
|
1088
1260
|
* @param names - The names no line defines any more.
|
|
1089
1261
|
*/
|
|
1262
|
+
/**
|
|
1263
|
+
* Drop the entry a line holds, because the line no longer writes anything.
|
|
1264
|
+
*
|
|
1265
|
+
* A line's entry is replaced when the line writes again and left alone
|
|
1266
|
+
* otherwise, so a definition edited into an expression with no definition in
|
|
1267
|
+
* it (`:v3 = 44` edited to `7 + 7`) kept saying `v3 = 44` in the chain. The
|
|
1268
|
+
* lines below it that asked what the prefix holds were told 44, where a pass
|
|
1269
|
+
* from scratch has nothing there. The entry after it is re-parented to the
|
|
1270
|
+
* one before, the same way {@link snapshot} keeps the links straight.
|
|
1271
|
+
*
|
|
1272
|
+
* @param lineNumber - 1-based line whose entry, if any, goes.
|
|
1273
|
+
*/
|
|
1274
|
+
dropCheckpointAt(lineNumber: number): void;
|
|
1275
|
+
/**
|
|
1276
|
+
* Follow every line to its new position after a structural edit.
|
|
1277
|
+
*
|
|
1278
|
+
* An insert or a delete moves every line below it, and the chain is read
|
|
1279
|
+
* by position. It used to be cleared instead and rebuilt as lines ran, but
|
|
1280
|
+
* a clean line above the viewport never runs, so its entry was gone for
|
|
1281
|
+
* good and a line below asking what the prefix held was told nothing:
|
|
1282
|
+
* `:a = 5` above the viewport was reported as undefined by `:b = a + c`
|
|
1283
|
+
* under it. Each entry follows its line by id, the entry of a deleted
|
|
1284
|
+
* line goes, and the parents are linked again in the new order.
|
|
1285
|
+
*
|
|
1286
|
+
* @param positionOf - The 1-based position a line id has now, or -1 for a line that is gone.
|
|
1287
|
+
*/
|
|
1288
|
+
renumber(positionOf: (lineId: number) => number): void;
|
|
1090
1289
|
forget(names: readonly string[]): void;
|
|
1091
1290
|
/**
|
|
1092
1291
|
* Find the nearest checkpoint at or before the given line number.
|
|
@@ -1122,6 +1321,38 @@ declare class VMCheckpointer {
|
|
|
1122
1321
|
*
|
|
1123
1322
|
* @returns The Value, or undefined if the variable was never set.
|
|
1124
1323
|
*/
|
|
1324
|
+
/**
|
|
1325
|
+
* The value a name held at the end of the line before `lineNumber`, or
|
|
1326
|
+
* undefined if no line above it had set one.
|
|
1327
|
+
*
|
|
1328
|
+
* What a definition that failed leaves behind. A pass from scratch skips
|
|
1329
|
+
* the store when the right-hand side errors, so the name keeps whatever the
|
|
1330
|
+
* lines above it had put there: `:x = 1` then `:x = zz` leaves `x` at 1,
|
|
1331
|
+
* and `:x = zz` on its own leaves it undefined. The incremental path holds
|
|
1332
|
+
* the value from the previous pass instead, which for the line that failed
|
|
1333
|
+
* is its own old answer, so the evaluator asks here what the prefix holds
|
|
1334
|
+
* and puts that back. The chain records what each line wrote, in document
|
|
1335
|
+
* order, so the entry nearest before the line, followed through its
|
|
1336
|
+
* parents, is exactly the prefix.
|
|
1337
|
+
*
|
|
1338
|
+
* @param name - The variable.
|
|
1339
|
+
* @param lineNumber - The 1-based line whose own entry is to be excluded.
|
|
1340
|
+
* @returns The value the lines above set, or undefined.
|
|
1341
|
+
*/
|
|
1342
|
+
/**
|
|
1343
|
+
* The function a name was bound to at the end of the line before
|
|
1344
|
+
* `lineNumber`, or undefined if no line above it had defined one.
|
|
1345
|
+
*
|
|
1346
|
+
* {@link lookupVariableBefore}, for the functions bag: a function
|
|
1347
|
+
* definition is a definition, and one edited away or failed leaves the name
|
|
1348
|
+
* as the lines above left it just as a variable does.
|
|
1349
|
+
*
|
|
1350
|
+
* @param name - The function name.
|
|
1351
|
+
* @param lineNumber - The 1-based line whose own entry is to be excluded.
|
|
1352
|
+
* @returns The definition the lines above made, or undefined.
|
|
1353
|
+
*/
|
|
1354
|
+
lookupFunctionBefore(name: string, lineNumber: number): UserFunctionDef | undefined;
|
|
1355
|
+
lookupVariableBefore(name: string, lineNumber: number): Value | undefined;
|
|
1125
1356
|
lookupVariable(name: string): Value | undefined;
|
|
1126
1357
|
/**
|
|
1127
1358
|
* Clear all checkpoints. The underlying VM is NOT reset, call
|