functionalscript 0.46.0 → 0.47.0

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.
Files changed (178) hide show
  1. package/fjs/basen/cbase32/module.f.mjs +18 -10
  2. package/fjs/basen/cbase32/proof.f.d.mts +3 -0
  3. package/fjs/basen/cbase32/proof.f.mjs +24 -2
  4. package/fjs/basen/proof.f.mjs +8 -16
  5. package/fjs/bnf/ll1/proof.f.d.mts +2 -0
  6. package/fjs/bnf/ll1/proof.f.mjs +33 -18
  7. package/fjs/bnf/module.f.d.mts +2 -2
  8. package/fjs/bnf/module.f.mjs +2 -2
  9. package/fjs/cas/proof.f.mjs +4 -26
  10. package/fjs/ci/common/module.f.mjs +6 -0
  11. package/fjs/ci/config/module.f.d.mts +7 -7
  12. package/fjs/ci/config/module.f.mjs +7 -7
  13. package/fjs/cli/module.f.mjs +14 -10
  14. package/fjs/crypto/vdf/module.f.d.mts +0 -1
  15. package/fjs/crypto/vdf/module.f.mjs +3 -14
  16. package/fjs/dev/module.f.mjs +10 -20
  17. package/fjs/djs/parser/module.f.d.mts +101 -53
  18. package/fjs/djs/parser/module.f.mjs +732 -525
  19. package/fjs/djs/parser/proof.f.d.mts +6 -0
  20. package/fjs/djs/parser/proof.f.mjs +315 -11
  21. package/fjs/djs/parser/types.d.ts +29 -2
  22. package/fjs/djs/tokenizer/module.f.mjs +122 -105
  23. package/fjs/djs/tokenizer/proof.f.mjs +17 -0
  24. package/fjs/djs/transpiler/module.f.mjs +4 -5
  25. package/fjs/djs/transpiler/proof.f.d.mts +2 -0
  26. package/fjs/djs/transpiler/proof.f.mjs +25 -0
  27. package/fjs/edag/amnesia/module.f.d.mts +20 -0
  28. package/fjs/edag/amnesia/module.f.mjs +303 -0
  29. package/fjs/edag/amnesia/proof.f.d.mts +79 -0
  30. package/fjs/edag/amnesia/proof.f.mjs +573 -0
  31. package/fjs/edag/amnesia/types.d.ts +15 -0
  32. package/fjs/edag/module.f.d.mts +410 -0
  33. package/fjs/edag/module.f.mjs +559 -0
  34. package/fjs/edag/proof.f.d.mts +116 -0
  35. package/fjs/edag/proof.f.mjs +686 -0
  36. package/fjs/edag/types.d.ts +55 -0
  37. package/fjs/effects/node/memory/module.d.mts +37 -3
  38. package/fjs/effects/node/memory/module.mjs +38 -4
  39. package/fjs/effects/node/memory/proof.d.mts +5 -2
  40. package/fjs/effects/node/memory/proof.mjs +36 -6
  41. package/fjs/effects/node/module.d.mts +9 -1
  42. package/fjs/effects/node/module.f.d.mts +39 -0
  43. package/fjs/effects/node/module.f.mjs +46 -0
  44. package/fjs/effects/node/module.mjs +234 -32
  45. package/fjs/effects/node/types.d.ts +28 -2
  46. package/fjs/effects/node/virtual/module.f.d.mts +19 -10
  47. package/fjs/effects/node/virtual/module.f.mjs +246 -32
  48. package/fjs/effects/node/virtual/proof.f.d.mts +17 -2
  49. package/fjs/effects/node/virtual/proof.f.mjs +232 -8
  50. package/fjs/effects/node/virtual/types.d.ts +57 -1
  51. package/fjs/emergent_testing/browser/proof.d.mts +55 -0
  52. package/fjs/emergent_testing/browser/proof.mjs +352 -0
  53. package/fjs/emergent_testing/browser/species.proof.d.mts +4 -0
  54. package/fjs/emergent_testing/browser/species.proof.mjs +45 -0
  55. package/fjs/emergent_testing/browser.d.mts +79 -0
  56. package/fjs/emergent_testing/browser.mjs +432 -0
  57. package/fjs/emergent_testing/proof.f.d.mts +1 -1
  58. package/fjs/emergent_testing/proof.f.mjs +2 -2
  59. package/fjs/js/string_escape/module.f.d.mts +47 -0
  60. package/fjs/js/string_escape/module.f.mjs +95 -0
  61. package/fjs/js/string_escape/proof.f.d.mts +8 -0
  62. package/fjs/js/string_escape/proof.f.mjs +68 -0
  63. package/fjs/js/tokenizer/module.f.mjs +14 -12
  64. package/fjs/mcp/cas/module.f.d.mts +1 -7
  65. package/fjs/mcp/cas/module.f.mjs +24 -15
  66. package/fjs/mcp/evo/module.f.mjs +9 -24
  67. package/fjs/mcp/module.f.d.mts +3 -1
  68. package/fjs/mcp/module.f.mjs +4 -2
  69. package/fjs/media/json/rtti/module.f.d.mts +2 -2
  70. package/fjs/media/json/rtti/module.f.mjs +1 -1
  71. package/fjs/media/json/schema/module.f.d.mts +15 -5
  72. package/fjs/media/json/schema/module.f.mjs +42 -15
  73. package/fjs/media/json/schema/proof.f.d.mts +10 -1
  74. package/fjs/media/json/schema/proof.f.mjs +88 -16
  75. package/fjs/media/json/serializer/module.f.mjs +14 -26
  76. package/fjs/media/json/types.d.ts +1 -1
  77. package/fjs/media/lock/module.f.d.mts +8 -3
  78. package/fjs/media/lock/module.f.mjs +9 -3
  79. package/fjs/media/lock/proof.f.d.mts +1 -1
  80. package/fjs/media/lock/proof.f.mjs +2 -2
  81. package/fjs/media/lock/types.d.ts +1 -3
  82. package/fjs/media/module.f.d.mts +20 -13
  83. package/fjs/media/module.f.mjs +29 -16
  84. package/fjs/media/note/module.f.d.mts +14 -7
  85. package/fjs/media/note/module.f.mjs +14 -7
  86. package/fjs/media/note/proof.f.mjs +1 -1
  87. package/fjs/media/proof.f.mjs +5 -5
  88. package/fjs/media/revision/module.f.d.mts +8 -2
  89. package/fjs/media/revision/module.f.mjs +9 -3
  90. package/fjs/media/revision/proof.f.mjs +1 -1
  91. package/fjs/media/revision/types.d.ts +1 -1
  92. package/fjs/media/type/module.f.d.mts +20 -0
  93. package/fjs/media/type/module.f.mjs +74 -0
  94. package/fjs/media/type/proof.f.d.mts +5 -0
  95. package/fjs/media/type/proof.f.mjs +24 -1
  96. package/fjs/module.f.mjs +6 -0
  97. package/fjs/path/module.f.d.mts +60 -3
  98. package/fjs/path/module.f.mjs +138 -14
  99. package/fjs/path/proof.f.d.mts +3 -0
  100. package/fjs/path/proof.f.mjs +298 -2
  101. package/fjs/protocol/json_rpc/module.f.d.mts +65 -28
  102. package/fjs/protocol/json_rpc/module.f.mjs +49 -13
  103. package/fjs/protocol/json_rpc/proof.f.d.mts +4 -0
  104. package/fjs/protocol/json_rpc/proof.f.mjs +29 -0
  105. package/fjs/protocol/json_rpc/types.d.ts +12 -2
  106. package/fjs/protocol/mcp/module.f.d.mts +89 -54
  107. package/fjs/protocol/mcp/module.f.mjs +110 -56
  108. package/fjs/protocol/mcp/proof.f.d.mts +13 -0
  109. package/fjs/protocol/mcp/proof.f.mjs +107 -7
  110. package/fjs/protocol/mcp/stdio/module.f.mjs +3 -4
  111. package/fjs/protocol/mcp/stdio/proof.f.mjs +2 -2
  112. package/fjs/protocol/mcp/types.d.ts +14 -2
  113. package/fjs/text/utf8/module.f.mjs +27 -1
  114. package/fjs/text/utf8/proof.f.mjs +37 -0
  115. package/fjs/types/array/module.f.mjs +18 -11
  116. package/fjs/types/array/proof.f.mjs +27 -1
  117. package/fjs/types/bigfloat/module.f.d.mts +48 -9
  118. package/fjs/types/bigfloat/module.f.mjs +147 -59
  119. package/fjs/types/bigfloat/proof.f.d.mts +2 -0
  120. package/fjs/types/bigfloat/proof.f.mjs +136 -4
  121. package/fjs/types/bigfloat/types.d.ts +17 -0
  122. package/fjs/types/function/module.f.d.mts +11 -2
  123. package/fjs/types/function/module.f.mjs +20 -2
  124. package/fjs/types/function/proof.f.mjs +5 -1
  125. package/fjs/types/phantom/types.d.ts +21 -0
  126. package/fjs/types/result/module.f.d.mts +4 -4
  127. package/fjs/types/result/module.f.mjs +2 -2
  128. package/fjs/types/result/proof.f.d.mts +6 -2
  129. package/fjs/types/result/proof.f.mjs +17 -1
  130. package/fjs/types/rtti/common/module.f.d.mts +78 -5
  131. package/fjs/types/rtti/common/module.f.mjs +168 -3
  132. package/fjs/types/rtti/common/proof.f.d.mts +14 -0
  133. package/fjs/types/rtti/common/proof.f.mjs +61 -2
  134. package/fjs/types/rtti/common/types.d.ts +23 -1
  135. package/fjs/types/rtti/data/module.f.d.mts +57 -1
  136. package/fjs/types/rtti/data/module.f.mjs +241 -47
  137. package/fjs/types/rtti/data/proof.f.d.mts +10 -0
  138. package/fjs/types/rtti/data/proof.f.mjs +272 -39
  139. package/fjs/types/rtti/data/types.d.ts +14 -7
  140. package/fjs/types/rtti/host.proof.d.mts +33 -0
  141. package/fjs/types/rtti/host.proof.mjs +170 -0
  142. package/fjs/types/rtti/module.f.d.mts +51 -6
  143. package/fjs/types/rtti/module.f.mjs +50 -3
  144. package/fjs/types/rtti/parse/module.f.d.mts +31 -24
  145. package/fjs/types/rtti/parse/module.f.mjs +197 -59
  146. package/fjs/types/rtti/parse/proof.f.d.mts +37 -2
  147. package/fjs/types/rtti/parse/proof.f.mjs +171 -47
  148. package/fjs/types/rtti/proof.f.d.mts +6 -0
  149. package/fjs/types/rtti/proof.f.mjs +42 -1
  150. package/fjs/types/rtti/ts/module.f.d.mts +9 -3
  151. package/fjs/types/rtti/ts/module.f.mjs +68 -15
  152. package/fjs/types/rtti/ts/proof.f.d.mts +42 -2
  153. package/fjs/types/rtti/ts/proof.f.mjs +139 -6
  154. package/fjs/types/rtti/ts/types.d.ts +164 -16
  155. package/fjs/types/rtti/types.d.ts +31 -3
  156. package/fjs/types/rtti/validate/module.f.d.mts +120 -0
  157. package/fjs/types/rtti/validate/module.f.mjs +351 -0
  158. package/fjs/types/rtti/validate/proof.f.d.mts +154 -0
  159. package/fjs/types/rtti/validate/proof.f.mjs +781 -0
  160. package/fjs/types/ts/types.d.ts +4 -0
  161. package/fjs/web/module.f.d.mts +115 -0
  162. package/fjs/web/module.f.mjs +581 -0
  163. package/fjs/web/proof.f.d.mts +39 -0
  164. package/fjs/web/proof.f.mjs +413 -0
  165. package/fjs/web/types.d.ts +39 -0
  166. package/fjs/website/browser-prepare.d.mts +5 -0
  167. package/fjs/website/browser-prepare.mjs +115 -0
  168. package/fjs/website/browser-source.d.mts +37 -0
  169. package/fjs/website/browser-source.mjs +202 -0
  170. package/fjs/website/browser-source.proof.d.mts +31 -0
  171. package/fjs/website/browser-source.proof.mjs +162 -0
  172. package/fjs/website/browser.d.mts +5 -0
  173. package/fjs/website/browser.mjs +8 -0
  174. package/fjs/website/module.f.d.mts +3 -3
  175. package/fjs/website/module.f.mjs +62 -9
  176. package/fjs/website/proof.f.d.mts +4 -0
  177. package/fjs/website/proof.f.mjs +18 -3
  178. package/package.json +2 -3
