functionalscript 0.44.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (571) 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 +15 -0
  4. package/fjs/asn.1/proof.f.mjs +31 -3
  5. package/fjs/asserts/module.f.d.mts +14 -0
  6. package/fjs/asserts/module.f.mjs +20 -0
  7. package/fjs/asserts/proof.f.d.mts +3 -0
  8. package/fjs/asserts/proof.f.mjs +15 -1
  9. package/fjs/basen/base128/module.f.mjs +22 -5
  10. package/fjs/basen/base128/proof.f.d.mts +3 -1
  11. package/fjs/basen/base128/proof.f.mjs +3 -1
  12. package/fjs/basen/base64/module.f.mjs +7 -3
  13. package/fjs/basen/base64/proof.f.d.mts +3 -1
  14. package/fjs/basen/base64/proof.f.mjs +7 -4
  15. package/fjs/basen/cbase32/proof.f.d.mts +3 -1
  16. package/fjs/basen/cbase32/proof.f.mjs +3 -1
  17. package/fjs/bnf/data/module.f.d.mts +32 -6
  18. package/fjs/bnf/data/module.f.mjs +112 -7
  19. package/fjs/bnf/data/proof.f.d.mts +2 -0
  20. package/fjs/bnf/data/proof.f.mjs +74 -4
  21. package/fjs/bnf/data/types.d.ts +20 -2
  22. package/fjs/bnf/descent/module.f.d.mts +34 -5
  23. package/fjs/bnf/descent/module.f.mjs +176 -54
  24. package/fjs/bnf/descent/proof.f.d.mts +3 -0
  25. package/fjs/bnf/descent/proof.f.mjs +189 -27
  26. package/fjs/bnf/descent/types.d.ts +24 -18
  27. package/fjs/bnf/ll1/module.f.d.mts +74 -6
  28. package/fjs/bnf/ll1/module.f.mjs +297 -95
  29. package/fjs/bnf/ll1/proof.f.d.mts +17 -2
  30. package/fjs/bnf/ll1/proof.f.mjs +372 -137
  31. package/fjs/bnf/ll1/types.d.ts +25 -27
  32. package/fjs/bnf/matcher/module.f.d.mts +66 -0
  33. package/fjs/bnf/matcher/module.f.mjs +81 -0
  34. package/fjs/bnf/matcher/proof.f.d.mts +10 -0
  35. package/fjs/bnf/matcher/proof.f.mjs +79 -0
  36. package/fjs/bnf/matcher/types.d.ts +54 -0
  37. package/fjs/bnf/module.f.d.mts +15 -6
  38. package/fjs/bnf/module.f.mjs +52 -11
  39. package/fjs/bnf/proof.f.d.mts +2 -0
  40. package/fjs/bnf/proof.f.mjs +79 -3
  41. package/fjs/bnf/testlib.f.d.mts +31 -0
  42. package/fjs/bnf/testlib.f.mjs +80 -0
  43. package/fjs/bnf/token_symbol/module.f.d.mts +4 -3
  44. package/fjs/bnf/token_symbol/module.f.mjs +7 -6
  45. package/fjs/bnf/token_symbol/proof.f.mjs +5 -2
  46. package/fjs/bnf/token_symbol/types.d.ts +2 -2
  47. package/fjs/bnf/types.d.ts +10 -3
  48. package/fjs/cas/cli/module.f.d.mts +1 -1
  49. package/fjs/cas/cli/module.f.mjs +14 -20
  50. package/fjs/cas/cli/proof.f.d.mts +4 -4
  51. package/fjs/cas/cli/proof.f.mjs +47 -34
  52. package/fjs/cas/evo/module.f.d.mts +71 -31
  53. package/fjs/cas/evo/module.f.mjs +223 -138
  54. package/fjs/cas/evo/proof.f.d.mts +10 -1
  55. package/fjs/cas/evo/proof.f.mjs +311 -226
  56. package/fjs/cas/evo/types.d.ts +45 -9
  57. package/fjs/cas/module.f.d.mts +18 -32
  58. package/fjs/cas/module.f.mjs +164 -176
  59. package/fjs/cas/proof.f.d.mts +11 -8
  60. package/fjs/cas/proof.f.mjs +259 -147
  61. package/fjs/cas/types.d.ts +24 -10
  62. package/fjs/ci/common/module.f.d.mts +1 -1
  63. package/fjs/ci/common/module.f.mjs +1 -0
  64. package/fjs/ci/config/module.f.d.mts +3 -3
  65. package/fjs/ci/config/module.f.mjs +3 -3
  66. package/fjs/ci/module.f.d.mts +5 -5
  67. package/fjs/ci/module.f.mjs +8 -7
  68. package/fjs/ci/nix/module.f.d.mts +7 -5
  69. package/fjs/ci/nix/module.f.mjs +13 -12
  70. package/fjs/ci/nix/proof.f.d.mts +2 -0
  71. package/fjs/ci/nix/proof.f.mjs +4 -4
  72. package/fjs/ci/proof.f.d.mts +4 -2
  73. package/fjs/ci/proof.f.mjs +13 -8
  74. package/fjs/cli/module.f.d.mts +4 -6
  75. package/fjs/cli/module.f.mjs +4 -8
  76. package/fjs/cli/proof.f.d.mts +4 -2
  77. package/fjs/cli/proof.f.mjs +21 -18
  78. package/fjs/cli/types.d.ts +2 -3
  79. package/fjs/common/monoid/module.f.d.mts +70 -12
  80. package/fjs/common/monoid/module.f.mjs +177 -14
  81. package/fjs/common/monoid/proof.f.d.mts +12 -1
  82. package/fjs/common/monoid/proof.f.mjs +88 -4
  83. package/fjs/common/monoid/types.d.ts +23 -0
  84. package/fjs/crypto/hmac/module.f.mjs +2 -2
  85. package/fjs/crypto/secp/proof.f.d.mts +3 -1
  86. package/fjs/crypto/secp/proof.f.mjs +3 -1
  87. package/fjs/crypto/sha2/module.f.mjs +3 -1
  88. package/fjs/crypto/sha2/proof.f.d.mts +4 -1
  89. package/fjs/crypto/sha2/proof.f.mjs +27 -1
  90. package/fjs/crypto/sha2/types.d.ts +11 -0
  91. package/fjs/crypto/sign/module.f.mjs +2 -2
  92. package/fjs/crypto/vdf/module.f.d.mts +23 -4
  93. package/fjs/crypto/vdf/module.f.mjs +6 -4
  94. package/fjs/dev/module.f.d.mts +17 -5
  95. package/fjs/dev/module.f.mjs +60 -30
  96. package/fjs/dev/update/module.f.d.mts +11 -3
  97. package/fjs/dev/update/module.f.mjs +16 -11
  98. package/fjs/dev/update/proof.f.d.mts +4 -3
  99. package/fjs/dev/update/proof.f.mjs +11 -7
  100. package/fjs/djs/module.f.d.mts +13 -5
  101. package/fjs/djs/module.f.mjs +31 -16
  102. package/fjs/djs/parser/module.f.d.mts +16 -3
  103. package/fjs/djs/parser/module.f.mjs +135 -16
  104. package/fjs/djs/parser/proof.f.d.mts +8 -1
  105. package/fjs/djs/parser/proof.f.mjs +287 -13
  106. package/fjs/djs/parser/types.d.ts +7 -1
  107. package/fjs/djs/proof.f.d.mts +20 -1
  108. package/fjs/djs/proof.f.mjs +190 -12
  109. package/fjs/djs/serializer/module.f.d.mts +25 -8
  110. package/fjs/djs/serializer/module.f.mjs +66 -19
  111. package/fjs/djs/serializer/proof.f.d.mts +5 -0
  112. package/fjs/djs/serializer/proof.f.mjs +23 -1
  113. package/fjs/djs/tokenizer/module.f.d.mts +17 -5
  114. package/fjs/djs/tokenizer/module.f.mjs +120 -73
  115. package/fjs/djs/tokenizer/proof.f.d.mts +3 -0
  116. package/fjs/djs/tokenizer/proof.f.mjs +86 -67
  117. package/fjs/djs/transpiler/module.f.d.mts +13 -19
  118. package/fjs/djs/transpiler/module.f.mjs +79 -72
  119. package/fjs/djs/transpiler/types.d.ts +29 -0
  120. package/fjs/djs/types.d.ts +7 -1
  121. package/fjs/effects/list/module.f.d.mts +23 -12
  122. package/fjs/effects/list/module.f.mjs +16 -12
  123. package/fjs/effects/list/types.d.ts +27 -7
  124. package/fjs/effects/memory/module.f.d.mts +6 -3
  125. package/fjs/effects/memory/module.f.mjs +7 -7
  126. package/fjs/effects/memory/proof.f.d.mts +4 -0
  127. package/fjs/effects/memory/proof.f.mjs +18 -9
  128. package/fjs/effects/memory/types.d.ts +4 -3
  129. package/fjs/effects/mock/module.f.d.mts +28 -4
  130. package/fjs/effects/mock/module.f.mjs +39 -5
  131. package/fjs/effects/mock/types.d.ts +10 -1
  132. package/fjs/effects/module.d.mts +12 -2
  133. package/fjs/effects/module.f.d.mts +469 -281
  134. package/fjs/effects/module.f.mjs +538 -299
  135. package/fjs/effects/module.mjs +11 -2
  136. package/fjs/effects/node/memory/module.d.mts +7 -2
  137. package/fjs/effects/node/memory/module.mjs +9 -5
  138. package/fjs/effects/node/memory/proof.d.mts +2 -0
  139. package/fjs/effects/node/memory/proof.mjs +12 -5
  140. package/fjs/effects/node/module.d.mts +8 -2
  141. package/fjs/effects/node/module.f.d.mts +183 -43
  142. package/fjs/effects/node/module.f.mjs +260 -62
  143. package/fjs/effects/node/module.mjs +61 -50
  144. package/fjs/effects/node/proof.f.d.mts +28 -2
  145. package/fjs/effects/node/proof.f.mjs +161 -42
  146. package/fjs/effects/node/types.d.ts +106 -18
  147. package/fjs/effects/node/virtual/module.f.d.mts +21 -4
  148. package/fjs/effects/node/virtual/module.f.mjs +113 -70
  149. package/fjs/effects/node/virtual/proof.f.d.mts +31 -2
  150. package/fjs/effects/node/virtual/proof.f.mjs +201 -8
  151. package/fjs/effects/proof.f.d.mts +69 -34
  152. package/fjs/effects/proof.f.mjs +413 -130
  153. package/fjs/effects/types.d.ts +161 -33
  154. package/fjs/emergent_testing/all.test.d.mts +8 -0
  155. package/fjs/emergent_testing/all.test.mjs +14 -0
  156. package/fjs/emergent_testing/module.f.d.mts +22 -10
  157. package/fjs/emergent_testing/module.f.mjs +119 -85
  158. package/fjs/emergent_testing/proof.f.d.mts +21 -7
  159. package/fjs/emergent_testing/proof.f.mjs +169 -35
  160. package/fjs/emergent_testing/types.d.ts +22 -4
  161. package/fjs/fsc/bnf.f.d.mts +3 -0
  162. package/fjs/fsc/bnf.f.mjs +4 -1
  163. package/fjs/fsc/json.f.d.mts +3 -0
  164. package/fjs/fsc/json.f.mjs +4 -1
  165. package/fjs/fsc/module.f.d.mts +9 -0
  166. package/fjs/fsc/module.f.mjs +5 -3
  167. package/fjs/fsm/module.f.d.mts +14 -4
  168. package/fjs/fsm/module.f.mjs +54 -37
  169. package/fjs/fsm/proof.f.d.mts +5 -0
  170. package/fjs/fsm/proof.f.mjs +87 -115
  171. package/fjs/js/keywords/module.f.d.mts +52 -0
  172. package/fjs/js/keywords/module.f.mjs +72 -0
  173. package/fjs/{emergent_testing/scenarios/return-value.pass.d.ts → js/keywords/proof.f.d.mts} +1 -1
  174. package/fjs/js/keywords/proof.f.mjs +13 -0
  175. package/fjs/js/tokenizer/module.f.d.mts +30 -3
  176. package/fjs/js/tokenizer/module.f.mjs +161 -211
  177. package/fjs/js/tokenizer/proof.f.d.mts +1 -0
  178. package/fjs/js/tokenizer/proof.f.mjs +54 -24
  179. package/fjs/js/tokenizer/types.d.ts +33 -24
  180. package/fjs/mcp/cas/module.f.d.mts +1 -6
  181. package/fjs/mcp/cas/module.f.mjs +55 -51
  182. package/fjs/mcp/cas/proof.f.d.mts +15 -0
  183. package/fjs/mcp/cas/proof.f.mjs +174 -0
  184. package/fjs/mcp/evo/module.f.d.mts +19 -10
  185. package/fjs/mcp/evo/module.f.mjs +48 -27
  186. package/fjs/mcp/evo/proof.f.d.mts +6 -1
  187. package/fjs/mcp/evo/proof.f.mjs +115 -31
  188. package/fjs/mcp/module.f.d.mts +39 -4
  189. package/fjs/mcp/module.f.mjs +14 -12
  190. package/fjs/mcp/proof.f.d.mts +13 -1
  191. package/fjs/mcp/proof.f.mjs +120 -61
  192. package/fjs/media/html/module.f.d.mts +12 -0
  193. package/fjs/media/html/module.f.mjs +7 -5
  194. package/fjs/media/html/proof.f.d.mts +3 -0
  195. package/fjs/media/html/proof.f.mjs +4 -1
  196. package/fjs/media/json/extended/module.f.d.mts +82 -0
  197. package/fjs/media/json/extended/module.f.mjs +153 -0
  198. package/fjs/media/json/extended/proof.f.d.mts +42 -0
  199. package/fjs/media/json/extended/proof.f.mjs +127 -0
  200. package/fjs/media/json/extended/types.d.ts +23 -0
  201. package/fjs/media/json/module.f.d.mts +8 -2
  202. package/fjs/media/json/module.f.mjs +43 -41
  203. package/fjs/media/json/number/module.f.d.mts +59 -0
  204. package/fjs/media/json/number/module.f.mjs +136 -0
  205. package/fjs/media/json/number/proof.f.d.mts +24 -0
  206. package/fjs/media/json/number/proof.f.mjs +86 -0
  207. package/fjs/media/json/number/types.d.ts +28 -0
  208. package/fjs/media/json/parser/module.f.d.mts +25 -13
  209. package/fjs/media/json/parser/module.f.mjs +133 -72
  210. package/fjs/media/json/parser/proof.f.d.mts +5 -0
  211. package/fjs/media/json/parser/proof.f.mjs +31 -1
  212. package/fjs/media/json/parser/types.d.ts +38 -14
  213. package/fjs/media/json/rtti/module.f.d.mts +1 -1
  214. package/fjs/media/json/rtti/module.f.mjs +1 -1
  215. package/fjs/media/json/rtti/proof.f.d.mts +3 -0
  216. package/fjs/media/json/rtti/proof.f.mjs +12 -12
  217. package/fjs/media/json/schema/module.f.d.mts +61 -27
  218. package/fjs/media/json/schema/module.f.mjs +218 -63
  219. package/fjs/media/json/schema/proof.f.d.mts +41 -1
  220. package/fjs/media/json/schema/proof.f.mjs +220 -9
  221. package/fjs/media/json/serializer/module.f.d.mts +44 -0
  222. package/fjs/media/json/serializer/module.f.mjs +71 -9
  223. package/fjs/media/json/tokenizer/module.f.d.mts +8 -0
  224. package/fjs/media/json/tokenizer/module.f.mjs +31 -8
  225. package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
  226. package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
  227. package/fjs/media/json/types.d.ts +36 -10
  228. package/fjs/media/lock/module.f.d.mts +100 -0
  229. package/fjs/media/lock/module.f.mjs +125 -0
  230. package/fjs/media/lock/proof.f.d.mts +33 -0
  231. package/fjs/media/lock/proof.f.mjs +196 -0
  232. package/fjs/media/lock/types.d.ts +15 -0
  233. package/fjs/media/module.f.d.mts +6 -5
  234. package/fjs/media/module.f.mjs +8 -7
  235. package/fjs/media/nix/module.f.d.mts +13 -0
  236. package/fjs/media/nix/module.f.mjs +4 -2
  237. package/fjs/media/nix/proof.f.d.mts +3 -0
  238. package/fjs/media/nix/proof.f.mjs +4 -1
  239. package/fjs/media/note/module.f.d.mts +121 -0
  240. package/fjs/media/note/module.f.mjs +131 -0
  241. package/fjs/media/note/proof.f.d.mts +29 -0
  242. package/fjs/media/note/proof.f.mjs +150 -0
  243. package/fjs/media/note/types.d.ts +10 -0
  244. package/fjs/media/proof.f.d.mts +4 -1
  245. package/fjs/media/proof.f.mjs +40 -21
  246. package/fjs/media/revision/module.f.d.mts +83 -7
  247. package/fjs/media/revision/module.f.mjs +127 -23
  248. package/fjs/media/revision/proof.f.d.mts +14 -0
  249. package/fjs/media/revision/proof.f.mjs +93 -2
  250. package/fjs/media/revision/types.d.ts +34 -5
  251. package/fjs/media/type/module.f.d.mts +53 -18
  252. package/fjs/media/type/module.f.mjs +87 -97
  253. package/fjs/media/type/proof.f.d.mts +17 -0
  254. package/fjs/media/type/proof.f.mjs +73 -13
  255. package/fjs/module.d.mts +5 -0
  256. package/fjs/module.f.d.mts +8 -0
  257. package/fjs/module.f.mjs +33 -10
  258. package/fjs/module.mjs +6 -0
  259. package/fjs/nanvm/proof.f.mjs +3 -3
  260. package/fjs/nanvm/rust/module.f.mjs +1 -1
  261. package/fjs/nanvm/update/module.f.d.mts +4 -4
  262. package/fjs/nanvm/update/module.f.mjs +8 -9
  263. package/fjs/nanvm/update/proof.f.mjs +4 -3
  264. package/fjs/path/module.f.d.mts +8 -0
  265. package/fjs/path/module.f.mjs +4 -2
  266. package/fjs/proof.f.d.mts +7 -3
  267. package/fjs/proof.f.mjs +41 -12
  268. package/fjs/protocol/json_rpc/module.f.d.mts +3 -3
  269. package/fjs/protocol/json_rpc/module.f.mjs +10 -7
  270. package/fjs/protocol/json_rpc/proof.f.d.mts +6 -0
  271. package/fjs/protocol/json_rpc/proof.f.mjs +26 -5
  272. package/fjs/protocol/mcp/module.f.d.mts +10 -13
  273. package/fjs/protocol/mcp/module.f.mjs +74 -58
  274. package/fjs/protocol/mcp/proof.f.d.mts +16 -3
  275. package/fjs/protocol/mcp/proof.f.mjs +224 -69
  276. package/fjs/protocol/mcp/stdio/module.f.d.mts +17 -11
  277. package/fjs/protocol/mcp/stdio/module.f.mjs +39 -33
  278. package/fjs/protocol/mcp/stdio/proof.f.d.mts +5 -3
  279. package/fjs/protocol/mcp/stdio/proof.f.mjs +46 -13
  280. package/fjs/protocol/mcp/stdio/types.d.ts +14 -0
  281. package/fjs/protocol/mcp/types.d.ts +17 -6
  282. package/fjs/sul/id/module.f.d.mts +4 -0
  283. package/fjs/sul/id/module.f.mjs +6 -6
  284. package/fjs/sul/level/hash/module.f.d.mts +4 -1
  285. package/fjs/sul/level/hash/module.f.mjs +6 -4
  286. package/fjs/sul/level/hash/proof.f.d.mts +4 -0
  287. package/fjs/sul/level/hash/proof.f.mjs +7 -4
  288. package/fjs/sul/level/literal/module.f.d.mts +4 -1
  289. package/fjs/sul/level/literal/module.f.mjs +4 -3
  290. package/fjs/sul/level/literal/proof.f.d.mts +3 -0
  291. package/fjs/sul/level/literal/proof.f.mjs +4 -1
  292. package/fjs/sul/module.f.d.mts +5 -3
  293. package/fjs/sul/module.f.mjs +23 -17
  294. package/fjs/sul/proof.f.d.mts +4 -0
  295. package/fjs/sul/proof.f.mjs +5 -2
  296. package/fjs/text/ascii/module.f.d.mts +26 -0
  297. package/fjs/text/ascii/module.f.mjs +49 -1
  298. package/fjs/text/ascii/proof.f.d.mts +10 -0
  299. package/fjs/text/ascii/proof.f.mjs +33 -1
  300. package/fjs/text/code_point/module.f.d.mts +29 -3
  301. package/fjs/text/code_point/module.f.mjs +32 -9
  302. package/fjs/text/code_point/proof.f.d.mts +2 -0
  303. package/fjs/text/code_point/proof.f.mjs +39 -0
  304. package/fjs/text/module.f.d.mts +4 -2
  305. package/fjs/text/module.f.mjs +4 -3
  306. package/fjs/text/proof.f.d.mts +3 -0
  307. package/fjs/text/proof.f.mjs +4 -1
  308. package/fjs/text/sgr/module.f.d.mts +6 -5
  309. package/fjs/text/sgr/module.f.mjs +8 -8
  310. package/fjs/text/sgr/proof.f.d.mts +3 -0
  311. package/fjs/text/sgr/proof.f.mjs +4 -1
  312. package/fjs/text/utf16/module.f.d.mts +5 -1
  313. package/fjs/text/utf16/module.f.mjs +38 -35
  314. package/fjs/text/utf16/proof.f.d.mts +3 -1
  315. package/fjs/text/utf16/proof.f.mjs +19 -2
  316. package/fjs/text/utf8/module.f.d.mts +9 -5
  317. package/fjs/text/utf8/module.f.mjs +20 -20
  318. package/fjs/types/array/module.f.d.mts +2 -1
  319. package/fjs/types/array/module.f.mjs +16 -4
  320. package/fjs/types/bigfloat/module.f.d.mts +21 -1
  321. package/fjs/types/bigfloat/module.f.mjs +33 -7
  322. package/fjs/types/bigfloat/proof.f.d.mts +1 -0
  323. package/fjs/types/bigfloat/proof.f.mjs +46 -0
  324. package/fjs/types/bigint/module.f.d.mts +4 -0
  325. package/fjs/types/bigint/module.f.mjs +4 -3
  326. package/fjs/types/bit_vec/module.f.d.mts +10 -16
  327. package/fjs/types/bit_vec/module.f.mjs +99 -95
  328. package/fjs/types/bit_vec/proof.f.d.mts +6 -0
  329. package/fjs/types/bit_vec/proof.f.mjs +31 -5
  330. package/fjs/types/btree/find/module.f.d.mts +5 -1
  331. package/fjs/types/btree/find/module.f.mjs +5 -5
  332. package/fjs/types/btree/find/proof.f.d.mts +5 -1
  333. package/fjs/types/btree/find/proof.f.mjs +5 -3
  334. package/fjs/types/btree/module.f.d.mts +3 -0
  335. package/fjs/types/btree/module.f.mjs +3 -2
  336. package/fjs/types/btree/proof.f.d.mts +5 -1
  337. package/fjs/types/btree/proof.f.mjs +5 -3
  338. package/fjs/types/btree/remove/module.f.d.mts +11 -0
  339. package/fjs/types/btree/remove/module.f.mjs +10 -10
  340. package/fjs/types/btree/remove/proof.f.d.mts +3 -0
  341. package/fjs/types/btree/remove/proof.f.mjs +4 -1
  342. package/fjs/types/btree/set/module.f.d.mts +9 -0
  343. package/fjs/types/btree/set/module.f.mjs +14 -17
  344. package/fjs/types/btree/set/proof.f.d.mts +3 -0
  345. package/fjs/types/btree/set/proof.f.mjs +16 -1
  346. package/fjs/types/btree/types/module.f.d.mts +2 -1
  347. package/fjs/types/btree/types/module.f.mjs +2 -1
  348. package/fjs/types/byte_set/module.f.d.mts +20 -4
  349. package/fjs/types/byte_set/module.f.mjs +18 -8
  350. package/fjs/types/byte_set/proof.f.d.mts +3 -1
  351. package/fjs/types/byte_set/proof.f.mjs +10 -8
  352. package/fjs/types/function/compare/module.f.d.mts +3 -2
  353. package/fjs/types/function/compare/module.f.mjs +13 -5
  354. package/fjs/types/function/module.f.d.mts +8 -1
  355. package/fjs/types/function/module.f.mjs +8 -1
  356. package/fjs/types/function/operator/module.f.d.mts +2 -1
  357. package/fjs/types/function/operator/module.f.mjs +2 -2
  358. package/fjs/types/list/module.f.d.mts +10 -3
  359. package/fjs/types/list/module.f.mjs +6 -4
  360. package/fjs/types/list/proof.f.d.mts +4 -1
  361. package/fjs/types/list/proof.f.mjs +4 -2
  362. package/fjs/types/nibble_set/module.f.d.mts +2 -1
  363. package/fjs/types/nibble_set/module.f.mjs +2 -2
  364. package/fjs/types/nominal/module.f.d.mts +2 -1
  365. package/fjs/types/nominal/module.f.mjs +2 -1
  366. package/fjs/types/nullable/module.f.d.mts +26 -6
  367. package/fjs/types/nullable/module.f.mjs +25 -6
  368. package/fjs/types/nullable/proof.f.d.mts +4 -0
  369. package/fjs/types/nullable/proof.f.mjs +15 -0
  370. package/fjs/types/number/module.f.d.mts +4 -0
  371. package/fjs/types/number/module.f.mjs +4 -3
  372. package/fjs/types/object/module.f.d.mts +26 -4
  373. package/fjs/types/object/module.f.mjs +26 -7
  374. package/fjs/types/object/proof.f.d.mts +5 -2
  375. package/fjs/types/object/proof.f.mjs +6 -3
  376. package/fjs/types/object/structurally_same/module.f.d.mts +39 -0
  377. package/fjs/types/object/structurally_same/module.f.mjs +59 -0
  378. package/fjs/types/object/structurally_same/proof.f.d.mts +6 -0
  379. package/fjs/types/object/structurally_same/proof.f.mjs +73 -0
  380. package/fjs/types/ordered_map/module.f.d.mts +5 -0
  381. package/fjs/types/ordered_map/module.f.mjs +5 -4
  382. package/fjs/types/ordered_map/proof.f.d.mts +3 -0
  383. package/fjs/types/ordered_map/proof.f.mjs +4 -1
  384. package/fjs/types/patricia_trie/module.f.d.mts +2 -1
  385. package/fjs/types/patricia_trie/module.f.mjs +27 -12
  386. package/fjs/types/patricia_trie/proof.f.d.mts +3 -0
  387. package/fjs/types/patricia_trie/proof.f.mjs +4 -1
  388. package/fjs/types/prime_field/module.f.d.mts +3 -1
  389. package/fjs/types/prime_field/module.f.mjs +3 -2
  390. package/fjs/types/range/module.f.d.mts +2 -1
  391. package/fjs/types/range/module.f.mjs +2 -2
  392. package/fjs/types/range_map/module.f.d.mts +6 -0
  393. package/fjs/types/range_map/module.f.mjs +6 -9
  394. package/fjs/types/range_map/proof.f.d.mts +5 -1
  395. package/fjs/types/range_map/proof.f.mjs +5 -3
  396. package/fjs/types/range_set/module.f.d.mts +5 -0
  397. package/fjs/types/range_set/module.f.mjs +1 -0
  398. package/fjs/types/range_set/proof.f.d.mts +3 -0
  399. package/fjs/types/range_set/proof.f.mjs +4 -1
  400. package/fjs/types/result/module.d.mts +8 -0
  401. package/fjs/types/result/module.f.d.mts +37 -7
  402. package/fjs/types/result/module.f.mjs +38 -8
  403. package/fjs/types/result/module.mjs +9 -1
  404. package/fjs/types/result/proof.f.d.mts +5 -0
  405. package/fjs/types/result/proof.f.mjs +22 -2
  406. package/fjs/types/rtti/common/module.f.d.mts +44 -14
  407. package/fjs/types/rtti/common/module.f.mjs +42 -36
  408. package/fjs/types/rtti/common/proof.f.d.mts +4 -0
  409. package/fjs/types/rtti/common/proof.f.mjs +10 -7
  410. package/fjs/types/rtti/data/module.f.d.mts +134 -0
  411. package/fjs/types/rtti/data/module.f.mjs +1053 -0
  412. package/fjs/types/rtti/data/proof.f.d.mts +76 -0
  413. package/fjs/types/rtti/data/proof.f.mjs +589 -0
  414. package/fjs/types/rtti/data/types.d.ts +83 -0
  415. package/fjs/types/rtti/module.f.d.mts +12 -5
  416. package/fjs/types/rtti/module.f.mjs +7 -5
  417. package/fjs/types/rtti/parse/module.f.d.mts +48 -0
  418. package/fjs/types/rtti/parse/module.f.mjs +45 -34
  419. package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
  420. package/fjs/types/rtti/parse/proof.f.mjs +51 -52
  421. package/fjs/types/rtti/proof.f.d.mts +3 -1
  422. package/fjs/types/rtti/proof.f.mjs +6 -2
  423. package/fjs/types/rtti/ts/module.f.d.mts +68 -9
  424. package/fjs/types/rtti/ts/module.f.mjs +258 -30
  425. package/fjs/types/rtti/ts/proof.f.d.mts +44 -0
  426. package/fjs/types/rtti/ts/proof.f.mjs +152 -4
  427. package/fjs/types/rtti/ts/types.d.ts +25 -1
  428. package/fjs/types/rtti/types.d.ts +40 -0
  429. package/fjs/types/sorted_list/module.f.d.mts +4 -1
  430. package/fjs/types/sorted_list/module.f.mjs +21 -12
  431. package/fjs/types/sorted_list/proof.f.d.mts +3 -1
  432. package/fjs/types/sorted_list/proof.f.mjs +3 -1
  433. package/fjs/types/sorted_set/module.f.d.mts +49 -1
  434. package/fjs/types/sorted_set/module.f.mjs +26 -2
  435. package/fjs/types/sorted_set/proof.f.d.mts +4 -1
  436. package/fjs/types/sorted_set/proof.f.mjs +19 -2
  437. package/fjs/types/string/module.f.d.mts +4 -0
  438. package/fjs/types/string/module.f.mjs +4 -3
  439. package/fjs/types/string_set/module.f.d.mts +3 -1
  440. package/fjs/types/string_set/module.f.mjs +3 -2
  441. package/fjs/types/ts/module.f.d.mts +2 -0
  442. package/fjs/types/ts/module.f.mjs +3 -3
  443. package/fjs/types/ts/proof.f.d.mts +1 -0
  444. package/fjs/types/ts/proof.f.mjs +5 -0
  445. package/fjs/types/ts/types.d.ts +6 -1
  446. package/fjs/types/uint8array/module.f.d.mts +13 -2
  447. package/fjs/types/uint8array/module.f.mjs +20 -15
  448. package/fjs/website/module.f.d.mts +5 -2
  449. package/fjs/website/module.f.mjs +6 -8
  450. package/fjs/website/proof.f.mjs +2 -1
  451. package/package.json +3 -3
  452. package/fjs/asn.1/types.js +0 -6
  453. package/fjs/asserts/types.js +0 -6
  454. package/fjs/basen/types.js +0 -6
  455. package/fjs/bnf/data/types.js +0 -6
  456. package/fjs/bnf/descent/types.js +0 -6
  457. package/fjs/bnf/ll1/types.js +0 -6
  458. package/fjs/bnf/token_symbol/types.js +0 -6
  459. package/fjs/bnf/types.js +0 -6
  460. package/fjs/cas/evo/types.js +0 -7
  461. package/fjs/cas/types.js +0 -6
  462. package/fjs/ci/common/types.js +0 -1
  463. package/fjs/ci/nix/types.js +0 -6
  464. package/fjs/ci/types.js +0 -6
  465. package/fjs/cli/types.js +0 -6
  466. package/fjs/common/monoid/types.js +0 -6
  467. package/fjs/crypto/pow/types.js +0 -6
  468. package/fjs/crypto/secp/types.js +0 -6
  469. package/fjs/crypto/sha2/types.js +0 -6
  470. package/fjs/crypto/sign/types.js +0 -6
  471. package/fjs/crypto/vdf/types.js +0 -6
  472. package/fjs/dev/package_json/module.f.d.mts +0 -32
  473. package/fjs/dev/package_json/module.f.mjs +0 -37
  474. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  475. package/fjs/dev/package_json/proof.f.mjs +0 -32
  476. package/fjs/dev/types.js +0 -6
  477. package/fjs/djs/ast/types.js +0 -8
  478. package/fjs/djs/parser/types.js +0 -7
  479. package/fjs/djs/tokenizer/types.js +0 -7
  480. package/fjs/djs/types.js +0 -7
  481. package/fjs/effects/eff/module.f.d.mts +0 -10
  482. package/fjs/effects/eff/module.f.mjs +0 -68
  483. package/fjs/effects/eff/proof.f.d.mts +0 -12
  484. package/fjs/effects/eff/proof.f.mjs +0 -66
  485. package/fjs/effects/eff/types.d.ts +0 -71
  486. package/fjs/effects/eff/types.js +0 -6
  487. package/fjs/effects/list/types.js +0 -6
  488. package/fjs/effects/memory/types.js +0 -6
  489. package/fjs/effects/mock/types.js +0 -6
  490. package/fjs/effects/node/types.js +0 -6
  491. package/fjs/effects/node/virtual/types.js +0 -7
  492. package/fjs/effects/types.js +0 -6
  493. package/fjs/emergent_testing/all.test.d.ts +0 -1
  494. package/fjs/emergent_testing/all.test.js +0 -5
  495. package/fjs/emergent_testing/scenarios/all.d.ts +0 -1
  496. package/fjs/emergent_testing/scenarios/all.js +0 -1
  497. package/fjs/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -6
  498. package/fjs/emergent_testing/scenarios/async-subtests.fail.js +0 -9
  499. package/fjs/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -6
  500. package/fjs/emergent_testing/scenarios/async-subtests.pass.js +0 -9
  501. package/fjs/emergent_testing/scenarios/async.fail.d.ts +0 -3
  502. package/fjs/emergent_testing/scenarios/async.fail.js +0 -6
  503. package/fjs/emergent_testing/scenarios/async.pass.d.ts +0 -3
  504. package/fjs/emergent_testing/scenarios/async.pass.js +0 -5
  505. package/fjs/emergent_testing/scenarios/fail.fail.d.ts +0 -3
  506. package/fjs/emergent_testing/scenarios/fail.fail.js +0 -3
  507. package/fjs/emergent_testing/scenarios/return-value.pass.js +0 -4
  508. package/fjs/emergent_testing/scenarios/thenable.pass.d.ts +0 -5
  509. package/fjs/emergent_testing/scenarios/thenable.pass.js +0 -11
  510. package/fjs/emergent_testing/scenarios/thenable2.pass.d.ts +0 -5
  511. package/fjs/emergent_testing/scenarios/thenable2.pass.js +0 -3
  512. package/fjs/emergent_testing/scenarios/throw.pass.d.ts +0 -5
  513. package/fjs/emergent_testing/scenarios/throw.pass.js +0 -3
  514. package/fjs/emergent_testing/types.js +0 -6
  515. package/fjs/js/tokenizer/types.js +0 -6
  516. package/fjs/media/html/types.js +0 -6
  517. package/fjs/media/json/parser/types.js +0 -6
  518. package/fjs/media/json/tokenizer/types.js +0 -6
  519. package/fjs/media/json/types.js +0 -13
  520. package/fjs/media/nix/types.js +0 -6
  521. package/fjs/media/revision/types.js +0 -8
  522. package/fjs/media/type/types.js +0 -6
  523. package/fjs/media/types.js +0 -7
  524. package/fjs/nanvm/types.js +0 -11
  525. package/fjs/protocol/json_rpc/types.js +0 -8
  526. package/fjs/protocol/mcp/types.js +0 -8
  527. package/fjs/sul/id/types.js +0 -6
  528. package/fjs/sul/level/hash/types.js +0 -6
  529. package/fjs/sul/level/literal/types.js +0 -6
  530. package/fjs/sul/types.js +0 -6
  531. package/fjs/text/sgr/types.js +0 -6
  532. package/fjs/text/types.js +0 -6
  533. package/fjs/text/utf16/types.js +0 -6
  534. package/fjs/text/utf8/types.js +0 -6
  535. package/fjs/types/array/types.js +0 -6
  536. package/fjs/types/bigfloat/types.js +0 -6
  537. package/fjs/types/bigint/types.js +0 -6
  538. package/fjs/types/bit_vec/types.js +0 -6
  539. package/fjs/types/btree/find/types.js +0 -6
  540. package/fjs/types/btree/types/types.js +0 -6
  541. package/fjs/types/byte_set/types.js +0 -6
  542. package/fjs/types/function/compare/types.js +0 -6
  543. package/fjs/types/function/operator/types.js +0 -6
  544. package/fjs/types/function/types.js +0 -6
  545. package/fjs/types/list/types.js +0 -6
  546. package/fjs/types/nibble_set/types.js +0 -6
  547. package/fjs/types/nominal/types.js +0 -6
  548. package/fjs/types/nullable/types.js +0 -6
  549. package/fjs/types/object/types.js +0 -8
  550. package/fjs/types/option/types.js +0 -6
  551. package/fjs/types/ordered_map/types.js +0 -6
  552. package/fjs/types/patricia_trie/types.js +0 -6
  553. package/fjs/types/phantom/types.js +0 -11
  554. package/fjs/types/prime_field/types.js +0 -6
  555. package/fjs/types/range/types.js +0 -6
  556. package/fjs/types/range_map/types.js +0 -6
  557. package/fjs/types/result/types.js +0 -6
  558. package/fjs/types/rtti/common/types.js +0 -1
  559. package/fjs/types/rtti/parse/types.js +0 -1
  560. package/fjs/types/rtti/ts/types.js +0 -1
  561. package/fjs/types/rtti/types.js +0 -1
  562. package/fjs/types/rtti/validate/module.f.d.mts +0 -6
  563. package/fjs/types/rtti/validate/module.f.mjs +0 -169
  564. package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
  565. package/fjs/types/rtti/validate/proof.f.mjs +0 -437
  566. package/fjs/types/rtti/validate/types.d.ts +0 -6
  567. package/fjs/types/rtti/validate/types.js +0 -1
  568. package/fjs/types/sorted_list/types.js +0 -6
  569. package/fjs/types/sorted_set/types.js +0 -6
  570. package/fjs/types/string_set/types.js +0 -6
  571. package/fjs/types/ts/types.js +0 -8
