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
@@ -6,43 +6,35 @@
6
6
  import type { CodePoint } from '../../text/utf16/types.ts';
7
7
  import type { RangeMapArray } from '../../types/range_map/types.ts';
8
8
  import type { StringMap } from '../../types/object/types.ts';
9
- import type { EmptyTag } from '../data/types.ts';
10
- /** @internal */
9
+ import type { Ast } from '../matcher/types.ts';
10
+ /**
11
+ * A rule's dispatch entry: its first set as a range map, and — for a variant
12
+ * that can match empty — the branch a dispatch miss selects.
13
+ *
14
+ * @internal
15
+ */
11
16
  export type _DispatchRule = {
12
- readonly emptyTag: EmptyTag;
17
+ readonly empty: _DispatchBranch | undefined;
13
18
  readonly rangeMap: _Dispatch;
14
19
  };
15
20
  /** @internal */
16
21
  export type _Dispatch = RangeMapArray<_DispatchResult>;
17
22
  /** @internal */
18
- export type _DispatchResult = _DispatchRuleCollection | null;
23
+ export type _DispatchResult = _DispatchBranch | null;
19
24
  /**
20
- * The rules a dispatched symbol selects, to be matched one after another. They
21
- * are names into the {@link _DispatchMap}: the builder only ever appends rule
22
- * names, so the matcher resolves each one there.
25
+ * A branch as dispatch selects it: the name of the rule to invoke — a name
26
+ * into the {@link _DispatchMap} — and the tag its node gets. Only a variant's
27
+ * entries are ever read as branches; every other rule kind consults its range
28
+ * map solely for first-set membership.
23
29
  *
24
30
  * @internal
25
31
  */
