functionalscript 0.45.0 → 0.46.1

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 (296) hide show
  1. package/README.md +5 -3
  2. package/fjs/asn.1/module.f.mjs +8 -1
  3. package/fjs/asn.1/proof.f.d.mts +10 -0
  4. package/fjs/asn.1/proof.f.mjs +16 -0
  5. package/fjs/basen/base128/module.f.mjs +22 -5
  6. package/fjs/bnf/data/module.f.d.mts +32 -6
  7. package/fjs/bnf/data/module.f.mjs +112 -7
  8. package/fjs/bnf/data/proof.f.d.mts +2 -0
  9. package/fjs/bnf/data/proof.f.mjs +74 -3
  10. package/fjs/bnf/data/types.d.ts +20 -2
  11. package/fjs/bnf/descent/module.f.d.mts +28 -14
  12. package/fjs/bnf/descent/module.f.mjs +122 -77
  13. package/fjs/bnf/descent/proof.f.d.mts +2 -0
  14. package/fjs/bnf/descent/proof.f.mjs +117 -31
  15. package/fjs/bnf/descent/types.d.ts +12 -14
  16. package/fjs/bnf/ll1/module.f.d.mts +64 -22
  17. package/fjs/bnf/ll1/module.f.mjs +214 -154
  18. package/fjs/bnf/ll1/proof.f.d.mts +15 -2
  19. package/fjs/bnf/ll1/proof.f.mjs +323 -149
  20. package/fjs/bnf/ll1/types.d.ts +16 -24
  21. package/fjs/bnf/matcher/module.f.d.mts +66 -0
  22. package/fjs/bnf/matcher/module.f.mjs +81 -0
  23. package/fjs/bnf/matcher/proof.f.d.mts +10 -0
  24. package/fjs/bnf/matcher/proof.f.mjs +79 -0
  25. package/fjs/bnf/matcher/types.d.ts +54 -0
  26. package/fjs/bnf/testlib.f.d.mts +31 -0
  27. package/fjs/bnf/testlib.f.mjs +80 -0
  28. package/fjs/cas/cli/module.f.d.mts +1 -1
  29. package/fjs/cas/cli/module.f.mjs +14 -20
  30. package/fjs/cas/cli/proof.f.d.mts +1 -3
  31. package/fjs/cas/cli/proof.f.mjs +44 -33
  32. package/fjs/cas/evo/module.f.d.mts +64 -18
  33. package/fjs/cas/evo/module.f.mjs +148 -70
  34. package/fjs/cas/evo/proof.f.d.mts +10 -1
  35. package/fjs/cas/evo/proof.f.mjs +305 -223
  36. package/fjs/cas/evo/types.d.ts +45 -9
  37. package/fjs/cas/module.f.d.mts +18 -32
  38. package/fjs/cas/module.f.mjs +129 -128
  39. package/fjs/cas/proof.f.d.mts +11 -8
  40. package/fjs/cas/proof.f.mjs +259 -147
  41. package/fjs/cas/types.d.ts +24 -10
  42. package/fjs/ci/config/module.f.d.mts +2 -2
  43. package/fjs/ci/config/module.f.mjs +2 -2
  44. package/fjs/ci/module.f.d.mts +5 -5
  45. package/fjs/ci/module.f.mjs +8 -7
  46. package/fjs/ci/nix/module.f.d.mts +7 -5
  47. package/fjs/ci/nix/module.f.mjs +13 -12
  48. package/fjs/ci/nix/proof.f.mjs +2 -2
  49. package/fjs/ci/proof.f.mjs +9 -5
  50. package/fjs/cli/module.f.d.mts +4 -6
  51. package/fjs/cli/module.f.mjs +4 -8
  52. package/fjs/cli/proof.f.mjs +17 -16
  53. package/fjs/cli/types.d.ts +2 -3
  54. package/fjs/common/monoid/types.d.ts +1 -1
  55. package/fjs/crypto/hmac/module.f.mjs +2 -2
  56. package/fjs/crypto/sha2/module.f.mjs +3 -1
  57. package/fjs/crypto/sha2/proof.f.d.mts +1 -0
  58. package/fjs/crypto/sha2/proof.f.mjs +24 -0
  59. package/fjs/crypto/sha2/types.d.ts +11 -0
  60. package/fjs/crypto/sign/module.f.mjs +2 -2
  61. package/fjs/dev/module.f.d.mts +13 -4
  62. package/fjs/dev/module.f.mjs +56 -27
  63. package/fjs/dev/update/module.f.d.mts +9 -4
  64. package/fjs/dev/update/module.f.mjs +14 -10
  65. package/fjs/dev/update/proof.f.d.mts +1 -3
  66. package/fjs/dev/update/proof.f.mjs +10 -5
  67. package/fjs/djs/module.f.d.mts +13 -5
  68. package/fjs/djs/module.f.mjs +31 -16
  69. package/fjs/djs/parser/module.f.d.mts +13 -3
  70. package/fjs/djs/parser/module.f.mjs +117 -16
  71. package/fjs/djs/parser/proof.f.d.mts +5 -1
  72. package/fjs/djs/parser/proof.f.mjs +274 -12
  73. package/fjs/djs/parser/types.d.ts +7 -1
  74. package/fjs/djs/proof.f.d.mts +18 -2
  75. package/fjs/djs/proof.f.mjs +187 -12
  76. package/fjs/djs/serializer/module.f.d.mts +25 -8
  77. package/fjs/djs/serializer/module.f.mjs +61 -15
  78. package/fjs/djs/serializer/proof.f.d.mts +5 -0
  79. package/fjs/djs/serializer/proof.f.mjs +23 -1
  80. package/fjs/djs/tokenizer/module.f.d.mts +17 -5
  81. package/fjs/djs/tokenizer/module.f.mjs +99 -60
  82. package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
  83. package/fjs/djs/tokenizer/proof.f.mjs +74 -67
  84. package/fjs/djs/transpiler/module.f.d.mts +12 -7
  85. package/fjs/djs/transpiler/module.f.mjs +82 -56
  86. package/fjs/djs/transpiler/types.d.ts +7 -3
  87. package/fjs/djs/types.d.ts +7 -1
  88. package/fjs/effects/list/module.f.d.mts +14 -11
  89. package/fjs/effects/list/module.f.mjs +13 -11
  90. package/fjs/effects/list/types.d.ts +27 -7
  91. package/fjs/effects/memory/module.f.d.mts +2 -1
  92. package/fjs/effects/memory/module.f.mjs +3 -4
  93. package/fjs/effects/memory/proof.f.mjs +13 -7
  94. package/fjs/effects/memory/types.d.ts +4 -3
  95. package/fjs/effects/mock/module.f.d.mts +20 -4
  96. package/fjs/effects/mock/module.f.mjs +37 -5
  97. package/fjs/effects/mock/types.d.ts +10 -1
  98. package/fjs/effects/module.d.mts +4 -2
  99. package/fjs/effects/module.f.d.mts +466 -280
  100. package/fjs/effects/module.f.mjs +537 -299
  101. package/fjs/effects/module.mjs +2 -1
  102. package/fjs/effects/node/memory/module.d.mts +4 -2
  103. package/fjs/effects/node/memory/module.mjs +6 -3
  104. package/fjs/effects/node/memory/proof.mjs +10 -4
  105. package/fjs/effects/node/module.d.mts +4 -3
  106. package/fjs/effects/node/module.f.d.mts +168 -33
  107. package/fjs/effects/node/module.f.mjs +256 -52
  108. package/fjs/effects/node/module.mjs +57 -34
  109. package/fjs/effects/node/proof.f.d.mts +28 -2
  110. package/fjs/effects/node/proof.f.mjs +161 -42
  111. package/fjs/effects/node/types.d.ts +106 -18
  112. package/fjs/effects/node/virtual/module.f.d.mts +18 -4
  113. package/fjs/effects/node/virtual/module.f.mjs +110 -68
  114. package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
  115. package/fjs/effects/node/virtual/proof.f.mjs +190 -9
  116. package/fjs/effects/proof.f.d.mts +69 -37
  117. package/fjs/effects/proof.f.mjs +410 -130
  118. package/fjs/effects/types.d.ts +161 -33
  119. package/fjs/emergent_testing/module.f.d.mts +19 -12
  120. package/fjs/emergent_testing/module.f.mjs +93 -33
  121. package/fjs/emergent_testing/proof.f.d.mts +21 -7
  122. package/fjs/emergent_testing/proof.f.mjs +166 -32
  123. package/fjs/emergent_testing/types.d.ts +22 -4
  124. package/fjs/fsm/module.f.d.mts +14 -4
  125. package/fjs/fsm/module.f.mjs +54 -37
  126. package/fjs/fsm/proof.f.d.mts +2 -0
  127. package/fjs/fsm/proof.f.mjs +83 -114
  128. package/fjs/js/keywords/module.f.d.mts +52 -0
  129. package/fjs/js/keywords/module.f.mjs +72 -0
  130. package/fjs/js/keywords/proof.f.d.mts +3 -0
  131. package/fjs/js/keywords/proof.f.mjs +13 -0
  132. package/fjs/js/tokenizer/module.f.d.mts +26 -6
  133. package/fjs/js/tokenizer/module.f.mjs +145 -159
  134. package/fjs/js/tokenizer/proof.f.d.mts +1 -0
  135. package/fjs/js/tokenizer/proof.f.mjs +54 -24
  136. package/fjs/js/tokenizer/types.d.ts +33 -24
  137. package/fjs/mcp/cas/module.f.d.mts +1 -6
  138. package/fjs/mcp/cas/module.f.mjs +55 -51
  139. package/fjs/mcp/cas/proof.f.d.mts +15 -0
  140. package/fjs/mcp/cas/proof.f.mjs +174 -0
  141. package/fjs/mcp/evo/module.f.d.mts +19 -10
  142. package/fjs/mcp/evo/module.f.mjs +48 -27
  143. package/fjs/mcp/evo/proof.f.d.mts +6 -1
  144. package/fjs/mcp/evo/proof.f.mjs +115 -31
  145. package/fjs/mcp/module.f.d.mts +4 -4
  146. package/fjs/mcp/module.f.mjs +6 -6
  147. package/fjs/mcp/proof.f.d.mts +5 -3
  148. package/fjs/mcp/proof.f.mjs +112 -46
  149. package/fjs/media/html/module.f.mjs +1 -1
  150. package/fjs/media/json/extended/module.f.d.mts +82 -0
  151. package/fjs/media/json/extended/module.f.mjs +153 -0
  152. package/fjs/media/json/extended/proof.f.d.mts +42 -0
  153. package/fjs/media/json/extended/proof.f.mjs +127 -0
  154. package/fjs/media/json/extended/types.d.ts +23 -0
  155. package/fjs/media/json/module.f.d.mts +8 -2
  156. package/fjs/media/json/module.f.mjs +43 -41
  157. package/fjs/media/json/number/module.f.d.mts +59 -0
  158. package/fjs/media/json/number/module.f.mjs +136 -0
  159. package/fjs/media/json/number/proof.f.d.mts +24 -0
  160. package/fjs/media/json/number/proof.f.mjs +86 -0
  161. package/fjs/media/json/number/types.d.ts +28 -0
  162. package/fjs/media/json/parser/module.f.d.mts +25 -13
  163. package/fjs/media/json/parser/module.f.mjs +114 -70
  164. package/fjs/media/json/parser/proof.f.d.mts +5 -0
  165. package/fjs/media/json/parser/proof.f.mjs +31 -1
  166. package/fjs/media/json/parser/types.d.ts +33 -14
  167. package/fjs/media/json/rtti/module.f.d.mts +1 -1
  168. package/fjs/media/json/rtti/module.f.mjs +1 -1
  169. package/fjs/media/json/rtti/proof.f.mjs +9 -9
  170. package/fjs/media/json/schema/module.f.mjs +3 -13
  171. package/fjs/media/json/schema/proof.f.d.mts +0 -1
  172. package/fjs/media/json/schema/proof.f.mjs +1 -2
  173. package/fjs/media/json/serializer/module.f.d.mts +32 -1
  174. package/fjs/media/json/serializer/module.f.mjs +64 -2
  175. package/fjs/media/json/tokenizer/module.f.mjs +7 -3
  176. package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
  177. package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
  178. package/fjs/media/json/types.d.ts +36 -10
  179. package/fjs/media/lock/module.f.d.mts +100 -0
  180. package/fjs/media/lock/module.f.mjs +125 -0
  181. package/fjs/media/lock/proof.f.d.mts +33 -0
  182. package/fjs/media/lock/proof.f.mjs +196 -0
  183. package/fjs/media/lock/types.d.ts +15 -0
  184. package/fjs/media/module.f.d.mts +6 -5
  185. package/fjs/media/module.f.mjs +8 -7
  186. package/fjs/media/note/module.f.d.mts +121 -0
  187. package/fjs/media/note/module.f.mjs +131 -0
  188. package/fjs/media/note/proof.f.d.mts +29 -0
  189. package/fjs/media/note/proof.f.mjs +150 -0
  190. package/fjs/media/note/types.d.ts +10 -0
  191. package/fjs/media/proof.f.d.mts +4 -1
  192. package/fjs/media/proof.f.mjs +40 -21
  193. package/fjs/media/revision/module.f.d.mts +78 -7
  194. package/fjs/media/revision/module.f.mjs +119 -12
  195. package/fjs/media/revision/proof.f.d.mts +10 -0
  196. package/fjs/media/revision/proof.f.mjs +88 -0
  197. package/fjs/media/revision/types.d.ts +34 -5
  198. package/fjs/media/type/module.f.d.mts +33 -15
  199. package/fjs/media/type/module.f.mjs +35 -29
  200. package/fjs/media/type/proof.f.d.mts +2 -1
  201. package/fjs/media/type/proof.f.mjs +30 -10
  202. package/fjs/module.f.mjs +29 -8
  203. package/fjs/nanvm/proof.f.mjs +3 -3
  204. package/fjs/nanvm/rust/module.f.mjs +1 -1
  205. package/fjs/nanvm/update/module.f.d.mts +4 -4
  206. package/fjs/nanvm/update/module.f.mjs +8 -9
  207. package/fjs/nanvm/update/proof.f.mjs +4 -3
  208. package/fjs/proof.f.d.mts +3 -3
  209. package/fjs/proof.f.mjs +36 -10
  210. package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
  211. package/fjs/protocol/json_rpc/module.f.mjs +3 -3
  212. package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
  213. package/fjs/protocol/mcp/module.f.d.mts +10 -13
  214. package/fjs/protocol/mcp/module.f.mjs +74 -58
  215. package/fjs/protocol/mcp/proof.f.d.mts +13 -4
  216. package/fjs/protocol/mcp/proof.f.mjs +193 -61
  217. package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
  218. package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
  219. package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
  220. package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
  221. package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
  222. package/fjs/protocol/mcp/types.d.ts +17 -6
  223. package/fjs/sul/id/module.f.d.mts +0 -1
  224. package/fjs/sul/id/module.f.mjs +2 -3
  225. package/fjs/sul/level/hash/module.f.mjs +2 -1
  226. package/fjs/sul/level/hash/proof.f.mjs +2 -2
  227. package/fjs/sul/module.f.mjs +18 -13
  228. package/fjs/text/code_point/module.f.d.mts +8 -0
  229. package/fjs/text/code_point/module.f.mjs +8 -1
  230. package/fjs/text/code_point/proof.f.d.mts +1 -0
  231. package/fjs/text/code_point/proof.f.mjs +11 -0
  232. package/fjs/text/sgr/module.f.d.mts +4 -6
  233. package/fjs/text/sgr/module.f.mjs +6 -7
  234. package/fjs/text/utf16/module.f.mjs +7 -2
  235. package/fjs/text/utf16/proof.f.mjs +3 -3
  236. package/fjs/text/utf8/module.f.mjs +4 -2
  237. package/fjs/types/array/module.f.mjs +14 -2
  238. package/fjs/types/bit_vec/module.f.d.mts +0 -2
  239. package/fjs/types/bit_vec/module.f.mjs +46 -32
  240. package/fjs/types/bit_vec/proof.f.mjs +2 -2
  241. package/fjs/types/btree/remove/module.f.mjs +1 -1
  242. package/fjs/types/btree/set/module.f.mjs +9 -11
  243. package/fjs/types/btree/set/proof.f.mjs +12 -0
  244. package/fjs/types/byte_set/module.f.d.mts +11 -4
  245. package/fjs/types/byte_set/module.f.mjs +14 -6
  246. package/fjs/types/byte_set/proof.f.mjs +7 -7
  247. package/fjs/types/function/compare/module.f.mjs +10 -3
  248. package/fjs/types/list/module.f.d.mts +1 -1
  249. package/fjs/types/list/module.f.mjs +1 -1
  250. package/fjs/types/nullable/module.f.d.mts +18 -4
  251. package/fjs/types/nullable/module.f.mjs +21 -4
  252. package/fjs/types/nullable/proof.f.d.mts +4 -0
  253. package/fjs/types/nullable/proof.f.mjs +15 -0
  254. package/fjs/types/object/module.f.d.mts +12 -2
  255. package/fjs/types/object/module.f.mjs +11 -1
  256. package/fjs/types/patricia_trie/module.f.mjs +26 -11
  257. package/fjs/types/result/module.f.d.mts +3 -3
  258. package/fjs/types/result/module.f.mjs +3 -3
  259. package/fjs/types/rtti/common/module.f.d.mts +25 -28
  260. package/fjs/types/rtti/common/module.f.mjs +36 -32
  261. package/fjs/types/rtti/common/proof.f.mjs +5 -5
  262. package/fjs/types/rtti/data/module.f.d.mts +14 -0
  263. package/fjs/types/rtti/data/module.f.mjs +25 -2
  264. package/fjs/types/rtti/data/proof.f.d.mts +1 -0
  265. package/fjs/types/rtti/data/proof.f.mjs +25 -2
  266. package/fjs/types/rtti/parse/module.f.d.mts +24 -14
  267. package/fjs/types/rtti/parse/module.f.mjs +37 -28
  268. package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
  269. package/fjs/types/rtti/parse/proof.f.mjs +33 -14
  270. package/fjs/types/rtti/proof.f.mjs +3 -1
  271. package/fjs/types/rtti/ts/module.f.mjs +13 -17
  272. package/fjs/types/rtti/ts/types.d.ts +14 -1
  273. package/fjs/types/rtti/validate/module.f.d.mts +81 -19
  274. package/fjs/types/rtti/validate/module.f.mjs +107 -61
  275. package/fjs/types/rtti/validate/proof.f.d.mts +13 -10
  276. package/fjs/types/rtti/validate/proof.f.mjs +186 -197
  277. package/fjs/types/sorted_set/module.f.d.mts +18 -0
  278. package/fjs/types/sorted_set/module.f.mjs +22 -0
  279. package/fjs/types/sorted_set/proof.f.d.mts +1 -0
  280. package/fjs/types/sorted_set/proof.f.mjs +16 -1
  281. package/fjs/types/uint8array/module.f.d.mts +1 -1
  282. package/fjs/types/uint8array/module.f.mjs +1 -1
  283. package/fjs/website/module.f.d.mts +3 -3
  284. package/fjs/website/module.f.mjs +4 -7
  285. package/fjs/website/proof.f.mjs +2 -1
  286. package/package.json +2 -2
  287. package/fjs/dev/package_json/module.f.d.mts +0 -39
  288. package/fjs/dev/package_json/module.f.mjs +0 -40
  289. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  290. package/fjs/dev/package_json/proof.f.mjs +0 -32
  291. package/fjs/effects/eff/module.f.d.mts +0 -20
  292. package/fjs/effects/eff/module.f.mjs +0 -70
  293. package/fjs/effects/eff/proof.f.d.mts +0 -15
  294. package/fjs/effects/eff/proof.f.mjs +0 -69
  295. package/fjs/effects/eff/types.d.ts +0 -71
  296. package/fjs/types/rtti/validate/types.d.ts +0 -6