@@ -1,23 +1,69 @@
1
1
  /**
2
- * Core effect type constructors and combinators.
3
- *
4
- * An `Effect<O, T>` **is** the raw value — a `Pure` thunk (`() => T`) or a `Do`
5
- * node (`{ command, payload, continuation }`). It is plain data with no methods.
6
- * Composition is provided externally by {@link step}. The optional
7
- * method-chaining wrapper lives in `fjs/effects/eff/module.f.mjs`.
8
- *
9
- * **Three functions discriminate `Pure` from `Do`** — {@link step},
10
- * {@link match}, and {@link runPure} — plus the node proof in
11
- * `fjs/effects/proof.f.mjs` that pins the representation on purpose. Everything
12
- * else, interpreters included, goes through `match` or `runPure`. The count is
13
- * the point: a `typeof e === 'function'` check appearing in a fifth place is a
14
- * review flag, because the representation is only cheap to change while its
15
- * readers stay enumerable.
16
- *
17
- * A `decode` function (`(e: Effect<O, T>) => Decoded<O, T>`) once funnelled all
18
- * of that through a single `{ done, result }` / `{ done, command, payload,
2
+ * The effect system: the representation, its interpreters, and the combinators
3
+ * that compose it.
4
+ *
5
+ * An `Effect<O, T, E>` **is** the raw value a `Pure` thunk
6
+ * (`() => Result<T, E>`) or a `Do` node (`{ command, payload, continuation }`).
7
+ * It is plain data with no methods; see [`./types.ts`](./types.ts) for the
8
+ * type-level API and [`./README.md`](./README.md) for why the error channel is
9
+ * part of it.
10
+ *
11
+ * **The three branch-aware operations are the whole composition vocabulary:**
12
+ *
13
+ * - {@link step} continue on `ok`, propagate the `error`. The normal path.
14
+ * - {@link catchStep} continue on `error`, preserve the `ok`. The error path.
15
+ * - {@link resultStep} — continue with the complete `Result`. Both paths.
16
+ *
17
+ * Around them: {@link pure} and the two lifts {@link pureOk} / {@link pureError}
18
+ * that enter the layer, the projections {@link mapStep} and
19
+ * {@link resultMapStep} that end a chain, {@link history} /
20
+ * {@link historyStep} for a chain whose later links read earlier values, and
21
+ * {@link foldStep} / {@link forEachStep} for iteration. The operation
22
+ * constructor is {@link do_}, and the eliminators are {@link match},
23
+ * {@link partialMatch} and {@link runPure}.
24
+ *
25
+ * **The error channel is unioned, not unified**, following `okThen`
26
+ * (`fjs/types/result/module.f.mjs`), the pure sibling of this bind: neither
27
+ * side is pre-widened, and a branch that is passed through stays the very tuple
28
+ * it arrived as rather than being rebuilt to retag it into a wider type.
29
+ * {@link step} unions the error channel and replaces the success type;
30
+ * {@link catchStep} mirrors it, unioning the success channel and replacing the
31
+ * error type.
32
+ *
33
+ * Recovery therefore never needs `try`/`catch` — which FunctionalScript does
34
+ * not offer, and whose `throw` stays reserved for panics. Escalating an error
35
+ * to a panic is a decision the program makes explicitly, by `unwrap`ping what
36
+ * {@link resultStep} hands it.
37
+ *
38
+ * **This was two modules, and briefly two of each combinator.** A `./io/`
39
+ * directory held the branch-aware set while this file held a `Result`-blind
40
+ * `step`, `mapStep`, `history`, `historyStep`, `foldStep` and `forEachStep`
41
+ * beside the representation. Those were traps rather than a layer: an operation
42
+ * must return a `Result`, so every effect carries one, and a `step` that ran
43
+ * its continuation whether or not the previous effect failed described no case
44
+ * worth having. They are gone — {@link resultStep} *is* that former general
45
+ * `step`, at the type that says what its continuation receives — and with the
46
+ * name collision went the only reason for two modules. The directory was called
47
+ * `io` because it was the fallible layer over a raw one; nothing in it was ever
48
+ * specific to IO.
49
+ *
50
+ * **Three functions discriminate `Pure` from `Do`** — {@link resultStep},
51
+ * {@link _matchWith} and {@link runPure} — plus the node proof in
52
+ * `./proof.f.mjs` that pins the representation on purpose. Everything else,
53
+ * interpreters included, goes through `match`, {@link partialMatch}, or
54
+ * `runPure`. The count is the point: a `typeof e === 'function'` check
55
+ * appearing in a fourth place is a review flag, because the representation is
56
+ * only cheap to change while its readers stay enumerable. It used to be a
57
+ * cross-module claim, with one of the three on the far side of the boundary.
58
+ *
59
+ * `match` and `partialMatch` are two entry points, not two discriminators:
60
+ * they differ only in what a missing handler means and share `_matchWith` for
61
+ * the shape test, so adding the partial variant left the count where it was.
62
+ *
63
+ * A `decode` function (`(e: Effect<O, T, E>) => Decoded<O, T, E>`) once funnelled
64
+ * all of that through a single `{ done, result }` / `{ done, command, payload,
19
65
  * continuation }` record, so that exactly one function held the shape test. It
20
- * has been removed. `Effect` is a function type unioned with an object type, so
66
+ * has been removed. An effect is a function type unioned with an object type, so
21
67
  * `typeof e === 'function'` is already a complete discriminant: `decode` bought
22
68
  * no narrowing, it re-encoded that narrowing as a `done` flag to be re-narrowed
23
69
  * one indirection later, and its `Decoded` record was declared in terms of the
@@ -26,357 +72,550 @@
26
72
  * the same nothing — and with {@link Do} now carrying named fields there is not
27
73
  * even a positional layout left for it to insulate anyone from.
28
74
  *
29
- * Effect helpers come in two shapes. **Step adapters** return a continuation
30
- * `(t: T) => Effect<Q, R>` meant to be passed into a step see {@link okStep}.
31
- * **Step variants** take the effect itself first, like {@link step} — see
32
- * {@link historyStep}. {@link mapStep} is the variant for the end of a chain:
33
- * a pure projection over an effect's result, which is a `step` that continues
34
- * with no further effect.
75
+ * **The composition rules:** bind each link in a sequence to its own name at one
76
+ * level, do not nest steps, and break a call that does not fit one line after
77
+ * `(` with one argument per line.
35
78
  *
36
- * **Do not nest steps.** Bind each intermediate effect to its own name, so a
37
- * sequence reads top-to-bottom in evaluation order:
79
+ * @module
38
80
  *
39
- * ```js
40
- * // avoid reads inside-out, and gains a level of indentation per link
41
- * step(a, x => step(f(x), y => step(g(y), z => h(z))))
81
+ * @import { List } from '../types/list/types.ts'
82
+ * @import { Fold } from '../types/function/operator/types.ts'
83
+ * @import { Option } from '../types/option/types.ts'
84
+ * @import { Result } from '../types/result/types.ts'
85
+ * @import { Commands, Effect, ErrOf, Func, MatchResult, NotImplemented, OkOf, Operation, OperationMap, PartialOperationMap } from './types.ts'
86
+ */
87
+
88
+ import { assert } from '../asserts/module.f.mjs'
89
+ import { fold } from '../types/list/module.f.mjs'
90
+ import { error, mapOk, ok } from '../types/result/module.f.mjs'
91
+ import { at } from '../types/object/module.f.mjs'
92
+
93
+ /**
94
+ * Lifts an already-computed {@link Result} into an effect that performs no
95
+ * command.
96
+ *
97
+ * It takes the `Result` rather than a bare value because that is what a `Pure`
98
+ * holds: the two channels are the representation's, so a constructor that took
99
+ * only a success would be `pureOk`, which is exactly what
100
+ * [`./module.f.mjs`](./module.f.mjs) exports alongside `pureError`. Reach
101
+ * for those; this one is for the `Result` you already have in your hand — a
102
+ * branch passing an incoming error through unchanged, or a runner's answer.
103
+ *
104
+ * **Both channels are read off the argument**, via {@link OkOf} / {@link ErrOf}
105
+ * rather than by matching `Result<T, E>` directly. Inference against the union
106
+ * cannot tell which half a one-sided argument belongs to — `pure(ok(v))` would
107
+ * infer the error channel as `T` as readily as `never` — so the halves are
108
+ * projected out of the concrete type instead. That is what makes `pureOk` land
109
+ * on `Effect<never, T, never>` and `pureError` on `Effect<never, never, E>`.
110
+ *
111
+ * @type {<R extends Result<unknown, unknown>>(r: R) => Effect<never, OkOf<R>, ErrOf<R>>}
112
+ */
113
+ export const pure = r =>
114
+ // The thunk *is* the effect. TypeScript cannot see that `R` and
115
+ // `Result<OkOf<R>, ErrOf<R>>` are the same type for a generic `R`, so the
116
+ // one place the representation is constructed says so by hand.
117
+ /** @type {any} */ (() => r)
118
+
119
+ /**
120
+ * @type {<O extends Operation>(command: O[0]) => Func<O>}
121
+ */
122
+ export const do_ = command => (...payload) => ({ command, payload, continuation: pure })
123
+
124
+ /**
125
+ * Runs an effect that reaches its result without performing a command: `[r]`
126
+ * for a {@link Pure}, empty for a {@link Do}. Forces the thunk in the `Pure`
127
+ * case, which {@link Pure}'s contract makes free of consequence.
42
128
  *
43
- * // prefer flat, one name per link
44
- * const x0 = step(a, f)
45
- * const x1 = step(x0, g)
46
- * return step(x1, h)
47
- * ```
129
+ * The eliminator for callers that expect no operations at all — the other side
130
+ * of {@link match}, which is for callers that intend to perform them.
48
131
  *
49
- * **A step call that does not fit one line breaks after `(`, one argument per
50
- * line.** This holds for every step variant {@link step}, {@link mapStep},
51
- * {@link historyStep}, {@link foldStep}, {@link forEachStep} and it is the
52
- * same rule as taking the effect first, written out at the call site. A step
53
- * variant is this module's
54
- * `do` notation: the arguments are a statement list in execution order, so each
55
- * one gets a line and the sequence reads down the page. Packing the leading
56
- * effect onto the `(` line and wrapping the rest beneath it hides which of them
57
- * runs first. The closing `)` may sit on its own line or trail the last
58
- * argument:
132
+ * **The result is tagged on purpose**, and the tag is not the `Result`'s. An
133
+ * `Option` distinguishes "reached a value" from "stopped at a command";
134
+ * the `Result` inside it distinguishes success from failure. Collapsing them
135
+ * would lose the case this exists to rule out an effect that unexpectedly
136
+ * stopped at a `Do` node — so `[r]` is a pure result and `[]` is a `Do`.
59
137
  *
60
- * ```js
61
- * return step(
62
- * collectRead(cas.read(hash)),
63
- * ([tag, value]) => pure(tag === 'error' ? null : decodeRevisionVec(value)))
64
- * ```
138
+ * `O` stays generic rather than narrowing to `Effect<never, T, E>`. An effect is
139
+ * covariant in `O`, so `Effect<never, T, E>` is assignable to `Effect<O, T, E>`
140
+ * and not the reverse — a continuation's result is always the wider type and
141
+ * would be rejected. `Do<never, T, E>` is uninhabited besides, which would make
142
+ * the empty case unreachable without a cast.
65
143
  *
66
- * When a later link needs a value from an earlier one, that is not a reason to
67
- * nest: a nested continuation only reaches back because it closes over the
68
- * enclosing scope. {@link historyStep} carries the value forward instead, so
69
- * the chain stays flat:
144
+ * @type {<O extends Operation, T, E>(e: Effect<O, T, E>) => Option<Result<T, E>>}
145
+ */
146
+ export const runPure = e =>
147
+ typeof e === 'function' ? [e()] : []
148
+
149
+ /**
150
+ * Decodes an effect's next step and dispatches its command to `map`,
151
+ * returning either the final result or the operation's output `R` paired
152
+ * with the continuation. The one world-specific step — `await` for async
153
+ * runners, state threading for sync ones — is left to the caller, so every
154
+ * interpreter loop is this skeleton plus a single eliminator line.
70
155
  *
71
- * ```js
72
- * // avoid nested only so `h` can still see `x`
73
- * step(a, x => step(f(x), y => h(x, y)))
156
+ * **An interpreter sees the whole `Result` and must not short-circuit on it.**
157
+ * A runner answers a failed command through the *ordinary* continuation — that
158
+ * is what makes `error(notImplemented)` recoverable so the `done` payload
159
+ * here is `Result<T, E>` rather than the `ok` half. Separating the channels is
160
+ * the composition layer's job, one level up.
74
161
  *
75
- * // prefer the history tuple carries `x` forward alongside `y`
76
- * const x0 = historyStep(history(a), f)
77
- * return step(x0, ([y, x]) => h(x, y))
78
- * ```
162
+ * **The handler is looked up with `at`, never with `map[command]`.**
163
+ * `OperationMap<O, R>` pins `command` to `O[0]` at the type level, but a `Do`
164
+ * node's `command` is runtime data it can reach an interpreter from a decoded
165
+ * payload or a deserialized continuation, where no type ever constrained it.
166
+ * `map` is an ordinary object, so a plain index read resolves an inherited name
167
+ * (`'constructor'`, `'toString'`, `'hasOwnProperty'`) to the `Object.prototype`
168
+ * member instead of `undefined`, and the line below would then call it with the
169
+ * node's payload: a value the type system promised was `(...payload) => R` turns
170
+ * out to be an arbitrary inherited function, chosen by the same input that
171
+ * supplies its arguments. `at` reads through `getOwnPropertyDescriptor`, which
172
+ * only ever sees own properties, so such a command yields `null` and never a
173
+ * callable.
79
174
  *
80
- * Nesting is often forced by nothing more than a local declared inside a
81
- * continuation that does not depend on it. Hoist such locals above the chain
82
- * and the nesting usually dissolves on its own.
175
+ * **A `null` handler means one of two different things**, and this is the only
176
+ * place that can still tell them apart. With a total {@link OperationMap} every
177
+ * `O1 extends O` the signature admits has its command in `map`, so a miss means
178
+ * the node's `command` was never the `O1[0]` it claimed to be — a malformed
179
+ * node, and a panic. With a {@link PartialOperationMap} a miss may instead be an
180
+ * operation the runner deliberately does not implement, which is an *outcome*: a
181
+ * program receives `error(notImplemented)` through the ordinary continuation and
182
+ * decides for itself whether to recover, fall back, or panic. {@link partialMatch}
183
+ * is the variant that distinguishes the two; this one keeps the strict reading,
184
+ * because a total map has no second case to distinguish.
83
185
  *
84
- * That advice is for code *using* this module, and the combinators defined
85
- * here are what make it followable. The nesting has to exist somewhere: a name
86
- * cannot be bound to an effect that has not been produced yet, so `f(param)`
87
- * cannot become a `const` until `e` resolves. {@link step} recurses into
88
- * itself inside the continuation it rebuilds, {@link foldStep} composes one
89
- * step per item, and {@link historyStep} runs `f` inside `e`'s continuation.
90
- * Each writes that nesting down **once**, in one line, so that no caller ever
91
- * writes it again — that is what a combinator here is *for*. Without
92
- * {@link historyStep} the flat form would be unavailable the moment a later
93
- * link needed an earlier link's value.
186
+ * The two share {@link _matchWith}, so `typeof e === 'function'` still appears
187
+ * in exactly the three places the module header names.
94
188
  *
95
- * See `./types.ts` for the type-level API.
189
+ * @template {Operation} O
190
+ * @template R
191
+ * @param {OperationMap<O, R>} map
192
+ */
193
+ export const match = map =>
194
+ _matchWith(/** @type {(command: O[0]) => R} */ (command => {
195
+ assert(false, command)
196
+ }))(map)
197
+
198
+ /**
199
+ * {@link match} for a runner that is *meant* to lack operations.
200
+ *
201
+ * A command in `commands` with no handler in `map` is a capability this runner
202
+ * does not have: `onMissing` builds the answer and the program resumes with it,
203
+ * which is what lets `O` mean "the operations a computation may request" rather
204
+ * than "the operations every runner implements". A command outside `commands`
205
+ * is still a malformed node and still panics — an omitted handler and a garbled
206
+ * `command` are not the same failure, and collapsing them would turn a probable
207
+ * bug into a routine outcome.
208
+ *
209
+ * **`onMissing` is supplied by the caller because only the caller can build an
210
+ * `R`.** `R` is the *runner's* wrapper — `Promise<…>` for an async loop,
211
+ * `(state) => [state, …]` for a state-threading one — not the operation's
212
+ * return type, so this function has no way to construct one. Each runner writes
213
+ * the injector once, next to the loop that defines the shape.
96
214
  *
97
- * @module
215
+ * @template {Operation} O
216
+ * @template R
217
+ * @param {Commands<O>} commands
218
+ * @param {(command: O[0]) => R} onMissing
98
219
  */
