functionalscript 0.45.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 (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/sorted_set/module.f.d.mts +18 -0
  274. package/fjs/types/sorted_set/module.f.mjs +22 -0
  275. package/fjs/types/sorted_set/proof.f.d.mts +1 -0
  276. package/fjs/types/sorted_set/proof.f.mjs +16 -1
  277. package/fjs/types/uint8array/module.f.d.mts +1 -1
  278. package/fjs/types/uint8array/module.f.mjs +1 -1
  279. package/fjs/website/module.f.d.mts +3 -3
  280. package/fjs/website/module.f.mjs +4 -7
  281. package/fjs/website/proof.f.mjs +2 -1
  282. package/package.json +2 -2
  283. package/fjs/dev/package_json/module.f.d.mts +0 -39
  284. package/fjs/dev/package_json/module.f.mjs +0 -40
  285. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  286. package/fjs/dev/package_json/proof.f.mjs +0 -32
  287. package/fjs/effects/eff/module.f.d.mts +0 -20
  288. package/fjs/effects/eff/module.f.mjs +0 -70
  289. package/fjs/effects/eff/proof.f.d.mts +0 -15
  290. package/fjs/effects/eff/proof.f.mjs +0 -69
  291. package/fjs/effects/eff/types.d.ts +0 -71
  292. package/fjs/types/rtti/validate/module.f.d.mts +0 -41
  293. package/fjs/types/rtti/validate/module.f.mjs +0 -171
  294. package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
  295. package/fjs/types/rtti/validate/proof.f.mjs +0 -437
  296. package/fjs/types/rtti/validate/types.d.ts +0 -6
@@ -67,7 +67,7 @@ const escapeTable = /** @type {const} */ ({
67
67
 
68
68
  /** @type {(code: number) => string} */
69
69
  const escapeCharCode = code =>
70
- escapeTable[/** @type {keyof typeof escapeTable} */ (code)] ?? fromCharCode(code)
70
+ escapeTable[code] ?? fromCharCode(code)
71
71
 
72
72
  const escape = compose(stringToList)(map(escapeCharCode))
73
73
 
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Extended JSON: the ordinary JSON data model with `bigint` added to the
3
+ * primitive leaves, so bare integer syntax survives a parse exactly.
4
+ *
5
+ * It is a runtime representation, not a syntax. `stringify` emits ordinary,
6
+ * valid JSON text — there is no `123n` literal, tagged object, or
7
+ * quoted-integer convention — and ordinary JavaScript consumers of that text
8
+ * are free to read it back into whatever numeric representation they use,
9
+ * `JSON.parse`'s `number` included. What the extended codec adds is that
10
+ * *this* codec reads it back into the same runtime value it wrote.
11
+ *
12
+ * ### Parse
13
+ *
14
+ * The split is lexical, not mathematical: **a token containing `.` or `e` /
15
+ * `E` is a `number`, even when its value is an integer.**
16
+ *
17
+ * ```text
18
+ * 123 -> 123n -123 -> -123n 0 -> 0n
19
+ * -0 -> -0 1.5 -> 1.5 1.0 -> 1
20
+ * 1e3 -> 1000 1E3 -> 1000
21
+ * ```
22
+ *
23
+ * `-0` is the exception to bare integer syntax: `bigint` has no negative zero,
24
+ * so keeping it as a `number` is what preserves the sign the JSON text spells.
25
+ *
26
+ * The extended domain is exact where it claims to be, so it rejects rather
27
+ * than rounds: a token whose value is outside the finite `number` range
28
+ * (`1e400`) is a parse `error`, not `Infinity`. Ordinary rounding within that
29
+ * range is inherent to `number` and is not an error — `1e-400` is `0`, and
30
+ * `0.1` is the nearest double, as everywhere else.
31
+ *
32
+ * ### Serialize
33
+ *
34
+ * Spelling follows the runtime type of the leaf, so parsing the output returns
35
+ * the value that was written:
36
+ *
37
+ * ```text
38
+ * 0n -> 0 -> 0n 3n -> 3 -> 3n
39
+ * 0 -> 0.0 -> 0 3 -> 3.0 -> 3
40
+ * -0 -> -0 -> -0
41
+ * ```
42
+ *
43
+ * A `bigint` is always its full base-10 digits, **never** exponent notation,
44
+ * however large: exponent syntax belongs to the `number` side and would parse
45
+ * back as one. A whole-valued `number` other than `-0` gets a non-integer
46
+ * spelling (`3.0`) for the same reason. This `.0` rule is the extended codec's
47
+ * own; the standard codec in [`../module.f.mjs`](../module.f.mjs) has its own
48
+ * numeric spelling and does not route through here.
49
+ *
50
+ * `NaN`, `Infinity` and `-Infinity` cannot arrive from JSON text but can be
51
+ * supplied programmatically, and JSON has no syntax for them. They serialize
52
+ * as `null`, matching what `JSON.stringify` does with them.
53
+ *
54
+ * @module
55
+ *
56
+ * @import { Result } from '../../../types/result/types.ts'
57
+ * @import { List } from '../../../types/list/types.ts'
58
+ * @import { NumberPolicy } from '../parser/types.ts'
59
+ * @import { Primitive, Unknown, _MapEntries } from './types.ts'
60
+ */
61
+ import type { Result } from '../../../types/result/types.ts';
62
+ import type { List } from '../../../types/list/types.ts';
63
+ import type { Unknown, _MapEntries } from './types.ts';
64
+ /**
65
+ * Parses `text` as extended JSON, reporting failure as a `Result` rather than
66
+ * throwing.
67
+ *
68
+ * @type {(text: string) => Result<Unknown, string>}
69
+ */
70
+ export declare const parse: (text: string) => Result<Unknown, string>;
71
+ /**
72
+ * Serializes an extended JSON value as a list of string chunks.
73
+ *
74
+ * @type {(mapEntries: _MapEntries) => (value: Unknown) => List<string>}
75
+ */
76
+ export declare const serialize: (mapEntries: _MapEntries) => (value: Unknown) => List<string>;
77
+ /**
78
+ * Serializes an extended JSON value as ordinary JSON text.
79
+ *
80
+ * @type {(mapEntries: _MapEntries) => (value: Unknown) => string}
81
+ */
82
+ export declare const stringify: (mapEntries: _MapEntries) => (value: Unknown) => string;
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Extended JSON: the ordinary JSON data model with `bigint` added to the
3
+ * primitive leaves, so bare integer syntax survives a parse exactly.
4
+ *
5
+ * It is a runtime representation, not a syntax. `stringify` emits ordinary,
6
+ * valid JSON text — there is no `123n` literal, tagged object, or
7
+ * quoted-integer convention — and ordinary JavaScript consumers of that text
8
+ * are free to read it back into whatever numeric representation they use,
9
+ * `JSON.parse`'s `number` included. What the extended codec adds is that
10
+ * *this* codec reads it back into the same runtime value it wrote.
11
+ *
12
+ * ### Parse
13
+ *
14
+ * The split is lexical, not mathematical: **a token containing `.` or `e` /
15
+ * `E` is a `number`, even when its value is an integer.**
16
+ *
17
+ * ```text
18
+ * 123 -> 123n -123 -> -123n 0 -> 0n
19
+ * -0 -> -0 1.5 -> 1.5 1.0 -> 1
20
+ * 1e3 -> 1000 1E3 -> 1000
21
+ * ```
22
+ *
23
+ * `-0` is the exception to bare integer syntax: `bigint` has no negative zero,
24
+ * so keeping it as a `number` is what preserves the sign the JSON text spells.
25
+ *
26
+ * The extended domain is exact where it claims to be, so it rejects rather
27
+ * than rounds: a token whose value is outside the finite `number` range
28
+ * (`1e400`) is a parse `error`, not `Infinity`. Ordinary rounding within that
29
+ * range is inherent to `number` and is not an error — `1e-400` is `0`, and
30
+ * `0.1` is the nearest double, as everywhere else.
31
+ *
32
+ * ### Serialize
33
+ *
34
+ * Spelling follows the runtime type of the leaf, so parsing the output returns
35
+ * the value that was written:
36
+ *
37
+ * ```text
38
+ * 0n -> 0 -> 0n 3n -> 3 -> 3n
39
+ * 0 -> 0.0 -> 0 3 -> 3.0 -> 3
40
+ * -0 -> -0 -> -0
41
+ * ```
42
+ *
43
+ * A `bigint` is always its full base-10 digits, **never** exponent notation,
44
+ * however large: exponent syntax belongs to the `number` side and would parse
45
+ * back as one. A whole-valued `number` other than `-0` gets a non-integer
46
+ * spelling (`3.0`) for the same reason. This `.0` rule is the extended codec's
47
+ * own; the standard codec in [`../module.f.mjs`](../module.f.mjs) has its own
48
+ * numeric spelling and does not route through here.
49
+ *
50
+ * `NaN`, `Infinity` and `-Infinity` cannot arrive from JSON text but can be
51
+ * supplied programmatically, and JSON has no syntax for them. They serialize
52
+ * as `null`, matching what `JSON.stringify` does with them.
53
+ *
54
+ * @module
55
+ *
56
+ * @import { Result } from '../../../types/result/types.ts'
57
+ * @import { List } from '../../../types/list/types.ts'
58
+ * @import { NumberPolicy } from '../parser/types.ts'
59
+ * @import { Primitive, Unknown, _MapEntries } from './types.ts'
60
+ */
61
+
62
+ import { concat } from '../../../types/string/module.f.mjs'
63
+ import { compose } from '../../../types/function/module.f.mjs'
64
+ import { error, ok } from '../../../types/result/module.f.mjs'
65
+ import { stringToList } from '../../../text/utf16/module.f.mjs'
66
+ import { parse as parseTokens } from '../parser/module.f.mjs'
67
+ import { tokenize } from '../tokenizer/module.f.mjs'
68
+ import { isBareInteger, numberLexeme } from '../number/module.f.mjs'
69
+ import { treeSerialize, stringSerialize, nullSerialize, boolSerialize } from '../serializer/module.f.mjs'
70
+
71
+ const { isFinite } = Number
72
+
73
+ const { is } = Object
74
+
75
+ /**
76
+ * The extended numeric policy, applied to the token's exact lexeme.
77
+ *
78
+ * Bare integer syntax is materialized as `bigint` straight from that lexeme —
79
+ * never through `number`, which would round anything above
80
+ * `Number.MAX_SAFE_INTEGER`. Everything else is `number`, and is rejected if
81
+ * the finite `number` range cannot hold it.
82
+ *
83
+ * @type {NumberPolicy<number | bigint>}
84
+ */
85
+ const numberPolicy = ({ value }) => {
86
+ if (isBareInteger(numberLexeme(value))) {
87
+ return ok(value === '-0' ? -0 : BigInt(value))
88
+ }
89
+ const n = Number(value)
90
+ return isFinite(n) ? ok(n) : error(`number is out of the finite range: ${value}`)
91
+ }
92
+
93
+ /**
94
+ * Parses `text` as extended JSON, reporting failure as a `Result` rather than
95
+ * throwing.
96
+ *
97
+ * @type {(text: string) => Result<Unknown, string>}
98
+ */
99
+ export const parse = text => parseTokens(numberPolicy)(tokenize(stringToList(text)))
100
+
101
+ const negativeZeroSerialize = ['-0']
102
+
103
+ /**
104
+ * Spells a `number` so that reparsing it returns a `number` — never a
105
+ * `bigint`.
106
+ *
107
+ * A whole-valued `number` already spells itself with `.` or `e` often enough
108
+ * (`1e+21`, `1.5`); when it does not, `.0` is appended, which is the same
109
+ * value in JSON and the other lexical branch on the way back. `-0` is written
110
+ * out as the exact token `-0`, the one bare integer the parser keeps as a
111
+ * `number`.
112
+ *
113
+ * @type {(value: number) => List<string>}
114
+ */
115
+ const numberSerialize = value => {
116
+ if (is(value, -0)) { return negativeZeroSerialize }
117
+ if (!isFinite(value)) { return nullSerialize }
118
+ const text = `${value}`
119
+ return [isBareInteger(numberLexeme(text)) ? `${text}.0` : text]
120
+ }
121
+
122
+ /**
123
+ * Spells a `bigint` as its full base-10 digits. `BigInt`'s own decimal form is
124
+ * exactly that: no `n` suffix, and no exponent notation at any magnitude.
125
+ *
126
+ * @type {(value: bigint) => List<string>}
127
+ */
128
+ const bigintSerialize = value => [`${value}`]
129
+
130
+ /** @type {(value: Primitive) => List<string>} */
131
+ const primitiveSerialize = value => {
132
+ switch (typeof value) {
133
+ case 'boolean': { return boolSerialize(value) }
134
+ case 'bigint': { return bigintSerialize(value) }
135
+ case 'number': { return numberSerialize(value) }
136
+ case 'string': { return stringSerialize(value) }
137
+ default: { return nullSerialize }
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Serializes an extended JSON value as a list of string chunks.
143
+ *
144
+ * @type {(mapEntries: _MapEntries) => (value: Unknown) => List<string>}
145
+ */
146
+ export const serialize = treeSerialize(primitiveSerialize)
147
+
148
+ /**
149
+ * Serializes an extended JSON value as ordinary JSON text.
150
+ *
151
+ * @type {(mapEntries: _MapEntries) => (value: Unknown) => string}
152
+ */
153
+ export const stringify = sort => compose(serialize(sort))(concat)
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @import { Unknown } from './types.ts'
3
+ */
4
+ export declare const proof: {
5
+ bigint: {
6
+ positive: () => void;
7
+ negative: () => void;
8
+ zero: () => void;
9
+ beyondSafeInteger: () => void;
10
+ oversized: () => void;
11
+ };
12
+ number: {
13
+ negativeZero: () => void;
14
+ fraction: () => void;
15
+ wholeFraction: () => void;
16
+ exponent: () => void;
17
+ capitalExponent: () => void;
18
+ negativeExponent: () => void;
19
+ underflow: () => void;
20
+ exponentSpelling: () => void;
21
+ };
22
+ overflow: {
23
+ exponent: () => void;
24
+ negativeExponent: () => void;
25
+ unboundedExponent: () => void;
26
+ malformed: () => void;
27
+ };
28
+ containers: {
29
+ array: () => void;
30
+ object: () => void;
31
+ undefinedProperty: () => void;
32
+ };
33
+ nonFinite: {
34
+ nan: () => void;
35
+ infinity: () => void;
36
+ negativeInfinity: () => void;
37
+ };
38
+ serialize: {
39
+ oneToOne: () => void;
40
+ largeBigintHasNoExponent: () => void;
41
+ };
42
+ };
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @import { Unknown } from './types.ts'
3
+ */
4
+
5
+ import { parse, stringify as extendedStringify } from './module.f.mjs'
6
+ import { sort } from '../../../types/object/module.f.mjs'
7
+ import { unwrap } from '../../../types/result/module.f.mjs'
8
+ import { assert, assertEq, assertStructurallySame } from '../../../asserts/module.f.mjs'
9
+
10
+ const stringify = extendedStringify(sort)
11
+
12
+ /**
13
+ * The runtime type a token parses to, and the text that value serializes back
14
+ * to — the two halves of the extended codec's round trip.
15
+ *
16
+ * @type {(text: string) => readonly [string, string]}
17
+ */
18
+ const parsed = text => {
19
+ const value = unwrap(parse(text))
20
+ return [typeof value, stringify(value)]
21
+ }
22
+
23
+ /** @type {(text: string) => Unknown} */
24
+ const parseValue = text => unwrap(parse(text))
25
+
26
+ /** @type {(text: string) => string} */
27
+ const parseError = text => {
28
+ const [tag, message] = parse(text)
29
+ assertEq(tag, 'error')
30
+ return `${message}`
31
+ }
32
+
33
+ // Long enough that `Number` of it is `Infinity` and `10 ** exponent` is not a
34
+ // computation anyone can afford.
35
+ const hugeExp = '99999999999999999999'
36
+
37
+ export const proof = {
38
+ // bare integer syntax is `bigint`, whatever the magnitude
39
+ bigint: {
40
+ positive: () => assertStructurallySame(parsed('123'), ['bigint', '123']),
41
+ negative: () => assertStructurallySame(parsed('-123'), ['bigint', '-123']),
42
+ zero: () => assertStructurallySame(parsed('0'), ['bigint', '0']),
43
+ // beyond `Number.MAX_SAFE_INTEGER`, so a materializer that went
44
+ // through `number` first would round here
45
+ beyondSafeInteger: () => {
46
+ assertEq(parseValue('12345678901234567890123'), 12345678901234567890123n)
47
+ assertEq(parseValue('-12345678901234567890123'), -12345678901234567890123n)
48
+ },
49
+ // an integer of a size no `number` can even approximate
50
+ oversized: () => {
51
+ const digits = `1${'0'.repeat(2000)}`
52
+ assertStructurallySame(parsed(digits), ['bigint', digits])
53
+ assertEq(parseValue(digits), 10n ** 2000n)
54
+ },
55
+ },
56
+ // `.`/`e`/`E` means `number`, even when the value is a whole number
57
+ number: {
58
+ negativeZero: () => {
59
+ assertStructurallySame(parsed('-0'), ['number', '-0'])
60
+ // the sign is the whole point: `bigint` has no negative zero
61
+ assert(Object.is(parseValue('-0'), -0))
62
+ },
63
+ fraction: () => assertStructurallySame(parsed('1.5'), ['number', '1.5']),
64
+ wholeFraction: () => assertStructurallySame(parsed('1.0'), ['number', '1.0']),
65
+ exponent: () => assertStructurallySame(parsed('1e3'), ['number', '1000.0']),
66
+ capitalExponent: () => assertStructurallySame(parsed('1E3'), ['number', '1000.0']),
67
+ negativeExponent: () => assertStructurallySame(parsed('1e-3'), ['number', '0.001']),
68
+ // ordinary `number` rounding is not an error: an exponent below the
69
+ // range is zero, as it is everywhere else in JavaScript
70
+ underflow: () => assertStructurallySame(parsed('1e-400'), ['number', '0.0']),
71
+ // a `number` big enough to spell itself with an exponent keeps that
72
+ // spelling — appending `.0` to it would not even be valid JSON
73
+ exponentSpelling: () => assertStructurallySame(parsed('1e21'), ['number', '1e+21']),
74
+ },
75
+ // a valid token the extended domain cannot represent is an ordinary
76
+ // parse error, never `Infinity` and never a throw
77
+ overflow: {
78
+ exponent: () => assertEq(
79
+ parseError('1e400'),
80
+ 'number is out of the finite range: 1e400'),
81
+ negativeExponent: () => assertEq(
82
+ parseError('-1e400'),
83
+ 'number is out of the finite range: -1e400'),
84
+ // exponent text far beyond `number` precision: the tokenizer keeps
85
+ // every digit, and the policy rejects the token rather than losing them
86
+ unboundedExponent: () => assertEq(
87
+ parseError(`1e${hugeExp}`),
88
+ `number is out of the finite range: 1e${hugeExp}`),
89
+ // malformed input is still an ordinary error
90
+ malformed: () => assertEq(parseError('{'), 'unexpected end'),
91
+ },
92
+ containers: {
93
+ array: () => assertEq(
94
+ stringify(parseValue('[1,2.0,-0,"x",true,false,null]')),
95
+ '[1,2.0,-0,"x",true,false,null]'),
96
+ object: () => assertEq(
97
+ stringify(parseValue('{"b":[1e2],"a":{"c":-7}}')),
98
+ '{"a":{"c":-7},"b":[100.0]}'),
99
+ // a missing property is not a leaf
100
+ undefinedProperty: () => assertEq(stringify({ a: 1n, b: undefined }), '{"a":1}'),
101
+ },
102
+ // programmatic values: JSON has no syntax for these, so the serializer
103
+ // spells them `null` — the same choice `JSON.stringify` makes
104
+ nonFinite: {
105
+ nan: () => assertEq(stringify(NaN), 'null'),
106
+ infinity: () => assertEq(stringify(Infinity), 'null'),
107
+ negativeInfinity: () => assertEq(stringify(-Infinity), 'null'),
108
+ },
109
+ // the spellings that keep `number` and `bigint` apart across a round trip
110
+ serialize: {
111
+ oneToOne: () => {
112
+ assertEq(stringify(0n), '0')
113
+ assertEq(stringify(0), '0.0')
114
+ assertEq(stringify(-0), '-0')
115
+ assertEq(stringify(3n), '3')
116
+ assertEq(stringify(3), '3.0')
117
+ assertEq(stringify(1.5), '1.5')
118
+ },
119
+ // a bigint is never shortened to exponent notation, however large:
120
+ // that syntax would parse back as a `number`
121
+ largeBigintHasNoExponent: () => {
122
+ const text = stringify(10n ** 30n)
123
+ assertEq(text, `1${'0'.repeat(30)}`)
124
+ assertStructurallySame(parsed(text), ['bigint', text])
125
+ },
126
+ },
127
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * TypeScript counterparts of the extended JSON data model: ordinary JSON's
3
+ * containers with `bigint` added to the primitive leaf set.
4
+ *
5
+ * This is a runtime representation, not a new syntax: an extended value's
6
+ * serialized form is ordinary valid JSON text, with no `123n` literal, tagged
7
+ * object, or quoted-integer convention.
8
+ *
9
+ * @module
10
+ */
11
+ import type { Primitive as JsonPrimitive, Tree, TreeObject, TreeArray, TreeMapEntries } from '../types.ts';
12
+ /**
13
+ * `null | boolean | string | number | bigint`.
14
+ *
15
+ * `bigint` carries JSON's bare integer syntax exactly, whatever its
16
+ * magnitude; `number` carries decimal and exponent syntax, and the one bare
17
+ * integer that `bigint` cannot represent — negative zero.
18
+ */
19
+ export type Primitive = JsonPrimitive | bigint;
20
+ export type Unknown = Tree<Primitive>;
21
+ export type Object = TreeObject<Primitive>;
22
+ export type Array = TreeArray<Primitive>;
23
+ export type _MapEntries = TreeMapEntries<Primitive>;
@@ -9,11 +9,17 @@
9
9
  * [`./types.ts`](./types.ts), and the rtti schemas they are pinned against in
10
10
  * [`./rtti/module.f.mjs`](./rtti/module.f.mjs).
11
11
  *
12
+ * This is the standard, bigint-free codec: numbers are JavaScript `number`s.
13
+ * [`./extended/module.f.mjs`](./extended/module.f.mjs) is the sibling codec
14
+ * that keeps JSON's bare integer syntax as `bigint`. Both are numeric policies
15
+ * over the same tokenizer and the same structural parser — see
16
+ * [`./README.md`](./README.md).
17
+ *
12
18
  * @module
13
19
  *
14
- * @import { StringMap } from '../../types/object/types.ts'
15
20
  * @import { Result } from '../../types/result/types.ts'
16
- * @import { _MapEntries, Object, Unknown, } from './types.ts'
21
+ * @import { _MapEntries, Primitive, Unknown, } from './types.ts'
22
+ * @import { NumberPolicy } from './parser/types.ts'
17
23
  * @import { List } from '../../types/list/types.ts'
18
24
  */
19
25
  import type { Result } from '../../types/result/types.ts';
@@ -9,22 +9,29 @@
9
9
  * [`./types.ts`](./types.ts), and the rtti schemas they are pinned against in
10
10
  * [`./rtti/module.f.mjs`](./rtti/module.f.mjs).
11
11
  *
12
+ * This is the standard, bigint-free codec: numbers are JavaScript `number`s.
13
+ * [`./extended/module.f.mjs`](./extended/module.f.mjs) is the sibling codec
14
+ * that keeps JSON's bare integer syntax as `bigint`. Both are numeric policies
15
+ * over the same tokenizer and the same structural parser — see
16
+ * [`./README.md`](./README.md).
17
+ *
12
18
  * @module
13
19
  *
14
- * @import { StringMap } from '../../types/object/types.ts'
15
20
  * @import { Result } from '../../types/result/types.ts'
16
- * @import { _MapEntries, Object, Unknown, } from './types.ts'
21
+ * @import { _MapEntries, Primitive, Unknown, } from './types.ts'
22
+ * @import { NumberPolicy } from './parser/types.ts'
17
23
  * @import { List } from '../../types/list/types.ts'
18
24
  */
19
25
 
20
- import { next, flat, map } from '../../types/list/module.f.mjs'
26
+ import { next } from '../../types/list/module.f.mjs'
21
27
  import { concat } from '../../types/string/module.f.mjs'
22
28
  import { stringToList } from '../../text/utf16/module.f.mjs'
23
29
  import { parse as parseTokens } from './parser/module.f.mjs'
24
30
  import { tokenize } from './tokenizer/module.f.mjs'
25
- import { at, definedEntries } from '../../types/object/module.f.mjs'
26
- import { compose, fn } from '../../types/function/module.f.mjs'
27
- import { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from './serializer/module.f.mjs'
31
+ import { at } from '../../types/object/module.f.mjs'
32
+ import { compose } from '../../types/function/module.f.mjs'
33
+ import { ok } from '../../types/result/module.f.mjs'
34
+ import { treeSerialize, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from './serializer/module.f.mjs'
28
35
 
29
36
  // ── JSON utilities ────────────────────────────────────────────────────────────
30
37
 
@@ -43,42 +50,23 @@ export const setProperty = value => {
43
50
  return f
44
51
  }
45
52
 
46
- const colon = [':']
47
-
48
- /** @type {(cmd: StringMap<Unknown>) => readonly (readonly [string, Unknown])[]} */
49
- const df = definedEntries
53
+ /**
54
+ * The standard codec's leaf spelling. The containers around it are
55
+ * `treeSerialize`'s, shared with every other JSON codec.
56
+ *
57
+ * @type {(value: Primitive) => List<string>}
58
+ */
59
+ const primitiveSerialize = value => {
60
+ switch (typeof value) {
61
+ case 'boolean': { return boolSerialize(value) }
62
+ case 'number': { return numberSerialize(value) }
63
+ case 'string': { return stringSerialize(value) }
64
+ default: { return nullSerialize }
65
+ }
66
+ }
50
67
 
51
68
  /** @type {(mapEntries: _MapEntries) => (value: Unknown) => List<string>} */
52
- export const serialize = sort => {
53
- /** @type {(kv: readonly[string, Unknown]) => List<string>} */
54
- const propertySerialize = ([k, v]) => flat([
55
- stringSerialize(k),
56
- colon,
57
- f(v)
58
- ])
59
- const mapPropertySerialize = map(propertySerialize)
60
- /** @type {(object: Object) => List<string>} */
61
- const objectSerialize = fn(df)
62
- .map(sort)
63
- .map(mapPropertySerialize)
64
- .map(objectWrap)
65
- .result
66
- /** @type {(value: Unknown) => List<string>} */
67
- const f = value => {
68
- switch (typeof value) {
69
- case 'boolean': { return boolSerialize(value) }
70
- case 'number': { return numberSerialize(value) }
71
- case 'string': { return stringSerialize(value) }
72
- default: {
73
- if (value === null) { return nullSerialize }
74
- if (value instanceof Array) { return arraySerialize(value) }
75
- return objectSerialize(value)
76
- }
77
- }
78
- }
79
- const arraySerialize = compose(map(f))(arrayWrap)
80
- return f
81
- }
69
+ export const serialize = treeSerialize(primitiveSerialize)
82
70
 
83
71
  /**
84
72
  * The standard `JSON.stringify` rules determined by
@@ -89,6 +77,20 @@ export const serialize = sort => {
89
77
  */
90
78
  export const stringify = sort => compose(serialize(sort))(concat)
91
79
 
80
+ /**
81
+ * The standard codec's numeric policy: every JSON number token becomes a
82
+ * JavaScript `number`, read from the token's own lexeme.
83
+ *
84
+ * It is total — no valid JSON number is rejected — so a magnitude outside the
85
+ * finite `number` range materializes the way JavaScript itself reads that
86
+ * text (`1e400` is `Infinity`, `1e-400` is `0`). The bigint-free domain has
87
+ * nothing more exact to offer; the extended codec keeps such distinctions,
88
+ * from the same token, without this one having to.
89
+ *
90
+ * @type {NumberPolicy<number>}
91
+ */
92
+ const numberPolicy = token => ok(parseFloat(token.value))
93
+
92
94
  /**
93
95
  * Parses `text` as JSON with this module's own pure tokenizer and parser,
94
96
  * reporting failure as a `Result` rather than throwing: malformed input is
@@ -101,4 +103,4 @@ export const stringify = sort => compose(serialize(sort))(concat)
101
103
  *
102
104
  * @type {(text: string) => Result<Unknown, string>}
103
105
  */
104
- export const parse = text => parseTokens(tokenize(stringToList(text)))
106
+ export const parse = text => parseTokens(numberPolicy)(tokenize(stringToList(text)))
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Bounded lexical analysis of a JSON number token.
3
+ *
4
+ * `NumberToken.value` is the canonical lossless numeric source, and these
5
+ * helpers read it **without narrowing it first**: every operation here costs
6
+ * at most the length of the token, so a valid JSON number is classified
7
+ * correctly whatever its magnitude. In particular no helper builds a
8
+ * coefficient bigint, converts an arbitrary exponent to `number`, or evaluates
9
+ * a power such as `10 ** exponent`.
10
+ *
11
+ * That matters for schema-directed consumers, which have to decide questions
12
+ * such as "is this token an integer?" *before* a materializer rounds the value
13
+ * into `number`: `1.00000000000000001` and `1` are the same `number` but
14
+ * different tokens.
15
+ *
16
+ * @module
17
+ *
18
+ * @import { Sign } from '../../../types/function/compare/types.ts'
19
+ * @import { NumberLexeme } from './types.ts'
20
+ */
21
+ import type { NumberLexeme } from './types.ts';
22
+ /**
23
+ * Splits a JSON number token into its lexical parts.
24
+ *
25
+ * The token is grammar-validated by the tokenizer —
26
+ * `-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?` — so this is a split, not a
27
+ * validation.
28
+ *
29
+ * @type {(value: string) => NumberLexeme}
30
+ */
31
+ export declare const numberLexeme: (value: string) => NumberLexeme;
32
+ /**
33
+ * Whether the lexeme is bare integer syntax: no `.` and no `e` / `E`.
34
+ *
35
+ * The distinction is lexical, not mathematical — `1e3` is not bare integer
36
+ * syntax even though its value is the integer `1000`.
37
+ *
38
+ * @type {(lexeme: NumberLexeme) => boolean}
39
+ */
40
+ export declare const isBareInteger: (lexeme: NumberLexeme) => boolean;
41
+ /**
42
+ * Whether the lexeme spells a mathematical integer.
43
+ *
44
+ * This is the exact question, not the lexical one: `1e3` and `1.00` are
45
+ * integral while `1.5` is not. It stays bounded by the token's length.
46
+ *
47
+ * The value is `coefficient × 10 ** (exponent - fractionDigits)`, so it is an
48
+ * integer exactly when the exponent shifts the decimal point no further right
49
+ * than the coefficient's own trailing zeros allow. Both sides of that
50
+ * comparison — the fraction-digit count and the trailing-zero count — are
51
+ * bounded by the token, so the exponent only ever has to be compared against a
52
+ * small number.
53
+ *
54
+ * A zero coefficient is the simple case: zero is integral for any exponent, so
55
+ * the exponent is not examined at all.
56
+ *
57
+ * @type {(lexeme: NumberLexeme) => boolean}
58
+ */
59
+ export declare const isIntegral: (lexeme: NumberLexeme) => boolean;