@@ -3,13 +3,11 @@
3
3
  *
4
4
  * @module
5
5
  *
6
+ * @import { Ast, AstSequence, AstTag } from '../../bnf/matcher/types.ts'
6
7
  * @import {
7
- * AstRuleMeta,
8
- * AstSequenceMeta,
9
- * AstTag,
10
8
  * CodePointMeta,
11
9
  * DescentMatch,
12
- * DescentMatchResult
10
+ * DescentMatchResult,
13
11
  * } from '../../bnf/descent/types.ts'
14
12
  * @import { DataRule, Rule } from '../../bnf/types.ts'
15
13
  * @import {
@@ -29,11 +27,14 @@
29
27
  * @import { CodePoint } from '../../text/utf16/types.ts'
30
28
  * @import { StateScan } from '../../types/function/operator/types.ts'
31
29
  * @import { List } from '../../types/list/types.ts'
32
- * @import { Unknown } from '../types.ts'
33
30
  * @import { DjsToken, DjsTokenWithMetadata } from './types.ts'
31
+ * @import { TriviaKind } from '../../js/tokenizer/types.ts'
32
+ * @import { Nullable } from '../../types/nullable/types.ts'
34
33
  */
35
34
 
36
- import { descentParser } from '../../bnf/descent/module.f.mjs'
35
+ import { assert, assertEq } from '../../asserts/module.f.mjs'
36
+ import { descentParserRuleSet } from '../../bnf/descent/module.f.mjs'
37
+ import { toData } from '../../bnf/data/module.f.mjs'
37
38
  import {
38
39
  eof,
39
40
  none,
@@ -47,8 +48,8 @@ import {
47
48
  unicodeMax,
48
49
  unicodeRange,
49
50
  } from '../../bnf/module.f.mjs'
50
- import { isKeywordToken } from '../../js/tokenizer/module.f.mjs'
51
- import { multiply } from '../../types/bigfloat/module.f.mjs'
51
+ import { keywords } from '../../js/keywords/module.f.mjs'
52
+ import { isKeywordToken, mergeTrivia } from '../../js/tokenizer/module.f.mjs'
52
53
  import {
53
54
  asterisk, backspace, ht, lf, ff, cr,
54
55
  quotationMark, solidus, reverseSolidus,
@@ -242,6 +243,20 @@ const buildToken = () => {
242
243
  /** @type {() => Rule} */
243
244
  export const jsGrammar = () => repeat0Plus(buildToken())
244
245
 
246
+ /**
247
+ * The whole-file matcher together with the name of the rule to start it at.
248
+ *
249
+ * `toData` generates rule names, so the entry name belongs to the conversion
250
+ * rather than to the grammar's spelling and is read back from it here. Building
251
+ * both from one conversion also keeps the grammar built once per matcher.
252
+ *
253
+ * @type {<T>() => readonly [DescentMatch<T>, string]}
254
+ */
255
+ export const jsMatcher = () => {
256
+ const [ruleSet, entry] = toData(jsGrammar())
257
+ return [descentParserRuleSet(ruleSet), entry]
258
+ }
259
+
245
260
  const stringify = stringifyAsTree(sort)
246
261
 
247
262
  /** @type {(cp: CodePoint) => CodePointMeta<unknown>} */
@@ -273,19 +288,29 @@ const codePointsWithMetadata = path => cp => toArray(flat(stateScan(metadataScan
273
288
 
274
289
  /** @typedef {[string, TokenMetadata | null, List<number>]} _TokenScanState */
275
290
 
276
- /** @type {(tag: string) => boolean} */
277
- const isNlTag = tag => tag === '\n' || tag === '\r'
278
- /** @type {(tag: string) => boolean} */
279
- const isWsTag = tag => tag === ' ' || tag === '\t'
291
+ /**
292
+ * The grammar tag of a trivia code point, as the kind `mergeTrivia` speaks in;
293
+ * `null` for every other tag.
294
+ *
295
+ * @type {(tag: string) => Nullable<TriviaKind>}
296
+ */
297
+ const triviaKind = tag =>
298
+ tag === '\n' || tag === '\r' ? 'nl' :
299
+ tag === ' ' || tag === '\t' ? 'ws' :
300
+ null
280
301
 
281
302
  /** @type {StateScan<_FlatToken, _TokenScanState, List<_Token>>} */
282
303
  const scanFunc = (input, state) => {
283
304
  const [stateTag, stateMetadata, stateCodePoints] = state
284
305
  if (typeof input === 'string') {
285
- if (isNlTag(input) && isNlTag(stateTag)) return [null, state]
286
- if (isWsTag(input) && isWsTag(stateTag)) return [null, state]
287
- if (isNlTag(input) && isWsTag(stateTag)) return [null, [input, null, []]]
288
- if (isWsTag(input) && isNlTag(stateTag)) return [null, state]
306
+ // A trivia run continues: `mergeTrivia` decides the run's kind, and
307
+ // the pending token only has to be restarted under the incoming tag
308
+ // when that kind is not the one it already has (ws followed by nl).
309
+ const inputKind = triviaKind(input)
310
+ const stateKind = triviaKind(stateTag)
311
+ if (inputKind !== null && stateKind !== null) {
312
+ return [null, mergeTrivia(stateKind, inputKind) === stateKind ? state : [input, null, []]]
313
+ }
289
314
  /** @type {_TokenScanState} */
290
315
  const newState = [input, null, []]
291
316
  if (stateTag === '') {
@@ -301,7 +326,7 @@ const scanFunc = (input, state) => {
301
326
  }
302
327
 
303
328
  // All operator tag strings produced by the grammar's operator rule
304
- const operatorTags = /** @type {ReadonlySet<string>} */ (new Set([
329
+ const operatorTags = new Set([
305
330
  '.', '=>', '===', '==', '=', '!==', '!=', '!',
306
331
  '>>>=', '>>>', '>>=', '>>', '>=', '>',
307
332
  '<<=', '<<', '<=', '<',
@@ -310,7 +335,7 @@ const operatorTags = /** @type {ReadonlySet<string>} */ (new Set([
310
335
  '&&=', '&&', '&=', '&', '||=', '||', '|=', '|',
311
336
  '^=', '^', '~', '??=', '??', '?.', '?',
312
337
  '[', ']', '{', '}', '(', ')', ',', ':'
313
- ]))
338
+ ])
314
339
 
315
340
  /** @type {(tk: _FlatToken) => boolean} */
316
341
  const filterFunc = tk => {
@@ -348,7 +373,17 @@ const unwrapHexDigitValue = mapUnwrap(hexDigitValue)
348
373
  /** @type {StateScan<number, _StringDecodeState, List<number>>} */
349
374
  const stringDecodeScan = (cp, state) => {
350
375
  switch (state.kind) {
351
- case 'escape':
376
+ case 'escape': {
377
+ // The grammar's own `escape` rule (`buildToken`'s `string`) only ever
378
+ // accepts `"`, `\`, `/`, `b`, `f`, `n`, `r`, `t`, or `u` right after a
379
+ // backslash — any other character fails to parse before a token
380
+ // 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)
352
387
  switch (cp) {
353
388
  case quotationMark: return [[quotationMark], { kind: 'normal' }] // \" → "
354
389
  case reverseSolidus: return [[reverseSolidus], { kind: 'normal' }] // \\ → \
@@ -358,9 +393,14 @@ const stringDecodeScan = (cp, state) => {
358
393
  case latinSmallLetterN: return [[lf], { kind: 'normal' }] // \n → line feed (LF)
359
394
  case latinSmallLetterR: return [[cr], { kind: 'normal' }] // \r → carriage return (CR)
360
395
  case latinSmallLetterT: return [[ht], { kind: 'normal' }] // \t → horizontal tab (HT)
361
- case latinSmallLetterU: return [null, { kind: 'unicode', acc: 0, count: 0 }] // \u → start 4 hex digits
362
- default: return [[cp], { kind: 'normal' }]
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
363
402
  }
403
+ }
364
404
  case 'unicode': {
365
405
  const acc = (state.acc << 4) | unwrapHexDigitValue(cp)
366
406
  return state.count === 3 ? [[acc], { kind: 'normal' }] : [null, { kind: 'unicode', acc, count: state.count + 1 }]
@@ -373,31 +413,8 @@ const stringDecodeScan = (cp, state) => {
373
413
  /** @type {(codePoints: readonly number[]) => string} */
374
414
  const decodeJsonString = codePoints => codePointListToString(flat(stateScan(stringDecodeScan)({ kind: 'normal' })(codePoints.slice(1, -1))))
375
415
 
376
- // value is grammar-validated: (0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)? — no need to re-check its shape here.
377
- /** @type {(value: string) => readonly [bigint, number]} */
378
- const decodeNumber = value => {
379
- // at most one of 'e'/'E' can occur, so whichever indexOf finds it (if any) is the exponent marker
380
- const lowerEIndex = value.indexOf('e')
381
- const eIndex = lowerEIndex < 0 ? value.indexOf('E') : lowerEIndex
382
- const mantissaText = eIndex < 0 ? value : value.slice(0, eIndex)
383
- const expText = eIndex < 0 ? '' : value.slice(eIndex + 1)
384
- const dotIndex = mantissaText.indexOf('.')
385
- const intDigits = dotIndex < 0 ? mantissaText : mantissaText.slice(0, dotIndex)
386
- const fracDigits = dotIndex < 0 ? '' : mantissaText.slice(dotIndex + 1)
387
- const mantissa = BigInt(intDigits + fracDigits)
388
- const exp = (expText === '' ? 0 : Number(expText)) - fracDigits.length
389
- return [mantissa, exp]
390
- }
391
-
392
- const keywords = /** @type {ReadonlySet<string>} */ (new Set([
393
- 'true', 'false', 'null', 'undefined',
394
- 'arguments', 'await', 'break', 'case', 'catch', 'class', 'const', 'continue',
395
- 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'eval', 'export',
396
- 'extends', 'finally', 'for', 'function', 'if', 'implements', 'import', 'in',
397
- 'instanceof', 'interface', 'let', 'new', 'package', 'private', 'protected',
398
- 'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'try',
399
- 'typeof', 'var', 'void', 'while', 'with', 'yield',
400
- ]))
416
+ /** @type {ReadonlySet<string>} */
417
+ const keywordSet = new Set(keywords)
401
418
 
402
419
  /** @type {(tk: _Token) => JsToken} */
403
420
  const toJsToken = tk => {
@@ -413,13 +430,13 @@ const toJsToken = tk => {
413
430
  return { kind: 'string', value: decodeJsonString(codePoints) }
414
431
  case 'id': {
415
432
  const value = codePointListToString(codePoints)
416
- if (keywords.has(value)) return /** @type {JsToken} */ ({ kind: value })
433
+ if (keywordSet.has(value)) return /** @type {JsToken} */ ({ kind: value })
417
434
  return { kind: 'id', value }
418
435
  }
419
436
  case 'number': {
420
437
  const value = codePointListToString(codePoints)
421
438
  if (value.endsWith('n')) return { kind: 'bigint', value: BigInt(value.slice(0, -1)) }
422
- return { kind: 'number', value, bf: decodeNumber(value) }
439
+ return { kind: 'number', value }
423
440
  }
424
441
  case 'comment':
425
442
  if (codePoints[1] === asterisk) // block comment /*...*/
@@ -453,7 +470,7 @@ const toJsTokenWithMetadata = tk => {
453
470
  return [{ token, metadata }]
454
471
  }
455
472
 
456
- /** @type {(value: AstRuleMeta<TokenMetadata>|CodePointMeta<TokenMetadata>) => List<_FlatToken>} */
473
+ /** @type {(value: Ast<CodePointMeta<TokenMetadata>>|CodePointMeta<TokenMetadata>) => List<_FlatToken>} */
457
474
  const getTokensFromAstRuleOrCodePoint = value => {
458
475
  if (value instanceof Array)
459
476
  return [value]
@@ -461,7 +478,7 @@ const getTokensFromAstRuleOrCodePoint = value => {
461
478
  return getTokensFromAstRule(value)
462
479
  }
463
480
 
464
- /** @type {(seq: AstSequenceMeta<TokenMetadata>) => List<_FlatToken>} */
481
+ /** @type {(seq: AstSequence<CodePointMeta<TokenMetadata>>) => List<_FlatToken>} */
465
482
  const getTokensFromAstSequence = seq => {
466
483
  return flatMap(getTokensFromAstRuleOrCodePoint)(seq)
467
484
  }
@@ -475,7 +492,7 @@ const tagToToken = tag => {
475
492
  }
476
493
  }
477
494
 
478
- /** @type {(ast: AstRuleMeta<TokenMetadata>) => List<_FlatToken>} */
495
+ /** @type {(ast: Ast<CodePointMeta<TokenMetadata>>) => List<_FlatToken>} */
479
496
  const getTokensFromAstRule = ast => {
480
497
  const token = tagToToken(ast.tag)
481
498
  if (ast.sequence.length === 0)
@@ -488,11 +505,11 @@ const getTokensFromAstRule = ast => {
488
505
  export const tokenizeString = s => {
489
506
  const cp = toArray(stringToCodePointList(s))
490
507
  if (cp.length === 0) {
491
- return stringify(/** @type {Unknown} */ ([{ kind: 'eof' }]))
508
+ return stringify([{ kind: 'eof' }])
492
509
  }
493
- const m = /** @type {DescentMatch<TokenMetadata>} */ (descentParser(jsGrammar()))
510
+ const [m, entry] = jsMatcher()
494
511
  const cpm = codePointsWithMetadata('')(cp)
495
- const { ast, success: ok, idx: len } = m('', cpm)
512
+ const { ast, success: ok, idx: len } = m(entry, cpm)
496
513
  if (!ok || len !== cp.length)
497
514
  return 'error'
498
515
 
@@ -505,7 +522,7 @@ export const tokenizeString = s => {
505
522
  const tokens = flat(stateScan(scanFunc)(['', null, []])(filterTokens))
506
523
  const jsTokens = concat(flatMap(toJsTokens)(tokens))([{ kind: 'eof' }])
507
524
  const result = toArray(jsTokens)
508
- return stringify(/** @type {Unknown} */ (result))
525
+ return stringify(result)
509
526
  }
510
527
 
511
528
  // Finds `tag` in flatTokens and returns the metadata of the next code point after it.
@@ -528,14 +545,19 @@ export const tokenizeJs = input => path => {
528
545
  const initial = { path, line: 1, column: 1 }
529
546
  if (cp.length === 0) return [{ token: { kind: 'eof' }, metadata: initial }]
530
547
 
531
- const m = /** @type {DescentMatch<TokenMetadata>} */ (descentParser(jsGrammar()))
548
+ const [m, entry] = jsMatcher()
532
549
  const cpm = codePointsWithMetadata(path)(cp)
533
- const { ast, success: ok, idx: len } = m('', cpm)
550
+ const { ast, success: ok, idx: len } = m(entry, cpm)
534
551
  const finalMetadata = fold(advanceMetadata)(initial)(cp)
535
552
 
536
553
  if (!ok || len !== cp.length) {
537
- const errorMetadata = len < cpm.length ? cpm[len][1] : finalMetadata
538
- return [{ token: { kind: 'error', message: 'invalid token' }, metadata: errorMetadata }]
554
+ // `len` is always `< cpm.length` (`=== cp.length`) here: `ok` false only
555
+ // ever happens with `len === 0` (nothing matched at position 0), and a
556
+ // `len !== cp.length` failure with `ok` true is by definition a partial
557
+ // match (`len < cp.length`) — `repeat0Plus` never fails after
558
+ // successfully consuming the whole input, so there is no way to reach
559
+ // this branch with `len === cp.length`.
560
+ return [{ token: { kind: 'error', message: 'invalid token' }, metadata: cpm[len][1] }]
539
561
  }
540
562
 
541
563
  const flatTokens = toArray(getTokensFromAstRule(ast))
@@ -606,7 +628,9 @@ const parseDjsMinusState = input => {
606
628
  switch (input.kind) {
607
629
  case 'eof': return [[{ kind: 'error', message: 'invalid token' }, { kind: 'eof' }], { kind: 'def' }]
608
630
  case 'bigint': return [[{ kind: 'bigint', value: -1n * input.value }], { kind: 'def' }]
609
- case 'number': return [[{ kind: 'number', bf: multiply(input.bf)(-1n), value: `-${input.value}` }], { kind: 'def' }]
631
+ // negation is lexical: the minus sign joins the lexeme, so the token
632
+ // stays the exact source text of the number.
633
+ case 'number': return [[{ kind: 'number', value: `-${input.value}` }], { kind: 'def' }]
610
634
  default: return [{ first: { kind: 'error', message: 'invalid token' }, tail: mapDjsToken(input) }, { kind: 'def' }]
611
635
  }
612
636
  }
@@ -630,3 +654,18 @@ const scanDjsTokenWithMetadata = (input, state) => {
630
654
 
631
655
  /** @type {(input: List<number>) => (path: string) => List<DjsTokenWithMetadata>} */
632
656
  export const tokenize = input => path => flat(stateScan(scanDjsTokenWithMetadata)({ kind: 'def' })(tokenizeJs(input)(path)))
657
+
658
+ export const proof = {
659
+ // `tagToToken`'s `true` arm fires only for an `AstTag` of literal `true`.
660
+ // `bnf/data`'s `emptyTagOf` is the only source of that value, and
661
+ // `bnf/descent/module.f.mjs` reads it in exactly one place (its variant
662
+ // arm), always wrapped in `mrFail` — a failure. A failed variant only
663
+ // propagates as the overall `result` when nothing in it matches, so it
664
+ // never survives into a successful sequence/AST; a `true` tag therefore
665
+ // can never appear on a successful `descentParser` match for any
666
+ // grammar, `jsGrammar` included, so `tokenizeJs` can't reach this arm.
667
+ // Call it directly to cover that branch.
668
+ tagToTokenTrueTag: () => {
669
+ assertEq(tagToToken(true), 'true')
670
+ },
671
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @import { Unknown } from '../types.ts'
3
2
  */
4
3
  export declare const proof: {
4
+ jsGrammar: () => void;
5
5
  isValid: (() => void)[];
6
6
  tokenizer: (() => void)[];
7
7
  djs: (() => void)[];