220
+ export const partialMatch = (commands, onMissing) =>
221
+ _matchWith((/** @type {O[0]} */ command) => {
222
+ assert(commands.includes(command), command)
223
+ return onMissing(command)
224
+ })
99
225
 
100
- import { assert } from '../asserts/module.f.mjs'
101
- /** @import { List } from '../types/list/types.ts' */
102
- import { fold } from '../types/list/module.f.mjs'
103
- import { at } from '../types/object/module.f.mjs'
104
- /** @import { Option } from '../types/option/types.ts' */
105
- /** @import { Result } from '../types/result/types.ts' */
106
- /** @import { Fold } from '../types/function/operator/types.ts' */
107
- /** @import { Cont, Do, Effect, F, History, MatchResult, Operation, OperationMap, Param, Pr, Pure, Return, ToAsyncOperationMap } from './types.ts' */
226
+ /**
227
+ * The shared body of {@link match} and {@link partialMatch}: decode the node,
228
+ * look the handler up by own property, and hand a miss to `onMissing`.
229
+ *
230
+ * @template {Operation} O
231
+ * @template R
232
+ * @param {(command: O[0]) => R} onMissing
233
+ */
234
+ const _matchWith = onMissing =>
235
+ /** @param {PartialOperationMap<O, R>} map */
236
+ map =>
237
+ /**
238
+ * @template {O} O1
239
+ * @template T
240
+ * @template E
241
+ * @param {Effect<O1, T, E>} e
242
+ * @returns {MatchResult<O1, T, E, R>}
243
+ */
244
+ e => {
245
+ if (typeof e === 'function') { return ['done', e()] }
246
+ const { command, payload, continuation } = e
247
+ const handler = at(command)(map)
248
+ return [
249
+ 'cont',
250
+ handler === null ? onMissing(command) : handler(...payload),
251
+ continuation,
252
+ ]
253
+ }
108
254
 