26
- export type _DispatchRuleCollection = {
32
+ export type _DispatchBranch = {
27
33
  readonly tag: string | undefined;
28
- readonly rules: readonly string[];
34
+ readonly name: string;
29
35
  };
30
36
  /** @internal */
31
37
  export type _DispatchMap = StringMap<_DispatchRule>;
32
- /**
33
- * Represents a parsed AST rule, consisting of a rule name and its parsed sequence.
34
- *
35
- * @internal
36
- */
37
- export type _AstRule = {
38
- readonly tag: AstTag;
39
- readonly sequence: AstSequence;
40
- };
41
- /**
42
- * Represents a parsed AST sequence.
43
- */
44
- export type AstSequence = readonly (_AstRule | CodePoint)[];
45
- export type AstTag = string | true | undefined;
46
38
  /**
47
39
  * Represents the remaining input after a match attempt, or `null` if no match is possible.
48
40
  *
@@ -55,7 +47,7 @@ export type Remainder = readonly CodePoint[] | null;
55
47
  *
56
48
  * Represents the result of a match operation, including the parsed AST rule and the remainder of the input.
57
49
  */
58
- export type MatchResult = readonly [_AstRule, boolean, Remainder];
50
+ export type MatchResult = readonly [Ast<CodePoint>, boolean, Remainder];
59
51
  /**
60
52
  * LL(1) parser function for matching by rule name.
61
53
  *
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The layer every BNF matcher backend shares: the {@link Cursor} it matches at,
3
+ * the {@link Ast} it builds, and the constructors that pair them.
4
+ *
5
+ * `fjs/bnf/ll1` and `fjs/bnf/descent` are two machines over one contract, and
6
+ * the contract is what lives here — not the machines. Backtracking, frame
7
+ * shapes, failure reporting and the public result type are each backend's own,
8
+ * and deliberately different; where the input sits, what a consumed symbol
9
+ * contributes to the AST, and how a node is built are not.
10
+ *
11
+ * The three are one module rather than three because they are interdependent:
12
+ * {@link leafAt} produces AST leaves, and {@link mrSuccess} builds AST nodes
13
+ * positioned by a cursor. Splitting them would put one concept behind three
14
+ * imports.
15
+ *
16
+ * See `./types.ts` for the type-level API and `./README.md` for the contract
17
+ * this implements.
18
+ *
19
+ * @module
20
+ *
21
+ * @import { Ast, AstResult, AstSequence, AstTag, Cursor } from './types.ts'
22
+ */
23
+ import type { AstResult, AstSequence, AstTag, Cursor } from './types.ts';
24
+ /**
25
+ * What consuming the symbol at a cursor contributes to the AST: the leaf
26
+ * itself, and nothing for the synthesized end-of-input symbol — it has no
27
+ * physical source element, so it never reaches an AST.
28
+ *
29
+ * @type {<L>(input: readonly L[], pos: Cursor) => AstSequence<L>}
30
+ */
31
+ export declare const leafAt: <L>(input: readonly L[], pos: Cursor) => AstSequence<L>;
32
+ /**
33
+ * The semantic symbol a cursor points at: one read out of the physical input,
34
+ * and the synthesized {@link eofSymbol} at its end. Only meaningful where the
35
+ * cursor still has a symbol, `pos <= input.length`.
36
+ *
37
+ * `symbolOf` is the one place backends differ — it is how a leaf yields its
38
+ * symbol, `identity` where the leaf *is* the code point and a destructuring
39
+ * where it carries metadata alongside. Each backend binds its own partial
40
+ * application once at module scope.
41
+ *
42
+ * @type {<L>(symbolOf: (leaf: L) => number) => (input: readonly L[], pos: Cursor) => number}
43
+ */
44
+ export declare const symbolAt: <L>(symbolOf: (leaf: L) => number) => (input: readonly L[], pos: Cursor) => number;
45
+ /**
46
+ * The public, physical index of a cursor. Consuming the synthesized
47
+ * end-of-input symbol moves the cursor past the physical end, and both cursors
48
+ * report `length`.
49
+ *
50
+ * @type {(length: number) => (pos: Cursor) => number}
51
+ */
52
+ export declare const physicalIdx: (length: number) => (pos: Cursor) => number;
53
+ export type _Mr<L, P> = (tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>;
54
+ /**
55
+ * A matched node at a position.
56
+ *
57
+ * @type {<L, P>(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>}
58
+ */
59
+ export declare const mrSuccess: <L, P>(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>;
60
+ /**
61
+ * A node that did not match, at the position the caller should resume from —
62
+ * which a backtracking backend rewinds and a predictive one does not.
63
+ *
64
+ * @type {<L, P>(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>}
65
+ */
66
+ export declare const mrFail: <L, P>(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The layer every BNF matcher backend shares: the {@link Cursor} it matches at,
3
+ * the {@link Ast} it builds, and the constructors that pair them.
4
+ *
5
+ * `fjs/bnf/ll1` and `fjs/bnf/descent` are two machines over one contract, and
6
+ * the contract is what lives here — not the machines. Backtracking, frame
7
+ * shapes, failure reporting and the public result type are each backend's own,
8
+ * and deliberately different; where the input sits, what a consumed symbol
9
+ * contributes to the AST, and how a node is built are not.
10
+ *
11
+ * The three are one module rather than three because they are interdependent:
12
+ * {@link leafAt} produces AST leaves, and {@link mrSuccess} builds AST nodes
13
+ * positioned by a cursor. Splitting them would put one concept behind three
14
+ * imports.
15
+ *
16
+ * See `./types.ts` for the type-level API and `./README.md` for the contract
17
+ * this implements.
18
+ *
19
+ * @module
20
+ *
21
+ * @import { Ast, AstResult, AstSequence, AstTag, Cursor } from './types.ts'
22
+ */
23
+
24
+ import { eofSymbol } from '../module.f.mjs'
25
+
26
+ /**
27
+ * What consuming the symbol at a cursor contributes to the AST: the leaf
28
+ * itself, and nothing for the synthesized end-of-input symbol — it has no
29
+ * physical source element, so it never reaches an AST.
30
+ *
31
+ * @type {<L>(input: readonly L[], pos: Cursor) => AstSequence<L>}
32
+ */
33
+ export const leafAt = (input, pos) => pos < input.length ? [input[pos]] : []
34
+
35
+ /**
36
+ * The semantic symbol a cursor points at: one read out of the physical input,
37
+ * and the synthesized {@link eofSymbol} at its end. Only meaningful where the
38
+ * cursor still has a symbol, `pos <= input.length`.
39
+ *
40
+ * `symbolOf` is the one place backends differ — it is how a leaf yields its
41
+ * symbol, `identity` where the leaf *is* the code point and a destructuring
42
+ * where it carries metadata alongside. Each backend binds its own partial
43
+ * application once at module scope.
44
+ *
45
+ * @type {<L>(symbolOf: (leaf: L) => number) => (input: readonly L[], pos: Cursor) => number}
46
+ */
47
+ export const symbolAt = symbolOf => (input, pos) =>
48
+ pos < input.length ? symbolOf(input[pos]) : eofSymbol
49
+
50
+ /**
51
+ * The public, physical index of a cursor. Consuming the synthesized
52
+ * end-of-input symbol moves the cursor past the physical end, and both cursors
53
+ * report `length`.
54
+ *
55
+ * @type {(length: number) => (pos: Cursor) => number}
56
+ */
57
+ export const physicalIdx = length => pos => Math.min(pos, length)
58
+
59
+ /**
60
+ * @template L
61
+ * @template P
62
+ * @typedef {(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>} _Mr
63
+ */
64
+
65
+ /** @type {<L, P>(success: boolean) => _Mr<L, P>} */
66
+ const mr = success => (tag, sequence, pos) => ({ ast: { tag, sequence }, success, pos })
67
+
68
+ /**
69
+ * A matched node at a position.
70
+ *
71
+ * @type {<L, P>(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>}
72
+ */
73
+ export const mrSuccess = mr(true)
74
+
75
+ /**
76
+ * A node that did not match, at the position the caller should resume from —
77
+ * which a backtracking backend rewinds and a predictive one does not.
78
+ *
79
+ * @type {<L, P>(tag: AstTag, sequence: AstSequence<L>, pos: P) => AstResult<L, P>}
80
+ */
81
+ export const mrFail = mr(false)
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @import { CodePointMeta } from '../descent/types.ts'
3
+ */
4
+ export declare const proof: {
5
+ leafAt: (() => void)[];
6
+ symbolAt: (() => void)[];
7
+ physicalIdx: () => void;
8
+ mrSuccess: () => void;
9
+ mrFail: () => void;
10
+ };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @import { CodePointMeta } from '../descent/types.ts'
3
+ */
4
+
5
+ import { assertEq } from '../../asserts/module.f.mjs'
6
+ import { identity } from '../../types/function/module.f.mjs'
7
+ import { eofSymbol } from '../module.f.mjs'
8
+ import { leafAt, mrFail, mrSuccess, physicalIdx, symbolAt } from './module.f.mjs'
9
+
10
+ /** @type {readonly CodePointMeta<string>[]} */
11
+ const withMeta = [[0x41, 'a'], [0x42, 'b']]
12
+
13
+ /** @type {(leaf: CodePointMeta<string>) => number} */
14
+ const metaSymbolOf = ([symbol]) => symbol
15
+
16
+ export const proof = {
17
+ leafAt: [
18
+ () => {
19
+ // Inside the physical input a leaf is contributed whole, whatever a
20
+ // backend chose a leaf to be.
21
+ assertEq(JSON.stringify(leafAt([65, 66], 0)), '[65]')
22
+ assertEq(JSON.stringify(leafAt([65, 66], 1)), '[66]')
23
+ assertEq(JSON.stringify(leafAt(withMeta, 0)), '[[65,"a"]]')
24
+ },
25
+ () => {
26
+ // At and past the physical end there is nothing to contribute: the
27
+ // synthesized end-of-input symbol has no source element, so it never
28
+ // reaches an AST.
29
+ assertEq(JSON.stringify(leafAt([65, 66], 2)), '[]')
30
+ assertEq(JSON.stringify(leafAt([65, 66], 3)), '[]')
31
+ assertEq(JSON.stringify(leafAt([], 0)), '[]')
32
+ },
33
+ ],
34
+ symbolAt: [
35
+ () => {
36
+ // `identity` is the leaf reader of a backend whose leaf *is* the
37
+ // symbol; a pair's reader takes its first half. Same positions, same
38
+ // symbols.
39
+ /** @type {(leaf: number) => number} */
40
+ const symbolOf = identity
41
+ assertEq(symbolAt(symbolOf)([65, 66], 0), 65)
42
+ assertEq(symbolAt(metaSymbolOf)(withMeta, 0), 65)
43
+ assertEq(symbolAt(metaSymbolOf)(withMeta, 1), 66)
44
+ },
45
+ () => {
46
+ // The one synthesized end-of-input symbol sits at the physical end,
47
+ // for either leaf shape.
48
+ /** @type {(leaf: number) => number} */
49
+ const symbolOf = identity
50
+ assertEq(symbolAt(symbolOf)([65, 66], 2), eofSymbol)
51
+ assertEq(symbolAt(metaSymbolOf)(withMeta, 2), eofSymbol)
52
+ assertEq(symbolAt(symbolOf)([], 0), eofSymbol)
53
+ },
54
+ ],
55
+ physicalIdx: () => {
56
+ const physical = physicalIdx(2)
57
+ assertEq(physical(0), 0)
58
+ assertEq(physical(2), 2)
59
+ // Consuming the end-of-input symbol moves the cursor past the physical
60
+ // end, and both cursors report the same public index — which is what
61
+ // keeps a public position physical.
62
+ assertEq(physical(3), 2)
63
+ },
64
+ mrSuccess: () => {
65
+ assertEq(
66
+ JSON.stringify(mrSuccess('some', [65], 1)),
67
+ '{"ast":{"tag":"some","sequence":[65]},"success":true,"pos":1}')
68
+ // The position type is the backend's own: `null` is how a predictive
69
+ // backend says it ran out of input.
70
+ assertEq(
71
+ JSON.stringify(mrSuccess(undefined, [], null)),
72
+ '{"ast":{"sequence":[]},"success":true,"pos":null}')
73
+ },
74
+ mrFail: () => {
75
+ assertEq(
76
+ JSON.stringify(mrFail(true, [], 0)),
77
+ '{"ast":{"tag":true,"sequence":[]},"success":false,"pos":0}')
78
+ },
79
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Type-level API for the layer every BNF matcher backend shares: the position
3
+ * it matches at, the AST it builds, and the result that pairs them.
4
+ *
5
+ * @module
6
+ */
7
+ /**
8
+ * Tag of an AST node: the variant branch that matched, `true` where a rule
9
+ * matched empty input without naming a branch, and `undefined` where the rule
10
+ * is not a choice at all.
11
+ */
12
+ export type AstTag = string | true | undefined;
13
+ /**
14
+ * An AST over leaves of type `L`. A backend picks `L` for what it keeps of a
15
+ * consumed symbol — the code point alone, or the code point with metadata.
16
+ */
17
+ export type Ast<L> = {
18
+ readonly tag: AstTag;
19
+ readonly sequence: AstSequence<L>;
20
+ };
21
+ /** The children of an {@link Ast} node: nested nodes and consumed leaves. */
22
+ export type AstSequence<L> = readonly (Ast<L> | L)[];
23
+ /**
24
+ * A match position over input of `length` leaves: `0 .. length` are the
25
+ * physical positions, and `length + 1` is where the one synthesized
26
+ * end-of-input symbol has been consumed.
27
+ *
28
+ * This is the complete cursor `(idx, eofConsumed)` of
29
+ * [the BNF contract](../README.md#logical-eof-in-parser-input) written as one
30
+ * number. `eofConsumed` can only be true at the physical end, so the pair and
31
+ * the extended position hold the same information — and being one number is
32
+ * what makes every ordering a backend needs a plain `<`, because consuming EOF
33
+ * *is* progress even though the public index does not move. A backend that
34
+ * treated it as no progress would loop forever on a repetition over a rule that
35
+ * can match EOF.
36
+ *
37
+ * Public positions are physical, so a cursor is converted back with
38
+ * `physicalIdx` before it leaves a backend.
39
+ */
40
+ export type Cursor = number;
41
+ /**
42
+ * A matcher's own result: the AST built so far, whether it matched, and where
43
+ * it stopped.
44
+ *
45
+ * `P` is the position type. A backend whose match always has one uses
46
+ * {@link Cursor}; one that also reports running out of input uses
47
+ * `Cursor | null`. Public results are each backend's own type — this is the
48
+ * shape they are built from, not the shape they return.
49
+ */
50
+ export type AstResult<L, P> = {
51
+ readonly ast: Ast<L>;
52
+ readonly success: boolean;
53
+ readonly pos: P;
54
+ };
@@ -1,10 +1,41 @@
1
1
  /**
2
2
  * @module
3
3
  *
4
+ * @import { Ast, AstTag } from './matcher/types.ts'
4
5
  * @import { Rule } from './types.ts'
5
6
  */
7
+ import type { Ast } from './matcher/types.ts';
6
8
  import type { Rule } from './types.ts';
7
9
  /** @type {() => Rule} */
8
10
  export declare const classic: () => Rule;
9
11
  /** @type {() => Rule} */
10
12
  export declare const deterministic: () => Rule;
13
+ export type _Leaf = number | readonly [number, unknown];
14
+ export type _AstNode = Ast<_Leaf>;
15
+ export type _AstChild = _AstNode | _Leaf;
16
+ export type _Parts = {
17
+ readonly parts: readonly string[];
18
+ readonly text: string;
19
+ };
20
+ /**
21
+ * Renders a matcher AST as one line of `tag(children)`, with the code points a
22
+ * node consumed directly written as one quoted string.
23
+ *
24
+ * A proof that pins a whole AST is checking its *shape*, and raw JSON buries
25
+ * that under `{"tag":…,"sequence":[…]}` and a `[32,null]` per space — several
26
+ * kilobytes for an input a reader can hold in their head. This keeps the two
27
+ * things a repetition changes legible: how deep the nesting goes, and which
28
+ * tags survive. Repeated items are siblings under one node, whereas the
29
+ * right-recursive encoding puts each item one level deeper than the last.
30
+ *
31
+ * @type {(node: _AstNode) => string}
32
+ *
33
+ * @example
34
+ *
35
+ * ```ts
36
+ * // three spaces matched by a flat `repeat`, then by right-recursion
37
+ * '(" "(" ") " "(" ") " "(" "))'
38
+ * '" "(" " " "(" " " "(" " *())'
39
+ * ```
40
+ */
41
+ export declare const showAst: (node: _AstNode) => string;
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * @module
3
3
  *
4
+ * @import { Ast, AstTag } from './matcher/types.ts'
4
5
  * @import { Rule } from './types.ts'
5
6
  */
6
7
 
8
+ import { codePointToString } from '../text/utf16/module.f.mjs'
7
9
  import {
8
10
  commaJoin0Plus,
9
11
  none,
@@ -194,3 +196,81 @@ export const deterministic = () => {
194
196
 
195
197
  return json
196
198
  }
199
+
200
+ //
201
+
202
+ /**
203
+ * The leaf of either backend's AST: `bnf/ll1` keeps the code point alone and
204
+ * `bnf/descent` pairs it with metadata, so a renderer that takes both is
205
+ * generic over exactly this.
206
+ *
207
+ * @typedef {number | readonly [number, unknown]} _Leaf
208
+ */
209
+
210
+ /** @typedef {Ast<_Leaf>} _AstNode */
211
+
212
+ /** @typedef {_AstNode | _Leaf} _AstChild */
213
+
214
+ /**
215
+ * @param {_AstChild} child
216
+ * @returns {child is _AstNode}
217
+ */
218
+ const isAstNode = child => typeof child !== 'number' && !(child instanceof Array)
219
+
220
+ /** @type {(child: _Leaf) => number} */
221
+ const codePointOf = child => typeof child === 'number' ? child : child[0]
222
+
223
+ /**
224
+ * A tag as `showAst` writes it: a quoted string, `*` for the tagless empty
225
+ * match, and nothing at all for an untagged node. `*` rather than `true`
226
+ * because a branch may itself be named `true` — the JSON grammars have one.
227
+ *
228
+ * @type {(tag: AstTag) => string}
229
+ */
230
+ const showTag = tag =>
231
+ tag === undefined ? '' : tag === true ? '*' : JSON.stringify(tag)
232
+
233
+ /** @typedef {{ readonly parts: readonly string[], readonly text: string }} _Parts */
234
+
235
+ /**
236
+ * Ends the run of consumed code points being accumulated, if there is one, so
237
+ * that a node's text appears as one quoted string rather than one part per
238
+ * symbol.
239
+ *
240
+ * @type {(acc: _Parts) => readonly string[]}
241
+ */
242
+ const flushText = acc =>
243
+ acc.text === '' ? acc.parts : [...acc.parts, JSON.stringify(acc.text)]
244
+
245
+ /** @type {(acc: _Parts, child: _AstChild) => _Parts} */
246
+ const addChild = (acc, child) =>
247
+ isAstNode(child)
248
+ ? { parts: [...flushText(acc), showAst(child)], text: '' }
249
+ : { parts: acc.parts, text: acc.text + codePointToString(codePointOf(child)) }
250
+
251
+ /** @type {_Parts} */
252
+ const noParts = { parts: [], text: '' }
253
+
254
+ /**
255
+ * Renders a matcher AST as one line of `tag(children)`, with the code points a
256
+ * node consumed directly written as one quoted string.
257
+ *
258
+ * A proof that pins a whole AST is checking its *shape*, and raw JSON buries
259
+ * that under `{"tag":…,"sequence":[…]}` and a `[32,null]` per space — several
260
+ * kilobytes for an input a reader can hold in their head. This keeps the two
261
+ * things a repetition changes legible: how deep the nesting goes, and which
262
+ * tags survive. Repeated items are siblings under one node, whereas the
263
+ * right-recursive encoding puts each item one level deeper than the last.
264
+ *
265
+ * @type {(node: _AstNode) => string}
266
+ *
267
+ * @example
268
+ *
269
+ * ```ts
270
+ * // three spaces matched by a flat `repeat`, then by right-recursion
271
+ * '(" "(" ") " "(" ") " "(" "))'
272
+ * '" "(" " " "(" " " "(" " *())'
273
+ * ```
274
+ */
275
+ export const showAst = node =>
276
+ `${showTag(node.tag)}(${flushText(node.sequence.reduce(addChild, noParts)).join(' ')})`
@@ -14,4 +14,4 @@ import type { MemOp } from '../../effects/memory/types.ts';
14
14
  import type { FileCasOperation } from '../types.ts';
15
15
  /** @type {Commands<FileCasOperation | WriteFile | Write | All | MemOp | Read>} */
16
16
  export declare const commands: Commands<FileCasOperation | WriteFile | Write | All | MemOp | Read>;
17
- export declare const main: (options: import("../../effects/node/types.ts").NodeProgramOptions) => import("../../effects/types.ts").Effect<All | Read | Write | WriteFile | FileCasOperation | MemOp, number>;
17
+ export declare const main: import("../../effects/node/types.ts").Program<All | Read | Write | WriteFile | FileCasOperation | MemOp>;
@@ -11,8 +11,9 @@
11
11
 
12
12
  import { sha256 } from '../../crypto/sha2/module.f.mjs'
13
13
  import { cBase32ToVec, vecToCBase32 } from '../../basen/cbase32/module.f.mjs'
14
- import { forEachStep, pure, step } from '../../effects/module.f.mjs'
15
- import { errorExit, log, writeFromStream } from '../../effects/node/module.f.mjs'
14
+
15
+ import { errorExit, exitStep, log, writeFromStream } from '../../effects/node/module.f.mjs'
16
+ import { forEachStep, step as ioStep } from '../../effects/module.f.mjs'
16
17
  import { dispatch } from '../../cli/module.f.mjs'
17
18
  import { casAddFile, fileCas } from '../module.f.mjs'
18
19
 
@@ -26,15 +27,9 @@ export const commands = [
26
27
  return errorExit("'cas add' expects one parameter")
27
28
  }
28
29
  const c = fileCas(sha256)(home)
29
- return step(
30
- casAddFile(c)(path),
31
- hashResult => hashResult[0] === 'error'
32
- ? pure(1)
33
- : step(
34
- log(vecToCBase32(hashResult[1])),
35
- () => pure(0)
36
- )
37
- )
30
+ const added = casAddFile(c)(path)
31
+ const logged = ioStep(added, hash => log(vecToCBase32(hash)))
32
+ return exitStep(logged)
38
33
  },
39
34
  },
40
35
  {
@@ -50,10 +45,7 @@ export const commands = [
50
45
  }
51
46
  const c = fileCas(sha256)(home)
52
47
  const x = c.read(hash)
53
- return step(
54
- writeFromStream(path, x),
55
- ([r, v]) => r === 'error' ? errorExit(`e: ` + String(v)) : pure(0),
56
- )
48
+ return exitStep(writeFromStream(path, x))
57
49
  },
58
50
  },
59
51
  {
@@ -61,11 +53,13 @@ export const commands = [
61
53
  description: 'List all stored content hashes',
62
54
  handler: ({ home }) => {
63
55
  const c = fileCas(sha256)(home)
64
- const x0 = forEachStep(c.list(), j => log(vecToCBase32(j)))
65
- return step(
66
- x0,
67
- () => pure(0)
68
- )
56
+ // The fold's `items` is deliberately a raw effect, so a fallible
57
+ // producer composes with `step` ahead of it rather than the fold
58
+ // growing an error channel of its own.
59
+ // `c.list()` feeds the fold directly: the step that used to sit
60
+ // here existed only to unwrap the list so `pure` could wrap it
61
+ // again.
62
+ return exitStep(forEachStep(c.list(), j => log(vecToCBase32(j))))
69
63
  },
70
64
  },
71
65
  ]
@@ -14,7 +14,5 @@ export declare const proof: {
14
14
  mainListEmptyStore: () => void;
15
15
  mainNoCmd: () => void;
16
16
  mainUnknownCmd: () => void;
17
- throw: {
18
- mainListCorruptStore: () => readonly [import("../../effects/node/virtual/types.ts").State, number];
19
- };
17
+ mainListCorruptStore: () => void;
20
18
  };