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
@@ -49,13 +49,13 @@ import {
49
49
  unicodeRange,
50
50
  } from '../../bnf/module.f.mjs'
51
51
  import { keywords } from '../../js/keywords/module.f.mjs'
52
+ import { escapeToCodePoint } from '../../js/string_escape/module.f.mjs'
52
53
  import { isKeywordToken, mergeTrivia } from '../../js/tokenizer/module.f.mjs'
53
54
  import {
54
- asterisk, backspace, ht, lf, ff, cr,
55
- quotationMark, solidus, reverseSolidus,
55
+ asterisk, lf,
56
+ solidus, reverseSolidus,
56
57
  hexDigitValue,
57
- latinSmallLetterB, latinSmallLetterF,
58
- latinSmallLetterN, latinSmallLetterR, latinSmallLetterT, latinSmallLetterU,
58
+ latinSmallLetterU,
59
59
  } from '../../text/ascii/module.f.mjs'
60
60
  import { codePointListToString, stringToCodePointList } from '../../text/utf16/module.f.mjs'
61
61
  import { mapUnwrap } from '../../types/nullable/module.f.mjs'
@@ -64,6 +64,97 @@ import { stringifyAsTree } from '../serializer/module.f.mjs'
64
64
  import { sort } from '../../types/object/module.f.mjs'
65
65
 
66
66
  // Builds the single-token grammar that jsGrammar's whole-file `tokens` rule repeats.
67
+ /**
68
+ * The whitespace characters the grammar's `ws` rule matches.
69
+ *
70
+ * The grammar's rule and every downstream check of a trivia tag are built from
71
+ * this one string: the descent parser emits a range-variant branch's tag as the
72
+ * matched character itself, so the characters the rule accepts *are* the tags it
73
+ * produces. Spelling them a second time is what let the two drift apart.
74
+ *
75
+ * @type {string}
76
+ */
77
+ const wsChars = ' \t'
78
+
79
+ /**
80
+ * The newline characters the grammar's `newLine` rule matches, the single source
81
+ * for that rule and its tags exactly as {@link wsChars} is.
82
+ *
83
+ * @type {string}
84
+ */
85
+ const nlChars = '\n\r'
86
+
87
+ /** @type {ReadonlySet<string>} */
88
+ const wsTags = new Set(wsChars)
89
+
90
+ /** @type {ReadonlySet<string>} */
91
+ const nlTags = new Set(nlChars)
92
+
93
+ /**
94
+ * The operator vocabulary: each key is the tag the descent parser emits for that
95
+ * branch, and each value the characters it matches.
96
+ *
97
+ * At module scope because it captures nothing from `buildToken`, and because
98
+ * `operatorTags` derives the tag set from these keys rather than re-listing them.
99
+ */
100
+ const operator = {
101
+ '.': '.',
102
+ '=>': '=>',
103
+ '===': '===',
104
+ '==': '==',
105
+ '=': '=',
106
+ '!==': '!==',
107
+ '!=': '!=',
108
+ '!': '!',
109
+ '>>>=': '>>>=',
110
+ '>>>': '>>>',
111
+ '>>=': '>>=',
112
+ '>>': '>>',
113
+ '>=': '>=',
114
+ '>': '>',
115
+ '<<=': '<<=',
116
+ '<<': '<<',
117
+ '<=': '<=',
118
+ '<': '<',
119
+ '+=': '+=',
120
+ '++': '++',
121
+ '+': '+',
122
+ '-=': '-=',
123
+ '--': '--',
124
+ '-': '-',
125
+ '**=': '**=',
126
+ '**': '**',
127
+ '*=': '*=',
128
+ '*': '*',
129
+ '/=': '/=',
130
+ '/': '/',
131
+ '%=': '%=',
132
+ '%': '%',
133
+ '&&=': '&&=',
134
+ '&&': '&&',
135
+ '&=': '&=',
136
+ '&': '&',
137
+ '||=': '||=',
138
+ '||': '||',
139
+ '|=': '|=',
140
+ '|': '|',
141
+ '^=': '^=',
142
+ '^': '^',
143
+ '~': '~',
144
+ '??=': '??=',
145
+ '??': '??',
146
+ '?.': '?.',
147
+ '?': '?',
148
+ '[': '[',
149
+ ']': ']',
150
+ '{': '{',
151
+ '}': '}',
152
+ '(': '(',
153
+ ')': ')',
154
+ ',': ',',
155
+ ':': ':'
156
+ }
157
+
67
158
  /** @type {() => Rule} */