109
- /** @type {<T>(v: T) => Effect<never, T>} */
110
- export const pure = v => () => v
255
+ /**
256
+ * Lifts a value into a successful `Effect` — `pure(ok(v))` written once.
257
+ *
258
+ * One of the two entry points into the layer: {@link step} and its siblings
259
+ * compose `Effect`s but cannot produce the first one, and the only other source
260
+ * is an operation's own `Result`.
261
+ *
262
+ * The error channel is `never`, which is not a special case to handle but the
263
+ * ordinary consequence of the union rules: `never | E` is `E`, so a lifted
264
+ * value composes with any chain without widening its errors.
265
+ *
266
+ * @type {<T>(v: T) => Effect<never, T, never>}
267
+ */
268
+ export const pureOk = v => pure(ok(v))
269
+
270
+ /**
271
+ * Lifts an error into a failed `Effect` — `pure(error(e))` written once, and
272
+ * the mirror of {@link pureOk}, with the success channel `never` instead.
273
+ *
274
+ * This is how a program *originates* a failure: a fallback that has run out of
275
+ * options, or a guard that rejects its input before performing anything. A
276
+ * runner producing `error(notImplemented)` does not go through here — that
277
+ * error arrives through an operation's own continuation.
278
+ *
279
+ * @type {<E>(e: E) => Effect<never, never, E>}
280
+ */
281
+ export const pureError = e => pure(error(e))
282
+
283
+ /**
284
+ * Builds the {@link NotImplemented} a runner answers with when it cannot
285
+ * dispatch `command`.
286
+ *
287
+ * It names the command and nothing else. A `Do` node's payload may hold
288
+ * functions — `createServer`'s listener, `sandbox`'s thunk, `test`'s body — so
289
+ * carrying it would break the serializability this error type promises, and the
290
+ * command name is the part a program can act on anyway.
291
+ *
292
+ * @type {(command: string) => NotImplemented}
293
+ */
294
+ export const notImplemented = command => ['notImplemented', command]
295
+
296
+ /**
297
+ * The normal path: run `e`, and continue with `f` **only** if it succeeded. An
298
+ * `error` short-circuits the rest of the chain and is passed through unchanged.
299
+ *
300
+ * This is the default error propagation the migration exists to provide — the
301
+ * structured replacement for exception-style propagation, analogous to Rust's
302
+ * `?`. A sequence therefore reads as its success path, and mentions errors only
303
+ * where it intentionally handles them:
304
+ *
305
+ * ```js
306
+ * const a = writeFile(...)
307
+ * const b = step(a, () => console('written'))
308
+ * ```
309
+ *
310
+ * `'written'` is printed only when `writeFile` returned `ok`. Written with the
311
+ * `Result`-blind `step` this replaced, the same line printed it either way —
312
+ * and note that it was the *value-discarding* continuation that hid the
313
+ * hazard, since one that read the value would not have compiled.
314
+ *
315
+ * **The error types are unioned** (`E | F`), so `f` may fail in its own way
316
+ * without either side being pre-widened; the operation sets union too, since
317
+ * `f` performs effects of its own.
318
+ *
319
+ * The body is {@link resultStep} over the one branch this layer is named for:
320
+ * an `error` is handed back as the very tuple it arrived as rather than rebuilt
321
+ * to retag it into a wider type, which is what makes `E | F` expressible instead
322
+ * of forcing both sides to one error type. The continuation is annotated for
323
+ * that reason — its two branches have different types, and the annotation
324
+ * states the union they belong to rather than leaving the compiler to infer it
325
+ * from whichever it reads first.
326
+ *
327
+ * This used to route through an `okStep` exported by the representation
328
+ * module. Nothing
329
+ * else ever called it: the adapter *was* this function's body, one indirection
330
+ * away, so it is written here now and that module has one export fewer.
331
+ *
332
+ * @template {Operation} O
333
+ * @template T
334
+ * @template E
335
+ * @template {Operation} Q
336
+ * @template R
337
+ * @template F
338
+ * @param {Effect<O, T, E>} e
339
+ * @param {(t: T) => Effect<Q, R, F>} f
340
+ * @returns {Effect<O | Q, R, E | F>}
341
+ */
342
+ export const step = (e, f) => {
343
+ /** @type {(r: Result<T, E>) => Effect<Q, R, E | F>} */
344
+ const cont = r => r[0] === 'error' ? pure(r) : f(r[1])
345
+ return resultStep(e, cont)
346
+ }
111
347
 
