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
@@ -1,26 +1,28 @@
1
1
  /**
2
- * @import { Effect } from '../effects/types.ts'
3
- * @import { NodeProgramOptions, Sandbox, Write } from '../effects/node/types.ts'
2
+ * @import { RunInstance } from '../effects/mock/types.ts'
3
+ * @import { Effect, NotImplemented } from '../effects/types.ts'
4
+ * @import { NodeProgramOptions, OpResult, Sandbox, Write } from '../effects/node/types.ts'
4
5
  * @import { JsModule } from '../effects/node/virtual/types.ts'
5
6
  * @import { Reporter } from './types.ts'
6
- * @import { All, Await, Test, TestContext } from '../effects/node/types.ts'
7
+ * @import { All, Await, Import, Readdir, Test, TestContext } from '../effects/node/types.ts'
7
8
  * @import { Ts } from '../types/rtti/ts/types.ts'
8
9
  */
9
10
 
11
+ import { exitCode } from '../effects/node/module.f.mjs'
10
12
  import { log } from '../effects/node/module.f.mjs'
11
13
  import { defaultNodeProgramOptions, emptyState, virtual } from '../effects/node/virtual/module.f.mjs'
12
- import { assert, assertEq } from '../asserts/module.f.mjs'
14
+ import { assert, assertEq, todo } from '../asserts/module.f.mjs'
13
15
  import {
14
16
  testAll, fmtPath, fmtTerm, fmtImport, ghEscape, isInteger, isIdentifier,
15
17
  registerModule, parseTestSet,
16
- defaultTest, main,
18
+ defaultTest, main, register,
17
19
  } from './module.f.mjs'
18
20
  import { run as mockRun } from '../effects/mock/module.f.mjs'
19
21
  import { shouldLoad } from '../dev/module.f.mjs'
20
22
  import { parse as parseJson } from '../media/json/module.f.mjs'
21
23
  import { array, number as rttiNumber, or, string as rttiString } from '../types/rtti/module.f.mjs'
22
24
  import { parse as rttiParse } from '../types/rtti/parse/module.f.mjs'
23
- import { unwrap } from '../types/result/module.f.mjs'
25
+ import { error, ok, unwrap } from '../types/result/module.f.mjs'
24
26
 
25
27
  /**
26
28
  * The mock reporter's stdout lines. A schema rather than a hand-written type:
@@ -43,7 +45,7 @@ const parseEvent = rttiParse(event)
43
45
 
44
46
  /** @typedef {Reporter<Sandbox | Write>} _TestReporter */
45
47
 
46
- /** @type {(e: _Event) => ReturnType<typeof log>} */
48
+ /** @type {(e: _Event) => Effect<Write, void, NotImplemented>} */
47
49
  const writeEvent = e => log(JSON.stringify(e))
48
50
 
49
51
  /** @type {(stdout: string) => readonly _Event[]} */