68
159
  const buildToken = () => {
69
160
 
@@ -99,9 +190,9 @@ const buildToken = () => {
99
190
 
100
191
  const digits = [digit, digits0]
101
192
 
102
- const ws = set(' \t')
193
+ const ws = set(wsChars)
103
194
 
104
- const newLine = set('\n\r')
195
+ const newLine = set(nlChars)
105
196
 
106
197
  const idStart = {
107
198
  smallLetter: range('az'),
@@ -143,64 +234,6 @@ const buildToken = () => {
143
234
 
144
235
  const id = [idStart, repeat0Plus(idChar)]
145
236
 
146
- const operator = {
147
- '.': '.',
148
- '=>': '=>',
149
- '===': '===',
150
- '==': '==',
151
- '=': '=',
152
- '!==': '!==',
153
- '!=': '!=',
154
- '!': '!',
155
- '>>>=': '>>>=',
156
- '>>>': '>>>',
157
- '>>=': '>>=',
158
- '>>': '>>',
159
- '>=': '>=',
160
- '>': '>',
161
- '<<=': '<<=',
162
- '<<': '<<',
163
- '<=': '<=',
164
- '<': '<',
165
- '+=': '+=',
166
- '++': '++',
167
- '+': '+',
168
- '-=': '-=',
169
- '--': '--',
170
- '-': '-',
171
- '**=': '**=',
172
- '**': '**',
173
- '*=': '*=',
174
- '*': '*',
175
- '/=': '/=',
176
- '/': '/',
177
- '%=': '%=',
178
- '%': '%',
179
- '&&=': '&&=',
180
- '&&': '&&',
181
- '&=': '&=',
182
- '&': '&',
183
- '||=': '||=',
184
- '||': '||',
185
- '|=': '|=',
186
- '|': '|',
187
- '^=': '^=',
188
- '^': '^',
189
- '~': '~',
190
- '??=': '??=',
191
- '??': '??',
192
- '?.': '?.',
193
- '?': '?',
194
- '[': '[',
195
- ']': ']',
196
- '{': '{',
197
- '}': '}',
198
- '(': '(',
199
- ')': ')',
200
- ',': ',',
201
- ':': ':'
202
- }
203
-
204
237
  // Recursive rule: tries end (*/) first at every position so **/ → content(*) + terminator(*/).
205
238
  // Falls back to the empty `unterminated` alternative at EOF instead of failing, so `comment`
206
239
  // always succeeds and the descent parser never backtracks into matching '/' and '*' as
@@ -295,8 +328,8 @@ const codePointsWithMetadata = path => cp => toArray(flat(stateScan(metadataScan
295
328
  * @type {(tag: string) => Nullable<TriviaKind>}
296
329
  */
297
330
  const triviaKind = tag =>
298
- tag === '\n' || tag === '\r' ? 'nl' :
299
- tag === ' ' || tag === '\t' ? 'ws' :
331
+ nlTags.has(tag) ? 'nl' :
332
+ wsTags.has(tag) ? 'ws' :
300
333
  null
301
334
 
302
335
  /** @type {StateScan<_FlatToken, _TokenScanState, List<_Token>>} */
@@ -325,17 +358,18 @@ const scanFunc = (input, state) => {
325
358
  return [null, [stateTag, startMetadata, concat(stateCodePoints)([cp])]]
326
359
  }
327
360
 
328
- // All operator tag strings produced by the grammar's operator rule
329
- const operatorTags = new Set([
330
- '.', '=>', '===', '==', '=', '!==', '!=', '!',
331
- '>>>=', '>>>', '>>=', '>>', '>=', '>',
332
- '<<=', '<<', '<=', '<',
333
- '+=', '++', '+', '-=', '--', '-',
334
- '**=', '**', '*=', '*', '/=', '/', '%=', '%', // TODO: '/' here causes multi-char line comments (e.g. //ab\n) to fall through as two '/' operator tokens because the oneline rule only consumes one non-newline character (option vs repeat0Plus). Fix the comment rule to use repeat0Plus, or make filterFunc distinguish operator-branch '/' from slash characters inside comments.
335
- '&&=', '&&', '&=', '&', '||=', '||', '|=', '|',
336
- '^=', '^', '~', '??=', '??', '?.', '?',
337
- '[', ']', '{', '}', '(', ')', ',', ':'
338
- ])
361
+ /**
362
+ * All operator tag strings the grammar's `operator` rule produces, derived from
363
+ * the rule itself: the descent parser emits a variant branch's key as its tag,
364
+ * so the keys of {@link operator} *are* the tag set.
365
+ *
366
+ * `'/'` is a member because division is an operator; it does not also swallow
367
+ * the slashes of a comment, since `oneline` consumes the whole rest of the line
368
+ * with `repeat0Plus` and the comment rule matches before the tag reaches here.
369
+ *
370
+ * @type {ReadonlySet<string>}
371
+ */
372
+ const operatorTags = new Set(Object.keys(operator))
339
373
 
340
374
  /** @type {(tk: _FlatToken) => boolean} */
341
375
  const filterFunc = tk => {
@@ -346,13 +380,11 @@ const filterFunc = tk => {
346
380
  case 'string':
347
381
  case 'id':
348
382
  case 'comment':
349
- case '\n':
350
- case '\r':
351
- case ' ':
352
- case '\t':
353
383
  return true
354
384
  default:
355
- return operatorTags.has(tk)
385
+ // Trivia tags go through `triviaKind` rather than a third copy of
386
+ // the characters, so they cannot drift from the grammar's rules.
387
+ return triviaKind(tk) !== null || operatorTags.has(tk)
356
388
  }
357
389
  }
358
390
 
@@ -374,32 +406,17 @@ const unwrapHexDigitValue = mapUnwrap(hexDigitValue)
374
406
  const stringDecodeScan = (cp, state) => {
375
407
  switch (state.kind) {
376
408
  case 'escape': {
409
+ const codePoint = escapeToCodePoint(cp)
377
410
  // The grammar's own `escape` rule (`buildToken`'s `string`) only ever
378
- // accepts `"`, `\`, `/`, `b`, `f`, `n`, `r`, `t`, or `u` right after a
411
+ // accepts one of the eight simple escapes or `u` right after a
379
412
  // backslash — any other character fails to parse before a token
380
413
  // reaches this scan at all, so narrowing to those nine is provable,
381
- // not merely assumed.
382
- assert(
383
- cp === quotationMark || cp === reverseSolidus || cp === solidus ||
384
- cp === latinSmallLetterB || cp === latinSmallLetterF || cp === latinSmallLetterN ||
385
- cp === latinSmallLetterR || cp === latinSmallLetterT || cp === latinSmallLetterU,
386
- cp)
387
- switch (cp) {
388
- case quotationMark: return [[quotationMark], { kind: 'normal' }] // \" → "
389
- case reverseSolidus: return [[reverseSolidus], { kind: 'normal' }] // \\ → \
390
- case solidus: return [[solidus], { kind: 'normal' }] // \/ → /
391
- case latinSmallLetterB: return [[backspace], { kind: 'normal' }] // \b → backspace (BS)
392
- case latinSmallLetterF: return [[ff], { kind: 'normal' }] // \f → form feed (FF)
393
- case latinSmallLetterN: return [[lf], { kind: 'normal' }] // \n → line feed (LF)
394
- case latinSmallLetterR: return [[cr], { kind: 'normal' }] // \r → carriage return (CR)
395
- case latinSmallLetterT: return [[ht], { kind: 'normal' }] // \t → horizontal tab (HT)
396
- // `\u` is the only case the assertion above leaves. It is a
397
- // `default` rather than a `case latinSmallLetterU` because the
398
- // ASCII constants are plain `number`s, so the switch can never
399
- // be exhaustive to TypeScript and the clause would fall through
400
- // into `unicode` below.
401
- default: return [null, { kind: 'unicode', acc: 0, count: 0 }] // \u → start 4 hex digits
402
- }
414
+ // not merely assumed. `u` is the one the table does not answer for:
415
+ // the four hex digits that follow decide its meaning.
416
+ assert(codePoint !== null || cp === latinSmallLetterU, cp)
417
+ return codePoint === null
418
+ ? [null, { kind: 'unicode', acc: 0, count: 0 }] // \u → start 4 hex digits
419
+ : [[codePoint], { kind: 'normal' }]
403
420
  }
404
421
  case 'unicode': {
405
422
  const acc = (state.acc << 4) | unwrapHexDigitValue(cp)
@@ -800,6 +800,23 @@ export const proof = {
800
800
  const result = tokenizeString('/* multiline comment *\n * **/')
801
801
  if (result !== '[{"kind":"/*","value":" multiline comment *\\n * *"},{"kind":"nl"},{"kind":"eof"}]') { throw result }
802
802
  },
803
+ // `'/'` is an `operatorTags` member for division, so a line comment's own
804
+ // slashes must be consumed by the comment rule before the tag reaches
805
+ // `filterFunc`. These pin that: a multi-character line comment stays one
806
+ // token, inner slashes included, and division still tokenizes as an
807
+ // operator.
808
+ () => {
809
+ const result = tokenizeString('//ab\n')
810
+ assertEq(result, '[{"kind":"//","value":"ab"},{"kind":"nl"},{"kind":"eof"}]')
811
+ },
812
+ () => {
813
+ const result = tokenizeString('//a//b\n')
814
+ assertEq(result, '[{"kind":"//","value":"a//b"},{"kind":"nl"},{"kind":"eof"}]')
815
+ },
816
+ () => {
817
+ const result = tokenizeString('a/b')
818
+ assertEq(result, '[{"kind":"id","value":"a"},{"kind":"/"},{"kind":"id","value":"b"},{"kind":"eof"}]')
819
+ },
803
820
  ],
804
821
  metadata: [
805
822
  () => {
@@ -23,8 +23,7 @@ import { concat as pathConcat } from '../../path/module.f.mjs'
23
23
  import { parseFromTokens } from '../parser/module.f.mjs'
24
24
  import { parse as jsonParse } from '../../media/json/module.f.mjs'
25
25
  import { run } from '../ast/module.f.mjs'
26
- import { pure } from '../../effects/module.f.mjs'
27
- import { catchStep, foldStep, mapStep, pureError, pureOk, step } from '../../effects/module.f.mjs'
26
+ import { catchStep, foldStep, mapStep, pure, pureError, pureOk, step } from '../../effects/module.f.mjs'
28
27
  import { readUtf8File } from '../../effects/node/module.f.mjs'
29
28
 
30
29
  /**
@@ -65,16 +64,16 @@ const transpileWithImports = path => module => context => {
65
64
  const pathsArray = toArray(pathsCombine)
66
65
  const contextWithStack = { ...context, stack: { first: path, tail: context.stack } }
67
66
  const x0 = foldStep(pureOk(pathsArray), contextWithStack, foldNextModuleOp)
68
- return step(
67
+ return mapStep(
69
68
  x0,
70
69
  contextWithImports => {
71
70
  const args = toArray(listMap(mapDjs(contextWithImports))(pathsCombine))
72
71
  const djs = { djs: run(module[1])(args) }
73
- return pureOk({
72
+ return {
74
73
  ...contextWithImports,
75
74
  stack: drop(1)(contextWithImports.stack),
76
75
  complete: setReplace(path)(djs)(contextWithImports.complete),
77
- })
76
+ }
78
77
  })
79
78
  }
80
79
 
@@ -5,6 +5,8 @@ export declare const proof: {
5
5
  parseWithIdentifierKeys: () => void;
6
6
  parseWithConstIdentifier: () => void;
7
7
  parseWithUnaryMinusOperator: () => void;
8
+ parseAbsolutePath: () => void;
9
+ parseRelativePathEscapesRoot: () => void;
8
10
  parseWithFileNotFoundError: () => void;
9
11
  parseWithCycleError: () => void;
10
12
  };
@@ -59,6 +59,31 @@ export const proof = {
59
59
  const s = stringifyAsTree(sort)(result[1])
60
60
  assertEq(s, '[-1,2,-3]')
61
61
  },
62
+ // A module named by an absolute path resolves its imports: `transpile`
63
+ // reaches them through `concat(concat(path)('..'))(importPath)`, which
64
+ // used to drop the leading `/` and look the import up under the current
65
+ // directory instead. Here the import also names `..` from the root, so
66
+ // the answer depends on the root surviving both calls.
67
+ parseAbsolutePath: () => {
68
+ const result = run({
69
+ 'lib.f.js': [utf8('export default 8080')],
70
+ 'm.f.js': [utf8('import p from "../lib.f.js"\nexport default p')],
71
+ })('/m.f.js')
72
+ assert(result[0] !== 'error', result[1])
73
+ const s = stringifyAsTree(sort)(result[1])
74
+ assertEq(s, '8080')
75
+ },
76
+ // The control: with no root to clamp it, the same `..` escapes and finds
77
+ // nothing — which is why the case above is about the root and not about
78
+ // `..` being ignored.
79
+ parseRelativePathEscapesRoot: () => {
80
+ const result = run({
81
+ 'lib.f.js': [utf8('export default 8080')],
82
+ 'm.f.js': [utf8('import p from "../lib.f.js"\nexport default p')],
83
+ })('m.f.js')
84
+ assert(result[0] === 'error', result)
85
+ assertEq(result[1].message, 'file not found', result)
86
+ },
62
87
  parseWithFileNotFoundError: () => {
63
88
  const result = run({ a: [utf8('import b from "b"\nexport default b')] })('a')
64
89
  assert(result[0] === 'error', result)
@@ -0,0 +1,20 @@
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
+ import type { Exp, Op1 } from '../types.ts';
17
+ import type { Context } from './types.ts';
18
+ export type _Func1 = (c: Context, e: Op1) => unknown;
19
+ export type _Eval = (_: Exp) => unknown;
20
+ export declare const vm: (/**@type {Context}*/ context: Context) => (/**@type{Exp}*/ e: Exp) => unknown;