@elaraai/east 0.0.1-beta.9 → 1.0.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 (410) hide show
  1. package/LICENSE.md +15 -666
  2. package/README.md +113 -88
  3. package/dist/src/analyze.d.ts +3 -0
  4. package/dist/src/analyze.d.ts.map +1 -1
  5. package/dist/src/analyze.js +223 -111
  6. package/dist/src/analyze.js.map +1 -1
  7. package/dist/src/analyze.spec.d.ts +2 -0
  8. package/dist/src/analyze.spec.d.ts.map +1 -0
  9. package/dist/src/analyze.spec.js +445 -0
  10. package/dist/src/analyze.spec.js.map +1 -0
  11. package/dist/src/ast.d.ts +54 -35
  12. package/dist/src/ast.d.ts.map +1 -1
  13. package/dist/src/ast_to_ir.coerce_to.spec.d.ts +15 -0
  14. package/dist/src/ast_to_ir.coerce_to.spec.d.ts.map +1 -0
  15. package/dist/src/ast_to_ir.coerce_to.spec.js +420 -0
  16. package/dist/src/ast_to_ir.coerce_to.spec.js.map +1 -0
  17. package/dist/src/ast_to_ir.d.ts +18 -4
  18. package/dist/src/ast_to_ir.d.ts.map +1 -1
  19. package/dist/src/ast_to_ir.js +233 -178
  20. package/dist/src/ast_to_ir.js.map +1 -1
  21. package/dist/src/builtins.d.ts +1 -1
  22. package/dist/src/builtins.d.ts.map +1 -1
  23. package/dist/src/builtins.js +194 -2
  24. package/dist/src/builtins.js.map +1 -1
  25. package/dist/src/comparison.d.ts +2 -2
  26. package/dist/src/comparison.d.ts.map +1 -1
  27. package/dist/src/comparison.js +115 -40
  28. package/dist/src/comparison.js.map +1 -1
  29. package/dist/src/comparison.spec.d.ts +2 -0
  30. package/dist/src/comparison.spec.d.ts.map +1 -0
  31. package/dist/src/comparison.spec.js +1200 -0
  32. package/dist/src/comparison.spec.js.map +1 -0
  33. package/dist/src/compile.d.ts +31 -9
  34. package/dist/src/compile.d.ts.map +1 -1
  35. package/dist/src/compile.js +1048 -548
  36. package/dist/src/compile.js.map +1 -1
  37. package/dist/src/containers/matrix.d.ts +15 -0
  38. package/dist/src/containers/matrix.d.ts.map +1 -0
  39. package/dist/src/containers/matrix.js +15 -0
  40. package/dist/src/containers/matrix.js.map +1 -0
  41. package/dist/src/containers/ref.d.ts.map +1 -1
  42. package/dist/src/containers/ref.js +1 -1
  43. package/dist/src/containers/ref.js.map +1 -1
  44. package/dist/src/containers/sortedmap.spec.d.ts +2 -0
  45. package/dist/src/containers/sortedmap.spec.d.ts.map +1 -0
  46. package/dist/src/containers/sortedmap.spec.js +180 -0
  47. package/dist/src/containers/sortedmap.spec.js.map +1 -0
  48. package/dist/src/containers/sortedset.spec.d.ts +2 -0
  49. package/dist/src/containers/sortedset.spec.d.ts.map +1 -0
  50. package/dist/src/containers/sortedset.spec.js +228 -0
  51. package/dist/src/containers/sortedset.spec.js.map +1 -0
  52. package/dist/src/containers/variant.d.ts.map +1 -1
  53. package/dist/src/containers/variant.js +1 -1
  54. package/dist/src/containers/variant.js.map +1 -1
  55. package/dist/src/containers/variant.spec.d.ts +2 -0
  56. package/dist/src/containers/variant.spec.d.ts.map +1 -0
  57. package/dist/src/containers/variant.spec.js +217 -0
  58. package/dist/src/containers/variant.spec.js.map +1 -0
  59. package/dist/src/datetime_format/parse.spec.d.ts +6 -0
  60. package/dist/src/datetime_format/parse.spec.d.ts.map +1 -0
  61. package/dist/src/datetime_format/parse.spec.js +379 -0
  62. package/dist/src/datetime_format/parse.spec.js.map +1 -0
  63. package/dist/src/datetime_format/print.spec.d.ts +6 -0
  64. package/dist/src/datetime_format/print.spec.d.ts.map +1 -0
  65. package/dist/src/datetime_format/print.spec.js +257 -0
  66. package/dist/src/datetime_format/print.spec.js.map +1 -0
  67. package/dist/src/datetime_format/tokenize.spec.d.ts +2 -0
  68. package/dist/src/datetime_format/tokenize.spec.d.ts.map +1 -0
  69. package/dist/src/datetime_format/tokenize.spec.js +508 -0
  70. package/dist/src/datetime_format/tokenize.spec.js.map +1 -0
  71. package/dist/src/datetime_format/types.d.ts +23 -23
  72. package/dist/src/default.d.ts.map +1 -1
  73. package/dist/src/default.js +33 -0
  74. package/dist/src/default.js.map +1 -1
  75. package/dist/src/default.spec.d.ts +2 -0
  76. package/dist/src/default.spec.d.ts.map +1 -0
  77. package/dist/src/default.spec.js +178 -0
  78. package/dist/src/default.spec.js.map +1 -0
  79. package/dist/src/eastir.d.ts +7 -0
  80. package/dist/src/eastir.d.ts.map +1 -1
  81. package/dist/src/eastir.js +55 -7
  82. package/dist/src/eastir.js.map +1 -1
  83. package/dist/src/error.d.ts +14 -4
  84. package/dist/src/error.d.ts.map +1 -1
  85. package/dist/src/error.js +28 -3
  86. package/dist/src/error.js.map +1 -1
  87. package/dist/src/example.d.ts +87 -0
  88. package/dist/src/example.d.ts.map +1 -0
  89. package/dist/src/example.js +18 -0
  90. package/dist/src/example.js.map +1 -0
  91. package/dist/src/expr/array.d.ts +43 -1
  92. package/dist/src/expr/array.d.ts.map +1 -1
  93. package/dist/src/expr/array.js +103 -53
  94. package/dist/src/expr/array.js.map +1 -1
  95. package/dist/src/expr/ast.d.ts +1 -1
  96. package/dist/src/expr/ast.d.ts.map +1 -1
  97. package/dist/src/expr/ast.js +112 -54
  98. package/dist/src/expr/ast.js.map +1 -1
  99. package/dist/src/expr/asyncfunction.d.ts.map +1 -1
  100. package/dist/src/expr/asyncfunction.js +6 -4
  101. package/dist/src/expr/asyncfunction.js.map +1 -1
  102. package/dist/src/expr/blob.d.ts +48 -0
  103. package/dist/src/expr/blob.d.ts.map +1 -1
  104. package/dist/src/expr/blob.js +63 -8
  105. package/dist/src/expr/blob.js.map +1 -1
  106. package/dist/src/expr/block.d.ts +213 -12
  107. package/dist/src/expr/block.d.ts.map +1 -1
  108. package/dist/src/expr/block.js +796 -293
  109. package/dist/src/expr/block.js.map +1 -1
  110. package/dist/src/expr/boolean.d.ts +44 -0
  111. package/dist/src/expr/boolean.d.ts.map +1 -1
  112. package/dist/src/expr/boolean.js +58 -6
  113. package/dist/src/expr/boolean.js.map +1 -1
  114. package/dist/src/expr/datetime.d.ts +135 -0
  115. package/dist/src/expr/datetime.d.ts.map +1 -1
  116. package/dist/src/expr/datetime.js +184 -34
  117. package/dist/src/expr/datetime.js.map +1 -1
  118. package/dist/src/expr/dict.d.ts +47 -2
  119. package/dist/src/expr/dict.d.ts.map +1 -1
  120. package/dist/src/expr/dict.js +122 -61
  121. package/dist/src/expr/dict.js.map +1 -1
  122. package/dist/src/expr/expr.d.ts +3 -1
  123. package/dist/src/expr/expr.d.ts.map +1 -1
  124. package/dist/src/expr/expr.js +4 -3
  125. package/dist/src/expr/expr.js.map +1 -1
  126. package/dist/src/expr/float.d.ts +153 -0
  127. package/dist/src/expr/float.d.ts.map +1 -1
  128. package/dist/src/expr/float.js +191 -17
  129. package/dist/src/expr/float.js.map +1 -1
  130. package/dist/src/expr/function.d.ts +7 -2
  131. package/dist/src/expr/function.d.ts.map +1 -1
  132. package/dist/src/expr/function.js +6 -4
  133. package/dist/src/expr/function.js.map +1 -1
  134. package/dist/src/expr/index.d.ts +186 -2
  135. package/dist/src/expr/index.d.ts.map +1 -1
  136. package/dist/src/expr/index.js +183 -2
  137. package/dist/src/expr/index.js.map +1 -1
  138. package/dist/src/expr/integer.d.ts +180 -0
  139. package/dist/src/expr/integer.d.ts.map +1 -1
  140. package/dist/src/expr/integer.js +189 -18
  141. package/dist/src/expr/integer.js.map +1 -1
  142. package/dist/src/expr/libs/array.js +3 -3
  143. package/dist/src/expr/libs/array.js.map +1 -1
  144. package/dist/src/expr/libs/blob.js +3 -3
  145. package/dist/src/expr/libs/blob.js.map +1 -1
  146. package/dist/src/expr/libs/dict.js +1 -1
  147. package/dist/src/expr/libs/dict.js.map +1 -1
  148. package/dist/src/expr/libs/matrix.d.ts +17 -0
  149. package/dist/src/expr/libs/matrix.d.ts.map +1 -0
  150. package/dist/src/expr/libs/matrix.js +60 -0
  151. package/dist/src/expr/libs/matrix.js.map +1 -0
  152. package/dist/src/expr/libs/set.js +1 -1
  153. package/dist/src/expr/libs/set.js.map +1 -1
  154. package/dist/src/expr/libs/string.d.ts.map +1 -1
  155. package/dist/src/expr/libs/string.js +2 -1
  156. package/dist/src/expr/libs/string.js.map +1 -1
  157. package/dist/src/expr/libs/vector.d.ts +16 -0
  158. package/dist/src/expr/libs/vector.d.ts.map +1 -0
  159. package/dist/src/expr/libs/vector.js +44 -0
  160. package/dist/src/expr/libs/vector.js.map +1 -0
  161. package/dist/src/expr/matrix.d.ts +109 -0
  162. package/dist/src/expr/matrix.d.ts.map +1 -0
  163. package/dist/src/expr/matrix.js +224 -0
  164. package/dist/src/expr/matrix.js.map +1 -0
  165. package/dist/src/expr/recursive.d.ts +83 -0
  166. package/dist/src/expr/recursive.d.ts.map +1 -0
  167. package/dist/src/expr/recursive.js +99 -0
  168. package/dist/src/expr/recursive.js.map +1 -0
  169. package/dist/src/expr/ref.js +5 -5
  170. package/dist/src/expr/ref.js.map +1 -1
  171. package/dist/src/expr/set.d.ts +44 -2
  172. package/dist/src/expr/set.d.ts.map +1 -1
  173. package/dist/src/expr/set.js +102 -52
  174. package/dist/src/expr/set.js.map +1 -1
  175. package/dist/src/expr/string.d.ts +134 -0
  176. package/dist/src/expr/string.d.ts.map +1 -1
  177. package/dist/src/expr/string.js +173 -23
  178. package/dist/src/expr/string.js.map +1 -1
  179. package/dist/src/expr/struct.d.ts +1 -1
  180. package/dist/src/expr/struct.d.ts.map +1 -1
  181. package/dist/src/expr/struct.js +2 -2
  182. package/dist/src/expr/struct.js.map +1 -1
  183. package/dist/src/expr/types.d.ts +12 -9
  184. package/dist/src/expr/types.d.ts.map +1 -1
  185. package/dist/src/expr/variant.d.ts +108 -11
  186. package/dist/src/expr/variant.d.ts.map +1 -1
  187. package/dist/src/expr/variant.js +76 -38
  188. package/dist/src/expr/variant.js.map +1 -1
  189. package/dist/src/expr/vector.d.ts +102 -0
  190. package/dist/src/expr/vector.d.ts.map +1 -0
  191. package/dist/src/expr/vector.js +202 -0
  192. package/dist/src/expr/vector.js.map +1 -0
  193. package/dist/src/fuzz.d.ts +36 -2
  194. package/dist/src/fuzz.d.ts.map +1 -1
  195. package/dist/src/fuzz.js +409 -77
  196. package/dist/src/fuzz.js.map +1 -1
  197. package/dist/src/index.d.ts +4 -0
  198. package/dist/src/index.d.ts.map +1 -1
  199. package/dist/src/index.js +4 -0
  200. package/dist/src/index.js.map +1 -1
  201. package/dist/src/internal.d.ts +12 -2
  202. package/dist/src/internal.d.ts.map +1 -1
  203. package/dist/src/internal.js +13 -2
  204. package/dist/src/internal.js.map +1 -1
  205. package/dist/src/ir.d.ts +1754 -1484
  206. package/dist/src/ir.d.ts.map +1 -1
  207. package/dist/src/ir.js +51 -34
  208. package/dist/src/ir.js.map +1 -1
  209. package/dist/src/ir.spec.d.ts +2 -0
  210. package/dist/src/ir.spec.d.ts.map +1 -0
  211. package/dist/src/ir.spec.js +35 -0
  212. package/dist/src/ir.spec.js.map +1 -0
  213. package/dist/src/location.d.ts +56 -17
  214. package/dist/src/location.d.ts.map +1 -1
  215. package/dist/src/location.js +226 -29
  216. package/dist/src/location.js.map +1 -1
  217. package/dist/src/location.spec.d.ts +2 -0
  218. package/dist/src/location.spec.d.ts.map +1 -0
  219. package/dist/src/location.spec.js +102 -0
  220. package/dist/src/location.spec.js.map +1 -0
  221. package/dist/src/patch/apply.d.ts +15 -0
  222. package/dist/src/patch/apply.d.ts.map +1 -0
  223. package/dist/src/patch/apply.js +352 -0
  224. package/dist/src/patch/apply.js.map +1 -0
  225. package/dist/src/patch/compose.d.ts +15 -0
  226. package/dist/src/patch/compose.d.ts.map +1 -0
  227. package/dist/src/patch/compose.js +448 -0
  228. package/dist/src/patch/compose.js.map +1 -0
  229. package/dist/src/patch/diff.d.ts +15 -0
  230. package/dist/src/patch/diff.d.ts.map +1 -0
  231. package/dist/src/patch/diff.js +347 -0
  232. package/dist/src/patch/diff.js.map +1 -0
  233. package/dist/src/patch/fuzz.d.ts +73 -0
  234. package/dist/src/patch/fuzz.d.ts.map +1 -0
  235. package/dist/src/patch/fuzz.js +159 -0
  236. package/dist/src/patch/fuzz.js.map +1 -0
  237. package/dist/src/patch/index.d.ts +32 -0
  238. package/dist/src/patch/index.d.ts.map +1 -0
  239. package/dist/src/patch/index.js +48 -0
  240. package/dist/src/patch/index.js.map +1 -0
  241. package/dist/src/patch/invert.d.ts +15 -0
  242. package/dist/src/patch/invert.d.ts.map +1 -0
  243. package/dist/src/patch/invert.js +284 -0
  244. package/dist/src/patch/invert.js.map +1 -0
  245. package/dist/src/patch/merge.d.ts +56 -0
  246. package/dist/src/patch/merge.d.ts.map +1 -0
  247. package/dist/src/patch/merge.js +586 -0
  248. package/dist/src/patch/merge.js.map +1 -0
  249. package/dist/src/patch/merge.spec.d.ts +2 -0
  250. package/dist/src/patch/merge.spec.d.ts.map +1 -0
  251. package/dist/src/patch/merge.spec.js +1139 -0
  252. package/dist/src/patch/merge.spec.js.map +1 -0
  253. package/dist/src/patch/patch.spec.d.ts +2 -0
  254. package/dist/src/patch/patch.spec.d.ts.map +1 -0
  255. package/dist/src/patch/patch.spec.js +452 -0
  256. package/dist/src/patch/patch.spec.js.map +1 -0
  257. package/dist/src/patch/path.d.ts +115 -0
  258. package/dist/src/patch/path.d.ts.map +1 -0
  259. package/dist/src/patch/path.js +192 -0
  260. package/dist/src/patch/path.js.map +1 -0
  261. package/dist/src/patch/path.spec.d.ts +6 -0
  262. package/dist/src/patch/path.spec.d.ts.map +1 -0
  263. package/dist/src/patch/path.spec.js +322 -0
  264. package/dist/src/patch/path.spec.js.map +1 -0
  265. package/dist/src/patch/prune.d.ts +77 -0
  266. package/dist/src/patch/prune.d.ts.map +1 -0
  267. package/dist/src/patch/prune.js +115 -0
  268. package/dist/src/patch/prune.js.map +1 -0
  269. package/dist/src/patch/prune.spec.d.ts +6 -0
  270. package/dist/src/patch/prune.spec.d.ts.map +1 -0
  271. package/dist/src/patch/prune.spec.js +473 -0
  272. package/dist/src/patch/prune.spec.js.map +1 -0
  273. package/dist/src/patch/type_of_patch.d.ts +25 -0
  274. package/dist/src/patch/type_of_patch.d.ts.map +1 -0
  275. package/dist/src/patch/type_of_patch.js +144 -0
  276. package/dist/src/patch/type_of_patch.js.map +1 -0
  277. package/dist/src/patch/types.d.ts +220 -0
  278. package/dist/src/patch/types.d.ts.map +1 -0
  279. package/dist/src/patch/types.js +62 -0
  280. package/dist/src/patch/types.js.map +1 -0
  281. package/dist/src/patch/validate.d.ts +44 -0
  282. package/dist/src/patch/validate.d.ts.map +1 -0
  283. package/dist/src/patch/validate.js +190 -0
  284. package/dist/src/patch/validate.js.map +1 -0
  285. package/dist/src/patch/validate.spec.d.ts +6 -0
  286. package/dist/src/patch/validate.spec.d.ts.map +1 -0
  287. package/dist/src/patch/validate.spec.js +225 -0
  288. package/dist/src/patch/validate.spec.js.map +1 -0
  289. package/dist/src/patch/walk.d.ts +121 -0
  290. package/dist/src/patch/walk.d.ts.map +1 -0
  291. package/dist/src/patch/walk.js +385 -0
  292. package/dist/src/patch/walk.js.map +1 -0
  293. package/dist/src/patch/walk.spec.d.ts +6 -0
  294. package/dist/src/patch/walk.spec.d.ts.map +1 -0
  295. package/dist/src/patch/walk.spec.js +621 -0
  296. package/dist/src/patch/walk.spec.js.map +1 -0
  297. package/dist/src/platform.d.ts +6 -0
  298. package/dist/src/platform.d.ts.map +1 -1
  299. package/dist/src/platform.spec.d.ts +2 -0
  300. package/dist/src/platform.spec.d.ts.map +1 -0
  301. package/dist/src/platform.spec.js +330 -0
  302. package/dist/src/platform.spec.js.map +1 -0
  303. package/dist/src/serialization/beast.d.ts.map +1 -1
  304. package/dist/src/serialization/beast.js +12 -0
  305. package/dist/src/serialization/beast.js.map +1 -1
  306. package/dist/src/serialization/beast.spec.d.ts +6 -0
  307. package/dist/src/serialization/beast.spec.d.ts.map +1 -0
  308. package/dist/src/serialization/beast.spec.js +406 -0
  309. package/dist/src/serialization/beast.spec.js.map +1 -0
  310. package/dist/src/serialization/beast2/index.d.ts +50 -0
  311. package/dist/src/serialization/beast2/index.d.ts.map +1 -0
  312. package/dist/src/serialization/beast2/index.js +756 -0
  313. package/dist/src/serialization/beast2/index.js.map +1 -0
  314. package/dist/src/serialization/beast2/index.spec.d.ts +6 -0
  315. package/dist/src/serialization/beast2/index.spec.d.ts.map +1 -0
  316. package/dist/src/serialization/beast2/index.spec.js +528 -0
  317. package/dist/src/serialization/beast2/index.spec.js.map +1 -0
  318. package/dist/src/serialization/beast2/sourcemap-table.d.ts +29 -0
  319. package/dist/src/serialization/beast2/sourcemap-table.d.ts.map +1 -0
  320. package/dist/src/serialization/beast2/sourcemap-table.js +82 -0
  321. package/dist/src/serialization/beast2/sourcemap-table.js.map +1 -0
  322. package/dist/src/serialization/beast2/string-table.d.ts +16 -0
  323. package/dist/src/serialization/beast2/string-table.d.ts.map +1 -0
  324. package/dist/src/serialization/beast2/string-table.js +38 -0
  325. package/dist/src/serialization/beast2/string-table.js.map +1 -0
  326. package/dist/src/serialization/beast2/type-table.d.ts +86 -0
  327. package/dist/src/serialization/beast2/type-table.d.ts.map +1 -0
  328. package/dist/src/serialization/beast2/type-table.js +618 -0
  329. package/dist/src/serialization/beast2/type-table.js.map +1 -0
  330. package/dist/src/serialization/beast2/value-table.d.ts +40 -0
  331. package/dist/src/serialization/beast2/value-table.d.ts.map +1 -0
  332. package/dist/src/serialization/beast2/value-table.js +157 -0
  333. package/dist/src/serialization/beast2/value-table.js.map +1 -0
  334. package/dist/src/serialization/binary-utils.d.ts +33 -0
  335. package/dist/src/serialization/binary-utils.d.ts.map +1 -1
  336. package/dist/src/serialization/binary-utils.js +157 -0
  337. package/dist/src/serialization/binary-utils.js.map +1 -1
  338. package/dist/src/serialization/csv.d.ts +17 -17
  339. package/dist/src/serialization/csv.d.ts.map +1 -1
  340. package/dist/src/serialization/csv.js +10 -8
  341. package/dist/src/serialization/csv.js.map +1 -1
  342. package/dist/src/serialization/csv.spec.d.ts +2 -0
  343. package/dist/src/serialization/csv.spec.d.ts.map +1 -0
  344. package/dist/src/serialization/csv.spec.js +556 -0
  345. package/dist/src/serialization/csv.spec.js.map +1 -0
  346. package/dist/src/serialization/east-inferred.spec.d.ts +2 -0
  347. package/dist/src/serialization/east-inferred.spec.d.ts.map +1 -0
  348. package/dist/src/serialization/east-inferred.spec.js +322 -0
  349. package/dist/src/serialization/east-inferred.spec.js.map +1 -0
  350. package/dist/src/serialization/east.d.ts +1 -1
  351. package/dist/src/serialization/east.d.ts.map +1 -1
  352. package/dist/src/serialization/east.js +178 -26
  353. package/dist/src/serialization/east.js.map +1 -1
  354. package/dist/src/serialization/east.spec.d.ts +2 -0
  355. package/dist/src/serialization/east.spec.d.ts.map +1 -0
  356. package/dist/src/serialization/east.spec.js +1548 -0
  357. package/dist/src/serialization/east.spec.js.map +1 -0
  358. package/dist/src/serialization/index.d.ts +1 -2
  359. package/dist/src/serialization/index.d.ts.map +1 -1
  360. package/dist/src/serialization/index.js +1 -2
  361. package/dist/src/serialization/index.js.map +1 -1
  362. package/dist/src/serialization/json.d.ts +1 -1
  363. package/dist/src/serialization/json.d.ts.map +1 -1
  364. package/dist/src/serialization/json.js +123 -24
  365. package/dist/src/serialization/json.js.map +1 -1
  366. package/dist/src/serialization/json.spec.d.ts +2 -0
  367. package/dist/src/serialization/json.spec.d.ts.map +1 -0
  368. package/dist/src/serialization/json.spec.js +1297 -0
  369. package/dist/src/serialization/json.spec.js.map +1 -0
  370. package/dist/src/type_of_type.d.ts +72 -35
  371. package/dist/src/type_of_type.d.ts.map +1 -1
  372. package/dist/src/type_of_type.is_data.spec.d.ts +6 -0
  373. package/dist/src/type_of_type.is_data.spec.d.ts.map +1 -0
  374. package/dist/src/type_of_type.is_data.spec.js +221 -0
  375. package/dist/src/type_of_type.is_data.spec.js.map +1 -0
  376. package/dist/src/type_of_type.js +355 -80
  377. package/dist/src/type_of_type.js.map +1 -1
  378. package/dist/src/type_of_type.to_etv.spec.d.ts +6 -0
  379. package/dist/src/type_of_type.to_etv.spec.d.ts.map +1 -0
  380. package/dist/src/type_of_type.to_etv.spec.js +263 -0
  381. package/dist/src/type_of_type.to_etv.spec.js.map +1 -0
  382. package/dist/src/types.d.ts +82 -12
  383. package/dist/src/types.d.ts.map +1 -1
  384. package/dist/src/types.error.spec.d.ts +2 -0
  385. package/dist/src/types.error.spec.d.ts.map +1 -0
  386. package/dist/src/types.error.spec.js +665 -0
  387. package/dist/src/types.error.spec.js.map +1 -0
  388. package/dist/src/types.js +663 -156
  389. package/dist/src/types.js.map +1 -1
  390. package/dist/src/types.spec.d.ts +2 -0
  391. package/dist/src/types.spec.d.ts.map +1 -0
  392. package/dist/src/types.spec.js +946 -0
  393. package/dist/src/types.spec.js.map +1 -0
  394. package/dist/src/walker.d.ts +65 -0
  395. package/dist/src/walker.d.ts.map +1 -0
  396. package/dist/src/walker.js +165 -0
  397. package/dist/src/walker.js.map +1 -0
  398. package/dist/src/walker.spec.d.ts +6 -0
  399. package/dist/src/walker.spec.d.ts.map +1 -0
  400. package/dist/src/walker.spec.js +109 -0
  401. package/dist/src/walker.spec.js.map +1 -0
  402. package/package.json +16 -38
  403. package/dist/src/serialization/beast2-stream.d.ts +0 -38
  404. package/dist/src/serialization/beast2-stream.d.ts.map +0 -1
  405. package/dist/src/serialization/beast2-stream.js +0 -670
  406. package/dist/src/serialization/beast2-stream.js.map +0 -1
  407. package/dist/src/serialization/beast2.d.ts +0 -41
  408. package/dist/src/serialization/beast2.d.ts.map +0 -1
  409. package/dist/src/serialization/beast2.js +0 -495
  410. package/dist/src/serialization/beast2.js.map +0 -1