112
348
  /**
113
- * Composes effects: run `e`, then continue with `f` applied to its result.
114
- * The data-first primitive raw `Effect` in, raw `Effect` out. Chains as
115
- * `step(step(e, f), g)`.
349
+ * The error path: run `e`, and continue with `f` **only** if it failed. An `ok`
350
+ * is preserved unchanged, so the recovery is the only branch that mentions the
351
+ * failure.
352
+ *
353
+ * The exact mirror of {@link step}: where that unions the error channel and
354
+ * replaces the success type, this unions the success channel (`T | R` — the
355
+ * preserved value or the recovery's) and replaces the error type with `f`'s.
356
+ * Recovering from every error therefore leaves `F` uninhabited, and the type
357
+ * says so.
358
+ *
359
+ * Use it for *intentional* recovery — a fallback operation after a
360
+ * `NotImplemented`, a default for a missing file — never as a blanket
361
+ * "continue anyway"; that is what {@link step}'s propagation already prevents.
116
362
  *
117
- * **`step` is not lazy.** It reads `e`'s shape immediately, so a `Pure` head is
118
- * forced and `f` is called right there: `step(pure(v), f)` *is* `f(v)`,
363
+ * The local continuation is annotated for the same reason {@link step}'s is:
364
+ * its two branches have different types `f`'s effect and the untouched `ok`
365
+ * tuple — and the annotation states the union they belong to instead of
366
+ * leaving the compiler to infer it from whichever branch it reads first.
367
+ *
368
+ * @template {Operation} O
369
+ * @template T
370
+ * @template E
371
+ * @template {Operation} Q
372
+ * @template R
373
+ * @template F
374
+ * @param {Effect<O, T, E>} e
375
+ * @param {(err: E) => Effect<Q, R, F>} f
376
+ * @returns {Effect<O | Q, T | R, F>}
377
+ */
378
+ export const catchStep = (e, f) => {
379
+ /** @type {(r: Result<T, E>) => Effect<Q, T | R, F>} */
380
+ const cont = r => r[0] === 'error' ? f(r[1]) : pure(r)
381
+ return resultStep(e, cont)
382
+ }
383
+
384
+ /**
385
+ * Both paths: run `e` and hand `f` the complete `Result`, which then decides
386
+ * what the outcome is. Use it where both branches genuinely matter — a report
387
+ * that records the failure, a retry policy, or the point where a program
388
+ * escalates an error to a panic by `unwrap`ping it.
389
+ *
390
+ * **This is the layer's primitive**, and {@link step} and {@link catchStep} are
391
+ * written in terms of it — each is this function with a continuation that
392
+ * inspects the tag first. It used to be the other way round: a `step` in the
393
+ * representation module composed effects with opaque payloads, and this was
394
+ * that function re-exported under a narrower type. Since every effect carries a
395
+ * `Result`, the opaque spelling described nothing the `Result`-shaped one does
396
+ * not, so the general function lives here now, at the type that says what its
397
+ * continuation receives.
398
+ *
399
+ * `finallyStep` is declined on the principle that a derivable form earns a name
400
+ * by being canonical vocabulary, and that one has not shown it is. It is
401
+ * `resultStep` plus a policy, and adds no expressive power until real consumers
402
+ * demonstrate a repeated policy worth naming.
403
+ *
404
+ * **It is not lazy.** It reads `e`'s shape immediately, so a `Pure` head is
405
+ * forced and `f` is called right there: `resultStep(pure(r), f)` *is* `f(r)`,
119
406
  * evaluated where the composition is written rather than where the effect is
120
407
  * run. Only the `Do` case defers — the continuation rebuilt around `f` runs
121
408
  * when a runner reaches that node.
122
409
  *
123
410
  * That is sound rather than an oversight, and it is sound only because of
124
- * {@link Pure}'s contract: a `Pure` holds a value that has already been
125
- * computed, so forcing it early observes nothing, repeats nothing, and can
126
- * throw nothing. `step` never performs a `Do` node, which is where anything
127
- * real lives. Break the contract — hide work behind the thunk — and merely
128
- * composing a chain starts running the program.
411
+ * `Pure`'s contract: a `Pure` holds a result that has already been computed, so
412
+ * forcing it early observes nothing, repeats nothing, and can throw nothing.
413
+ * Composing never performs a `Do` node, which is where anything real lives.
414
+ * Break the contract — hide work behind the thunk — and merely composing a
415
+ * chain starts running the program.
129
416
  *
130
417
  * A composition cannot be suspended, and no combinator can fix that:
131
- * `defer: (() => Effect<O, T>) => Effect<O, T>` cannot be written here, because
418
+ * `defer: (() => Effect<O, T, E>) => Effect<O, T, E>` cannot be written, because
132
419
  * the `Pure` / `Do` tag must be known before anything runs and the union has no
133
420
  * third case meaning "not yet decided". That is inherent to the representation,
134
421
  * not a gap in this module's API. A caller that needs to name a composition
135
- * without performing it yet has to keep the ingredients and defer the `step`
136
- * itself — `Eff` does exactly this, holding its history tuple as a thunk (`h`)
137
- * precisely because composing it eagerly is the one thing it cannot take back.
422
+ * without performing it yet has to keep the ingredients and defer the step
423
+ * itself.
138
424
  *
139
- * @type {<O extends Operation, T, Q extends Operation, R>(e: Effect<O, T>, f: (t: T) => Effect<Q, R>) => Effect<O | Q, R>}
425
+ * @type {<O extends Operation, T, E, Q extends Operation, R, F>(
426
+ * e: Effect<O, T, E>,
427
+ * f: (r: Result<T, E>) => Effect<Q, R, F>
428
+ * ) => Effect<O | Q, R, F>}
140
429
  */
