solve-engine 1.0.0-beta.0 → 1.0.0-beta.2
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/BytecodeBuilder-3egMyuDi.d.cts +274 -0
- package/dist/BytecodeBuilder-3egMyuDi.d.ts +274 -0
- package/dist/Configuration-fVpd-HC-.d.cts +228 -0
- package/dist/Configuration-fVpd-HC-.d.ts +228 -0
- package/dist/EngineError-DvPSnhZi.d.cts +304 -0
- package/dist/EngineError-DvPSnhZi.d.ts +304 -0
- package/dist/Lexer-BJdhlnej.d.cts +531 -0
- package/dist/Lexer-D9l4Yrk2.d.ts +531 -0
- package/dist/NormalizerRule-BrVoVjmP.d.cts +163 -0
- package/dist/NormalizerRule-CEjf1FyD.d.ts +163 -0
- package/dist/PackageRegistry-D-Tv_7ca.d.cts +2572 -0
- package/dist/PackageRegistry-DaH4aIKP.d.ts +2572 -0
- package/dist/Parselet-CK8cQu2a.d.cts +299 -0
- package/dist/Parselet-ConOIdRO.d.ts +299 -0
- package/dist/ScopeManager-B5k0nk05.d.ts +559 -0
- package/dist/ScopeManager-CKfQtl7l.d.cts +559 -0
- package/dist/Token-0jpvUdPY.d.cts +245 -0
- package/dist/Token-0jpvUdPY.d.ts +245 -0
- package/dist/VMCheckpoints-BmDwIXgK.d.ts +171 -0
- package/dist/VMCheckpoints-CqFuLwrT.d.cts +171 -0
- package/dist/Value-KtAQNHur.d.cts +295 -0
- package/dist/Value-KtAQNHur.d.ts +295 -0
- package/dist/chunk-2RWAXT6O.js +3 -0
- package/dist/chunk-2RWAXT6O.js.map +1 -0
- package/dist/chunk-34RRD7PC.js +1492 -0
- package/dist/chunk-34RRD7PC.js.map +1 -0
- package/dist/chunk-3PPFLFH4.js +5097 -0
- package/dist/chunk-3PPFLFH4.js.map +1 -0
- package/dist/chunk-3VGDNEE3.js +84 -0
- package/dist/chunk-3VGDNEE3.js.map +1 -0
- package/dist/chunk-3YNVWKR2.cjs +370 -0
- package/dist/chunk-3YNVWKR2.cjs.map +1 -0
- package/dist/chunk-47LRVGOT.cjs +316 -0
- package/dist/chunk-47LRVGOT.cjs.map +1 -0
- package/dist/chunk-4MG4XKO2.js +1644 -0
- package/dist/chunk-4MG4XKO2.js.map +1 -0
- package/dist/chunk-4QADQTWS.js +2392 -0
- package/dist/chunk-4QADQTWS.js.map +1 -0
- package/dist/chunk-53B6KDDJ.cjs +1651 -0
- package/dist/chunk-53B6KDDJ.cjs.map +1 -0
- package/dist/chunk-5X2PTP6F.cjs +104 -0
- package/dist/chunk-5X2PTP6F.cjs.map +1 -0
- package/dist/chunk-5YEMOYSE.js +264 -0
- package/dist/chunk-5YEMOYSE.js.map +1 -0
- package/dist/chunk-64W6GLLZ.js +481 -0
- package/dist/chunk-64W6GLLZ.js.map +1 -0
- package/dist/chunk-6BKTCEUP.cjs +233 -0
- package/dist/chunk-6BKTCEUP.cjs.map +1 -0
- package/dist/chunk-6NTVRDQV.cjs +1642 -0
- package/dist/chunk-6NTVRDQV.cjs.map +1 -0
- package/dist/chunk-6RDSQURE.js +290 -0
- package/dist/chunk-6RDSQURE.js.map +1 -0
- package/dist/chunk-75JP4BZX.js +93 -0
- package/dist/chunk-75JP4BZX.js.map +1 -0
- package/dist/chunk-B7LXJ6LC.cjs +36 -0
- package/dist/chunk-B7LXJ6LC.cjs.map +1 -0
- package/dist/chunk-BVAR5J2F.js +257 -0
- package/dist/chunk-BVAR5J2F.js.map +1 -0
- package/dist/chunk-C4XZV6E7.cjs +269 -0
- package/dist/chunk-C4XZV6E7.cjs.map +1 -0
- package/dist/chunk-CCJPSHGI.cjs +40 -0
- package/dist/chunk-CCJPSHGI.cjs.map +1 -0
- package/dist/chunk-CLL7RUQV.cjs +316 -0
- package/dist/chunk-CLL7RUQV.cjs.map +1 -0
- package/dist/chunk-DM3LMRBC.js +329 -0
- package/dist/chunk-DM3LMRBC.js.map +1 -0
- package/dist/chunk-DUEZFTK2.js +38 -0
- package/dist/chunk-DUEZFTK2.js.map +1 -0
- package/dist/chunk-EBSPLUW4.cjs +489 -0
- package/dist/chunk-EBSPLUW4.cjs.map +1 -0
- package/dist/chunk-EHAHVROS.cjs +261 -0
- package/dist/chunk-EHAHVROS.cjs.map +1 -0
- package/dist/chunk-EIGTWK5N.js +167 -0
- package/dist/chunk-EIGTWK5N.js.map +1 -0
- package/dist/chunk-EPOXXJBK.js +96 -0
- package/dist/chunk-EPOXXJBK.js.map +1 -0
- package/dist/chunk-FEAIOR7N.cjs +91 -0
- package/dist/chunk-FEAIOR7N.cjs.map +1 -0
- package/dist/chunk-G535KJEG.js +312 -0
- package/dist/chunk-G535KJEG.js.map +1 -0
- package/dist/chunk-GCM5JHMX.js +88 -0
- package/dist/chunk-GCM5JHMX.js.map +1 -0
- package/dist/chunk-GOLDJNMZ.js +368 -0
- package/dist/chunk-GOLDJNMZ.js.map +1 -0
- package/dist/chunk-GW32KPCU.cjs +360 -0
- package/dist/chunk-GW32KPCU.cjs.map +1 -0
- package/dist/chunk-HTXVVJRA.cjs +1549 -0
- package/dist/chunk-HTXVVJRA.cjs.map +1 -0
- package/dist/chunk-HWSZJQCI.js +311 -0
- package/dist/chunk-HWSZJQCI.js.map +1 -0
- package/dist/chunk-IF532O7C.js +101 -0
- package/dist/chunk-IF532O7C.js.map +1 -0
- package/dist/chunk-J73SJHR3.cjs +2415 -0
- package/dist/chunk-J73SJHR3.cjs.map +1 -0
- package/dist/chunk-JBSYC7BB.cjs +7473 -0
- package/dist/chunk-JBSYC7BB.cjs.map +1 -0
- package/dist/chunk-KVILKGMS.js +228 -0
- package/dist/chunk-KVILKGMS.js.map +1 -0
- package/dist/chunk-LIPPNDBE.js +258 -0
- package/dist/chunk-LIPPNDBE.js.map +1 -0
- package/dist/chunk-LR7YASZF.cjs +172 -0
- package/dist/chunk-LR7YASZF.cjs.map +1 -0
- package/dist/chunk-M4N5GA5Z.cjs +309 -0
- package/dist/chunk-M4N5GA5Z.cjs.map +1 -0
- package/dist/chunk-M5LX5AOO.js +7459 -0
- package/dist/chunk-M5LX5AOO.js.map +1 -0
- package/dist/chunk-MZOVP3WI.cjs +96 -0
- package/dist/chunk-MZOVP3WI.cjs.map +1 -0
- package/dist/chunk-N5YFR4UP.cjs +10 -0
- package/dist/chunk-N5YFR4UP.cjs.map +1 -0
- package/dist/chunk-NGBBNL4K.cjs +4 -0
- package/dist/chunk-NGBBNL4K.cjs.map +1 -0
- package/dist/chunk-NH2O2AUR.js +146 -0
- package/dist/chunk-NH2O2AUR.js.map +1 -0
- package/dist/chunk-NLNDMWZC.js +31 -0
- package/dist/chunk-NLNDMWZC.js.map +1 -0
- package/dist/chunk-NMCRQP3Z.cjs +778 -0
- package/dist/chunk-NMCRQP3Z.cjs.map +1 -0
- package/dist/chunk-NMD5VRN4.cjs +1327 -0
- package/dist/chunk-NMD5VRN4.cjs.map +1 -0
- package/dist/chunk-OC6LTXYS.cjs +286 -0
- package/dist/chunk-OC6LTXYS.cjs.map +1 -0
- package/dist/chunk-OT6OJY7C.cjs +114 -0
- package/dist/chunk-OT6OJY7C.cjs.map +1 -0
- package/dist/chunk-PFSDGGYL.js +8 -0
- package/dist/chunk-PFSDGGYL.js.map +1 -0
- package/dist/chunk-QNJ4ACRT.cjs +155 -0
- package/dist/chunk-QNJ4ACRT.cjs.map +1 -0
- package/dist/chunk-QWY3VEZN.js +1637 -0
- package/dist/chunk-QWY3VEZN.js.map +1 -0
- package/dist/chunk-RFYD5TJE.js +111 -0
- package/dist/chunk-RFYD5TJE.js.map +1 -0
- package/dist/chunk-RIN643A3.js +354 -0
- package/dist/chunk-RIN643A3.js.map +1 -0
- package/dist/chunk-RZCWSXTA.cjs +5122 -0
- package/dist/chunk-RZCWSXTA.cjs.map +1 -0
- package/dist/chunk-SDGRK7EP.js +774 -0
- package/dist/chunk-SDGRK7EP.js.map +1 -0
- package/dist/chunk-VEKIWQ3F.cjs +39 -0
- package/dist/chunk-VEKIWQ3F.cjs.map +1 -0
- package/dist/chunk-WQTTOGXC.cjs +99 -0
- package/dist/chunk-WQTTOGXC.cjs.map +1 -0
- package/dist/chunk-X6K3HUOY.cjs +86 -0
- package/dist/chunk-X6K3HUOY.cjs.map +1 -0
- package/dist/chunk-XJCMXB2E.cjs +333 -0
- package/dist/chunk-XJCMXB2E.cjs.map +1 -0
- package/dist/chunk-XVWCOTR6.js +1324 -0
- package/dist/chunk-XVWCOTR6.js.map +1 -0
- package/dist/chunk-YLJ4XMA6.js +33 -0
- package/dist/chunk-YLJ4XMA6.js.map +1 -0
- package/dist/chunk-Z2XP767T.cjs +35 -0
- package/dist/chunk-Z2XP767T.cjs.map +1 -0
- package/dist/chunk-Z4X2RWOF.js +37 -0
- package/dist/chunk-Z4X2RWOF.js.map +1 -0
- package/dist/constants.cjs +22 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +12 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/engine.cjs +79 -0
- package/dist/engine.cjs.map +1 -0
- package/dist/engine.d.cts +587 -0
- package/dist/engine.d.ts +587 -0
- package/dist/engine.js +34 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.cjs +81 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +95 -0
- package/dist/errors.d.ts +95 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/format.cjs +171 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.cts +51 -0
- package/dist/format.d.ts +51 -0
- package/dist/format.js +168 -0
- package/dist/format.js.map +1 -0
- package/dist/index.cjs +97 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +152 -0
- package/dist/index.d.ts +152 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/language.cjs +308 -0
- package/dist/language.cjs.map +1 -0
- package/dist/language.d.cts +110 -0
- package/dist/language.d.ts +110 -0
- package/dist/language.js +287 -0
- package/dist/language.js.map +1 -0
- package/dist/lexer.cjs +64 -0
- package/dist/lexer.cjs.map +1 -0
- package/dist/lexer.d.cts +56 -0
- package/dist/lexer.d.ts +56 -0
- package/dist/lexer.js +11 -0
- package/dist/lexer.js.map +1 -0
- package/dist/normalizer.cjs +40 -0
- package/dist/normalizer.cjs.map +1 -0
- package/dist/normalizer.d.cts +364 -0
- package/dist/normalizer.d.ts +364 -0
- package/dist/normalizer.js +11 -0
- package/dist/normalizer.js.map +1 -0
- package/dist/packages.cjs +121 -0
- package/dist/packages.cjs.map +1 -0
- package/dist/packages.d.cts +691 -0
- package/dist/packages.d.ts +691 -0
- package/dist/packages.js +24 -0
- package/dist/packages.js.map +1 -0
- package/dist/parser.cjs +55 -0
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +46 -0
- package/dist/parser.d.ts +46 -0
- package/dist/parser.js +10 -0
- package/dist/parser.js.map +1 -0
- package/dist/pipeline-CrsRPmsv.d.ts +285 -0
- package/dist/pipeline-DPUQt7yL.d.cts +285 -0
- package/dist/resolvers.cjs +13 -0
- package/dist/resolvers.cjs.map +1 -0
- package/dist/resolvers.d.cts +111 -0
- package/dist/resolvers.d.ts +111 -0
- package/dist/resolvers.js +4 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/services.cjs +21 -0
- package/dist/services.cjs.map +1 -0
- package/dist/services.d.cts +30 -0
- package/dist/services.d.ts +30 -0
- package/dist/services.js +4 -0
- package/dist/services.js.map +1 -0
- package/dist/uom.cjs +56 -0
- package/dist/uom.cjs.map +1 -0
- package/dist/uom.d.cts +224 -0
- package/dist/uom.d.ts +224 -0
- package/dist/uom.js +11 -0
- package/dist/uom.js.map +1 -0
- package/dist/utilities.cjs +32 -0
- package/dist/utilities.cjs.map +1 -0
- package/dist/utilities.d.cts +113 -0
- package/dist/utilities.d.ts +113 -0
- package/dist/utilities.js +7 -0
- package/dist/utilities.js.map +1 -0
- package/dist/variables.cjs +17 -0
- package/dist/variables.cjs.map +1 -0
- package/dist/variables.d.cts +87 -0
- package/dist/variables.d.ts +87 -0
- package/dist/variables.js +4 -0
- package/dist/variables.js.map +1 -0
- package/dist/vm.cjs +284 -0
- package/dist/vm.cjs.map +1 -0
- package/dist/vm.d.cts +68 -0
- package/dist/vm.d.ts +68 -0
- package/dist/vm.js +194 -0
- package/dist/vm.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The VM's bytecode instruction set.
|
|
3
|
+
*
|
|
4
|
+
* Emitted by parselets (via {@link BytecodeBuilder}) during parsing and
|
|
5
|
+
* consumed by the VM's dispatch loop during execution. Values are grouped
|
|
6
|
+
* into numeric bands by category (0-9 stack ops, 10-19 push-literal, 20-29
|
|
7
|
+
* arithmetic, ...) purely for readability, the VM dispatches on the exact
|
|
8
|
+
* numeric value, not the band.
|
|
9
|
+
*
|
|
10
|
+
* Third-party packages emit `CALL_PLUGIN` (with a plugin-function index
|
|
11
|
+
* from {@link allocatePluginFunctionIndex}) to invoke their own logic
|
|
12
|
+
* see `IEnginePackage.pluginFunctions`. The other opcodes are used
|
|
13
|
+
* internally by the built-in packages' parselets.
|
|
14
|
+
*/
|
|
15
|
+
declare enum OpCode {
|
|
16
|
+
NOP = 0,
|
|
17
|
+
HALT = 1,
|
|
18
|
+
SWAP = 2,
|
|
19
|
+
DUP = 3,
|
|
20
|
+
PUSH_NUMBER = 10,
|
|
21
|
+
PUSH_BIGINT = 11,
|
|
22
|
+
PUSH_HEX = 12,
|
|
23
|
+
PUSH_STRING = 13,
|
|
24
|
+
PUSH_BOOLEAN = 14,
|
|
25
|
+
PUSH_VARIABLE = 15,
|
|
26
|
+
ADD = 20,
|
|
27
|
+
SUB = 21,
|
|
28
|
+
MUL = 22,
|
|
29
|
+
DIV = 23,
|
|
30
|
+
MOD = 24,
|
|
31
|
+
EXP = 25,
|
|
32
|
+
NEG = 26,
|
|
33
|
+
POS = 27,
|
|
34
|
+
LSHIFT = 30,
|
|
35
|
+
RSHIFT = 31,
|
|
36
|
+
URSHIFT = 32,
|
|
37
|
+
BIT_AND = 33,
|
|
38
|
+
BIT_OR = 34,
|
|
39
|
+
BIT_XOR = 35,
|
|
40
|
+
BIT_NOT = 36,
|
|
41
|
+
EQ = 40,
|
|
42
|
+
NEQ = 41,
|
|
43
|
+
LT = 42,
|
|
44
|
+
LTE = 43,
|
|
45
|
+
GT = 44,
|
|
46
|
+
GTE = 45,
|
|
47
|
+
CALL_PLUGIN = 50,// Plugin-registered functions (may be async — pre-resolved by orchestrator)
|
|
48
|
+
CALL_BUILTIN = 51,// Sync built-in functions (sqrt, sin, diceRoll, matmul)
|
|
49
|
+
RETURN = 52,// Reserved for future user-defined functions
|
|
50
|
+
LOAD_VAR = 60,
|
|
51
|
+
STORE_VAR = 61,
|
|
52
|
+
LOAD_GLOBAL_VAR = 62,// Reads from the process-wide GlobalVariableStore, not the VM's local scope
|
|
53
|
+
STORE_GLOBAL_VAR = 63,// Writes to the process-wide GlobalVariableStore, visible to every document
|
|
54
|
+
TO_NUMBER = 70,
|
|
55
|
+
TO_HEX = 71,
|
|
56
|
+
TO_PERCENTAGE = 74,
|
|
57
|
+
UOM_CONVERT = 80,
|
|
58
|
+
UOM_CONVERT_TO = 81,
|
|
59
|
+
UOM_GET_VALUE = 82,
|
|
60
|
+
UOM_BEST = 83,
|
|
61
|
+
UOM_CONVERT_IN = 84,
|
|
62
|
+
UOM_POSSIBILITIES = 85,// "sourceUnit to ?" — list units convertible from sourceUnit
|
|
63
|
+
DATE_NOW = 90,
|
|
64
|
+
DATE_ADD = 91,
|
|
65
|
+
DATE_SUB = 92,
|
|
66
|
+
DATE_NEXT_WEEKDAY = 93,// "next <Weekday>" — the next occurrence strictly after now
|
|
67
|
+
DATE_LAST_WEEKDAY = 94,// "last <Weekday>" — the previous occurrence strictly before now
|
|
68
|
+
DATE_LITERAL = 95,// Push a datetime literal whose epoch-ms was already resolved at parse time (see DateLiteralParselet)
|
|
69
|
+
RATE_DIV = 110,// Uom ÷ Uom (different measures) -> Rate — the construction op
|
|
70
|
+
RATE_MUL = 111,// Rate × Uom (same measure as denominator) -> plain Uom (denominator cancels)
|
|
71
|
+
RATE_CONVERT = 112,// Rate -> Rate with a rescaled denominator unit (keeps the same real-world rate)
|
|
72
|
+
CLOCK_TIME_TODAY = 120,// minutes-since-midnight -> Datetime anchored to today's calendar date
|
|
73
|
+
LOGICAL_AND = 130,// Boolean && Boolean -> Boolean
|
|
74
|
+
LOGICAL_OR = 131,// Boolean || Boolean -> Boolean
|
|
75
|
+
SELECT = 132,// (thenVal, elseVal, condition) -> thenVal if condition else elseVal — EAGER (both
|
|
76
|
+
TO_FRACTION = 140,// Number -> String, simplified fraction ("0.5" -> "1/2")
|
|
77
|
+
TO_MULTIPLIER = 141,// Number -> String, "1 + n" growth multiplier ("0.5" -> "1.5x")
|
|
78
|
+
TO_SCI = 142,// Number -> String, scientific notation ("1500000" -> "1.5e+6")
|
|
79
|
+
TO_BINARY = 143,// Number -> String, base-2 display ("10" -> "0b1010")
|
|
80
|
+
TO_OCTAL = 144,// Number -> String, base-8 display ("10" -> "0o12")
|
|
81
|
+
CALL_AS_CONVERTER = 145,// (value, name) -> runtime asConverterRegistry lookup + call
|
|
82
|
+
DEFINE_USER_FUNCTION = 150,// (operand = index into bytecode.userFunctionBodies) -> register name/params/program into vm.userFunctions. Registration happens at VM-EXECUTION time, not parse time, so a diagnostic/lookahead parse that compiles but never executes a definition line has no side effect on the shared registry.
|
|
83
|
+
CALL_USER_FUNCTION = 151,// (N arg values already on stack) -> pop N args, bind by NAME into a new call frame, execute the named function's stored body (reentrant executeBytecode), push its result
|
|
84
|
+
MAT_NEW = 152,// (rows, cols operands; rows*cols values already on stack, ROW-MAJOR push order) -> pop rows*cols values, transpose to column-major, push a Matrix
|
|
85
|
+
MAT_INDEX1 = 153,// (matrix, index already on stack) -> column-major single-index read `a[i]`
|
|
86
|
+
MAT_INDEX2 = 154,// (matrix, row, col already on stack) -> `a[row, col]` read
|
|
87
|
+
MAT_SLICE = 155,// (matrix, rowRange, colRange already on stack) -> sub-matrix via two Range values
|
|
88
|
+
RANGE_NEW = 156,// (min, max already on stack) -> push a Range value `min:max`
|
|
89
|
+
MAP_INVOKE = 157,// map(...) — see parser/BytecodeBuilder.ts's `anonymousBodies` side-table
|
|
90
|
+
REDUCE_INVOKE = 158
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Gets the name of an OpCode as a string.
|
|
94
|
+
* @param op The OpCode value
|
|
95
|
+
* @returns The enum name as a string, or "UNKNOWN_<value>" if not found
|
|
96
|
+
*/
|
|
97
|
+
declare function getOpCodeName(op: number): string;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Compiled bytecode program produced by {@link BytecodeBuilder}.
|
|
101
|
+
* Ready for consumption by {@link executeBytecode} without further processing.
|
|
102
|
+
*/
|
|
103
|
+
interface BytecodeProgram {
|
|
104
|
+
opcodes: Uint8Array;
|
|
105
|
+
numbers: Float64Array;
|
|
106
|
+
strings: string[];
|
|
107
|
+
constants?: Map<number, number>;
|
|
108
|
+
/**
|
|
109
|
+
* Whether the program contains any async opcodes (CALL_PLUGIN, etc.).
|
|
110
|
+
* Set during compilation by the BytecodeBuilder. Allows the engine
|
|
111
|
+
* to skip the O(n) resolver preflight check in O(1) for purely
|
|
112
|
+
* synchronous expressions like `2 + 2`.
|
|
113
|
+
*/
|
|
114
|
+
hasAsync: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* User-defined-function bodies compiled alongside this program (one
|
|
117
|
+
* entry per `name(params) = body` definition on this line). See
|
|
118
|
+
* {@link BytecodeBuilder.emitUserFunctionBody}. `OpCode.DEFINE_USER_FUNCTION`'s
|
|
119
|
+
* operand is an index into this array, resolved at VM-execution time
|
|
120
|
+
* (not parse time) so a diagnostic/lookahead parse that never actually
|
|
121
|
+
* executes the definition line has no side effect on `vm.userFunctions`.
|
|
122
|
+
*/
|
|
123
|
+
userFunctionBodies?: UserFunctionDef[];
|
|
124
|
+
/**
|
|
125
|
+
* Anonymous function bodies compiled alongside this program, one entry
|
|
126
|
+
* per `map`/`reduce` inline transform expression (e.g. the `10*x` in
|
|
127
|
+
* `map(10*x, [0,1,500])`). See {@link BytecodeBuilder.emitAnonymousBody}.
|
|
128
|
+
* Deliberately a SEPARATE side-table from `userFunctionBodies`, not
|
|
129
|
+
* routed through `vm.userFunctions` at all: an inline body has no name
|
|
130
|
+
* and must never leak into the persistent name-keyed registry the way
|
|
131
|
+
* a real `f(x) = ...` definition does.
|
|
132
|
+
*/
|
|
133
|
+
anonymousBodies?: AnonymousBodyDef[];
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* An anonymous transform body for `map`/`reduce`'s inline-expression form
|
|
137
|
+
* (e.g. `10*x` in `map(10*x, [0,1,500])`, or `acc+x` in `reduce(acc+x,
|
|
138
|
+
* [1,2,3])`). Structurally identical to {@link UserFunctionDef} minus the
|
|
139
|
+
* `name`. See `OpCode.MAP_INVOKE`/`REDUCE_INVOKE` and
|
|
140
|
+
* `vm/VM.ts`'s handlers, which build a call frame from `params`/`args`
|
|
141
|
+
* exactly like `CALL_USER_FUNCTION` does, just without ever registering
|
|
142
|
+
* the body in `vm.userFunctions`.
|
|
143
|
+
*/
|
|
144
|
+
interface AnonymousBodyDef {
|
|
145
|
+
params: string[];
|
|
146
|
+
program: BytecodeProgram;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* A user-defined, parameterized, reusable function's compiled form
|
|
150
|
+
* (`f(x) = 2*x + 1`). See `OpCode.DEFINE_USER_FUNCTION`/`CALL_USER_FUNCTION`
|
|
151
|
+
* and `vm/VM.ts`'s `VM.defineUserFunction`/`getUserFunction`.
|
|
152
|
+
*
|
|
153
|
+
* `program` is the body compiled to its OWN independent `BytecodeProgram`,
|
|
154
|
+
* not a fragment of the definition line's own bytecode. Parameter names
|
|
155
|
+
* inside the body compile to ORDINARY `LOAD_VAR <name>` opcodes, no
|
|
156
|
+
* parse-time rewriting, because parameter resolution happens dynamically
|
|
157
|
+
* at the VM level: `CALL_USER_FUNCTION` pushes a name-keyed call frame
|
|
158
|
+
* (`Map<string, Value>`) before re-executing `program`, and `VM.getVar()`
|
|
159
|
+
* checks the innermost call frame before falling back to the flat
|
|
160
|
+
* document-variable store. This is why a `UNIT`-collision parameter name
|
|
161
|
+
* (e.g. `h` in `area(w, h) = w * h`, which lexes as the "hour" unit) needs
|
|
162
|
+
* no special handling anywhere, it's just another `LOAD_VAR "h"`, resolved
|
|
163
|
+
* the same way as any other name.
|
|
164
|
+
*/
|
|
165
|
+
interface UserFunctionDef {
|
|
166
|
+
name: string;
|
|
167
|
+
params: string[];
|
|
168
|
+
program: BytecodeProgram;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Direct-to-bytecode compiler for the Pratt parser.
|
|
172
|
+
*
|
|
173
|
+
* Accumulates opcodes, numeric constants, and string references during parsing,
|
|
174
|
+
* then produces a {@link BytecodeProgram} for VM execution. Supports:
|
|
175
|
+
* - Standard build via {@link build}
|
|
176
|
+
* - Zero-copy build into pre-allocated buffers via {@link buildInto}
|
|
177
|
+
* - In-place reset for reuse without reallocation
|
|
178
|
+
*/
|
|
179
|
+
declare class BytecodeBuilder {
|
|
180
|
+
private opcodes;
|
|
181
|
+
private numbers;
|
|
182
|
+
private strings;
|
|
183
|
+
private stringIndex;
|
|
184
|
+
private _hasAsync;
|
|
185
|
+
private userFunctionBodies;
|
|
186
|
+
private anonymousBodies;
|
|
187
|
+
/** Emit an {@link OpCode} instruction. */
|
|
188
|
+
emitOpcode(op: OpCode): void;
|
|
189
|
+
/**
|
|
190
|
+
* Emit a numeric literal: appends `n` to the program's constant pool and
|
|
191
|
+
* writes its index into the opcode stream (read back by the VM as e.g.
|
|
192
|
+
* `PUSH_NUMBER <idx>`).
|
|
193
|
+
*
|
|
194
|
+
* Numeric constants are NOT deduplicated (unlike {@link emitString})
|
|
195
|
+
* every call appends a new entry, so an expression with more than
|
|
196
|
+
* {@link MAX_CONSTANT_POOL_INDEX}+1 distinct numeric-literal occurrences
|
|
197
|
+
* throws rather than silently wrapping the index (see
|
|
198
|
+
* `MAX_CONSTANT_POOL_INDEX`'s doc for what that would otherwise do).
|
|
199
|
+
*
|
|
200
|
+
* @throws If the constant pool would exceed 256 entries.
|
|
201
|
+
*/
|
|
202
|
+
emitNumber(n: number): void;
|
|
203
|
+
/**
|
|
204
|
+
* Emit a string literal: interns `s` into the program's string pool
|
|
205
|
+
* (deduplicated via `stringIndex`) and writes its index into the opcode
|
|
206
|
+
* stream. Subject to the same constant-pool bound as {@link emitNumber},
|
|
207
|
+
* but since strings ARE deduplicated, only distinct string values count
|
|
208
|
+
* against the limit.
|
|
209
|
+
*
|
|
210
|
+
* @throws If the string pool would exceed 256 distinct entries.
|
|
211
|
+
*/
|
|
212
|
+
emitString(s: string): void;
|
|
213
|
+
/**
|
|
214
|
+
* Emit a raw numeric operand (0-255) following an opcode, e.g. a
|
|
215
|
+
* plugin-function index for `CALL_PLUGIN`, or an argument count. Unlike
|
|
216
|
+
* {@link emitOpcode}, this does not go through the `OpCode` enum, so
|
|
217
|
+
* package authors use this (not an unsafe cast to `OpCode`) to push
|
|
218
|
+
* operands their own opcode handler expects to read positionally.
|
|
219
|
+
*/
|
|
220
|
+
emitIndex(idx: number): void;
|
|
221
|
+
/** Emit a raw byte (0-255), used for fixed small operands like argument counts. */
|
|
222
|
+
emitByte(b: number): void;
|
|
223
|
+
/** Number of opcodes/operands emitted so far, used to compute jump targets before {@link patchJump}. */
|
|
224
|
+
get currentLength(): number;
|
|
225
|
+
/**
|
|
226
|
+
* Register a compiled user-defined-function body, returning its index
|
|
227
|
+
* into this program's `userFunctionBodies` side-table, the caller emits
|
|
228
|
+
* that index as `DEFINE_USER_FUNCTION`'s operand via {@link emitIndex}.
|
|
229
|
+
* Subject to the same {@link MAX_CONSTANT_POOL_INDEX} bound as
|
|
230
|
+
* {@link emitNumber}/{@link emitString} (the index itself is a single
|
|
231
|
+
* opcode-stream byte), in practice a single line defines at most a
|
|
232
|
+
* handful of functions, so this limit is never realistically reached.
|
|
233
|
+
*
|
|
234
|
+
* @throws If more than 256 function bodies are registered on one program.
|
|
235
|
+
*/
|
|
236
|
+
emitUserFunctionBody(name: string, params: string[], program: BytecodeProgram): number;
|
|
237
|
+
/**
|
|
238
|
+
* Register a compiled `map`/`reduce` anonymous transform body, returning
|
|
239
|
+
* its index into this program's `anonymousBodies` side-table, the
|
|
240
|
+
* caller emits that index as `MAP_INVOKE`/`REDUCE_INVOKE`'s operand via
|
|
241
|
+
* {@link emitIndex}. Same {@link MAX_CONSTANT_POOL_INDEX} bound as
|
|
242
|
+
* {@link emitUserFunctionBody}.
|
|
243
|
+
*
|
|
244
|
+
* @throws If more than 256 anonymous bodies are registered on one program.
|
|
245
|
+
*/
|
|
246
|
+
emitAnonymousBody(params: string[], program: BytecodeProgram): number;
|
|
247
|
+
/** Overwrite a previously-emitted placeholder operand at `position` with the real jump `target`, once known. */
|
|
248
|
+
patchJump(position: number, target: number): void;
|
|
249
|
+
/**
|
|
250
|
+
* Build the accumulated opcodes/numbers/strings into a BytecodeProgram.
|
|
251
|
+
* Creates new TypedArrays, the builder can be reused after this call.
|
|
252
|
+
*/
|
|
253
|
+
build(): BytecodeProgram;
|
|
254
|
+
/**
|
|
255
|
+
* Build directly into a pre-allocated buffer for zero-copy VM consumption.
|
|
256
|
+
*
|
|
257
|
+
* When `buf` is provided and large enough, writes into it and returns
|
|
258
|
+
* subarray **views** (not copies), the returned TypedArrays share the
|
|
259
|
+
* buffer's underlying ArrayBuffer. The caller MUST NOT mutate the buffer
|
|
260
|
+
* until the returned BytecodeProgram is no longer needed.
|
|
261
|
+
*
|
|
262
|
+
* If the caller intends to cache the result, they must copy the TypedArrays
|
|
263
|
+
* (e.g. `new Uint8Array(program.opcodes)`) before reusing the buffer pool.
|
|
264
|
+
*
|
|
265
|
+
* When `buf` is omitted or too small, allocates fresh TypedArrays.
|
|
266
|
+
*/
|
|
267
|
+
buildInto(buf?: {
|
|
268
|
+
opcodes: Uint8Array;
|
|
269
|
+
numbers: Float64Array;
|
|
270
|
+
}): BytecodeProgram;
|
|
271
|
+
reset(): void;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export { type AnonymousBodyDef as A, BytecodeBuilder as B, OpCode as O, type UserFunctionDef as U, type BytecodeProgram as a, getOpCodeName as g };
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The VM's bytecode instruction set.
|
|
3
|
+
*
|
|
4
|
+
* Emitted by parselets (via {@link BytecodeBuilder}) during parsing and
|
|
5
|
+
* consumed by the VM's dispatch loop during execution. Values are grouped
|
|
6
|
+
* into numeric bands by category (0-9 stack ops, 10-19 push-literal, 20-29
|
|
7
|
+
* arithmetic, ...) purely for readability, the VM dispatches on the exact
|
|
8
|
+
* numeric value, not the band.
|
|
9
|
+
*
|
|
10
|
+
* Third-party packages emit `CALL_PLUGIN` (with a plugin-function index
|
|
11
|
+
* from {@link allocatePluginFunctionIndex}) to invoke their own logic
|
|
12
|
+
* see `IEnginePackage.pluginFunctions`. The other opcodes are used
|
|
13
|
+
* internally by the built-in packages' parselets.
|
|
14
|
+
*/
|
|
15
|
+
declare enum OpCode {
|
|
16
|
+
NOP = 0,
|
|
17
|
+
HALT = 1,
|
|
18
|
+
SWAP = 2,
|
|
19
|
+
DUP = 3,
|
|
20
|
+
PUSH_NUMBER = 10,
|
|
21
|
+
PUSH_BIGINT = 11,
|
|
22
|
+
PUSH_HEX = 12,
|
|
23
|
+
PUSH_STRING = 13,
|
|
24
|
+
PUSH_BOOLEAN = 14,
|
|
25
|
+
PUSH_VARIABLE = 15,
|
|
26
|
+
ADD = 20,
|
|
27
|
+
SUB = 21,
|
|
28
|
+
MUL = 22,
|
|
29
|
+
DIV = 23,
|
|
30
|
+
MOD = 24,
|
|
31
|
+
EXP = 25,
|
|
32
|
+
NEG = 26,
|
|
33
|
+
POS = 27,
|
|
34
|
+
LSHIFT = 30,
|
|
35
|
+
RSHIFT = 31,
|
|
36
|
+
URSHIFT = 32,
|
|
37
|
+
BIT_AND = 33,
|
|
38
|
+
BIT_OR = 34,
|
|
39
|
+
BIT_XOR = 35,
|
|
40
|
+
BIT_NOT = 36,
|
|
41
|
+
EQ = 40,
|
|
42
|
+
NEQ = 41,
|
|
43
|
+
LT = 42,
|
|
44
|
+
LTE = 43,
|
|
45
|
+
GT = 44,
|
|
46
|
+
GTE = 45,
|
|
47
|
+
CALL_PLUGIN = 50,// Plugin-registered functions (may be async — pre-resolved by orchestrator)
|
|
48
|
+
CALL_BUILTIN = 51,// Sync built-in functions (sqrt, sin, diceRoll, matmul)
|
|
49
|
+
RETURN = 52,// Reserved for future user-defined functions
|
|
50
|
+
LOAD_VAR = 60,
|
|
51
|
+
STORE_VAR = 61,
|
|
52
|
+
LOAD_GLOBAL_VAR = 62,// Reads from the process-wide GlobalVariableStore, not the VM's local scope
|
|
53
|
+
STORE_GLOBAL_VAR = 63,// Writes to the process-wide GlobalVariableStore, visible to every document
|
|
54
|
+
TO_NUMBER = 70,
|
|
55
|
+
TO_HEX = 71,
|
|
56
|
+
TO_PERCENTAGE = 74,
|
|
57
|
+
UOM_CONVERT = 80,
|
|
58
|
+
UOM_CONVERT_TO = 81,
|
|
59
|
+
UOM_GET_VALUE = 82,
|
|
60
|
+
UOM_BEST = 83,
|
|
61
|
+
UOM_CONVERT_IN = 84,
|
|
62
|
+
UOM_POSSIBILITIES = 85,// "sourceUnit to ?" — list units convertible from sourceUnit
|
|
63
|
+
DATE_NOW = 90,
|
|
64
|
+
DATE_ADD = 91,
|
|
65
|
+
DATE_SUB = 92,
|
|
66
|
+
DATE_NEXT_WEEKDAY = 93,// "next <Weekday>" — the next occurrence strictly after now
|
|
67
|
+
DATE_LAST_WEEKDAY = 94,// "last <Weekday>" — the previous occurrence strictly before now
|
|
68
|
+
DATE_LITERAL = 95,// Push a datetime literal whose epoch-ms was already resolved at parse time (see DateLiteralParselet)
|
|
69
|
+
RATE_DIV = 110,// Uom ÷ Uom (different measures) -> Rate — the construction op
|
|
70
|
+
RATE_MUL = 111,// Rate × Uom (same measure as denominator) -> plain Uom (denominator cancels)
|
|
71
|
+
RATE_CONVERT = 112,// Rate -> Rate with a rescaled denominator unit (keeps the same real-world rate)
|
|
72
|
+
CLOCK_TIME_TODAY = 120,// minutes-since-midnight -> Datetime anchored to today's calendar date
|
|
73
|
+
LOGICAL_AND = 130,// Boolean && Boolean -> Boolean
|
|
74
|
+
LOGICAL_OR = 131,// Boolean || Boolean -> Boolean
|
|
75
|
+
SELECT = 132,// (thenVal, elseVal, condition) -> thenVal if condition else elseVal — EAGER (both
|
|
76
|
+
TO_FRACTION = 140,// Number -> String, simplified fraction ("0.5" -> "1/2")
|
|
77
|
+
TO_MULTIPLIER = 141,// Number -> String, "1 + n" growth multiplier ("0.5" -> "1.5x")
|
|
78
|
+
TO_SCI = 142,// Number -> String, scientific notation ("1500000" -> "1.5e+6")
|
|
79
|
+
TO_BINARY = 143,// Number -> String, base-2 display ("10" -> "0b1010")
|
|
80
|
+
TO_OCTAL = 144,// Number -> String, base-8 display ("10" -> "0o12")
|
|
81
|
+
CALL_AS_CONVERTER = 145,// (value, name) -> runtime asConverterRegistry lookup + call
|
|
82
|
+
DEFINE_USER_FUNCTION = 150,// (operand = index into bytecode.userFunctionBodies) -> register name/params/program into vm.userFunctions. Registration happens at VM-EXECUTION time, not parse time, so a diagnostic/lookahead parse that compiles but never executes a definition line has no side effect on the shared registry.
|
|
83
|
+
CALL_USER_FUNCTION = 151,// (N arg values already on stack) -> pop N args, bind by NAME into a new call frame, execute the named function's stored body (reentrant executeBytecode), push its result
|
|
84
|
+
MAT_NEW = 152,// (rows, cols operands; rows*cols values already on stack, ROW-MAJOR push order) -> pop rows*cols values, transpose to column-major, push a Matrix
|
|
85
|
+
MAT_INDEX1 = 153,// (matrix, index already on stack) -> column-major single-index read `a[i]`
|
|
86
|
+
MAT_INDEX2 = 154,// (matrix, row, col already on stack) -> `a[row, col]` read
|
|
87
|
+
MAT_SLICE = 155,// (matrix, rowRange, colRange already on stack) -> sub-matrix via two Range values
|
|
88
|
+
RANGE_NEW = 156,// (min, max already on stack) -> push a Range value `min:max`
|
|
89
|
+
MAP_INVOKE = 157,// map(...) — see parser/BytecodeBuilder.ts's `anonymousBodies` side-table
|
|
90
|
+
REDUCE_INVOKE = 158
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Gets the name of an OpCode as a string.
|
|
94
|
+
* @param op The OpCode value
|
|
95
|
+
* @returns The enum name as a string, or "UNKNOWN_<value>" if not found
|
|
96
|
+
*/
|
|
97
|
+
declare function getOpCodeName(op: number): string;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Compiled bytecode program produced by {@link BytecodeBuilder}.
|
|
101
|
+
* Ready for consumption by {@link executeBytecode} without further processing.
|
|
102
|
+
*/
|
|
103
|
+
interface BytecodeProgram {
|
|
104
|
+
opcodes: Uint8Array;
|
|
105
|
+
numbers: Float64Array;
|
|
106
|
+
strings: string[];
|
|
107
|
+
constants?: Map<number, number>;
|
|
108
|
+
/**
|
|
109
|
+
* Whether the program contains any async opcodes (CALL_PLUGIN, etc.).
|
|
110
|
+
* Set during compilation by the BytecodeBuilder. Allows the engine
|
|
111
|
+
* to skip the O(n) resolver preflight check in O(1) for purely
|
|
112
|
+
* synchronous expressions like `2 + 2`.
|
|
113
|
+
*/
|
|
114
|
+
hasAsync: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* User-defined-function bodies compiled alongside this program (one
|
|
117
|
+
* entry per `name(params) = body` definition on this line). See
|
|
118
|
+
* {@link BytecodeBuilder.emitUserFunctionBody}. `OpCode.DEFINE_USER_FUNCTION`'s
|
|
119
|
+
* operand is an index into this array, resolved at VM-execution time
|
|
120
|
+
* (not parse time) so a diagnostic/lookahead parse that never actually
|
|
121
|
+
* executes the definition line has no side effect on `vm.userFunctions`.
|
|
122
|
+
*/
|
|
123
|
+
userFunctionBodies?: UserFunctionDef[];
|
|
124
|
+
/**
|
|
125
|
+
* Anonymous function bodies compiled alongside this program, one entry
|
|
126
|
+
* per `map`/`reduce` inline transform expression (e.g. the `10*x` in
|
|
127
|
+
* `map(10*x, [0,1,500])`). See {@link BytecodeBuilder.emitAnonymousBody}.
|
|
128
|
+
* Deliberately a SEPARATE side-table from `userFunctionBodies`, not
|
|
129
|
+
* routed through `vm.userFunctions` at all: an inline body has no name
|
|
130
|
+
* and must never leak into the persistent name-keyed registry the way
|
|
131
|
+
* a real `f(x) = ...` definition does.
|
|
132
|
+
*/
|
|
133
|
+
anonymousBodies?: AnonymousBodyDef[];
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* An anonymous transform body for `map`/`reduce`'s inline-expression form
|
|
137
|
+
* (e.g. `10*x` in `map(10*x, [0,1,500])`, or `acc+x` in `reduce(acc+x,
|
|
138
|
+
* [1,2,3])`). Structurally identical to {@link UserFunctionDef} minus the
|
|
139
|
+
* `name`. See `OpCode.MAP_INVOKE`/`REDUCE_INVOKE` and
|
|
140
|
+
* `vm/VM.ts`'s handlers, which build a call frame from `params`/`args`
|
|
141
|
+
* exactly like `CALL_USER_FUNCTION` does, just without ever registering
|
|
142
|
+
* the body in `vm.userFunctions`.
|
|
143
|
+
*/
|
|
144
|
+
interface AnonymousBodyDef {
|
|
145
|
+
params: string[];
|
|
146
|
+
program: BytecodeProgram;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* A user-defined, parameterized, reusable function's compiled form
|
|
150
|
+
* (`f(x) = 2*x + 1`). See `OpCode.DEFINE_USER_FUNCTION`/`CALL_USER_FUNCTION`
|
|
151
|
+
* and `vm/VM.ts`'s `VM.defineUserFunction`/`getUserFunction`.
|
|
152
|
+
*
|
|
153
|
+
* `program` is the body compiled to its OWN independent `BytecodeProgram`,
|
|
154
|
+
* not a fragment of the definition line's own bytecode. Parameter names
|
|
155
|
+
* inside the body compile to ORDINARY `LOAD_VAR <name>` opcodes, no
|
|
156
|
+
* parse-time rewriting, because parameter resolution happens dynamically
|
|
157
|
+
* at the VM level: `CALL_USER_FUNCTION` pushes a name-keyed call frame
|
|
158
|
+
* (`Map<string, Value>`) before re-executing `program`, and `VM.getVar()`
|
|
159
|
+
* checks the innermost call frame before falling back to the flat
|
|
160
|
+
* document-variable store. This is why a `UNIT`-collision parameter name
|
|
161
|
+
* (e.g. `h` in `area(w, h) = w * h`, which lexes as the "hour" unit) needs
|
|
162
|
+
* no special handling anywhere, it's just another `LOAD_VAR "h"`, resolved
|
|
163
|
+
* the same way as any other name.
|
|
164
|
+
*/
|
|
165
|
+
interface UserFunctionDef {
|
|
166
|
+
name: string;
|
|
167
|
+
params: string[];
|
|
168
|
+
program: BytecodeProgram;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Direct-to-bytecode compiler for the Pratt parser.
|
|
172
|
+
*
|
|
173
|
+
* Accumulates opcodes, numeric constants, and string references during parsing,
|
|
174
|
+
* then produces a {@link BytecodeProgram} for VM execution. Supports:
|
|
175
|
+
* - Standard build via {@link build}
|
|
176
|
+
* - Zero-copy build into pre-allocated buffers via {@link buildInto}
|
|
177
|
+
* - In-place reset for reuse without reallocation
|
|
178
|
+
*/
|
|
179
|
+
declare class BytecodeBuilder {
|
|
180
|
+
private opcodes;
|
|
181
|
+
private numbers;
|
|
182
|
+
private strings;
|
|
183
|
+
private stringIndex;
|
|
184
|
+
private _hasAsync;
|
|
185
|
+
private userFunctionBodies;
|
|
186
|
+
private anonymousBodies;
|
|
187
|
+
/** Emit an {@link OpCode} instruction. */
|
|
188
|
+
emitOpcode(op: OpCode): void;
|
|
189
|
+
/**
|
|
190
|
+
* Emit a numeric literal: appends `n` to the program's constant pool and
|
|
191
|
+
* writes its index into the opcode stream (read back by the VM as e.g.
|
|
192
|
+
* `PUSH_NUMBER <idx>`).
|
|
193
|
+
*
|
|
194
|
+
* Numeric constants are NOT deduplicated (unlike {@link emitString})
|
|
195
|
+
* every call appends a new entry, so an expression with more than
|
|
196
|
+
* {@link MAX_CONSTANT_POOL_INDEX}+1 distinct numeric-literal occurrences
|
|
197
|
+
* throws rather than silently wrapping the index (see
|
|
198
|
+
* `MAX_CONSTANT_POOL_INDEX`'s doc for what that would otherwise do).
|
|
199
|
+
*
|
|
200
|
+
* @throws If the constant pool would exceed 256 entries.
|
|
201
|
+
*/
|
|
202
|
+
emitNumber(n: number): void;
|
|
203
|
+
/**
|
|
204
|
+
* Emit a string literal: interns `s` into the program's string pool
|
|
205
|
+
* (deduplicated via `stringIndex`) and writes its index into the opcode
|
|
206
|
+
* stream. Subject to the same constant-pool bound as {@link emitNumber},
|
|
207
|
+
* but since strings ARE deduplicated, only distinct string values count
|
|
208
|
+
* against the limit.
|
|
209
|
+
*
|
|
210
|
+
* @throws If the string pool would exceed 256 distinct entries.
|
|
211
|
+
*/
|
|
212
|
+
emitString(s: string): void;
|
|
213
|
+
/**
|
|
214
|
+
* Emit a raw numeric operand (0-255) following an opcode, e.g. a
|
|
215
|
+
* plugin-function index for `CALL_PLUGIN`, or an argument count. Unlike
|
|
216
|
+
* {@link emitOpcode}, this does not go through the `OpCode` enum, so
|
|
217
|
+
* package authors use this (not an unsafe cast to `OpCode`) to push
|
|
218
|
+
* operands their own opcode handler expects to read positionally.
|
|
219
|
+
*/
|
|
220
|
+
emitIndex(idx: number): void;
|
|
221
|
+
/** Emit a raw byte (0-255), used for fixed small operands like argument counts. */
|
|
222
|
+
emitByte(b: number): void;
|
|
223
|
+
/** Number of opcodes/operands emitted so far, used to compute jump targets before {@link patchJump}. */
|
|
224
|
+
get currentLength(): number;
|
|
225
|
+
/**
|
|
226
|
+
* Register a compiled user-defined-function body, returning its index
|
|
227
|
+
* into this program's `userFunctionBodies` side-table, the caller emits
|
|
228
|
+
* that index as `DEFINE_USER_FUNCTION`'s operand via {@link emitIndex}.
|
|
229
|
+
* Subject to the same {@link MAX_CONSTANT_POOL_INDEX} bound as
|
|
230
|
+
* {@link emitNumber}/{@link emitString} (the index itself is a single
|
|
231
|
+
* opcode-stream byte), in practice a single line defines at most a
|
|
232
|
+
* handful of functions, so this limit is never realistically reached.
|
|
233
|
+
*
|
|
234
|
+
* @throws If more than 256 function bodies are registered on one program.
|
|
235
|
+
*/
|
|
236
|
+
emitUserFunctionBody(name: string, params: string[], program: BytecodeProgram): number;
|
|
237
|
+
/**
|
|
238
|
+
* Register a compiled `map`/`reduce` anonymous transform body, returning
|
|
239
|
+
* its index into this program's `anonymousBodies` side-table, the
|
|
240
|
+
* caller emits that index as `MAP_INVOKE`/`REDUCE_INVOKE`'s operand via
|
|
241
|
+
* {@link emitIndex}. Same {@link MAX_CONSTANT_POOL_INDEX} bound as
|
|
242
|
+
* {@link emitUserFunctionBody}.
|
|
243
|
+
*
|
|
244
|
+
* @throws If more than 256 anonymous bodies are registered on one program.
|
|
245
|
+
*/
|
|
246
|
+
emitAnonymousBody(params: string[], program: BytecodeProgram): number;
|
|
247
|
+
/** Overwrite a previously-emitted placeholder operand at `position` with the real jump `target`, once known. */
|
|
248
|
+
patchJump(position: number, target: number): void;
|
|
249
|
+
/**
|
|
250
|
+
* Build the accumulated opcodes/numbers/strings into a BytecodeProgram.
|
|
251
|
+
* Creates new TypedArrays, the builder can be reused after this call.
|
|
252
|
+
*/
|
|
253
|
+
build(): BytecodeProgram;
|
|
254
|
+
/**
|
|
255
|
+
* Build directly into a pre-allocated buffer for zero-copy VM consumption.
|
|
256
|
+
*
|
|
257
|
+
* When `buf` is provided and large enough, writes into it and returns
|
|
258
|
+
* subarray **views** (not copies), the returned TypedArrays share the
|
|
259
|
+
* buffer's underlying ArrayBuffer. The caller MUST NOT mutate the buffer
|
|
260
|
+
* until the returned BytecodeProgram is no longer needed.
|
|
261
|
+
*
|
|
262
|
+
* If the caller intends to cache the result, they must copy the TypedArrays
|
|
263
|
+
* (e.g. `new Uint8Array(program.opcodes)`) before reusing the buffer pool.
|
|
264
|
+
*
|
|
265
|
+
* When `buf` is omitted or too small, allocates fresh TypedArrays.
|
|
266
|
+
*/
|
|
267
|
+
buildInto(buf?: {
|
|
268
|
+
opcodes: Uint8Array;
|
|
269
|
+
numbers: Float64Array;
|
|
270
|
+
}): BytecodeProgram;
|
|
271
|
+
reset(): void;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export { type AnonymousBodyDef as A, BytecodeBuilder as B, OpCode as O, type UserFunctionDef as U, type BytecodeProgram as a, getOpCodeName as g };
|