@@ -0,0 +1,1548 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import { describe, test } from "node:test";
6
+ import assert from "node:assert/strict";
7
+ import { decodeEastFor, encodeEastFor, parseFor, printFor, } from './east.js';
8
+ import { fuzzerTest } from '../fuzz.js';
9
+ import { NullType, BooleanType, IntegerType, FloatType, FunctionType, NeverType, StringType, DateTimeType, BlobType, ArrayType, SetType, DictType, StructType, VariantType, RecursiveType, AsyncFunctionType, VectorType, MatrixType, } from '../types.js';
10
+ import { compareFor, equalFor } from '../comparison.js';
11
+ import { SortedSet } from '../containers/sortedset.js';
12
+ import { SortedMap } from '../containers/sortedmap.js';
13
+ import { variant } from '../containers/variant.js';
14
+ import { matrix } from '../containers/matrix.js';
15
+ describe('parseFor (value parsing)', () => {
16
+ describe('primitive values', () => {
17
+ test('should parse null', () => {
18
+ const parser = parseFor(NullType);
19
+ const result = parser('null');
20
+ assert.equal(result.success, true);
21
+ if (result.success) {
22
+ assert.equal(result.value, null);
23
+ }
24
+ });
25
+ test('should parse booleans', () => {
26
+ const parser = parseFor(BooleanType);
27
+ const trueResult = parser('true');
28
+ assert.equal(trueResult.success, true);
29
+ if (trueResult.success) {
30
+ assert.equal(trueResult.value, true);
31
+ }
32
+ const falseResult = parser('false');
33
+ assert.equal(falseResult.success, true);
34
+ if (falseResult.success) {
35
+ assert.equal(falseResult.value, false);
36
+ }
37
+ });
38
+ test('should parse integers', () => {
39
+ const parser = parseFor(IntegerType);
40
+ const positiveResult = parser('42');
41
+ assert.equal(positiveResult.success, true);
42
+ if (positiveResult.success) {
43
+ assert.equal(positiveResult.value, 42n);
44
+ }
45
+ const negativeResult = parser('-123');
46
+ assert.equal(negativeResult.success, true);
47
+ if (negativeResult.success) {
48
+ assert.equal(negativeResult.value, -123n);
49
+ }
50
+ });
51
+ test('should parse floats', () => {
52
+ const parser = parseFor(FloatType);
53
+ const normalResult = parser('3.14');
54
+ assert.equal(normalResult.success, true);
55
+ if (normalResult.success) {
56
+ assert.equal(normalResult.value, 3.14);
57
+ }
58
+ const infinityResult = parser('Infinity');
59
+ assert.equal(infinityResult.success, true);
60
+ if (infinityResult.success) {
61
+ assert.equal(infinityResult.value, Infinity);
62
+ }
63
+ const nanResult = parser('NaN');
64
+ assert.equal(nanResult.success, true);
65
+ if (nanResult.success) {
66
+ assert.ok(Number.isNaN(nanResult.value));
67
+ }
68
+ });
69
+ test('should parse strings', () => {
70
+ const parser = parseFor(StringType);
71
+ const result = parser('"hello world"');
72
+ assert.equal(result.success, true);
73
+ if (result.success) {
74
+ assert.equal(result.value, 'hello world');
75
+ }
76
+ });
77
+ test('should parse strings with basic content', () => {
78
+ const parser = parseFor(StringType);
79
+ const result = parser('"hello world 123"');
80
+ assert.equal(result.success, true);
81
+ if (result.success) {
82
+ assert.equal(result.value, 'hello world 123');
83
+ }
84
+ });
85
+ test('should error on unsupported escape sequence \\n', () => {
86
+ const parser = parseFor(StringType);
87
+ const result = parser('"hello\\nworld"');
88
+ assert.equal(result.success, false);
89
+ if (!result.success) {
90
+ assert.equal(result.error, 'Error occurred because unexpected escape sequence in string (line 1, col 8) while parsing value of type ".String"');
91
+ }
92
+ });
93
+ test('should error on unsupported escape sequence \\t', () => {
94
+ const parser = parseFor(StringType);
95
+ const result = parser('"hello\\tworld"');
96
+ assert.equal(result.success, false);
97
+ if (!result.success) {
98
+ assert.equal(result.error, 'Error occurred because unexpected escape sequence in string (line 1, col 8) while parsing value of type ".String"');
99
+ }
100
+ });
101
+ test('should parse datetime', () => {
102
+ const parser = parseFor(DateTimeType);
103
+ const result = parser('2022-11-07T23:19:28.438');
104
+ assert.equal(result.success, true);
105
+ if (result.success) {
106
+ assert.deepEqual(result.value, new Date('2022-11-07T23:19:28.438Z'));
107
+ }
108
+ });
109
+ test('should parse blobs', () => {
110
+ const parser = parseFor(BlobType);
111
+ const result = parser('0x48656c6c6f');
112
+ assert.equal(result.success, true);
113
+ if (result.success) {
114
+ assert.deepEqual(result.value, new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]));
115
+ }
116
+ });
117
+ });
118
+ describe('collection values', () => {
119
+ test('should parse empty array', () => {
120
+ const parser = parseFor(ArrayType(StringType));
121
+ const result = parser('[]');
122
+ assert.equal(result.success, true);
123
+ if (result.success) {
124
+ assert.deepEqual(result.value, []);
125
+ }
126
+ });
127
+ test('should parse array with elements', () => {
128
+ const parser = parseFor(ArrayType(IntegerType));
129
+ const result = parser('[1, 2, 3]');
130
+ assert.equal(result.success, true);
131
+ if (result.success) {
132
+ assert.deepEqual(result.value, [1n, 2n, 3n]);
133
+ }
134
+ });
135
+ test('should error on array with trailing comma', () => {
136
+ const parser = parseFor(ArrayType(StringType));
137
+ const result = parser('["a", "b",]');
138
+ assert.equal(result.success, false);
139
+ if (!result.success) {
140
+ assert.equal(result.error, 'Error occurred because expected \'"\', got \']\' at [2] (line 1, col 11) while parsing value of type ".Array .String"');
141
+ }
142
+ });
143
+ test('should parse empty set', () => {
144
+ const type = SetType(StringType);
145
+ const parser = parseFor(type);
146
+ const equal = equalFor(type);
147
+ const compare = compareFor(StringType);
148
+ const result = parser('{}');
149
+ assert.equal(result.success, true);
150
+ if (result.success) {
151
+ assert.ok(equal(result.value, new SortedSet([], compare)));
152
+ }
153
+ });
154
+ test('should parse set with elements', () => {
155
+ const type = SetType(StringType);
156
+ const parser = parseFor(type);
157
+ const equal = equalFor(type);
158
+ const compare = compareFor(StringType);
159
+ const result = parser('{"a", "b", "c"}');
160
+ assert.equal(result.success, true);
161
+ if (result.success) {
162
+ assert.ok(equal(result.value, new SortedSet(['a', 'b', 'c'], compare)));
163
+ }
164
+ });
165
+ test('should error on set with trailing comma', () => {
166
+ const type = SetType(StringType);
167
+ const parser = parseFor(type);
168
+ const result = parser('{"a", "b",}');
169
+ assert.equal(result.success, false);
170
+ if (!result.success) {
171
+ assert.equal(result.error, 'Error occurred because expected \'"\', got \'}\' at [2] (line 1, col 11) while parsing value of type ".Set .String"');
172
+ }
173
+ });
174
+ test('should parse empty dict', () => {
175
+ const type = DictType(StringType, IntegerType);
176
+ const parser = parseFor(type);
177
+ const equal = equalFor(type);
178
+ const compare = compareFor(StringType);
179
+ const result = parser('{:}');
180
+ assert.equal(result.success, true);
181
+ if (result.success) {
182
+ assert.ok(equal(result.value, new SortedMap([], compare)));
183
+ }
184
+ });
185
+ test('should parse dict with entries', () => {
186
+ const type = DictType(StringType, IntegerType);
187
+ const parser = parseFor(type);
188
+ const equal = equalFor(type);
189
+ const compare = compareFor(StringType);
190
+ const result = parser('{"a": 1, "b": 2}');
191
+ assert.equal(result.success, true);
192
+ if (result.success) {
193
+ assert.ok(equal(result.value, new SortedMap([['a', 1n], ['b', 2n]], compare)));
194
+ }
195
+ });
196
+ test('should error on dict with trailing comma', () => {
197
+ const type = DictType(StringType, IntegerType);
198
+ const parser = parseFor(type);
199
+ const result = parser('{"a": 1, "b": 2,}');
200
+ assert.equal(result.success, false);
201
+ if (!result.success) {
202
+ assert.equal(result.error, 'Error occurred because expected \'"\', got \'}\' at [2](key) (line 1, col 17) while parsing value of type ".Dict (key=.String, value=.Integer)"');
203
+ }
204
+ });
205
+ });
206
+ describe('struct values', () => {
207
+ test('should parse empty struct', () => {
208
+ const parser = parseFor(StructType({}));
209
+ const result = parser('()');
210
+ assert.equal(result.success, true);
211
+ if (result.success) {
212
+ assert.deepEqual(result.value, {});
213
+ }
214
+ });
215
+ test('should parse struct with fields', () => {
216
+ const structType = StructType({ name: StringType, age: IntegerType });
217
+ const parser = parseFor(structType);
218
+ const result = parser('(name="Alice", age = 30)');
219
+ assert.equal(result.success, true);
220
+ if (result.success) {
221
+ assert.deepEqual(result.value, { name: 'Alice', age: 30n });
222
+ }
223
+ });
224
+ test('should parse struct with quoted field names', () => {
225
+ const structType = StructType({ 'field name': StringType });
226
+ const parser = parseFor(structType);
227
+ const result = parser('(`field name`="value")');
228
+ assert.equal(result.success, true);
229
+ if (result.success) {
230
+ assert.deepEqual(result.value, { 'field name': 'value' });
231
+ }
232
+ });
233
+ test('should error on missing required field', () => {
234
+ const structType = StructType({ name: StringType, age: IntegerType });
235
+ const parser = parseFor(structType);
236
+ const result = parser('(name="Alice")');
237
+ assert.equal(result.success, false);
238
+ if (!result.success) {
239
+ assert.equal(result.error, 'Error occurred because missing required field \'age\' (line 1, col 14) while parsing value of type ".Struct [(name="name", type=.String), (name="age", type=.Integer)]"');
240
+ }
241
+ });
242
+ test('should error on unknown field', () => {
243
+ const structType = StructType({ name: StringType });
244
+ const parser = parseFor(structType);
245
+ const result = parser('(name="Alice", unknown="value")');
246
+ assert.equal(result.success, false);
247
+ if (!result.success) {
248
+ assert.equal(result.error, 'Error occurred because expected \')\' to close struct (line 1, col 16) while parsing value of type ".Struct [(name="name", type=.String)]"');
249
+ }
250
+ });
251
+ });
252
+ describe('variant values', () => {
253
+ test('should parse nullary variant without explicit null', () => {
254
+ const variantType = VariantType({ success: NullType, error: StringType });
255
+ const parser = parseFor(variantType);
256
+ const result = parser('.success');
257
+ assert.equal(result.success, true);
258
+ if (result.success) {
259
+ assert.equal(result.value.type, 'success');
260
+ assert.equal(result.value.value, null);
261
+ }
262
+ });
263
+ test('should parse nullary variant with null provided', () => {
264
+ const variantType = VariantType({ success: NullType, error: StringType });
265
+ const parser = parseFor(variantType);
266
+ const result = parser('.success null');
267
+ assert.equal(result.success, true);
268
+ if (result.success) {
269
+ assert.equal(result.value.type, 'success');
270
+ assert.equal(result.value.value, null);
271
+ }
272
+ });
273
+ test('should parse variant with data', () => {
274
+ const variantType = VariantType({ success: NullType, error: StringType });
275
+ const parser = parseFor(variantType);
276
+ const result = parser('.error "Something went wrong"');
277
+ assert.equal(result.success, true);
278
+ if (result.success) {
279
+ assert.equal(result.value.type, 'error');
280
+ assert.equal(result.value.value, 'Something went wrong');
281
+ }
282
+ });
283
+ test('should error on unknown variant case', () => {
284
+ const variantType = VariantType({ success: NullType, error: StringType });
285
+ const parser = parseFor(variantType);
286
+ const result = parser('.unknown');
287
+ assert.equal(result.success, false);
288
+ if (!result.success) {
289
+ assert.equal(result.error, 'Error occurred because unknown variant case .unknown, expected one of: .error, .success (line 1, col 2) while parsing value of type ".Variant [(name="error", type=.String), (name="success", type=.Null)]"');
290
+ }
291
+ });
292
+ test('should error on variant case with incorrect payload', () => {
293
+ const variantType = VariantType({ success: NullType, error: StringType });
294
+ const parser = parseFor(variantType);
295
+ const result = parser('.error 42');
296
+ assert.equal(result.success, false);
297
+ if (!result.success) {
298
+ assert.equal(result.error, 'Error occurred because expected \'"\', got \'4\' at .error (line 1, col 8) while parsing value of type ".Variant [(name="error", type=.String), (name="success", type=.Null)]"');
299
+ }
300
+ });
301
+ test('should error when data is provided for nullary case', () => {
302
+ const variantType = VariantType({ success: NullType, error: StringType });
303
+ const parser = parseFor(variantType);
304
+ const result = parser('.success "unexpected"');
305
+ assert.equal(result.success, false);
306
+ if (!result.success) {
307
+ assert.equal(result.error, 'Error occurred because expected null, got \'"\' at .success (line 1, col 10) while parsing value of type ".Variant [(name="error", type=.String), (name="success", type=.Null)]"');
308
+ }
309
+ });
310
+ test('should error when no data is provided for data case', () => {
311
+ const variantType = VariantType({ success: NullType, error: StringType });
312
+ const parser = parseFor(variantType);
313
+ const result = parser('.error');
314
+ assert.equal(result.success, false);
315
+ if (!result.success) {
316
+ assert.equal(result.error, 'Error occurred because expected \'"\', got end of input at .error (line 1, col 7) while parsing value of type ".Variant [(name="error", type=.String), (name="success", type=.Null)]"');
317
+ }
318
+ });
319
+ });
320
+ describe('complex nested values', () => {
321
+ test('should parse complex nested structure', () => {
322
+ const complexType = StructType({
323
+ users: ArrayType(StructType({
324
+ name: StringType,
325
+ age: IntegerType
326
+ }))
327
+ });
328
+ const parser = parseFor(complexType);
329
+ const equal = equalFor(complexType);
330
+ const input = `(
331
+ users = [
332
+ (name="Alice", age=30),
333
+ (name="Bob", age=25)
334
+ ]
335
+ )`;
336
+ const result = parser(input);
337
+ assert.equal(result.success, true);
338
+ if (result.success) {
339
+ assert.ok(equal(result.value, {
340
+ users: [
341
+ { name: 'Alice', age: 30n },
342
+ { name: 'Bob', age: 25n }
343
+ ]
344
+ }));
345
+ }
346
+ });
347
+ test('should parse deeply nested structure with multiple collection types', () => {
348
+ // Dict<String, Struct{ items: Array<Variant<success: Struct{id: Integer, tags: Set<String>}, error: String>> }>
349
+ const deepType = DictType(StringType, StructType({
350
+ items: ArrayType(VariantType({
351
+ success: StructType({
352
+ id: IntegerType,
353
+ tags: SetType(StringType)
354
+ }),
355
+ error: StringType
356
+ }))
357
+ }));
358
+ const parser = parseFor(deepType);
359
+ const equal = equalFor(deepType);
360
+ const compare = compareFor(StringType);
361
+ const input = `{
362
+ "store1": (items=[
363
+ .success (id=1, tags={"urgent", "verified"}),
364
+ .success (id=2, tags={"pending"})
365
+ ]),
366
+ "store2": (items=[
367
+ .error "Failed to load",
368
+ .success (id=3, tags={})
369
+ ])
370
+ }`;
371
+ const result = parser(input);
372
+ assert.equal(result.success, true);
373
+ if (result.success) {
374
+ const expected = new SortedMap([
375
+ ['store1', {
376
+ items: [
377
+ variant('success', { id: 1n, tags: new SortedSet(['urgent', 'verified'], compare) }),
378
+ variant('success', { id: 2n, tags: new SortedSet(['pending'], compare) })
379
+ ]
380
+ }],
381
+ ['store2', {
382
+ items: [
383
+ variant('error', 'Failed to load'),
384
+ variant('success', { id: 3n, tags: new SortedSet([], compare) })
385
+ ]
386
+ }]
387
+ ], compare);
388
+ assert.ok(equal(result.value, expected));
389
+ }
390
+ });
391
+ });
392
+ describe('vector values', () => {
393
+ test('should parse float vector', () => {
394
+ const type = VectorType(FloatType);
395
+ const parser = parseFor(type);
396
+ const equal = equalFor(type);
397
+ const result = parser('vec[1.0, 2.0, 3.0]');
398
+ assert.equal(result.success, true);
399
+ if (result.success) {
400
+ assert.ok(equal(result.value, new Float64Array([1.0, 2.0, 3.0])));
401
+ }
402
+ });
403
+ test('should parse empty float vector', () => {
404
+ const type = VectorType(FloatType);
405
+ const parser = parseFor(type);
406
+ const equal = equalFor(type);
407
+ const result = parser('vec[]');
408
+ assert.equal(result.success, true);
409
+ if (result.success) {
410
+ assert.ok(equal(result.value, new Float64Array([])));
411
+ }
412
+ });
413
+ test('should parse integer vector', () => {
414
+ const type = VectorType(IntegerType);
415
+ const parser = parseFor(type);
416
+ const equal = equalFor(type);
417
+ const result = parser('vec[10, 20, 30]');
418
+ assert.equal(result.success, true);
419
+ if (result.success) {
420
+ assert.ok(equal(result.value, new BigInt64Array([10n, 20n, 30n])));
421
+ }
422
+ });
423
+ test('should parse boolean vector', () => {
424
+ const type = VectorType(BooleanType);
425
+ const parser = parseFor(type);
426
+ const equal = equalFor(type);
427
+ const result = parser('vec[true, false, true]');
428
+ assert.equal(result.success, true);
429
+ if (result.success) {
430
+ assert.ok(equal(result.value, new Uint8ClampedArray([1, 0, 1])));
431
+ }
432
+ });
433
+ test('should parse vector with special floats', () => {
434
+ const type = VectorType(FloatType);
435
+ const parser = parseFor(type);
436
+ const equal = equalFor(type);
437
+ const result = parser('vec[NaN, Infinity, -Infinity]');
438
+ assert.equal(result.success, true);
439
+ if (result.success) {
440
+ assert.ok(equal(result.value, new Float64Array([NaN, Infinity, -Infinity])));
441
+ }
442
+ });
443
+ });
444
+ describe('matrix values', () => {
445
+ test('should parse float matrix', () => {
446
+ const type = MatrixType(FloatType);
447
+ const parser = parseFor(type);
448
+ const equal = equalFor(type);
449
+ const result = parser('mat[[1.0, 2.0], [3.0, 4.0]]');
450
+ assert.equal(result.success, true);
451
+ if (result.success) {
452
+ assert.ok(equal(result.value, matrix(new Float64Array([1.0, 2.0, 3.0, 4.0]), 2, 2)));
453
+ }
454
+ });
455
+ test('should parse empty matrix', () => {
456
+ const type = MatrixType(FloatType);
457
+ const parser = parseFor(type);
458
+ const equal = equalFor(type);
459
+ const result = parser('mat[]');
460
+ assert.equal(result.success, true);
461
+ if (result.success) {
462
+ assert.ok(equal(result.value, matrix(new Float64Array([]), 0, 0)));
463
+ }
464
+ });
465
+ test('should parse integer matrix', () => {
466
+ const type = MatrixType(IntegerType);
467
+ const parser = parseFor(type);
468
+ const equal = equalFor(type);
469
+ const result = parser('mat[[1, 2, 3], [4, 5, 6]]');
470
+ assert.equal(result.success, true);
471
+ if (result.success) {
472
+ assert.ok(equal(result.value, matrix(new BigInt64Array([1n, 2n, 3n, 4n, 5n, 6n]), 2, 3)));
473
+ }
474
+ });
475
+ });
476
+ describe('error cases', () => {
477
+ test('should return error for type mismatch', () => {
478
+ const parser = parseFor(IntegerType);
479
+ const result = parser('"not a number"');
480
+ assert.equal(result.success, false);
481
+ if (!result.success) {
482
+ assert.equal(result.error, 'Error occurred because expected integer, got \'"\' (line 1, col 1) while parsing value of type ".Integer"');
483
+ }
484
+ });
485
+ test('should return error for malformed input', () => {
486
+ const parser = parseFor(ArrayType(StringType));
487
+ const result = parser('[unclosed array');
488
+ assert.equal(result.success, false);
489
+ if (!result.success) {
490
+ assert.equal(result.error, 'Error occurred because expected \'"\', got \'u\' at [0] (line 1, col 2) while parsing value of type ".Array .String"');
491
+ }
492
+ });
493
+ test('should return error for extra tokens', () => {
494
+ const parser = parseFor(StringType);
495
+ const result = parser('"hello" extra');
496
+ assert.equal(result.success, false);
497
+ if (!result.success) {
498
+ assert.equal(result.error, 'Error occurred because unexpected input after parsed value (line 1, col 9) while parsing value of type ".String"');
499
+ }
500
+ });
501
+ });
502
+ });
503
+ describe('printFor and round-trip tests', () => {
504
+ describe('primitive types round-trip', () => {
505
+ test('null should round-trip', () => {
506
+ const printer = printFor(NullType);
507
+ const parser = parseFor(NullType);
508
+ const equal = equalFor(NullType);
509
+ const value = null;
510
+ const printed = printer(value);
511
+ assert.equal(printed, 'null');
512
+ const result = parser(printed);
513
+ assert.equal(result.success, true);
514
+ if (result.success) {
515
+ assert.ok(equal(result.value, value));
516
+ }
517
+ });
518
+ test('booleans should round-trip', () => {
519
+ const printer = printFor(BooleanType);
520
+ const parser = parseFor(BooleanType);
521
+ const equal = equalFor(BooleanType);
522
+ const testValues = [true, false];
523
+ for (const value of testValues) {
524
+ const printed = printer(value);
525
+ assert.equal(printed, value.toString());
526
+ const result = parser(printed);
527
+ assert.equal(result.success, true);
528
+ if (result.success) {
529
+ assert.ok(equal(result.value, value));
530
+ }
531
+ }
532
+ });
533
+ test('integers should round-trip', () => {
534
+ const printer = printFor(IntegerType);
535
+ const parser = parseFor(IntegerType);
536
+ const equal = equalFor(IntegerType);
537
+ const testValues = [0n, 42n, -123n, 999999n, -999999n];
538
+ for (const value of testValues) {
539
+ const printed = printer(value);
540
+ assert.equal(printed, value.toString());
541
+ const result = parser(printed);
542
+ assert.equal(result.success, true);
543
+ if (result.success) {
544
+ assert.ok(equal(result.value, value));
545
+ }
546
+ }
547
+ });
548
+ test('floats should round-trip', () => {
549
+ const printer = printFor(FloatType);
550
+ const parser = parseFor(FloatType);
551
+ const testValues = [
552
+ { value: 3.14, expected: '3.14' },
553
+ { value: 0, expected: '0.0' },
554
+ { value: 1, expected: '1.0' },
555
+ { value: -5, expected: '-5.0' },
556
+ { value: Infinity, expected: 'Infinity' },
557
+ { value: -Infinity, expected: '-Infinity' },
558
+ { value: NaN, expected: 'NaN' },
559
+ ];
560
+ for (const { value, expected } of testValues) {
561
+ const printed = printer(value);
562
+ assert.equal(printed, expected, `Float ${value} should print as ${expected}`);
563
+ const result = parser(printed);
564
+ assert.equal(result.success, true);
565
+ if (result.success) {
566
+ if (Number.isNaN(value)) {
567
+ assert.ok(Number.isNaN(result.value));
568
+ }
569
+ else {
570
+ assert.equal(result.value, value);
571
+ }
572
+ }
573
+ }
574
+ });
575
+ test('strings should round-trip', () => {
576
+ const printer = printFor(StringType);
577
+ const parser = parseFor(StringType);
578
+ const equal = equalFor(StringType);
579
+ const testValues = [
580
+ '',
581
+ 'hello',
582
+ 'hello world',
583
+ 'with "quotes"',
584
+ 'with \\backslash',
585
+ 'with \\\\double backslash',
586
+ ];
587
+ for (const value of testValues) {
588
+ const printed = printer(value);
589
+ const result = parser(printed);
590
+ assert.equal(result.success, true, `Failed to parse: ${printed}`);
591
+ if (result.success) {
592
+ assert.ok(equal(result.value, value), `Round-trip failed for: ${value}`);
593
+ }
594
+ }
595
+ });
596
+ test('datetime should round-trip', () => {
597
+ const printer = printFor(DateTimeType);
598
+ const parser = parseFor(DateTimeType);
599
+ const equal = equalFor(DateTimeType);
600
+ const testValues = [
601
+ new Date('2022-11-07T23:19:28.438Z'),
602
+ new Date('2000-01-01T00:00:00.000Z'),
603
+ new Date('1970-01-01T00:00:00.000Z'),
604
+ ];
605
+ for (const value of testValues) {
606
+ const printed = printer(value);
607
+ const result = parser(printed);
608
+ assert.equal(result.success, true);
609
+ if (result.success) {
610
+ assert.ok(equal(result.value, value));
611
+ }
612
+ }
613
+ });
614
+ test('blobs should round-trip', () => {
615
+ const printer = printFor(BlobType);
616
+ const parser = parseFor(BlobType);
617
+ const equal = equalFor(BlobType);
618
+ const testValues = [
619
+ new Uint8Array([]),
620
+ new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]),
621
+ new Uint8Array([0, 255, 127, 128]),
622
+ ];
623
+ for (const value of testValues) {
624
+ const printed = printer(value);
625
+ const result = parser(printed);
626
+ assert.equal(result.success, true);
627
+ if (result.success) {
628
+ assert.ok(equal(result.value, value));
629
+ }
630
+ }
631
+ });
632
+ });
633
+ describe('collection types round-trip', () => {
634
+ test('arrays should round-trip', () => {
635
+ const type = ArrayType(IntegerType);
636
+ const printer = printFor(type);
637
+ const parser = parseFor(type);
638
+ const equal = equalFor(type);
639
+ const testValues = [
640
+ [],
641
+ [1n, 2n, 3n],
642
+ [0n],
643
+ [-1n, -2n, -3n],
644
+ ];
645
+ for (const value of testValues) {
646
+ const printed = printer(value);
647
+ const result = parser(printed);
648
+ assert.equal(result.success, true);
649
+ if (result.success) {
650
+ assert.ok(equal(result.value, value));
651
+ }
652
+ }
653
+ });
654
+ test('sets should round-trip', () => {
655
+ const type = SetType(StringType);
656
+ const printer = printFor(type);
657
+ const parser = parseFor(type);
658
+ const equal = equalFor(type);
659
+ const compare = compareFor(StringType);
660
+ const testValues = [
661
+ new SortedSet([], compare),
662
+ new SortedSet(['a', 'b', 'c'], compare),
663
+ new SortedSet(['single'], compare),
664
+ ];
665
+ for (const value of testValues) {
666
+ const printed = printer(value);
667
+ const result = parser(printed);
668
+ assert.equal(result.success, true);
669
+ if (result.success) {
670
+ assert.ok(equal(result.value, value));
671
+ }
672
+ }
673
+ });
674
+ test('dicts should round-trip', () => {
675
+ const type = DictType(StringType, IntegerType);
676
+ const printer = printFor(type);
677
+ const parser = parseFor(type);
678
+ const equal = equalFor(type);
679
+ const compare = compareFor(StringType);
680
+ const testValues = [
681
+ new SortedMap([], compare),
682
+ new SortedMap([['a', 1n], ['b', 2n]], compare),
683
+ new SortedMap([['key', 42n]], compare),
684
+ ];
685
+ for (const value of testValues) {
686
+ const printed = printer(value);
687
+ const result = parser(printed);
688
+ assert.equal(result.success, true);
689
+ if (result.success) {
690
+ assert.ok(equal(result.value, value));
691
+ }
692
+ }
693
+ });
694
+ });
695
+ describe('struct and variant types round-trip', () => {
696
+ test('empty struct should round-trip', () => {
697
+ const type = StructType({});
698
+ const printer = printFor(type);
699
+ const parser = parseFor(type);
700
+ const equal = equalFor(type);
701
+ const value = {};
702
+ const printed = printer(value);
703
+ assert.equal(printed, '()');
704
+ const result = parser(printed);
705
+ assert.equal(result.success, true);
706
+ if (result.success) {
707
+ assert.ok(equal(result.value, value));
708
+ }
709
+ });
710
+ test('struct with fields should round-trip', () => {
711
+ const type = StructType({ name: StringType, age: IntegerType });
712
+ const printer = printFor(type);
713
+ const parser = parseFor(type);
714
+ const equal = equalFor(type);
715
+ const testValues = [
716
+ { name: 'Alice', age: 30n },
717
+ { name: 'Bob', age: 25n },
718
+ ];
719
+ for (const value of testValues) {
720
+ const printed = printer(value);
721
+ const result = parser(printed);
722
+ assert.equal(result.success, true);
723
+ if (result.success) {
724
+ assert.ok(equal(result.value, value));
725
+ }
726
+ }
727
+ });
728
+ test('struct with quoted field names should round-trip', () => {
729
+ const type = StructType({ 'field name': StringType, 'another-field': IntegerType });
730
+ const printer = printFor(type);
731
+ const parser = parseFor(type);
732
+ const equal = equalFor(type);
733
+ const value = { 'field name': 'test', 'another-field': 42n };
734
+ const printed = printer(value);
735
+ const result = parser(printed);
736
+ assert.equal(result.success, true);
737
+ if (result.success) {
738
+ assert.ok(equal(result.value, value));
739
+ }
740
+ });
741
+ test('variant nullary case should round-trip', () => {
742
+ const type = VariantType({ success: NullType, error: StringType });
743
+ const printer = printFor(type);
744
+ const parser = parseFor(type);
745
+ const equal = equalFor(type);
746
+ const value = variant('success');
747
+ const printed = printer(value);
748
+ assert.equal(printed, '.success');
749
+ const result = parser(printed);
750
+ assert.equal(result.success, true);
751
+ if (result.success) {
752
+ assert.ok(equal(result.value, value));
753
+ }
754
+ });
755
+ test('variant with data should round-trip', () => {
756
+ const type = VariantType({ success: NullType, error: StringType });
757
+ const printer = printFor(type);
758
+ const parser = parseFor(type);
759
+ const equal = equalFor(type);
760
+ const value = variant('error', 'Something went wrong');
761
+ const printed = printer(value);
762
+ const result = parser(printed);
763
+ assert.equal(result.success, true);
764
+ if (result.success) {
765
+ assert.ok(equal(result.value, value));
766
+ }
767
+ });
768
+ });
769
+ describe('complex nested structures round-trip', () => {
770
+ test('nested arrays should round-trip', () => {
771
+ const type = ArrayType(ArrayType(IntegerType));
772
+ const printer = printFor(type);
773
+ const parser = parseFor(type);
774
+ const equal = equalFor(type);
775
+ const value = [[1n, 2n], [3n, 4n], []];
776
+ const printed = printer(value);
777
+ const result = parser(printed);
778
+ assert.equal(result.success, true);
779
+ if (result.success) {
780
+ assert.ok(equal(result.value, value));
781
+ }
782
+ });
783
+ test('struct with array field should round-trip', () => {
784
+ const type = StructType({
785
+ users: ArrayType(StructType({
786
+ name: StringType,
787
+ age: IntegerType
788
+ }))
789
+ });
790
+ const printer = printFor(type);
791
+ const parser = parseFor(type);
792
+ const equal = equalFor(type);
793
+ const value = {
794
+ users: [
795
+ { name: 'Alice', age: 30n },
796
+ { name: 'Bob', age: 25n }
797
+ ]
798
+ };
799
+ const printed = printer(value);
800
+ const result = parser(printed);
801
+ assert.equal(result.success, true);
802
+ if (result.success) {
803
+ assert.ok(equal(result.value, value));
804
+ }
805
+ });
806
+ test('deeply nested structure should round-trip', () => {
807
+ const type = DictType(StringType, StructType({
808
+ items: ArrayType(VariantType({
809
+ success: StructType({
810
+ id: IntegerType,
811
+ tags: SetType(StringType)
812
+ }),
813
+ error: StringType
814
+ }))
815
+ }));
816
+ const printer = printFor(type);
817
+ const parser = parseFor(type);
818
+ const equal = equalFor(type);
819
+ const compare = compareFor(StringType);
820
+ const value = new SortedMap([
821
+ ['store1', {
822
+ items: [
823
+ variant('success', { id: 1n, tags: new SortedSet(['urgent', 'verified'], compare) }),
824
+ variant('success', { id: 2n, tags: new SortedSet(['pending'], compare) })
825
+ ]
826
+ }],
827
+ ['store2', {
828
+ items: [
829
+ variant('error', 'Failed to load'),
830
+ variant('success', { id: 3n, tags: new SortedSet([], compare) })
831
+ ]
832
+ }]
833
+ ], compare);
834
+ const printed = printer(value);
835
+ const result = parser(printed);
836
+ assert.equal(result.success, true);
837
+ if (result.success) {
838
+ assert.ok(equal(result.value, value));
839
+ }
840
+ });
841
+ });
842
+ describe('vector and matrix types round-trip', () => {
843
+ test('float vector should round-trip', () => {
844
+ const type = VectorType(FloatType);
845
+ const printer = printFor(type);
846
+ const parser = parseFor(type);
847
+ const equal = equalFor(type);
848
+ const values = [
849
+ new Float64Array([]),
850
+ new Float64Array([1.0, 2.5, 3.14]),
851
+ new Float64Array([NaN, Infinity, -Infinity, -0.0]),
852
+ ];
853
+ for (const value of values) {
854
+ const printed = printer(value);
855
+ const result = parser(printed);
856
+ assert.equal(result.success, true);
857
+ if (result.success) {
858
+ assert.ok(equal(result.value, value), `Round-trip failed for ${printed}`);
859
+ }
860
+ }
861
+ });
862
+ test('integer vector should round-trip', () => {
863
+ const type = VectorType(IntegerType);
864
+ const printer = printFor(type);
865
+ const parser = parseFor(type);
866
+ const equal = equalFor(type);
867
+ const values = [
868
+ new BigInt64Array([]),
869
+ new BigInt64Array([1n, -2n, 300n]),
870
+ new BigInt64Array([9223372036854775807n, -9223372036854775808n]),
871
+ ];
872
+ for (const value of values) {
873
+ const printed = printer(value);
874
+ const result = parser(printed);
875
+ assert.equal(result.success, true);
876
+ if (result.success) {
877
+ assert.ok(equal(result.value, value), `Round-trip failed for ${printed}`);
878
+ }
879
+ }
880
+ });
881
+ test('boolean vector should round-trip', () => {
882
+ const type = VectorType(BooleanType);
883
+ const printer = printFor(type);
884
+ const parser = parseFor(type);
885
+ const equal = equalFor(type);
886
+ const values = [
887
+ new Uint8ClampedArray([]),
888
+ new Uint8ClampedArray([1, 0, 1, 1, 0]),
889
+ ];
890
+ for (const value of values) {
891
+ const printed = printer(value);
892
+ const result = parser(printed);
893
+ assert.equal(result.success, true);
894
+ if (result.success) {
895
+ assert.ok(equal(result.value, value), `Round-trip failed for ${printed}`);
896
+ }
897
+ }
898
+ });
899
+ test('float matrix should round-trip', () => {
900
+ const type = MatrixType(FloatType);
901
+ const printer = printFor(type);
902
+ const parser = parseFor(type);
903
+ const equal = equalFor(type);
904
+ const values = [
905
+ matrix(new Float64Array([]), 0, 0),
906
+ matrix(new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]), 2, 3),
907
+ matrix(new Float64Array([NaN, Infinity, -Infinity, 0.0]), 2, 2),
908
+ ];
909
+ for (const value of values) {
910
+ const printed = printer(value);
911
+ const result = parser(printed);
912
+ assert.equal(result.success, true);
913
+ if (result.success) {
914
+ assert.ok(equal(result.value, value), `Round-trip failed for ${printed}`);
915
+ }
916
+ }
917
+ });
918
+ test('integer matrix should round-trip', () => {
919
+ const type = MatrixType(IntegerType);
920
+ const printer = printFor(type);
921
+ const parser = parseFor(type);
922
+ const equal = equalFor(type);
923
+ const values = [
924
+ matrix(new BigInt64Array([]), 0, 0),
925
+ matrix(new BigInt64Array([1n, 2n, 3n, 4n]), 2, 2),
926
+ ];
927
+ for (const value of values) {
928
+ const printed = printer(value);
929
+ const result = parser(printed);
930
+ assert.equal(result.success, true);
931
+ if (result.success) {
932
+ assert.ok(equal(result.value, value), `Round-trip failed for ${printed}`);
933
+ }
934
+ }
935
+ });
936
+ });
937
+ describe('printFor edge cases', () => {
938
+ test('float formatting edge cases', () => {
939
+ const printer = printFor(FloatType);
940
+ // Integers should always have .0
941
+ assert.equal(printer(0), '0.0');
942
+ assert.equal(printer(1), '1.0');
943
+ assert.equal(printer(-1), '-1.0');
944
+ assert.equal(printer(100), '100.0');
945
+ // Decimals should be preserved
946
+ assert.equal(printer(3.14), '3.14');
947
+ assert.equal(printer(-2.5), '-2.5');
948
+ // Special values
949
+ assert.equal(printer(Infinity), 'Infinity');
950
+ assert.equal(printer(-Infinity), '-Infinity');
951
+ assert.equal(printer(NaN), 'NaN');
952
+ });
953
+ test('string escaping', () => {
954
+ const printer = printFor(StringType);
955
+ const parser = parseFor(StringType);
956
+ const testCases = [
957
+ { input: 'hello', expected: '"hello"' },
958
+ { input: 'with "quotes"', expected: '"with \\"quotes\\""' },
959
+ { input: 'with \\backslash', expected: '"with \\\\backslash"' },
960
+ ];
961
+ for (const { input, expected } of testCases) {
962
+ const printed = printer(input);
963
+ assert.equal(printed, expected);
964
+ const result = parser(printed);
965
+ assert.equal(result.success, true);
966
+ if (result.success) {
967
+ assert.equal(result.value, input);
968
+ }
969
+ }
970
+ });
971
+ test('identifier quoting in structs', () => {
972
+ const type = StructType({
973
+ normal: IntegerType,
974
+ 'needs quotes': IntegerType,
975
+ 'special-chars!': IntegerType
976
+ });
977
+ const printer = printFor(type);
978
+ const parser = parseFor(type);
979
+ const equal = equalFor(type);
980
+ const value = {
981
+ normal: 1n,
982
+ 'needs quotes': 2n,
983
+ 'special-chars!': 3n
984
+ };
985
+ const printed = printer(value);
986
+ // Should contain backticks for identifiers with spaces/special chars
987
+ assert.ok(printed.includes('`needs quotes`'));
988
+ assert.ok(printed.includes('`special-chars!`'));
989
+ assert.ok(printed.includes('normal='));
990
+ const result = parser(printed);
991
+ assert.equal(result.success, true);
992
+ if (result.success) {
993
+ assert.ok(equal(result.value, value));
994
+ }
995
+ });
996
+ test('empty collections formatting', () => {
997
+ const arrayPrinter = printFor(ArrayType(IntegerType));
998
+ const setPrinter = printFor(SetType(IntegerType));
999
+ const dictPrinter = printFor(DictType(IntegerType, IntegerType));
1000
+ const compare = compareFor(IntegerType);
1001
+ assert.equal(arrayPrinter([]), '[]');
1002
+ assert.equal(setPrinter(new SortedSet([], compare)), '{}');
1003
+ assert.equal(dictPrinter(new SortedMap([], compare)), '{:}');
1004
+ });
1005
+ test('variant case formatting', () => {
1006
+ const type = VariantType({
1007
+ none: NullType,
1008
+ some: IntegerType,
1009
+ 'complex-name': StringType
1010
+ });
1011
+ const printer = printFor(type);
1012
+ assert.equal(printer(variant('none', null)), '.none');
1013
+ assert.equal(printer(variant('some', 42n)), '.some 42');
1014
+ assert.equal(printer(variant('complex-name', 'test')), '.`complex-name` "test"');
1015
+ });
1016
+ });
1017
+ });
1018
+ describe('encodeEastFor and decodeEastFor (Uint8Array encoding)', () => {
1019
+ test('should encode/decode integers with Uint8Array', () => {
1020
+ const encode = encodeEastFor(IntegerType);
1021
+ const decode = decodeEastFor(IntegerType);
1022
+ const value = 42n;
1023
+ const encoded = encode(value);
1024
+ const decoded = decode(encoded);
1025
+ assert.ok(encoded instanceof Uint8Array);
1026
+ assert.strictEqual(decoded, value);
1027
+ });
1028
+ test('should encode/decode structs with Uint8Array', () => {
1029
+ const type = StructType({ name: StringType, age: IntegerType });
1030
+ const encode = encodeEastFor(type);
1031
+ const decode = decodeEastFor(type);
1032
+ const value = { name: 'Alice', age: 30n };
1033
+ const encoded = encode(value);
1034
+ const decoded = decode(encoded);
1035
+ assert.deepEqual(decoded, value);
1036
+ });
1037
+ test('should throw error when decoding invalid East format', () => {
1038
+ const textEncoder = new TextEncoder();
1039
+ const decode = decodeEastFor(IntegerType);
1040
+ const invalidData = textEncoder.encode('not an integer');
1041
+ assert.throws(() => decode(invalidData), /Failed to decode East value/);
1042
+ });
1043
+ });
1044
+ describe('Never type handling', () => {
1045
+ test('should throw when printing Never type', () => {
1046
+ const printer = printFor(NeverType);
1047
+ assert.throws(() => printer(null), /Attempted to print value of type/);
1048
+ });
1049
+ test('should throw when parsing Never type', () => {
1050
+ const parser = parseFor(NeverType);
1051
+ const result = parser("");
1052
+ assert.strictEqual(result.success, false);
1053
+ if (!result.success) {
1054
+ assert.match(result.error, /Attempted to parse value of type .Never/);
1055
+ }
1056
+ });
1057
+ });
1058
+ describe('Function type handling', () => {
1059
+ test('should print Function type summary', () => {
1060
+ const funcType = FunctionType([], IntegerType);
1061
+ const printer = printFor(funcType);
1062
+ const result = printer((() => 42));
1063
+ assert.strictEqual(result, '() => .Integer');
1064
+ });
1065
+ test('should throw when creating parser for Function type', () => {
1066
+ const funcType = FunctionType([], IntegerType);
1067
+ assert.throws(() => parseFor(funcType), /Cannot parse/);
1068
+ });
1069
+ test('should print AsyncFunction type summary', () => {
1070
+ const funcType = AsyncFunctionType([], IntegerType);
1071
+ const printer = printFor(funcType);
1072
+ const result = printer((async () => 42));
1073
+ assert.strictEqual(result, 'async () => .Integer');
1074
+ });
1075
+ test('should throw when creating parser for Function type', () => {
1076
+ const funcType = FunctionType([], IntegerType);
1077
+ assert.throws(() => parseFor(funcType), /Cannot parse/);
1078
+ });
1079
+ });
1080
+ describe('Frozen parameter tests', () => {
1081
+ test('should freeze DateTime when frozen=true', () => {
1082
+ const parser = parseFor(DateTimeType, true);
1083
+ const result = parser('2022-11-07T23:19:28.438');
1084
+ assert.strictEqual(result.success, true);
1085
+ if (result.success) {
1086
+ assert.ok(Object.isFrozen(result.value));
1087
+ }
1088
+ });
1089
+ test('should not freeze DateTime when frozen=false', () => {
1090
+ const parser = parseFor(DateTimeType, false);
1091
+ const result = parser('2022-11-07T23:19:28.438');
1092
+ assert.strictEqual(result.success, true);
1093
+ if (result.success) {
1094
+ assert.ok(!Object.isFrozen(result.value));
1095
+ }
1096
+ });
1097
+ test('should attempt to freeze Blob when frozen=true', () => {
1098
+ // Note: Uint8Array freezing may throw in some environments
1099
+ const parser = parseFor(BlobType, true);
1100
+ // This tests the frozen code path
1101
+ try {
1102
+ const result = parser('0x48656c6c6f');
1103
+ if (result.success) {
1104
+ // If it didn't throw, check if frozen
1105
+ assert.ok(Object.isFrozen(result.value) || !Object.isFrozen(result.value));
1106
+ }
1107
+ }
1108
+ catch (e) {
1109
+ // Freezing Uint8Array may throw
1110
+ assert.ok(e.message.includes('freeze') || e.message.includes('Blob'));
1111
+ }
1112
+ });
1113
+ test('should freeze Array when frozen=true', () => {
1114
+ const parser = parseFor(ArrayType(IntegerType), true);
1115
+ const result = parser('[1, 2, 3]');
1116
+ assert.strictEqual(result.success, true);
1117
+ if (result.success) {
1118
+ assert.ok(Object.isFrozen(result.value));
1119
+ }
1120
+ });
1121
+ test('should freeze Set when frozen=true', () => {
1122
+ const parser = parseFor(SetType(StringType), true);
1123
+ const result = parser('{"a", "b"}');
1124
+ assert.strictEqual(result.success, true);
1125
+ if (result.success) {
1126
+ assert.ok(Object.isFrozen(result.value));
1127
+ }
1128
+ });
1129
+ test('should freeze Dict when frozen=true', () => {
1130
+ const parser = parseFor(DictType(StringType, IntegerType), true);
1131
+ const result = parser('{"a": 1, "b": 2}');
1132
+ assert.strictEqual(result.success, true);
1133
+ if (result.success) {
1134
+ assert.ok(Object.isFrozen(result.value));
1135
+ }
1136
+ });
1137
+ test('should freeze Struct when frozen=true', () => {
1138
+ const parser = parseFor(StructType({ x: IntegerType }), true);
1139
+ const result = parser('(x=42)');
1140
+ assert.strictEqual(result.success, true);
1141
+ if (result.success) {
1142
+ assert.ok(Object.isFrozen(result.value));
1143
+ }
1144
+ });
1145
+ test('should freeze Variant when frozen=true', () => {
1146
+ const parser = parseFor(VariantType({ some: IntegerType }), true);
1147
+ const result = parser('.some 42');
1148
+ assert.strictEqual(result.success, true);
1149
+ if (result.success) {
1150
+ assert.ok(Object.isFrozen(result.value));
1151
+ }
1152
+ });
1153
+ });
1154
+ describe('Additional error cases', () => {
1155
+ test('should handle empty Dict with closing brace only', () => {
1156
+ const parser = parseFor(DictType(StringType, IntegerType));
1157
+ const result = parser('{}');
1158
+ assert.strictEqual(result.success, true);
1159
+ if (result.success) {
1160
+ assert.strictEqual(result.value.size, 0);
1161
+ }
1162
+ });
1163
+ test('should error on invalid empty Dict format', () => {
1164
+ const parser = parseFor(DictType(StringType, IntegerType));
1165
+ const result = parser('{: extra}');
1166
+ assert.strictEqual(result.success, false);
1167
+ if (!result.success) {
1168
+ assert.equal(result.error, 'Error occurred because expected \'}\' after \':\' in empty dict (line 1, col 5) while parsing value of type ".Dict (key=.String, value=.Integer)"');
1169
+ }
1170
+ });
1171
+ test('should error on unterminated string in parseString', () => {
1172
+ const parser = parseFor(StringType);
1173
+ const result = parser('"unterminated');
1174
+ assert.strictEqual(result.success, false);
1175
+ if (!result.success) {
1176
+ assert.equal(result.error, 'Error occurred because unterminated string (missing closing quote) (line 1, col 14) while parsing value of type ".String"');
1177
+ }
1178
+ });
1179
+ test('should error on string with only backslash at end', () => {
1180
+ const parser = parseFor(StringType);
1181
+ const result = parser('"ends with\\');
1182
+ assert.strictEqual(result.success, false);
1183
+ if (!result.success) {
1184
+ assert.equal(result.error, 'Error occurred because unterminated string (missing closing quote) (line 1, col 12) while parsing value of type ".String"');
1185
+ }
1186
+ });
1187
+ test('should error on unterminated quoted identifier', () => {
1188
+ const structType = StructType({ 'quoted': IntegerType });
1189
+ const parser = parseFor(structType);
1190
+ const result = parser('(`quoted: 42)');
1191
+ assert.strictEqual(result.success, false);
1192
+ if (!result.success) {
1193
+ assert.equal(result.error, 'Error occurred because missing required field \'quoted\' (line 1, col 2) while parsing value of type ".Struct [(name="quoted", type=.Integer)]"');
1194
+ }
1195
+ });
1196
+ test('should error on quoted identifier with only backslash at end', () => {
1197
+ const structType = StructType({ 'id': IntegerType });
1198
+ const parser = parseFor(structType);
1199
+ const result = parser('(`id\\: 42)');
1200
+ assert.strictEqual(result.success, false);
1201
+ if (!result.success) {
1202
+ assert.equal(result.error, 'Error occurred because missing required field \'id\' (line 1, col 2) while parsing value of type ".Struct [(name="id", type=.Integer)]"');
1203
+ }
1204
+ });
1205
+ test('should error on unterminated identifier via unexpected escape', () => {
1206
+ const structType = StructType({ 'field': IntegerType });
1207
+ const parser = parseFor(structType);
1208
+ const result = parser('(`field: 42)');
1209
+ assert.strictEqual(result.success, false);
1210
+ if (!result.success) {
1211
+ assert.equal(result.error, 'Error occurred because missing required field \'field\' (line 1, col 2) while parsing value of type ".Struct [(name="field", type=.Integer)]"');
1212
+ }
1213
+ });
1214
+ test('should error when expecting closing paren in struct', () => {
1215
+ const structType = StructType({ x: IntegerType, y: IntegerType });
1216
+ const parser = parseFor(structType);
1217
+ const result = parser('(x=1, y=2,');
1218
+ assert.strictEqual(result.success, false);
1219
+ if (!result.success) {
1220
+ assert.equal(result.error, 'Error occurred because expected \')\' to close struct (line 1, col 11) while parsing value of type ".Struct [(name="x", type=.Integer), (name="y", type=.Integer)]"');
1221
+ }
1222
+ });
1223
+ test('should error on struct with wrong field name', () => {
1224
+ const structType = StructType({ expected: IntegerType });
1225
+ const parser = parseFor(structType);
1226
+ const result = parser('(wrong=42)');
1227
+ assert.strictEqual(result.success, false);
1228
+ if (!result.success) {
1229
+ assert.equal(result.error, 'Error occurred because unknown field \'wrong\', expected one of: expected (line 1, col 2) while parsing value of type ".Struct [(name="expected", type=.Integer)]"');
1230
+ }
1231
+ });
1232
+ test('should error on missing colon after struct field name', () => {
1233
+ const structType = StructType({ x: IntegerType });
1234
+ const parser = parseFor(structType);
1235
+ const result = parser('(x 42)');
1236
+ assert.strictEqual(result.success, false);
1237
+ if (!result.success) {
1238
+ assert.equal(result.error, 'Error occurred because expected \'=\' after field name \'x\' (line 1, col 4) while parsing value of type ".Struct [(name="x", type=.Integer)]"');
1239
+ }
1240
+ });
1241
+ test('should error on unexpected end of input in struct', () => {
1242
+ const structType = StructType({ x: IntegerType, y: IntegerType });
1243
+ const parser = parseFor(structType);
1244
+ const result = parser('(x=1');
1245
+ assert.strictEqual(result.success, false);
1246
+ if (!result.success) {
1247
+ assert.equal(result.error, 'Error occurred because unexpected end of input in struct (line 1, col 5) while parsing value of type ".Struct [(name="x", type=.Integer), (name="y", type=.Integer)]"');
1248
+ }
1249
+ });
1250
+ test('should error on missing comma or closing paren in struct', () => {
1251
+ const structType = StructType({ x: IntegerType, y: IntegerType });
1252
+ const parser = parseFor(structType);
1253
+ const result = parser('(x=1 y=2)');
1254
+ assert.strictEqual(result.success, false);
1255
+ if (!result.success) {
1256
+ assert.equal(result.error, 'Error occurred because expected \',\' or \')\' after struct field (line 1, col 6) while parsing value of type ".Struct [(name="x", type=.Integer), (name="y", type=.Integer)]"');
1257
+ }
1258
+ });
1259
+ test('should error on variant with whitespace after dot', () => {
1260
+ const variantType = VariantType({ some: IntegerType });
1261
+ const parser = parseFor(variantType);
1262
+ const result = parser('. some 42');
1263
+ assert.strictEqual(result.success, false);
1264
+ if (!result.success) {
1265
+ assert.equal(result.error, 'Error occurred because whitespace not allowed between \'.\' and case identifier (line 1, col 2) while parsing value of type ".Variant [(name="some", type=.Integer)]"');
1266
+ }
1267
+ });
1268
+ test('should error on float with missing exponent digits', () => {
1269
+ const parser = parseFor(FloatType);
1270
+ const result = parser('1.5e');
1271
+ assert.strictEqual(result.success, false);
1272
+ if (!result.success) {
1273
+ assert.equal(result.error, 'Error occurred because expected digits in float exponent (line 1, col 5) while parsing value of type ".Float"');
1274
+ }
1275
+ });
1276
+ test('should error on DateTime with invalid format', () => {
1277
+ const parser = parseFor(DateTimeType);
1278
+ const result = parser('invalid-date');
1279
+ assert.strictEqual(result.success, false);
1280
+ if (!result.success) {
1281
+ assert.equal(result.error, 'Error occurred because expected DateTime in format YYYY-MM-DDTHH:MM:SS.sss (line 1, col 1) while parsing value of type ".DateTime"');
1282
+ }
1283
+ });
1284
+ test('should error on invalid DateTime value', () => {
1285
+ const parser = parseFor(DateTimeType);
1286
+ const result = parser('2022-13-40T25:61:61.999');
1287
+ assert.strictEqual(result.success, false);
1288
+ if (!result.success) {
1289
+ assert.equal(result.error, 'Error occurred because invalid DateTime value, got "2022-13-40T25:61:61.999" (line 1, col 1) while parsing value of type ".DateTime"');
1290
+ }
1291
+ });
1292
+ test('should error on Blob with odd number of hex digits', () => {
1293
+ const parser = parseFor(BlobType);
1294
+ const result = parser('0x123');
1295
+ assert.strictEqual(result.success, false);
1296
+ if (!result.success) {
1297
+ assert.equal(result.error, 'Error occurred because invalid hex string (odd length), got "0x123" (line 1, col 1) while parsing value of type ".Blob"');
1298
+ }
1299
+ });
1300
+ test('should error on Blob not starting with 0x', () => {
1301
+ const parser = parseFor(BlobType);
1302
+ const result = parser('123456');
1303
+ assert.strictEqual(result.success, false);
1304
+ if (!result.success) {
1305
+ assert.equal(result.error, 'Error occurred because expected Blob starting with 0x (line 1, col 1) while parsing value of type ".Blob"');
1306
+ }
1307
+ });
1308
+ test('should error on array without opening bracket', () => {
1309
+ const parser = parseFor(ArrayType(IntegerType));
1310
+ const result = parser('1, 2, 3]');
1311
+ assert.strictEqual(result.success, false);
1312
+ if (!result.success) {
1313
+ assert.equal(result.error, 'Error occurred because expected \'[\' to start array (line 1, col 1) while parsing value of type ".Array .Integer"');
1314
+ }
1315
+ });
1316
+ test('should error on missing comma or closing bracket in array', () => {
1317
+ const parser = parseFor(ArrayType(IntegerType));
1318
+ const result = parser('[1 2]');
1319
+ assert.strictEqual(result.success, false);
1320
+ if (!result.success) {
1321
+ assert.equal(result.error, 'Error occurred because expected \',\' or \']\' after array element (line 1, col 4) while parsing value of type ".Array .Integer"');
1322
+ }
1323
+ });
1324
+ test('should error on set without opening brace', () => {
1325
+ const parser = parseFor(SetType(StringType));
1326
+ const result = parser('"a", "b"}');
1327
+ assert.strictEqual(result.success, false);
1328
+ if (!result.success) {
1329
+ assert.equal(result.error, 'Error occurred because expected \'{\' to start set (line 1, col 1) while parsing value of type ".Set .String"');
1330
+ }
1331
+ });
1332
+ test('should error on missing comma or closing brace in set', () => {
1333
+ const parser = parseFor(SetType(StringType));
1334
+ const result = parser('{"a" "b"}');
1335
+ assert.strictEqual(result.success, false);
1336
+ if (!result.success) {
1337
+ assert.equal(result.error, 'Error occurred because expected \',\' or \'}\' after set element (line 1, col 6) while parsing value of type ".Set .String"');
1338
+ }
1339
+ });
1340
+ test('should error on dict without opening brace', () => {
1341
+ const parser = parseFor(DictType(StringType, IntegerType));
1342
+ const result = parser('"a": 1}');
1343
+ assert.strictEqual(result.success, false);
1344
+ if (!result.success) {
1345
+ assert.equal(result.error, 'Error occurred because expected \'{\' to start dict (line 1, col 1) while parsing value of type ".Dict (key=.String, value=.Integer)"');
1346
+ }
1347
+ });
1348
+ test('should error on missing colon in dict entry', () => {
1349
+ const parser = parseFor(DictType(StringType, IntegerType));
1350
+ const result = parser('{"a" 1}');
1351
+ assert.strictEqual(result.success, false);
1352
+ if (!result.success) {
1353
+ assert.equal(result.error, 'Error occurred because expected \':\' after dict key at entry 0 (line 1, col 6) while parsing value of type ".Dict (key=.String, value=.Integer)"');
1354
+ }
1355
+ });
1356
+ test('should error on missing comma or closing brace in dict', () => {
1357
+ const parser = parseFor(DictType(StringType, IntegerType));
1358
+ const result = parser('{"a": 1 "b": 2}');
1359
+ assert.strictEqual(result.success, false);
1360
+ if (!result.success) {
1361
+ assert.equal(result.error, 'Error occurred because expected \',\' or \'}\' after dict entry (line 1, col 9) while parsing value of type ".Dict (key=.String, value=.Integer)"');
1362
+ }
1363
+ });
1364
+ test('should error on struct without opening paren', () => {
1365
+ const structType = StructType({ x: IntegerType });
1366
+ const parser = parseFor(structType);
1367
+ const result = parser('x: 42)');
1368
+ assert.strictEqual(result.success, false);
1369
+ if (!result.success) {
1370
+ assert.equal(result.error, 'Error occurred because expected \'(\' to start struct (line 1, col 1) while parsing value of type ".Struct [(name="x", type=.Integer)]"');
1371
+ }
1372
+ });
1373
+ test('should error on variant without dot', () => {
1374
+ const variantType = VariantType({ some: IntegerType });
1375
+ const parser = parseFor(variantType);
1376
+ const result = parser('some 42');
1377
+ assert.strictEqual(result.success, false);
1378
+ if (!result.success) {
1379
+ assert.equal(result.error, 'Error occurred because expected \'.\' to start variant case (line 1, col 1) while parsing value of type ".Variant [(name="some", type=.Integer)]"');
1380
+ }
1381
+ });
1382
+ test('should handle non-ParseError exceptions in parseFor wrapper', () => {
1383
+ const parser = parseFor(IntegerType);
1384
+ // This should still work - parseFor wraps exceptions
1385
+ const result = parser('42');
1386
+ assert.strictEqual(result.success, true);
1387
+ });
1388
+ });
1389
+ describe('Fuzz tests', () => {
1390
+ test('should round-trip random types and values', { timeout: 60_000 }, async () => {
1391
+ const result = await fuzzerTest((type) => {
1392
+ const print = printFor(type);
1393
+ const parse = parseFor(type);
1394
+ const equal = equalFor(type);
1395
+ return async (value) => {
1396
+ // Print and parse
1397
+ const printed = print(value);
1398
+ const parseResult = parse(printed);
1399
+ // Check parse succeeded
1400
+ if (!parseResult.success) {
1401
+ throw new Error(`Parse failed: ${parseResult.error}`);
1402
+ }
1403
+ // Check value equality
1404
+ if (!equal(parseResult.value, value)) {
1405
+ throw new Error(`Round-trip failed: values not equal`);
1406
+ }
1407
+ };
1408
+ }, 100, // 100 random types
1409
+ 10, // 10 samples per type
1410
+ { includeRecursive: false } // TODO: recursive value generation needs work
1411
+ );
1412
+ assert.strictEqual(result, true, "Fuzz test failed");
1413
+ });
1414
+ test('should round-trip with Uint8Array encoding for random types', { timeout: 60_000 }, async () => {
1415
+ const result = await fuzzerTest((type) => {
1416
+ const encode = encodeEastFor(type);
1417
+ const decode = decodeEastFor(type);
1418
+ const equal = equalFor(type);
1419
+ return async (value) => {
1420
+ // Encode and decode
1421
+ const encoded = encode(value);
1422
+ const decoded = decode(encoded);
1423
+ // Verify it's a Uint8Array
1424
+ if (!(encoded instanceof Uint8Array)) {
1425
+ throw new Error(`Encoded value is not a Uint8Array`);
1426
+ }
1427
+ // Check value equality
1428
+ if (!equal(decoded, value)) {
1429
+ throw new Error(`Round-trip failed: values not equal`);
1430
+ }
1431
+ };
1432
+ }, 100, // 100 random types
1433
+ 10, // 10 samples per type
1434
+ { includeRecursive: false } // TODO: recursive value generation needs work
1435
+ );
1436
+ assert.strictEqual(result, true, "Fuzz test failed");
1437
+ });
1438
+ });
1439
+ describe('printFor with aliases', () => {
1440
+ test('should detect array aliases in struct', () => {
1441
+ const type = StructType({ a: ArrayType(IntegerType), b: ArrayType(IntegerType) });
1442
+ const printer = printFor(type);
1443
+ // Create struct with shared array reference
1444
+ const sharedArray = [1n, 2n, 3n];
1445
+ const value = { a: sharedArray, b: sharedArray };
1446
+ const result = printer(value);
1447
+ assert.equal(result, "(a=[1, 2, 3], b=1#.a)");
1448
+ });
1449
+ test('should detect set aliases in struct', () => {
1450
+ const type = StructType({ a: SetType(IntegerType), b: SetType(IntegerType) });
1451
+ const printer = printFor(type);
1452
+ // Create struct with shared set reference
1453
+ const sharedSet = new SortedSet([1n, 2n, 3n]);
1454
+ const value = { a: sharedSet, b: sharedSet };
1455
+ const result = printer(value);
1456
+ assert.equal(result, "(a={1,2,3}, b=1#.a)");
1457
+ });
1458
+ test('should detect dict aliases in struct', () => {
1459
+ const type = StructType({ a: DictType(IntegerType, StringType), b: DictType(IntegerType, StringType) });
1460
+ const printer = printFor(type);
1461
+ // Create struct with shared dict reference
1462
+ const sharedDict = new SortedMap([[1n, "x"], [2n, "y"]]);
1463
+ const value = { a: sharedDict, b: sharedDict };
1464
+ const result = printer(value);
1465
+ assert.equal(result, '(a={1:"x",2:"y"}, b=1#.a)');
1466
+ });
1467
+ test('should detect nested array aliases', () => {
1468
+ const type = ArrayType(ArrayType(IntegerType));
1469
+ const printer = printFor(type);
1470
+ // Create array with shared inner array
1471
+ const inner = [1n, 2n];
1472
+ const value = [inner, inner, inner];
1473
+ const result = printer(value);
1474
+ assert.equal(result, "[[1, 2], 1#[0], 1#[0]]");
1475
+ });
1476
+ });
1477
+ describe('printFor with recursive types', () => {
1478
+ test('should print tree without cycles', () => {
1479
+ const TreeType = RecursiveType(self => VariantType({
1480
+ leaf: NullType,
1481
+ node: StructType({
1482
+ value: IntegerType,
1483
+ left: self,
1484
+ right: self
1485
+ })
1486
+ }));
1487
+ const printer = printFor(TreeType);
1488
+ // Create simple tree: node(1, leaf, leaf)
1489
+ const tree = variant("node", {
1490
+ value: 1n,
1491
+ left: variant("leaf"),
1492
+ right: variant("leaf")
1493
+ });
1494
+ const result = printer(tree);
1495
+ assert.equal(result, ".node (value=1, left=.leaf, right=.leaf)");
1496
+ });
1497
+ test('should print larger tree without cycles', () => {
1498
+ const TreeType = RecursiveType(self => VariantType({
1499
+ leaf: NullType,
1500
+ node: StructType({
1501
+ value: IntegerType,
1502
+ left: self,
1503
+ right: self
1504
+ })
1505
+ }));
1506
+ const printer = printFor(TreeType);
1507
+ // Create tree: node(2, node(1, leaf, leaf), node(3, leaf, leaf))
1508
+ const tree = variant("node", {
1509
+ value: 2n,
1510
+ left: variant("node", {
1511
+ value: 1n,
1512
+ left: variant("leaf"),
1513
+ right: variant("leaf")
1514
+ }),
1515
+ right: variant("node", {
1516
+ value: 3n,
1517
+ left: variant("leaf"),
1518
+ right: variant("leaf")
1519
+ })
1520
+ });
1521
+ const result = printer(tree);
1522
+ assert.equal(result, ".node (value=2, left=.node (value=1, left=.leaf, right=.leaf), right=.node (value=3, left=.leaf, right=.leaf))");
1523
+ });
1524
+ test('should print linked list without cycles', () => {
1525
+ const LinkedListType = RecursiveType(self => VariantType({
1526
+ nil: NullType,
1527
+ cons: StructType({
1528
+ head: IntegerType,
1529
+ tail: self
1530
+ })
1531
+ }));
1532
+ const printer = printFor(LinkedListType);
1533
+ // Create list: cons(1, cons(2, cons(3, nil)))
1534
+ const list = variant("cons", {
1535
+ head: 1n,
1536
+ tail: variant("cons", {
1537
+ head: 2n,
1538
+ tail: variant("cons", {
1539
+ head: 3n,
1540
+ tail: variant("nil")
1541
+ })
1542
+ })
1543
+ });
1544
+ const result = printer(list);
1545
+ assert.equal(result, ".cons (head=1, tail=.cons (head=2, tail=.cons (head=3, tail=.nil)))");
1546
+ });
1547
+ });
1548
+ //# sourceMappingURL=east.spec.js.map