141
- export const step = (e, f) =>
430
+ export const resultStep = (e, f) =>
142
431
  typeof e === 'function'
143
432
  ? f(e())
144
- : { ...e, continuation: x => step(e.continuation(x), f) }
433
+ : { ...e, continuation: x => resultStep(e.continuation(x), f) }
145
434
 
146
435
  /**
147
- * Applies a pure function to an effect's result: the functor `map` of the
148
- * effect monad, and a {@link step} whose continuation performs nothing further.
149
- *
150
- * Prefer it over the `step(e, t => pure(f(t)))` it abbreviates. The two are the
151
- * same value, but they read as different things: a `step` announces another
152
- * link in a sequence of effects, and a trailing pure projection is not one —
153
- * it is where the sequence ends. Saying so in the combinator's name keeps the
154
- * "one name per link" shape of a chain honest about how many effects it runs.
155
- *
156
- * **The operation set does not widen.** The result is `Effect<O, R>`, not
157
- * `Effect<O | Q, R>`, because a pure projection issues no commands — nothing a
158
- * runner has to know how to interpret is added by `f`. That is what separates
159
- * this from `step`, beyond the shorter spelling.
160
- *
161
- * A constant variant (`constStep(e, v)`) is deliberately absent: `mapStep(e,
162
- * () => v)` already reads clearly, and it keeps `v`'s evaluation inside the
163
- * continuation where `step` puts it, rather than moving it to where the
164
- * composition is written.
165
- *
166
- * @type {<O extends Operation, T, R>(e: Effect<O, T>, f: (t: T) => R) => Effect<O, R>}
167
- */
168
- export const mapStep = (e, f) =>
169
- step(e, t => pure(f(t)))
170
-
171
- /**
172
- * Like {@link step}, but keeps the values instead of discarding them: runs `e`
173
- * to get the history `p`, continues with `f(...p)` to get `r`, and yields
174
- * `[r, ...p]` — the same history with `r` prepended.
175
- *
176
- * This is what a chain of named intermediate effects cannot otherwise express.
177
- * Each `step`'s continuation sees only the result of the effect it consumes, so
178
- * a later link has no way to reach an earlier one. `historyStep` carries every
179
- * earlier value forward, and the next destructuring names the parts:
436
+ * Applies a pure function to the `ok` value, passing an `error` through
437
+ * unchanged: the functor `map` of this layer, and a {@link step} whose
438
+ * continuation performs nothing further.
180
439
  *
181
- * ```js
182
- * const b = historyStep(history(a), decodeRevisionBlob(cas))
183
- * const c = step(b, ([revision, hash]) => ...)
184
- * ```
440
+ * A trailing pure projection is where a sequence *ends*, not another link in
441
+ * it, and spelling it as a step misreports how many effects a chain runs
442
+ * (`./todo/map-step-combinator.md`). Without this, every such site would
443
+ * regress to exactly that spelling, now with a `pureOk` inside it.
185
444
  *
186
- * Chaining mimics an async function, one `await` per link — `const hash = ...`
187
- * then `const revision = ...`, with both still reachable at the end. It takes a
188
- * history and returns one, so it composes with itself to any depth; only the
189
- * entry point needs {@link history}:
445
+ * **The operation set does not widen**: a pure projection issues no commands. Neither does the error channel — `f` cannot
446
+ * fail, so a chain that only projects its value keeps the errors it already
447
+ * had.
190
448
  *
191
- * ```js
192
- * const h0 = history(readHash(cas))
193
- * const h1 = historyStep(h0, hash => decodeRevisionBlob(cas)(hash))
194
- * const h2 = historyStep(h1, (revision, hash) => ...)
195
- * ```
196
- *
197
- * **Newest first.** A position is distance back from the current link, not
198
- * evaluation order, so a destructuring reads reverse-chronologically:
199
- * `([z, y, x]) => ...` binds `x` earliest. Reaching further back costs an index
200
- * rather than a traversal, but a long chain makes the positions hard to count.
201
- * When that starts to hurt, collapse it into a record of named fields
202
- * (`pure({ hash, revision } as const)`) and start a fresh history from there.
203
- *
204
- * `Readonly<P>` on `f`'s rest parameter is load-bearing: inferring `P` from a
205
- * bare rest parameter yields a *mutable*, labelled tuple (`[next: string]`),
206
- * which then rejects the `readonly` tuples every history is built from.
207
- *
208
- * @type {<O extends Operation, P extends readonly unknown[], Q extends Operation, R>(
209
- * e: History<O, P>,
210
- * f: (...p: Readonly<P>) => Effect<Q, R>
211
- * ) => History<O | Q, readonly[R, ...P]>}
449
+ * @type {<O extends Operation, T, E, R>(e: Effect<O, T, E>, f: (t: T) => R) => Effect<O, R, E>}
212
450
  */