@@ -0,0 +1,303 @@
1
+ /**
2
+ * A tree-walking evaluator for `exp`: `vm(context)(e)` returns a primitive
3
+ * unchanged and dispatches a tagged tuple through one handler per tag.
4
+ *
5
+ * It remembers no node values — every incoming edge evaluates its target
6
+ * again — so it is the Amnesia model of
7
+ * [execution-models.md](../execution-models.md), for proving semantics and
8
+ * not for running FunctionalScript. See [README.md](./README.md).
9
+ *
10
+ * @module
11
+ *
12
+ * @import { Exp, Op1, Properties } from '../types.ts'
13
+ * @import { OptionLambda, OptionPropertyLambda, PropertyLambda } from '../types.ts'
14
+ * @import { Context, Map, ExpOp, TagMap } from './types.ts'
15
+ */
16
+
17
+ import { assert } from '../../asserts/module.f.mjs'
18
+
19
+ const o2lazy =
20
+ (/**@type {(a: any, b: () => any) => unknown}*/o) =>
21
+ /**
22
+ * @template {Exp} A
23
+ * @param {Context} c
24
+ * @param {readonly[unknown, A, A]} _2
25
+ */
26
+ (c, [, a, b]) => {
27
+ const f = vm(c)
28
+ return o(f(a), () => f(b))
29
+ }
30
+
31
+ /**
32
+ * Eager pair: `o2lazy` already *is* the handler, so this forces `b` and
33
+ * hands it on — it must not wrap another `(c, e) =>` around it, or every
34
+ * binary op would evaluate to that inner handler instead of to a value.
35
+ */
36
+ const o2 =
37
+ (/**@type {(a: any, b: any) => unknown}*/o) =>
38
+ o2lazy((a, b) => o(a, b()))
39
+
40
+ /** @typedef {(c: Context, e: Op1) => unknown} _Func1 */
41
+
42
+ const o1 =
43
+ (/**@type {(a: any) => unknown}*/o) =>
44
+ /**@type {_Func1}*/
45
+ (c, [, a]) => o(vm(c)(a))
46
+
47
+ /** @typedef {(_: Exp) => unknown} _Eval */
48
+
49
+ /** Both ways of being nullish, which is what every optional step guards. */
50
+ /** @type {(v: unknown) => boolean} */
51
+ const nullish = v => v === undefined || v === null
52
+
53
+ /**
54
+ * The argument array of a call: one node evaluating to the *complete* array,
55
+ * spread at the call site — `f(a, b)` is `['()', f, ['[]', [a, b]]]`, and `=>`
56
+ * collects with `(...args)`. Passed as a single argument instead, the callee's
57
+ * `['args']` would be `[[a, b]]`.
58
+ *
59
+ * @type {(f: _Eval, e: Exp) => readonly any[]}
60
+ */
61
+ const argsOf = (f, e) => /**@type {any}*/(f(e))
62
+
63
+ /**
64
+ * Calls a bare value — no receiver.
65
+ *
66
+ * The temporary is load-bearing. Written as a property of whatever holds the
67
+ * callee, this would be a *method* call, so the callee would run with that
68
+ * holder as `this` — a receiver the chain does not have — and a detached host
69
+ * method would then silently succeed on the wrapper instead of throwing:
70
+ * `((a.at)(0))(0)` returned `Array.prototype.at`.
71
+ *
72
+ * @type {(f: _Eval, v: unknown, e: Exp) => unknown}
73
+ */
74
+ const callValue = (f, v, e) => /**@type {any}*/(v)(...argsOf(f, e))
75
+
76
+ /**
77
+ * Calls `obj[prop]` *on* `obj`. That receiver is the whole reason a property
78
+ * access owns its call rather than handing on a value: `[42].at(0)` is `42`
79
+ * only because `at` is called on the array.
80
+ *
81
+ * **The argument node, not the argument array.** Both helpers take the operand
82
+ * and evaluate it themselves, inside the call expression, so that JavaScript's
83
+ * own order applies: the callee is read first, then the arguments. That order
84
+ * is observable — `a.b(...c)` throws at the access when `a` is nullish with
85
+ * `c` untouched, where `(a?.b)(...c)` reaches the call and so evaluates `c`
86
+ * before throwing — and it is *not* provable here: both readings throw, this
87
+ * language has no mutation for an operand to record itself with, and a `throw`
88
+ * case is pass/fail rather than payload-inspecting (`fjs/AGENTS.md` §1.5). So
89
+ * the structure carries what a proof cannot. Taking an evaluated array instead
90
+ * would put every argument list ahead of the property read, and every test
91
+ * here would still pass.
92
+ *
93
+ * @type {(f: _Eval, obj: any, prop: any, e: Exp) => unknown}
94
+ */
95
+ const callProperty = (f, obj, prop, e) => obj[prop](...argsOf(f, e))
96
+
97
+ /**
98
+ * The short-circuit. A region whose guard failed produces `undefined` and
99
+ * skips every step of its continuation, operands and all — except `|!()`,
100
+ * which the parentheses put *outside* the region. That step runs anyway, on
101
+ * the `undefined` the region produced, which is why `(u?.b)(...c)` throws
102
+ * where `u?.b(...c)` is `undefined`; its arguments are evaluated first, as a
103
+ * call's always are, and then `undefined` is called.
104
+ *
105
+ * The walk carries no state and does not care which lambda type it is in:
106
+ * every step is `[tag, operand, continuation]`, and a `|!()` is reachable
107
+ * through `|.` steps from either — `(a?.(...b).c)(...d)` is exactly that.
108
+ *
109
+ * @type {(f: _Eval, k: OptionLambda | OptionPropertyLambda) => unknown}
110
+ */
111
+ const skip = (f, k) => {
112
+ if (k === null) { return undefined }
113
+ return k[0] === '|!()'
114
+ ? callValue(f, undefined, k[1])
115
+ : skip(f, k[2])
116
+ }
117
+
118
+ /**
119
+ * A plain value inside an open region — what `?.()` hands on, and what a call
120
+ * step leaves. Nothing here can short-circuit: the two productions are a call
121
+ * that stays in the region and a property access that hands on a receiver.
122
+ *
123
+ * @type {(f: _Eval, v: unknown, k: OptionLambda) => unknown}
124
+ */
125
+ const optionLambda = (f, v, k) => {
126
+ if (k === null) { return v }
127
+ const [o, e, cont] = k
128
+ switch (o) {
129
+ case '|()': return optionLambda(f, callValue(f, v, e), cont)
130
+ case '|.': return optionPropertyLambda(f, v, f(e), cont)
131
+ }
132
+ }
133
+
134
+ /**
135
+ * A property access inside an open region — both bits live, so this is the
136
+ * state every step is available in. `|()` inherits the region's guard,
137
+ * `|?.()` adds its own, `|!()` escapes it, and `|.` hands the receiver on
138
+ * within the region, which is the one production that exists to protect a bit
139
+ * other than the one it consumes.
140
+ *
141
+ * `obj[prop]` is read once per step, twice only where the guard has to see
142
+ * the value before the call is made.
143
+ *
144
+ * @type {(f: _Eval, obj: any, prop: any, k: OptionPropertyLambda) => unknown}
145
+ */
146
+ const optionPropertyLambda = (f, obj, prop, k) => {
147
+ if (k === null) { return obj[prop] }
148
+ const [o, e, cont] = k
149
+ switch (o) {
150
+ case '|.': return optionPropertyLambda(f, obj[prop], f(e), cont)
151
+ case '|()': return optionLambda(f, callProperty(f, obj, prop, e), cont)
152
+ case '|!()': return callProperty(f, obj, prop, e)
153
+ case '|?.()': return nullish(obj[prop])
154
+ ? skip(f, cont)
155
+ : optionLambda(f, callProperty(f, obj, prop, e), cont)
156
+ }
157
+ }
158
+
159
+ /**
160
+ * A property access with **no** region around it — the continuation of a `.`
161
+ * node. Only a call can be here, because only a call uses the receiver: `|()`
162
+ * spends it and exits, `|?.()` spends it and opens a region that owns the
163
+ * rest of the chain. With no region open, that guard failing is simply the
164
+ * node's value, since `optionLambda` has no `|!()` of its own — but the walk
165
+ * still goes through `skip`, which reaches one through a `|.`.
166
+ *
167
+ * @type {(f: _Eval, obj: any, prop: any, k: PropertyLambda) => unknown}
168
+ */
169
+ const propertyLambda = (f, obj, prop, k) => {
170
+ if (k === null) { return obj[prop] }
171
+ const [o, e, cont] = k
172
+ switch (o) {
173
+ case '|()': return callProperty(f, obj, prop, e)
174
+ case '|?.()': return nullish(obj[prop])
175
+ ? skip(f, cont)
176
+ : optionLambda(f, callProperty(f, obj, prop, e), cont)
177
+ }
178
+ }
179
+
180
+ /**@type {Map}*/
181
+ const map = {
182
+ '!': o1(a => !a),
183
+ '!==': o2((a, b) => a !== b),
184
+ '%': o2((a, b) => a % b),
185
+ '&': o2((a, b) => a & b),
186
+ '&&': o2lazy((a, b) => a && b()),
187
+ // The call with no receiver and no region: the callee is an ordinary
188
+ // expression, so `(0, a.b)(...c)` is this node over a complete `.` while
189
+ // `a.b(...c)` is that `.` node owning its call. The two differ, and
190
+ // `throw.detachedReceiver` is the difference.
191
+ '()': (x, [, a, b]) => {
192
+ const i = vm(x)
193
+ return callValue(i, i(a), b)
194
+ },
195
+ '*': o2((a, b) => a * b),
196
+ '**': o2((a, b) => a ** b),
197
+ '+': o2((a, b) => a + b),
198
+ ',': (x, [, a]) => {
199
+ const f = vm(x)
200
+ return a.reduce((/**@type {unknown}*/_, c) => f(c), undefined)
201
+ },
202
+ '-': o2((a, b) => a - b),
203
+ // Property access, owning whatever its receiver is used for: a `null`
204
+ // continuation drops it, as reading `a.b` for its value does, and the two
205
+ // call steps are the only things that can spend it.
206
+ '.': (x, [, a, k, p]) => {
207
+ const i = vm(x)
208
+ return propertyLambda(i, i(a), i(k), p)
209
+ },
210
+ '/': o2((a, b) => a / b),
211
+ '<': o2((a, b) => a < b),
212
+ '<<': o2((a, b) => a << b),
213
+ '<=': o2((a, b) => a <= b),
214
+ '===': o2((a, b) => a === b),
215
+ '=>': (x, [, frameExp, body]) => {
216
+ const frame = vm(x)(frameExp)
217
+ /**@type {(...arg: readonly unknown[]) => unknown}*/
218
+ return (...args) =>vm({ frame, args })(body)
219
+ },
220
+ '>': o2((a, b) => a > b),
221
+ '>=': o2((a, b) => a >= b),
222
+ '>>': o2((a, b) => a >> b),
223
+ '>>>': o2((a, b) => a >>> b),
224
+ // Optional property access, owning the rest of its optional region. On a
225
+ // nullish input the region short-circuits: the node's own `index` is not
226
+ // evaluated — which is why `a?.[k]` does not evaluate `k` — and neither is
227
+ // any step of the continuation, `|!()` excepted. `skip` is what carries
228
+ // that exception, and it is why `u?.b` and `(u?.b)(d)` part company:
229
+ // the first is `undefined`, the second calls it.
230
+ '?.': (x, [, a, k, p]) => {
231
+ const i = vm(x)
232
+ const obj = i(a)
233
+ return nullish(obj) ? skip(i, p) : optionPropertyLambda(i, obj, i(k), p)
234
+ },
235
+ // Optional call, the region-opening counterpart of `?.`. The callee is an
236
+ // ordinary expression, so this node never carries a receiver — `a.b?.(c)`
237
+ // is a `.` node with a `|?.()` continuation, not this one — and a nullish
238
+ // callee leaves the arguments unevaluated.
239
+ '?.()': (x, [, a, b, k]) => {
240
+ const i = vm(x)
241
+ const f = i(a)
242
+ return nullish(f) ? skip(i, k) : optionLambda(i, callValue(i, f, b), k)
243
+ },
244
+ '??': o2lazy((a, b) => a ?? b()),
245
+ Number: o1(Number),
246
+ String: o1(String),
247
+ '[]': (x, [, a]) => {
248
+ const f = vm(x)
249
+ // A spread operand is iterated, not spliced as one element: `[...'ab']`
250
+ // is `['a', 'b']` and `[...1]` throws, per "array spread" in
251
+ // `../README.md`. `flatMap` alone flattens only real arrays.
252
+ /**@type {(e: Exp) => readonly unknown[]}*/
253
+ const spread = e => [.../**@type {any}*/(f(e))]
254
+ return a.flatMap(e =>
255
+ (e instanceof Array) && e[0] === '...' ? spread(e[1]) : [f(e)])
256
+ },
257
+ '^': o2((a, b) => a ^ b),
258
+ args: ({args}) => args,
259
+ frame: ({frame}) => frame,
260
+ neg: o1(a => -a),
261
+ // The key must *evaluate* to a string — a runtime constraint the
262
+ // shape-only schema cannot express, so the executor upholds it. Without
263
+ // the check JS `ToPropertyKey` would coerce, and `['own', o, 1]` would
264
+ // silently read `o['1']`.
265
+ own: o2((a, b) => {
266
+ assert(typeof b === 'string', ['own: key is not a string', b])
267
+ return Object.getOwnPropertyDescriptor(a, b)?.value
268
+ }),
269
+ undefined: () => undefined,
270
+ '{}': (x, [, a]) => {
271
+ const f = vm(x)
272
+ /**@type {(e: Properties) => readonly[unknown, unknown][]}*/
273
+ const g = e => e[0] === ':'
274
+ ? [[f(e[1]), f(e[2])]]
275
+ // `Object(...)` is what makes a nullish operand contribute nothing
276
+ // (`{...null}` is `{}`) while a string still contributes its
277
+ // indices — `Object.entries` alone throws on `null`/`undefined`.
278
+ : Object.entries(Object(f(e[1])))
279
+ const kv = a.flatMap(g)
280
+ return Object.fromEntries(kv)
281
+ },
282
+ '|': o2((a, b) => a | b),
283
+ '||': o2lazy((a, b) => a || b()),
284
+ '~': o1(a => ~a),
285
+ }
286
+
287
+ export const vm = (/**@type {Context}*/context) => {
288
+ const compute =
289
+ /**
290
+ * Generic over the tag, not `(e: ExpOp) =>`: with a union-typed `e`,
291
+ * `map[e[0]]` is a union of every handler signature, callable only with
292
+ * the intersection of their tuples — `never`. Through `K` it stays the
293
+ * one signature `(c, r: TagMap[K])` — see `TagMap` in `./types.ts`.
294
+ *
295
+ * @type {<K extends ExpOp[0]>(
296
+ * e: TagMap[K] & readonly [K, ...readonly unknown[]]
297
+ * ) => unknown}
298
+ */
299
+ e => map[e[0]](context, e)
300
+ return (/**@type{Exp}*/e) => e instanceof Array
301
+ ? compute(e)
302
+ : e
303
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Execution semantics of `vm` — one section per operand shape, since that is
3
+ * how `map`'s handlers are built (`o1`/`o2`/`o2lazy`), plus the nodes that
4
+ * evaluate their operands themselves (`,`, `[]`, `{}`, and the four chain
5
+ * nodes — `()`, `.`, `?.`, and `?.()`). Nothing is `todo` any more.
6
+ * This is the executing counterpart of `../proof.f.mjs`, which pins what the
7
+ * schema *accepts*; nothing here validates.
8
+ *
9
+ * @import { Exp } from '../types.ts'
10
+ * @import { Context } from './types.ts'
11
+ * @import { Assert } from '../../asserts/types.ts'
12
+ * @import { Equal } from '../../types/ts/types.ts'
13
+ * @import { Array as ExpArray, Call, Dot, Index, Op1, Op2 } from '../types.ts'
14
+ * @import { Get } from './types.ts'
15
+ */
16
+ import type { Assert } from '../../asserts/types.ts';
17
+ import type { Equal } from '../../types/ts/types.ts';
18
+ import type { Array as ExpArray, Call, Dot, Op1, Op2 } from '../types.ts';
19
+ import type { Get } from './types.ts';
20
+ export type _PlusIsOp2 = Assert<Equal<Get<'+'>, Op2>>;
21
+ export type _NegIsOp1 = Assert<Equal<Get<'neg'>, Op1>>;
22
+ export type _BracketsIsArray = Assert<Equal<Get<'[]'>, ExpArray>>;
23
+ export type _CallIsCall = Assert<Equal<Get<'()'>, Call>>;
24
+ export type _DotIsDot = Assert<Equal<Get<'.'>, Dot>>;
25
+ export declare const proof: {
26
+ primitive: () => void;
27
+ op0: () => void;
28
+ op1: () => void;
29
+ op2: () => void;
30
+ property: () => void;
31
+ lazy: () => void;
32
+ comma: () => void;
33
+ array: () => void;
34
+ object: () => void;
35
+ nested: () => void;
36
+ lambda: () => void;
37
+ call: () => void;
38
+ chain: {
39
+ callStep: () => void;
40
+ optionCallStep: () => void;
41
+ optionCallStepSkips: () => void;
42
+ receiver: () => void;
43
+ throw: {
44
+ detachedReceiver: () => unknown;
45
+ detachedReceiverAfterCall: () => unknown;
46
+ callStepOnNonFunction: () => unknown;
47
+ propertyOnUndefined: () => unknown;
48
+ propertyOnNull: () => unknown;
49
+ };
50
+ };
51
+ optionDot: () => void;
52
+ optionCall: () => void;
53
+ optionRegion: {
54
+ skips: () => void;
55
+ throw: {
56
+ closeStepOnUndefined: () => unknown;
57
+ closeStepOnNull: () => unknown;
58
+ closeStepPastSkippedProperty: () => unknown;
59
+ closeStepAfterOptionCall: () => unknown;
60
+ closeStepAfterPropertyGuard: () => unknown;
61
+ callOfSkippedGuard: () => unknown;
62
+ };
63
+ };
64
+ closure: () => void;
65
+ higherOrder: () => void;
66
+ throw: {
67
+ evaluatedIndex: () => unknown;
68
+ evaluatedArgument: () => unknown;
69
+ optionCallOnNonFunction: () => unknown;
70
+ arraySpreadOfNumber: () => unknown;
71
+ arraySpreadOfNull: () => unknown;
72
+ ownNonStringKey: () => unknown;
73
+ callNonFunction: () => unknown;
74
+ forcedAnd: () => unknown;
75
+ forcedOr: () => unknown;
76
+ forcedCoalesce: () => unknown;
77
+ forcedEager: () => unknown;
78
+ };
79
+ };