@@ -75,8 +77,8 @@ const ok1 = () => ({ result: /** @type {const} */ (['ok', undefined]), duration:
75
77
  const run = (dir, initCwd = '.') => {
76
78
  const reporter = makeReporter()
77
79
  const state = { ...emptyState, root: dir }
78
- const [finalState, exitCode] = virtual(state)(testAll(reporter)(options(initCwd)))
79
- return [parseEvents(finalState.stdout), exitCode]
80
+ const [finalState, code] = virtual(state)(testAll(reporter)(options(initCwd)))
81
+ return [parseEvents(finalState.stdout), exitCode(code)]
80
82
  }
81
83
 
82
84
  // Runs the `fjs t` entry point (`main`) and returns its captured stdout/stderr
@@ -85,8 +87,8 @@ const run = (dir, initCwd = '.') => {
85
87
  const runMain = (dir, github = false) => {
86
88
  const state = { ...emptyState, root: dir }
87
89
  const opts = options('.', github)
88
- const [finalState, exitCode] = virtual(state)(main(opts))
89
- return [finalState.stdout, finalState.stderr, exitCode]
90
+ const [finalState, code] = virtual(state)(main(opts))
91
+ return [finalState.stdout, finalState.stderr, exitCode(code)]
90
92
  }
91
93
 
92
94
  // flat object: two passing tests
@@ -166,10 +168,10 @@ export const returnValueSubTree = () => {
166
168
  const [events, exit] = run({
167
169
  'r.proof.f.ts': () => ({
168
170
  proof: {
169
- outer: /** @type {() => unknown} */ (() => ({
171
+ outer: () => ({
170
172
  result: /** @type {const} */ (['ok', { inner }]),
171
173
  duration: 0,
172
- })),
174
+ }),
173
175
  }
174
176
  }),
175
177
  })
@@ -299,13 +301,45 @@ export const githubReporterOutput = () => {
299
301
  )
300
302
  }
301
303
 
304
+ /** @typedef {All | Import | Readdir | Sandbox | Write} _FailOps */
305
+
306
+ // A reporter that cannot write neither panics nor reports success. The failed
307
+ // `result` line short-circuits its own test, leaves `allOk` as the first error,
308
+ // skips the summary, and reaches the program tail — which answers exit `1`.
309
+ //
310
+ // `write` fails for every stream here, including the one `errorExit` reports
311
+ // the failure on, so the exit code rather than a message is what is observable:
312
+ // a run that cannot say anything at all still says it failed.
313
+ export const reporterWriteFailure = () => {
314
+ /** @type {RunInstance<_FailOps, undefined>} */
315
+ let runner
316
+ runner = mockRun(/** @type {Parameters<typeof mockRun<_FailOps, undefined>>[0]} */ ({
317
+ readdir: (_path, _o) => s => [s, ok([{ name: 'a.proof.f.ts', parentPath: '.', isFile: true }])],
318
+ import: _path => s => [s, ok({ proof: { x: () => { } } })],
319
+ all: (...effects) => s => {
320
+ const [st, rs] = effects.reduce(
321
+ ([st1, rs1], e) => {
322
+ const [ns, r] = runner(st1)(e)
323
+ return [ns, [...rs1, r]]
324
+ },
325
+ /** @type {readonly [undefined, readonly unknown[]]} */([s, []]),
326
+ )
327
+ return [st, ok(rs)]
328
+ },
329
+ sandbox: (/** @type {() => unknown} */ f) => (/** @type {undefined} */ s) =>
330
+ [s, ok({ result: ok(f()), duration: 0 })],
331
+ write: (_stream, _data) => s => [s, error(/** @type {const} */(['notImplemented', 'write']))],
332
+ }))
333
+ const [, code] = runner(undefined)(
334
+ /** @type {Effect<_FailOps, 0, number>} */(main(options('.'))))
335
+ assertEq(exitCode(code), 1)
336
+ }
337
+
302
338
  /** @typedef {readonly string[]} _RegisterMockState */
303
339
 
304
340
  /** @typedef {Test | All | Await} _RegisterMockOps */
305
341
 
306
- /**
307
- * @typedef {(s: _RegisterMockState) => <T>(e: Effect<_RegisterMockOps, T>) => readonly [_RegisterMockState, T]} _RegisterRunner
308
- */
342
+ /** @typedef {RunInstance<_RegisterMockOps, _RegisterMockState>} _RegisterRunner */
309
343
 
310
344
  /**
311
345
  * The `test` op body for a `registerModule` mock; `runner` is threaded in explicitly (rather than closed over) so it can recurse into sub-effects returned by `fn`.
@@ -314,8 +348,8 @@ export const githubReporterOutput = () => {
314
348
  * ctx: TestContext,
315
349
  * name: string,
316
350
  * expectFailure: boolean,
317
- * fn: (t: TestContext) => Effect<_RegisterMockOps, void>,
318
- * ) => (s: _RegisterMockState) => readonly [_RegisterMockState, void]} _RegisterTestOp
351
+ * fn: (t: TestContext) => Effect<_RegisterMockOps, void, never>,
352
+ * ) => (s: _RegisterMockState) => readonly [_RegisterMockState, OpResult<void>]} _RegisterTestOp
319
353
  */
320
354
 
321
355
  /** @type {TestContext} */
@@ -332,15 +366,17 @@ const makeRegisterRunner = testOp => {
332
366
  let runner
333
367
  runner = mockRun(/** @type {Parameters<typeof mockRun<_RegisterMockOps, _RegisterMockState>>[0]} */ ({
334
368
  test: (ctx, name, xf, fn) => testOp(runner, ctx, name, xf, fn),
335
- all: (...effects) => s =>
336
- effects.reduce(
337
- ([st, rs], e) => {
338
- const [ns, r] = runner(st)(e)
339
- return /** @type {readonly [_RegisterMockState, readonly unknown[]]} */ ([ns, [...rs, r]])
369
+ all: (...effects) => s => {
370
+ const [st, rs] = effects.reduce(
371
+ ([st1, rs1], e) => {
372
+ const [ns, r] = runner(st1)(e)
373
+ return [ns, [...rs1, r]]
340
374
  },
341
375
  /** @type {readonly [_RegisterMockState, readonly unknown[]]} */ ([s, []]),
342
- ),
343
- await: p => s => /** @type {const} */ ([s, [p]]),
376
+ )
377
+ return [st, ok(rs)]
378
+ },
379
+ await: p => s => /** @type {const} */ ([s, ok([p])]),
344
380
  }))
345
381
  return runner
346
382
  }
@@ -348,7 +384,7 @@ const makeRegisterRunner = testOp => {
348
384
  // registerModule appends ' ...' for inline runners (Bun).
349
385
  // This mock never invokes the registered callback; it only records names.
350
386
  export const registerSuffixes = () => {
351
- const runner = makeRegisterRunner((_runner, _ctx, name, _xf, _fn) => s => [[...s, name], undefined])
387
+ const runner = makeRegisterRunner((_runner, _ctx, name, _xf, _fn) => s => [[...s, name], ok(undefined)])
352
388
 
353
389
  const proof = /** @type {const} */ ({
354
390
  ok: () => {},
@@ -368,6 +404,33 @@ export const registerSuffixes = () => {
368
404
  assertEq(inlineNames[1], 'import("./a.f.ts").proof.throw.a()')
369
405
  }
370
406
 
407
+ // The registered callback panics when its own effects cannot be dispatched.
408
+ // `Test` hands the body to an external framework that reads a throw and
409
+ // nothing else, so a body that could not run must not be reported as a pass —
410
+ // which is why `registerOne` ends in a `catchStep` that throws rather than in
411
+ // a channel nobody reads.
412
+ const registerBodyPanicsOnUndispatchableEffect = () => {
413
+ /** @type {_RegisterRunner} */
414
+ let runner
415
+ runner = mockRun(/** @type {Parameters<typeof mockRun<_RegisterMockOps, _RegisterMockState>>[0]} */ ({
416
+ test: (ctx, _name, _xf, fn) => s => [runner(s)(fn(ctx))[0], ok(undefined)],
417
+ all: (...effects) => s => {
418
+ const [st, rs] = effects.reduce(
419
+ ([st1, rs1], e) => {
420
+ const [ns, r] = runner(st1)(e)
421
+ return [ns, [...rs1, r]]
422
+ },
423
+ /** @type {readonly [_RegisterMockState, readonly unknown[]]} */ ([s, []]),
424
+ )
425
+ return [st, ok(rs)]
426
+ },
427
+ // The runner has no `await`, which is what the body's channel carries.
428
+ await: _p => s => [s, error(/** @type {const} */ (['notImplemented', 'await']))],
429
+ }))
430
+ const proof = /** @type {const} */ ({ a: () => Promise.resolve(undefined) })
431
+ runner([])(registerModule(registerNoopCtx, './a.f.ts', proof, ''))
432
+ }
433
+
371
434
  // A `throw`-tagged test whose function completes without throwing (the
372
435
  // external framework, not this module, is responsible for turning that into
373
436
  // a failure via `expectFailure`). registerModule's own callback must still
@@ -381,7 +444,7 @@ export const registerThrowsWithoutThrowing = () => {
381
444
  const runner = makeRegisterRunner((runner, ctx, name, xf, fn) => s => {
382
445
  assert(xf)
383
446
  const [ns] = runner(s)(fn(ctx))
384
- return [[...ns, name], undefined]
447
+ return [[...ns, name], ok(undefined)]
385
448
  })
386
449
 
387
450
  // Returns a sub-tree that would register more tests if it were walked.
@@ -396,11 +459,76 @@ export const registerThrowsWithoutThrowing = () => {
396
459
  // registerModule with an empty proof object registers zero tests and
397
460
  // returns without invoking the mock's `test` op at all.
398
461
  export const registerEmptyProof = () => {
399
- const runner = makeRegisterRunner((_runner, _ctx, name, _xf, _fn) => s => [[...s, name], undefined])
462
+ const runner = makeRegisterRunner((_runner, _ctx, name, _xf, _fn) => s => [[...s, name], ok(undefined)])
400
463
  const [names] = runner([])(registerModule(registerNoopCtx, './a.f.ts', {}, ''))
401
464
  assertEq(names.length, 0)
402
465
  }
403
466
 
467
+ // register (the NodeProgram entry point) against an empty virtual root: no
468
+ // modules to register means registerModuleMap short-circuits before ever
469
+ // calling the selected TestContext's `test` op, so this reaches that branch
470
+ // without hitting the virtual harness's `test: todo` stub.
471
+ export const registerEmptyModuleMap = () => {
472
+ const state = { ...emptyState, root: {} }
473
+ const [, code] = virtual(state)(register(options('.')))
474
+ assertEq(exitCode(code), 0)
475
+ }
476
+
477
+ // register's `star`/`ctx` selection, proven observably: the virtual harness's
478
+ // own `test` op is `todo`, so a non-empty root can't go through `virtual()`
479
+ // here without throwing. Instead this interprets register's effect with a
480
+ // fully synthetic runner (discovery faked via `readdir`/`import`, mirroring
481
+ // makeRegisterRunner's approach to `test`/`all`/`await`) that records which
482
+ // TestContext object and which registered name each `test` call received —
483
+ // so a swapped `engine` ternary or a deleted `inlineTestContext` branch
484
+ // changes what's observed here, not just whether the line ran.
485
+ export const registerSelectsContextAndStar = () => {
486
+ /** @type {TestContext} */
487
+ const nodeCtx = { test: todo }
488
+ /** @type {TestContext} */
489
+ const bunCtx = { test: todo }
490
+
491
+ /** @type {(extra: Partial<NodeProgramOptions>) => readonly (readonly [TestContext, string])[]} */
492
+ const runRegister = extra => {
493
+ /** @type {(readonly [TestContext, string])[]} */
494
+ let calls = []
495
+ /** @type {RunInstance<_RegisterMockOps | Readdir | Import, undefined>} */
496
+ let runner
497
+ runner = mockRun(/** @type {Parameters<typeof mockRun<_RegisterMockOps | Readdir | Import, undefined>>[0]} */ ({
498
+ readdir: (_path, _o) => s => [s, ok([{ name: 'a.proof.f.ts', parentPath: '.', isFile: true }])],
499
+ import: _path => s => [s, ok({ proof: { ok: () => {} } })],
500
+ all: (...effects) => s => {
501
+ const [st, rs] = effects.reduce(
502
+ ([st1, rs1], e) => {
503
+ const [ns, r] = runner(st1)(e)
504
+ return [ns, [...rs1, r]]
505
+ },
506
+ /** @type {readonly [undefined, readonly unknown[]]} */ ([s, []]),
507
+ )
508
+ return [st, ok(rs)]
509
+ },
510
+ await: p => s => [s, ok([p])],
511
+ test: (ctx, name, _xf, _fn) => s => { calls = [...calls, [ctx, name]]; return [s, ok(undefined)] },
512
+ }))
513
+ runner(undefined)(/** @type {Effect<_RegisterMockOps | Readdir | Import, 0, number>} */ (register({
514
+ ...defaultNodeProgramOptions, env: {}, testContext: nodeCtx, bunTestContext: bunCtx, ...extra,
515
+ })))
516
+ return calls
517
+ }
518
+
519
+ // Node engine, non-inline context: registers under nodeCtx, no ' ...' suffix.
520
+ const nodeCalls = runRegister({})
521
+ assertEq(nodeCalls.length, 1)
522
+ assert(nodeCalls[0][0] === nodeCtx)
523
+ assertEq(nodeCalls[0][1], 'import("./a.proof.f.ts").proof.ok()')
524
+
525
+ // Bun engine, inline context: registers under bunCtx, with ' ...' suffix.
526
+ const bunCalls = runRegister({ inlineTestContext: true, engine: 'bun' })
527
+ assertEq(bunCalls.length, 1)
528
+ assert(bunCalls[0][0] === bunCtx)
529
+ assertEq(bunCalls[0][1], 'import("./a.proof.f.ts").proof.ok() ...')
530
+ }
531
+
404
532
  // direct unit tests for the pure path-format helpers
405
533
  export const helpers = {
406
534
  isInteger: () => {
@@ -472,13 +600,13 @@ export const helpers = {
472
600
  parseTestSet: {
473
601
  nullReturnsEmpty: () => {
474
602
  const result = parseTestSet(false, null)
475
- assertEq(Array.isArray(result), true)
476
- assertEq((/** @type {unknown[]} */ (result)).length, 0)
603
+ assert(result instanceof Array, result)
604
+ assertEq(result.length, 0)
477
605
  },
478
606
  functionWithParamsReturnsEmpty: () => {
479
607
  const result = parseTestSet(false, (/** @type {number} */ _x) => _x)
480
- assertEq(Array.isArray(result), true)
481
- assertEq((/** @type {unknown[]} */ (result)).length, 0)
608
+ assert(result instanceof Array, result)
609
+ assertEq(result.length, 0)
482
610
  },
483
611
  },
484
612
  }
@@ -495,6 +623,9 @@ const defaultReporterExpectedToThrow = () => {
495
623
  }
496
624
 
497
625
  export const proof = {
626
+ throw: {
627
+ registerBodyPanicsOnUndispatchableEffect,
628
+ },
498
629
  flat,
499
630
  nested,
500
631
  throwKey,
@@ -510,9 +641,12 @@ export const proof = {
510
641
  defaultReporterOutputLargeDuration,
511
642
  defaultReporterFailOutput,
512
643
  githubReporterOutput,
644
+ reporterWriteFailure,
513
645
  registerSuffixes,
514
646
  registerThrowsWithoutThrowing,
515
647
  registerEmptyProof,
648
+ registerEmptyModuleMap,
649
+ registerSelectsContextAndStar,
516
650
  defaultReporterExpectedToThrow,
517
651
  helpers
518
652
  }
@@ -4,7 +4,7 @@
4
4
  * @module
5
5
  */
6
6
  import type { Effect, Operation } from '../effects/types.ts';
7
- import type { SandboxResult } from '../effects/node/types.ts';
7
+ import type { IoChannel, SandboxResult } from '../effects/node/types.ts';
8
8
  /** A zero-argument test function whose return value may contain sub-tests. */
9
9
  export type TestFn = () => unknown;
10
10
  /**
@@ -37,11 +37,29 @@ export type Path = readonly (string | null)[];
37
37
  * leading to the current location; `null` marks a function-call boundary, e.g.
38
38
  * `['outer', null, 'inner']` means `outer` was invoked and its return value
39
39
  * contained `inner`.
40
+ *
41
+ * **Every method is fallible**, because reporting is IO and IO can fail: a
42
+ * write to a closed pipe, a runner that cannot dispatch `write` at all. The
43
+ * runner propagates what a method answers, so a reporter that cannot emit ends
44
+ * the run rather than being silently ignored.
45
+ *
46
+ * `result` and `summary` in particular *must* carry their `Result` in the type.
47
+ * They used to answer a raw effect of `void`, and TypeScript accepts an effect of
48
+ * any value type where a `void` one is expected — so an implementation whose
49
+ * writes were fallible type-checked while its failures went nowhere. That is
50
+ * the hazard the error channel exists to remove, and a `void` return position hides
51
+ * it exactly where a reporter's whole job is to perform IO.
52
+ *
53
+ * The channel is the standard node one ({@link IoChannel}) rather than a type
54
+ * parameter: a reporter is free in which *operations* it performs, but it fails
55
+ * the way node IO fails, and pinning it here keeps the type — and the program
56
+ * tail that reports it — free of a parameter every caller would have to thread
57
+ * through unchanged.
40
58
  */
41
59
  export type Reporter<O extends Operation> = {
42
- readonly result: (file: string, path: Path, r: SandboxResult<unknown>, throws: boolean) => Effect<O, void>;
43
- readonly summary: (pass: number, fail: number, time: number) => Effect<O, void>;
44
- readonly test: (file: string, path: Path, set: TestEntry) => Effect<O, SandboxResult<unknown>>;
60
+ readonly result: (file: string, path: Path, r: SandboxResult<unknown>, throws: boolean) => Effect<O, void, IoChannel>;
61
+ readonly summary: (pass: number, fail: number, time: number) => Effect<O, void, IoChannel>;
62
+ readonly test: (file: string, path: Path, set: TestEntry) => Effect<O, SandboxResult<unknown>, IoChannel>;
45
63
  };
46
64
  /** @internal */
47
65
  export type _TestState = {
@@ -8,7 +8,7 @@
8
8
  * @import { ByteSet } from '../types/byte_set/types.ts'
9
9
  * @import { SortedSet } from '../types/sorted_set/types.ts'
10
10
  * @import { RangeMap, Properties, RangeMapArray, Entry } from '../types/range_map/types.ts'
11
- * @import { Fold, Scan } from '../types/function/operator/types.ts'
11
+ * @import { Fold } from '../types/function/operator/types.ts'
12
12
  */
13
13
  import type { List } from '../types/list/types.ts';
14
14
  import type { StringMap } from '../types/object/types.ts';
@@ -17,10 +17,20 @@ import type { RangeMapArray } from '../types/range_map/types.ts';
17
17
  export type _Rule = readonly [string, ByteSet, string];
18
18
  export type Grammar = List<_Rule>;
19
19
  export type _Dfa = StringMap<RangeMapArray<string>>;
20
- /** @type {(s: string) => ByteSet} */
20
+ /** @typedef {readonly [string, ByteSet, string]} _Rule */
21
+ /** @typedef {List<_Rule>} Grammar */
22
+ /** @typedef {StringMap<RangeMapArray<string>>} _Dfa */
23
+ /**
24
+ * The byte set of an inclusive ASCII character range, written as the two
25
+ * endpoint characters: `toRange('az')`.
26
+ *
27
+ * `fjs/text/ascii` owns "two-character string to inclusive `Range`", including
28
+ * the one-character case where both endpoints are that character, so this is
29
+ * its composition with `byte_set.range` and nothing more.
30
+ *
31
+ * @type {(s: string) => ByteSet}
32
+ */
21
33
  export declare const toRange: (s: string) => ByteSet;
22
- /** @type {(s: string) => ByteSet} */
23
- export declare const toUnion: (s: string) => ByteSet;
24
34
  /** @type {(grammar: Grammar) => _Dfa} */
25
35
  export declare const dfa: (grammar: Grammar) => _Dfa;
26
36
  /** @type {(dfa: _Dfa) => (input: List<number>) => List<string>} */
@@ -8,17 +8,17 @@
8
8
  * @import { ByteSet } from '../types/byte_set/types.ts'
9
9
  * @import { SortedSet } from '../types/sorted_set/types.ts'
10
10
  * @import { RangeMap, Properties, RangeMapArray, Entry } from '../types/range_map/types.ts'
11
- * @import { Fold, Scan } from '../types/function/operator/types.ts'
11
+ * @import { Fold } from '../types/function/operator/types.ts'
12
12
  */
13
13
 
14
- import { equal, isEmpty, fold, toArray, scan, foldScan, empty as emptyList } from '../types/list/module.f.mjs'
15
- import { toRangeMap, union as byteSetUnion, one, empty, range } from '../types/byte_set/module.f.mjs'
16
- import { intersect, union as sortedSetUnion } from '../types/sorted_set/module.f.mjs'
14
+ import { equal, isEmpty, fold, map, toArray, foldScan, empty as emptyList } from '../types/list/module.f.mjs'
15
+ import { toRangeMap, range } from '../types/byte_set/module.f.mjs'
16
+ import { intersect, toKey, union as sortedSetUnion } from '../types/sorted_set/module.f.mjs'
17
17
  import { merge, get as rangeMapGet } from '../types/range_map/module.f.mjs'
18
18
  import { strictEqual } from '../types/function/operator/module.f.mjs'
19
- import { stringify } from '../media/json/module.f.mjs'
20
- import { identity } from '../types/function/module.f.mjs'
21
- import { stringToList } from '../text/utf16/module.f.mjs'
19
+ import { range as asciiRange } from '../text/ascii/module.f.mjs'
20
+ import { compose } from '../types/function/module.f.mjs'
21
+ import { at } from '../types/object/module.f.mjs'
22
22
  import { cmp } from '../types/string/module.f.mjs'
23
23
 
24
24
  /** @typedef {readonly [string, ByteSet, string]} _Rule */
@@ -27,22 +27,18 @@ import { cmp } from '../types/string/module.f.mjs'
27
27
 
28
28
  /** @typedef {StringMap<RangeMapArray<string>>} _Dfa */
29
29
 
30
- const stringifyIdentity = stringify(identity)
31
30
 
32
- /** @type {(s: string) => ByteSet} */
33
- export const toRange = s => {
34
- const [b, e] = toArray(stringToList(s))
35
- return range([b, e])
36
- }
37
-
38
- /** @type {Fold<number, ByteSet>} */
39
- const toUnionOp = i => bs => byteSetUnion(bs)(one(i))
40
-
41
- /** @type {(s: string) => ByteSet} */
42
- export const toUnion = s => {
43
- const codePoints = stringToList(s)
44
- return fold(toUnionOp)(empty)(codePoints)
45
- }
31
+ /**
32
+ * The byte set of an inclusive ASCII character range, written as the two
33
+ * endpoint characters: `toRange('az')`.
34
+ *
35
+ * `fjs/text/ascii` owns "two-character string to inclusive `Range`", including
36
+ * the one-character case where both endpoints are that character, so this is
37
+ * its composition with `byte_set.range` and nothing more.
38
+ *
39
+ * @type {(s: string) => ByteSet}
40
+ */
41
+ export const toRange = compose(asciiRange)(range)
46
42
 
47
43
  /** @type {Properties<SortedSet<string>>} */
48
44
  const mergeOp = { union: sortedSetUnion(cmp), equal: equal(strictEqual), def: [] }
@@ -50,50 +46,71 @@ const mergeOp = { union: sortedSetUnion(cmp), equal: equal(strictEqual), def: []
50
46
  /** @type {(s: string) => (set: SortedSet<string>) => boolean} */
51
47
  const hasState = s => set => !isEmpty(intersect(cmp)([s])(set))
52
48
 
49
+ /**
50
+ * Labels a byte set's ranges with the rule they lead to: a range inside the set
51
+ * transitions to `ruleOut`, one outside transitions nowhere.
52
+ *
53
+ * `byte_set.toRangeMap` answers only whether each range is in the set; which
54
+ * state that means is a DFA question, so it is answered here.
55
+ *
56
+ * @type {(ruleOut: string) => (entry: Entry<boolean>) => Entry<SortedSet<string>>}
57
+ */
58
+ const labelRange = ruleOut => ([inSet, max]) => [inSet ? [ruleOut] : [], max]
59
+
53
60
  /** @type {(set: SortedSet<string>) => Fold<_Rule, RangeMap<SortedSet<string>>>} */
54
61
  const foldOp = set => ([ruleIn, bs, ruleOut]) => rm => {
55
- if (hasState(ruleIn)(set)) { return merge(mergeOp)(rm)(toRangeMap(bs)(ruleOut)) }
62
+ if (hasState(ruleIn)(set)) {
63
+ return merge(mergeOp)(rm)(map(labelRange(ruleOut))(toRangeMap(bs)))
64
+ }
56
65
  return rm
57
66
  }
58
67
 
59
- /** @type {Scan<Entry<SortedSet<string>>, Entry<string>>} */
60
- const stringifyOp = ([sortedSet, max]) => [[stringifyIdentity(sortedSet), max], stringifyOp]
68
+ /**
69
+ * Renders an entry's state set as its `_Dfa` key, keeping the range boundary.
70
+ *
71
+ * @type {(entry: Entry<SortedSet<string>>) => Entry<string>}
72
+ */
73
+ const keyEntry = ([sortedSet, max]) => [toKey(sortedSet), max]
61
74
 
62
- const scanStringify = scan(stringifyOp)
75
+ const keyEntries = map(keyEntry)
63
76
 
64
- /** @type {Scan<Entry<SortedSet<string>>, SortedSet<string>>} */
65
- const fetchOp = ([item, _]) => [item, fetchOp]
77
+ /**
78
+ * Drops an entry's range boundary, leaving the state set.
79
+ *
80
+ * @type {(entry: Entry<SortedSet<string>>) => SortedSet<string>}
81
+ */
82
+ const entryValue = ([value]) => value
66
83
 
67
- const scanFetch = scan(fetchOp)
84
+ const entryValues = map(entryValue)
68
85
 
69
86
  /** @type {(grammar: Grammar) => Fold<SortedSet<string>, _Dfa>} */
70
87
  const addEntry = grammar => set => dfa => {
71
- const s = stringifyIdentity(set)
72
- if (s in dfa) { return dfa }
88
+ const s = toKey(set)
89
+ if (at(s)(dfa) !== null) { return dfa }
73
90
  const setMap = fold(foldOp(set))(emptyList)(grammar)
74
- const stringMap = toArray(scanStringify(setMap))
91
+ const stringMap = toArray(keyEntries(setMap))
75
92
  const newDfa = { ...dfa, [s]: stringMap }
76
- const newStates = scanFetch(setMap)
93
+ const newStates = entryValues(setMap)
77
94
  return fold(addEntry(grammar))(newDfa)(newStates)
78
95
  }
79
96
 
80
97
  /** @type {string[]} */
81
98
  const emptyState = []
82
99
 
83
- const emptyStateStringify = stringifyIdentity(emptyState)
100
+ const emptyStateKey = toKey(emptyState)
84
101
 
85
102
  const initialState = ['']
86
103
 
87
- const initialStateStringify = stringifyIdentity(initialState)
104
+ const initialStateKey = toKey(initialState)
88
105
 
89
106
  /** @type {(grammar: Grammar) => _Dfa} */
90
107
  export const dfa = grammar => addEntry(grammar)(initialState)({})
91
108
 
92
- const get = rangeMapGet(emptyStateStringify)
109
+ const get = rangeMapGet(emptyStateKey)
93
110
 
94
111
  /** @type {(dfa: _Dfa) => Fold<number, string>} */
95
112
  const runOp = dfa => input => s => get(dfa[s] ?? [])(input)
96
113
 
97
114
  /** @type {(dfa: _Dfa) => (input: List<number>) => List<string>} */
98
115
  export const run = dfa => input =>
99
- foldScan(runOp(dfa))(initialStateStringify)(input)
116
+ foldScan(runOp(dfa))(initialStateKey)(input)
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * @import { Grammar } from './module.f.mjs'
3
+ * @import { ByteSet } from '../types/byte_set/types.ts'
3
4
  */
4
5
  export declare const proof: {
6
+ toRange: (() => void)[];
5
7
  dfa: () => void;
6
8
  run: (() => void)[];
7
9
  };