213
- export const historyStep = (e, f) =>
214
- step(e, param => step(f(...param), result => pure([result, ...param])))
451
+ export const mapStep = (e, f) => resultMapStep(e, mapOk(f))
215
452
 
216
453
  /**
217
- * Starts a history, lifting a plain result into a one-element tuple so that
218
- * {@link historyStep} can extend it.
219
- *
220
- * Creating a history is the *only* thing this does — every later link goes
221
- * through `historyStep`, which is what lets one combinator cover chains of any
222
- * length. Fusing the two (a step that both starts and extends) is what makes
223
- * chains stop composing: such a step nests its predecessor's tuple instead of
224
- * flattening it, so link two would have to be spelled differently from link
225
- * three.
226
- *
227
- * @type {<O extends Operation, T>(e: Effect<O, T>) => History<O, readonly[T]>}
454
+ * Applies a pure function to the whole {@link Result}: the both-branches
455
+ * sibling of {@link mapStep}, and the {@link resultStep} whose continuation
456
+ * performs nothing further.
457
+ *
458
+ * Reach for it where a projection genuinely decides the outcome rather than
459
+ * transforming a value turning any answer into a fixed one, replacing a
460
+ * channel wholesale, re-tagging a failure. Where only the success is being
461
+ * transformed, {@link mapStep} says so and leaves the channel alone.
462
+ *
463
+ * **Neither channel is preserved**, which is the difference that matters
464
+ * against `mapStep`: `f` returns a `Result<R, F>` of its own, so a caller can
465
+ * discard errors here. That is exactly what makes it the honest spelling for a
466
+ * site that means to — the discarding is written down, in a function that says
467
+ * it takes both branches, instead of being implied by a value-shaped `map` that
468
+ * quietly received a `Result`.
469
+ *
470
+ * Its two output channels are read off `f`'s return type with {@link OkOf} /
471
+ * {@link ErrOf}, for the reason `pure` gives: inference against the `Result`
472
+ * union cannot place a one-sided return, so a projection that always answers
473
+ * `ok` would otherwise acquire an error channel it never produces.
474
+ *
475
+ * @type {<O extends Operation, T, E, R extends Result<unknown, unknown>>(
476
+ * e: Effect<O, T, E>,
477
+ * f: (r: Result<T, E>) => R
478
+ * ) => Effect<O, OkOf<R>, ErrOf<R>>}
228
479
  */
229
- export const history = e =>
230
- step(e, v => pure([v]))
480
+ export const resultMapStep = (e, f) => resultStep(e, r => pure(f(r)))
231
481
 
232
482
  /**
233
- * @type {<O extends Operation>(command: O[0]) => (...payload: Param<O>) => Effect<O, Return<O>>}
483
+ * Empties the error channel by **panicking** on it: `ok` values continue
484
+ * unchanged, an `error` is thrown as `summary(e)`, and what comes back is an
485
+ * `Effect<O, T, never>` — a `never` that is earned rather than asserted, since
486
+ * the only way past this point is success.
487
+ *
488
+ * This is the program exercising its right to treat a failure as fatal, and it
489
+ * is a policy — not a conversion. It belongs at a site that genuinely has no
490
+ * answer to the failure: a build tool that cannot read its own sources, a
491
+ * proof whose fixture is missing. Where a caller could do something else,
492
+ * {@link catchStep} or {@link resultStep} is the honest spelling, and a chain
493
+ * that merely passes the failure along wants {@link step}.
494
+ *
495
+ * **`summary` is what names the errors being panicked on, and it is required
496
+ * for that reason rather than for the message.** Without it this function was
497
+ * generic in `E` and therefore compiled however far a channel widened: one
498
+ * fallible read added upstream enlarged what every downstream call crashed on,
499
+ * silently. A renderer written for a particular channel cannot accept a wider
500
+ * one — parameters are contravariant — so widening becomes a compile error at
501
+ * the site that chose to panic, which is the site that has to choose again.
502
+ *
503
+ * The `IoChannel` renderer is `errorSummary` (`./node/module.f.mjs`); pass a
504
+ * narrower one where the channel is narrower. An inline `e => String(e)`
505
+ * accepts anything and gives the old behaviour back — that is an escape hatch,
506
+ * and being written out at the call site is the point.
507
+ *
508
+ * This being one greppable name still matters: every occurrence is a site that
509
+ * has chosen to panic, so the choice can be reviewed. What the name alone
510
+ * could not do is tell a reviewer that a site's *scope* had grown since they
511
+ * last looked at it, which is what the argument adds.
512
+ *
513
+ * @type {<O extends Operation, T, E>(e: Effect<O, T, E>, summary: (e: E) => string) => Effect<O, T, never>}
234
514
  */
235
- export const do_ = command => (...payload) => ({ command, payload, continuation: pure })
515
+ export const unwrapStep = (e, summary) => resultMapStep(e, r => {
516
+ if (r[0] === 'error') { throw summary(r[1]) }
517
+ return r
518
+ })
236
519
 
237
520
  /**
238
- * Sequentially threads a state value through an effect for each item produced by
239
- * `items`.
240
- *
241
- * Given `f: item => state => Effect<Q, state>`, `init: S`, and an `items` that
242
- * yields `[x₀, x₁, …]`, builds `step(step(f(x₀)(init), f(x₁)), f(x₂))…` and
243
- * yields a single effect producing the final state.
521
+ * Starts a history from a fallible effect, lifting its `ok` value into a
522
+ * one-element tuple that {@link historyStep} extends — the entry point a chain
523
+ * needs exactly once.
244
524
  *
245
- * Sequential each step depends on the previous state. Compare to `all`,
246
- * which fans out independent effects.
525
+ * @type {<O extends Operation, T, E>(e: Effect<O, T, E>) => Effect<O, readonly[T], E>}
526
+ */
527
+ export const history = e => mapStep(e, v => [v])
528
+
529
+ /**
530
+ * Like {@link step}, but carries the values forward instead of discarding
531
+ * them: runs `e` for the history `p`, continues with `f(...p)` for `r`, and
532
+ * yields `[r, ...p]`.
533
+ *
534
+ * This is what keeps a **fallible** chain flat. Each `step`'s continuation sees
535
+ * only the value it consumes, so a later link cannot reach an earlier one, and
536
+ * the alternative — nesting so the inner continuation closes over the outer
537
+ * one's parameter — is what `fjs/AGENTS.md` §3.4 rules out. A `Result`-blind
538
+ * `historyStep` could not serve: it carried each link's `Result` into the tuple
539
+ * rather than its value, so every later link had to destructure results it had
540
+ * no intention of handling. That is why this one exists and that one does not.
541
+ *
542
+ * The history holds `ok` values only. An `error` short-circuits the chain, so a
543
+ * failed link contributes nothing to the tuple — which is the point: a later
544
+ * link reads earlier values without asking whether they are there.
247
545
  *
248
- * **A step variant** (see the two shapes described in this module's header): the
249
- * effect comes first, as in {@link step} and {@link historyStep}. `items` is an
250
- * `Effect<O, List<T>>` rather than a bare `List<T>` because the list a caller
251
- * folds over is normally *produced* by an effect — `cas.list()`, a `readdir`.
252
- * Taking the plain list would force every such caller to open a continuation
253
- * just to name the list (`step(cas.list(), foldStep(…))`), which is the nesting
254
- * this module exists to keep out of call sites. A caller that already holds the
255
- * list lifts it with `pure`, which costs a wrapper but no indentation.
546
+ * @template {Operation} O
547
+ * @template {readonly unknown[]} P
548
+ * @template E
549
+ * @template {Operation} Q
550
+ * @template R
551
+ * @template F
552
+ * @param {Effect<O, P, E>} e
553
+ * @param {(...p: Readonly<P>) => Effect<Q, R, F>} f
554
+ * @returns {Effect<O | Q, readonly[R, ...P], E | F>}
555
+ */
556
+ export const historyStep = (e, f) => {
557
+ /** @type {(param: P) => Effect<Q, readonly[R, ...P], F>} */
558
+ const cont = param => mapStep(f(...param), result => [result, ...param])
559
+ return step(e, cont)
560
+ }
561
+
562
+ /**
563
+ * Threads a state through one effect per item, short-circuiting on the first
564
+ * `error`.
256
565
  *
257
- * `O` and `Q` are separate on purpose: the operations needed to produce the list
258
- * are rarely the ones the body performs, and the result unions them.
566
+ * **`items` is an `Effect` like everything else here.** Its payload was once
567
+ * unwrapped, on the argument that a held list has no error channel and
568
+ * requiring one would mean lifting at every call site. Lifting is one `pureOk`
569
+ * call, and that version made the *fallible* producer pay instead:
570
+ * `fjs/cas/cli` wrapped the whole fold in a `step` whose only job was to unwrap
571
+ * `list()` so `pure` could wrap it again. A producer that can fail now feeds
572
+ * the fold directly, and one that cannot is unaffected when it later can.
259
573
  *
260
574
  * **The argument order is deliberately not `fold`'s** from `fjs/types/list`, and
261
575
  * the difference is what the two combinators are *for*. `fold` is a data
262
576
  * pipeline: it is curried `f`-first because the list is the thing being threaded
263
577
  * through, and nothing about it happens in time. A step variant is a sequencing
264
- * construct — it is this module's `do` notation, and reading one top-to-bottom
265
- * is reading the order the program executes in. The effect therefore has to come
578
+ * construct — this module's `do` notation and reading one top-to-bottom is
579
+ * reading the order the program executes in. The effect therefore has to come
266
580
  * first, because it is what happens first. Currying `f` ahead of `items` would
267
581
  * put the *body* of the loop above the thing it loops over, which is exactly the
268
582
  * inversion `do` exists to remove.
269
583
  *
270
- * That is also why the whole family — `step`, `historyStep`, `foldStep`,
271
- * `forEachStep` — takes its effect first and breaks one argument per line when
272
- * it wraps (see this module's header): every such call is a statement list, and
273
- * each line is one statement in execution order.
584
+ * That is also why the whole family — {@link step}, {@link historyStep},
585
+ * `foldStep`, {@link forEachStep} — takes its effect first and breaks one
586
+ * argument per line when it wraps: every such call is a statement list, and each
587
+ * line is one statement in execution order.
274
588
  *
275
589
  * @template {Operation} O
276
590
  * @template T
277
591
  * @template {Operation} Q
278
592
  * @template S
279
- * @param {Effect<O, List<T>>} items
593
+ * @template E
594
+ * @param {Effect<O, List<T>, E>} items
280
595
  * @param {S} init
281
- * @param {(item: T) => (state: S) => Effect<Q, S>} f
282
- * @returns {Effect<O | Q, S>}
596
+ * @param {(item: T) => (state: S) => Effect<Q, S, E>} f
597
+ * @returns {Effect<O | Q, S, E>}
283
598
  */
284
599
  export const foldStep = (items, init, f) => {
285
- /** @type {Fold<T, Effect<O | Q, S>>} */
600
+ /** @type {Fold<T, Effect<Q, S, E>>} */
286
601
  const op = item => acc => step(acc, f(item))
287
- return step(items, fold(op)(pure(init)))
602
+ return step(items, fold(op)(pureOk(init)))
288
603
  }
289
604
 
290
605
  /**
291
- * Sequentially runs `f(item)` for each item produced by `items`, discarding
292
- * intermediate results. The `void` accumulator sibling of {@link foldStep}, and
293
- * a step variant on the same grounds.
294
- *
295
- * @type {<O extends Operation, T, Q extends Operation>(items: Effect<O, List<T>>, f: (item: T) => Effect<Q, void>) => Effect<O | Q, void>}
606
+ * Runs `f(item)` for each item in order, stopping at the first failure and
607
+ * propagating it. The `void` accumulator sibling of {@link foldStep}.
608
+ *
609
+ * Stopping is the difference against the `Result`-blind `forEachStep` this
610
+ * replaced: that one ran every item whatever each answered, because its `void`
611
+ * accumulator had nothing to carry a failure in — and TypeScript's `void`
612
+ * return position accepts a `Result`-valued effect silently, so the discard
613
+ * does not even show up as a type error.
614
+ *
615
+ * @type {<O extends Operation, T, Q extends Operation, E>(
616
+ * items: Effect<O, List<T>, E>,
617
+ * f: (item: T) => Effect<Q, void, E>
618
+ * ) => Effect<O | Q, void, E>}
296
619
  */
297
620
  export const forEachStep = (items, f) =>
298
621
  foldStep(items, undefined, item => () => f(item))
299
-
300
- /**
301
- * A step adapter for the `error` short-circuit: `error` → pass it through
302
- * unchanged as `pure`, `ok` → continue with `f`. Collapses the hand-written
303
- * `r[0] === 'error' ? pure(r) : f(r[1])` check that recurs at every site
304
- * chaining `Effect<O, Result<T, E>>` steps.
305
- *
306
- * @type {<T, E, O extends Operation, R>(f: (value: T) => Effect<O, Result<R, E>>) => (r: Result<T, E>) => Effect<O, Result<R, E>>}
307
- */
308
- export const okStep = f => r =>
309
- r[0] === 'error' ? pure(r) : f(r[1])
310
-
311
- /**
312
- * Runs an effect that reaches its value without performing a command: `[t]` for
313
- * a {@link Pure}, empty for a {@link Do}. Forces the thunk in the `Pure` case,
314
- * which {@link Pure}'s contract makes free of consequence.
315
- *
316
- * The eliminator for callers that expect no operations at all — the other side
317
- * of {@link match}, which is for callers that intend to perform them.
318
- *
319
- * **The result is tagged on purpose.** Returning `T | null` would collapse two
320
- * distinct outcomes whenever `T` itself admits `null`: `runPure(pure(null))` and
321
- * `runPure(someDo)` would both be `null`, so a caller asserting `null` would
322
- * accept an effect that unexpectedly stopped at a command — exactly the case
323
- * this exists to rule out. `Option<T>` keeps them apart: `[null]` is a pure
324
- * `null`, `[]` is a `Do`.
325
- *
326
- * `O` stays generic rather than narrowing to `Effect<never, T>`. `Effect` is
327
- * covariant in `O`, so `Effect<never, T>` is assignable to `Effect<O, T>` and
328
- * not the reverse — a continuation's result is always the wider type and would
329
- * be rejected. `Do<never, T>` is uninhabited besides, which would make the empty
330
- * case unreachable without a cast.
331
- *
332
- * @type {<O extends Operation, T>(e: Effect<O, T>) => Option<T>}
333
- */
334
- export const runPure = e =>
335
- typeof e === 'function' ? [e()] : []
336
-
337
- /**
338
- * Decodes an effect's next step and dispatches its command to `map`,
339
- * returning either the final result or the operation's output `R` paired
340
- * with the continuation. The one world-specific step — `await` for async
341
- * runners, state threading for sync ones — is left to the caller, so every
342
- * interpreter loop is this skeleton plus a single eliminator line.
343
- *
344
- * **The handler is looked up with `at`, never with `map[command]`.**
345
- * `OperationMap<O, R>` pins `command` to `O[0]` at the type level, but a `Do`
346
- * node's `command` is runtime data — it can reach an interpreter from a decoded
347
- * payload or a deserialized continuation, where no type ever constrained it.
348
- * `map` is an ordinary object, so a plain index read resolves an inherited name
349
- * (`'constructor'`, `'toString'`, `'hasOwnProperty'`) to the `Object.prototype`
350
- * member instead of `undefined`, and the line below would then call it with the
351
- * node's payload: a value the type system promised was `(...payload) => R` turns
352
- * out to be an arbitrary inherited function, chosen by the same input that
353
- * supplies its arguments. `at` reads through `getOwnPropertyDescriptor`, which
354
- * only ever sees own properties, so such a command yields `null` and never a
355
- * callable.
356
- *
357
- * A `null` handler is an invariant violation, not an outcome: every `O1 extends
358
- * O` the signature admits has its command in `map`, so reaching it means the
359
- * node's `command` was never the `O1[0]` it claimed to be. It therefore throws
360
- * (`assert`) rather than widening {@link MatchResult} with a variant no
361
- * type-correct caller could ever observe — a runner cannot resume a command it
362
- * has no handler for, so there is nothing for a recovery branch to do.
363
- *
364
- * @template {Operation} O
365
- * @template R
366
- * @param {OperationMap<O, R>} map
367
- */
368
- export const match = map =>
369
- /**
370
- * @template {O} O1
371
- * @template T
372
- * @param {Effect<O1, T>} e
373
- * @returns {MatchResult<O1, T, R>}
374
- */
375
- e => {
376
- if (typeof e === 'function') { return ['done', e()] }
377
- const { command, payload, continuation } = e
378
- const handler = /** @type {(...payload: readonly unknown[]) => R} */
379
- (at(command)(/** @type {any} */ (map)))
380
- assert(handler !== null, command)
381
- return ['cont', handler(...payload), continuation]
382
- }