@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
@@ -2,7 +2,6 @@
2
2
  * Copyright (c) 2025 Elara AI Pty Ltd
3
3
  * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
4
  */
5
- import { printLocationValue } from "./ir.js";
6
5
  import { isTypeValueEqual, isSubtypeValue, expandTypeValue, toEastTypeValue } from "./type_of_type.js";
7
6
  import { printTypeValue } from "./compile.js";
8
7
  import { variant } from "./containers/variant.js";
@@ -37,20 +36,30 @@ import { Builtins } from "./builtins.js";
37
36
  export function analyzeIR(ir, platformDef, ctx = {}) {
38
37
  // Working data for tracking during analysis
39
38
  const analysis = new Map();
39
+ // Pre-populate analysis Map with definedBy nodes from external context.
40
+ // This is needed when analyzing deserialized functions with captures - the external
41
+ // context contains variable metadata with definedBy references that need to be in
42
+ // the analysis Map so nested functions can properly mark them as captured.
43
+ for (const varName of Object.keys(ctx)) {
44
+ const varMeta = ctx[varName];
45
+ if (varMeta?.definedBy && !analysis.has(varMeta.definedBy)) {
46
+ analysis.set(varMeta.definedBy, { captured: varMeta.captured });
47
+ }
48
+ }
40
49
  // Build a lookup map for platform functions
41
50
  const platformMap = new Map();
42
51
  for (const p of platformDef) {
43
52
  if (platformMap.has(p.name)) {
44
53
  throw new Error(`Duplicate platform function definition for '${p.name}'`);
45
54
  }
46
- platformMap.set(p.name, { inputs: p.inputs, output: p.output, type: p.type });
55
+ platformMap.set(p.name, p);
47
56
  }
48
57
  // Track circular references
49
58
  const visiting = new Set();
50
59
  function visit(node, ctx, expectedReturnType) {
51
60
  // Detect circular IR (we don't cache because we're building new nodes)
52
61
  if (visiting.has(node)) {
53
- throw new Error(`Circular IR reference detected at ${printLocationValue(node.value.location)}`);
62
+ throw new Error(`Circular IR reference detected at loc_id ${node.value.loc_id}`);
54
63
  }
55
64
  visiting.add(node);
56
65
  try {
@@ -67,7 +76,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
67
76
  // Validate that the type matches the value
68
77
  if (node.value.type.type !== node.value.value.type) {
69
78
  throw new Error(`Value node expected value of type .${node.value.type.type} ` +
70
- `but got .${node.value.value.type} at ${printLocationValue(node.value.location)}`);
79
+ `but got .${node.value.value.type} at loc_id ${node.value.loc_id}`);
71
80
  }
72
81
  // Value is always sync (literal constant)
73
82
  return {
@@ -83,19 +92,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
83
92
  const varMeta = ctx[name];
84
93
  // Validate variable is in scope
85
94
  if (varMeta === undefined) {
86
- throw new Error(`Variable ${name} not in scope at ${printLocationValue(node.value.location)}`);
95
+ throw new Error(`Variable ${name} not in scope at loc_id ${node.value.loc_id}`);
87
96
  }
88
97
  // Validate type matches
89
98
  if (!isTypeValueEqual(varMeta.type, node.value.type)) {
90
99
  throw new Error(`Variable ${name} has type ${printTypeValue(varMeta.type)} ` +
91
- `but expected ${printTypeValue(node.value.type)} at ${printLocationValue(node.value.location)}`);
100
+ `but expected ${printTypeValue(node.value.type)} at loc_id ${node.value.loc_id}`);
92
101
  }
93
102
  // Validate mutability matches
94
103
  if (varMeta.mutable !== node.value.mutable) {
95
104
  throw new Error(`Variable ${name} mutability mismatch: ` +
96
105
  `context has ${varMeta.mutable ? 'mutable' : 'const'} ` +
97
106
  `but IR expects ${node.value.mutable ? 'mutable' : 'const'} ` +
98
- `at ${printLocationValue(node.value.location)}`);
107
+ `at loc_id ${node.value.loc_id}`);
99
108
  }
100
109
  // Detect capture: if variable is not in current scope but in parent, mark as captured
101
110
  if (!Object.hasOwn(ctx, name)) {
@@ -138,7 +147,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
138
147
  `has type ${printTypeValue(node.value.variable.value.type)} ` +
139
148
  `but value has type ${printTypeValue(valueInfo.value.type)}. ` +
140
149
  `Insert an As node if subtyping is intended. ` +
141
- `at ${printLocationValue(node.value.location)}`);
150
+ `at loc_id ${node.value.loc_id}`);
142
151
  }
143
152
  // Analyze the VariableIR node itself (so it has an entry in the analysis map)
144
153
  analysis.set(node.value.variable, {
@@ -168,17 +177,17 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
168
177
  // Validate variable exists in scope
169
178
  if (varMeta === undefined) {
170
179
  throw new Error(`Cannot assign to variable ${varName} which is not in scope ` +
171
- `at ${printLocationValue(node.value.location)}`);
180
+ `at loc_id ${node.value.loc_id}`);
172
181
  }
173
182
  // Validate variable is mutable in IR
174
183
  if (!node.value.variable.value.mutable) {
175
184
  throw new Error(`Cannot reassign const variable ${varName} ` +
176
- `at ${printLocationValue(node.value.location)}`);
185
+ `at loc_id ${node.value.loc_id}`);
177
186
  }
178
187
  // Validate variable is mutable in context (matches IR)
179
188
  if (!varMeta.mutable) {
180
189
  throw new Error(`Cannot reassign variable ${varName} - context says it's const ` +
181
- `at ${printLocationValue(node.value.location)}`);
190
+ `at loc_id ${node.value.loc_id}`);
182
191
  }
183
192
  // Visit the value expression
184
193
  const valueInfo = visit(node.value.value, ctx, expectedReturnType);
@@ -189,7 +198,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
189
198
  `Variable ${varName} has type ${printTypeValue(varMeta.type)} ` +
190
199
  `but value has type ${printTypeValue(valueInfo.value.type)}. ` +
191
200
  `Insert an As node if subtyping is intended. ` +
192
- `at ${printLocationValue(node.value.location)}`);
201
+ `at loc_id ${node.value.loc_id}`);
193
202
  }
194
203
  isAsync = valueInfo.value.isAsync; // Async if the value expression is async
195
204
  }
@@ -214,7 +223,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
214
223
  if (!isTypeValueEqual(lastType, node.value.type)) {
215
224
  throw new Error(`Block evaluates to type ${printTypeValue(lastType)} ` +
216
225
  `but expected ${printTypeValue(node.value.type)} ` +
217
- `at ${printLocationValue(node.value.location)}`);
226
+ `at loc_id ${node.value.loc_id}`);
218
227
  }
219
228
  // Return analyzed Block with analyzed statements
220
229
  return {
@@ -233,17 +242,17 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
233
242
  if (!isSubtypeValue(valueInfo.value.type, node.value.type)) {
234
243
  throw new Error(`Cannot cast value of type ${printTypeValue(valueInfo.value.type)} ` +
235
244
  `to type ${printTypeValue(node.value.type)} ` +
236
- `at ${printLocationValue(node.value.location)}`);
245
+ `at loc_id ${node.value.loc_id}`);
237
246
  }
238
247
  // More thorough checks for "unnecessary" As IR nodes:
239
248
  // Cannot cast Never to a value
240
249
  if (valueInfo.value.type.type === "Never") {
241
250
  throw new Error(`Cannot cast .Never to type ${printTypeValue(node.value.type)} ` +
242
- `at ${printLocationValue(node.value.location)}`);
251
+ `at loc_id ${node.value.loc_id}`);
243
252
  }
244
253
  if (isTypeValueEqual(valueInfo.value.type, node.value.type)) {
245
254
  throw new Error(`Unnecessary As node: value is already of type ${printTypeValue(node.value.type)} ` +
246
- `at ${printLocationValue(node.value.location)}`);
255
+ `at loc_id ${node.value.loc_id}`);
247
256
  }
248
257
  isAsync = valueInfo.value.isAsync; // Propagate async from child
249
258
  }
@@ -251,14 +260,57 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
251
260
  // Look up platform function
252
261
  const platformFn = platformMap.get(node.value.name);
253
262
  if (!platformFn) {
254
- throw new Error(`Platform function '${node.value.name}' not found ` +
255
- `at ${printLocationValue(node.value.location)}`);
263
+ // Allow missing platforms only if this specific platform function is marked as optional in the IR
264
+ if (!node.value.optional) {
265
+ throw new Error(`Platform function '${node.value.name}' not found ` +
266
+ `at loc_id ${node.value.loc_id}`);
267
+ }
268
+ // allowMissingPlatform is true - analyze arguments without type validation
269
+ // and let compile inject a runtime error stub
270
+ const analyzedArgs = [];
271
+ for (const arg of node.value.arguments) {
272
+ const argAnalyzed = visit(arg, ctx, expectedReturnType);
273
+ analyzedArgs.push(argAnalyzed);
274
+ if (argAnalyzed.value.isAsync) {
275
+ isAsync = true;
276
+ }
277
+ }
278
+ // Return analyzed Platform node with analyzed arguments (no type validation)
279
+ return {
280
+ ...node,
281
+ value: {
282
+ ...node.value,
283
+ arguments: analyzedArgs,
284
+ isAsync,
285
+ }
286
+ };
256
287
  }
257
- // Validate argument count
258
- if (node.value.arguments.length !== platformFn.inputs.length) {
259
- throw new Error(`Platform function '${node.value.name}' expects ${platformFn.inputs.length} arguments ` +
288
+ // Handle generic platform functions
289
+ const typeParams = node.value.type_parameters ?? [];
290
+ const expectedTypeParamCount = platformFn.type_parameters?.length ?? 0;
291
+ if (typeParams.length !== expectedTypeParamCount) {
292
+ throw new Error(`Platform function '${node.value.name}' expects ${expectedTypeParamCount} ` +
293
+ `type parameters, got ${typeParams.length} ` +
294
+ `at loc_id ${node.value.loc_id}`);
295
+ }
296
+ // Compute concrete input/output types by substituting type parameters
297
+ let inputTypes;
298
+ let outputType;
299
+ if (expectedTypeParamCount > 0 && platformFn.inputsFn && platformFn.outputsFn) {
300
+ // Generic platform function - use callbacks to compute types
301
+ inputTypes = platformFn.inputsFn(...typeParams);
302
+ outputType = platformFn.outputsFn(...typeParams);
303
+ }
304
+ else {
305
+ // Non-generic - use stored concrete types
306
+ inputTypes = platformFn.inputs;
307
+ outputType = platformFn.output;
308
+ }
309
+ // Validate argument count (now using computed inputTypes)
310
+ if (node.value.arguments.length !== inputTypes.length) {
311
+ throw new Error(`Platform function '${node.value.name}' expects ${inputTypes.length} arguments ` +
260
312
  `but got ${node.value.arguments.length} ` +
261
- `at ${printLocationValue(node.value.location)}`);
313
+ `at loc_id ${node.value.loc_id}`);
262
314
  }
263
315
  // Visit all arguments, check if any are async, and validate types
264
316
  const analyzedArgs = [];
@@ -269,28 +321,28 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
269
321
  if (argAnalyzed.value.isAsync) {
270
322
  isAsync = true;
271
323
  }
272
- // Validate argument type exactly matches expected
324
+ // Validate argument type exactly matches expected (using computed inputTypes)
273
325
  // (Subtyping should be handled by explicit As nodes)
274
- const expectedType = platformFn.inputs[i];
326
+ const expectedType = inputTypes[i];
275
327
  if (argAnalyzed.value.type.type !== "Never" && !isTypeValueEqual(argAnalyzed.value.type, expectedType)) {
276
328
  throw new Error(`Platform function '${node.value.name}' argument ${i + 1} ` +
277
329
  `requires exact type match. ` +
278
330
  `Expected type ${printTypeValue(expectedType)} ` +
279
331
  `but got ${printTypeValue(argAnalyzed.value.type)}. ` +
280
332
  `Insert an As node if subtyping is intended. ` +
281
- `at ${printLocationValue(node.value.location)}`);
333
+ `at loc_id ${node.value.loc_id}`);
282
334
  }
283
335
  }
284
336
  // Platform function itself might be async
285
337
  if (platformFn.type === 'async') {
286
338
  isAsync = true;
287
339
  }
288
- // Validate return type matches
289
- if (!isTypeValueEqual(node.value.type, platformFn.output)) {
340
+ // Validate return type matches (using computed outputType)
341
+ if (!isTypeValueEqual(node.value.type, outputType)) {
290
342
  throw new Error(`Platform function '${node.value.name}' return type ` +
291
- `expected to be ${printTypeValue(platformFn.output)} ` +
343
+ `expected to be ${printTypeValue(outputType)} ` +
292
344
  `but IR has ${printTypeValue(node.value.type)} ` +
293
- `at ${printLocationValue(node.value.location)}`);
345
+ `at loc_id ${node.value.loc_id}`);
294
346
  }
295
347
  // Return analyzed Platform node with analyzed arguments
296
348
  return {
@@ -306,7 +358,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
306
358
  // Validate it has a Function type
307
359
  if (node.value.type.type !== "Function") {
308
360
  throw new Error(`Expected Function type, got ${printTypeValue(node.value.type)} ` +
309
- `at ${printLocationValue(node.value.location)}`);
361
+ `at loc_id ${node.value.loc_id}`);
310
362
  }
311
363
  // Create new context for function body
312
364
  const fnCtx = {};
@@ -315,27 +367,31 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
315
367
  const outerVar = ctx[captureVar.value.name];
316
368
  if (outerVar === undefined) {
317
369
  throw new Error(`Captured variable ${captureVar.value.name} not in scope ` +
318
- `at ${printLocationValue(node.value.location)}`);
370
+ `at loc_id ${node.value.loc_id}`);
319
371
  }
320
372
  if (!isTypeValueEqual(outerVar.type, captureVar.value.type)) {
321
373
  throw new Error(`Captured variable ${captureVar.value.name} has type ${printTypeValue(outerVar.type)} ` +
322
374
  `but expected ${printTypeValue(captureVar.value.type)} ` +
323
- `at ${printLocationValue(node.value.location)}`);
375
+ `at loc_id ${node.value.loc_id}`);
324
376
  }
325
377
  if (outerVar.mutable !== captureVar.value.mutable) {
326
378
  throw new Error(`Captured variable ${captureVar.value.name} mutability mismatch: ` +
327
379
  `context has ${outerVar.mutable ? 'mutable' : 'const'} ` +
328
380
  `but IR expects ${captureVar.value.mutable ? 'mutable' : 'const'} ` +
329
- `at ${printLocationValue(node.value.location)}`);
381
+ `at loc_id ${node.value.loc_id}`);
330
382
  }
331
383
  // Mark the outer variable as captured (it's being closed over by this function)
384
+ const wasAlreadyCaptured = outerVar.captured;
332
385
  outerVar.captured = true;
333
386
  const defVarAnalysis = analysis.get(outerVar.definedBy);
334
- if (!defVarAnalysis) {
387
+ if (defVarAnalysis) {
388
+ defVarAnalysis.captured = true;
389
+ }
390
+ else if (!wasAlreadyCaptured) {
391
+ // Only error if this wasn't already marked as captured (from a synthetic/external context)
335
392
  throw new Error(`Internal error: VariableIR node for captured variable ${captureVar.value.name} not analyzed. ` +
336
393
  `This should never happen - all VariableIR nodes should be analyzed when encountered.`);
337
394
  }
338
- defVarAnalysis.captured = true;
339
395
  fnCtx[captureVar.value.name] = {
340
396
  type: captureVar.value.type,
341
397
  mutable: captureVar.value.mutable,
@@ -365,7 +421,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
365
421
  if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, expectedOutput)) {
366
422
  throw new Error(`Function body returns type ${printTypeValue(bodyInfo.value.type)} ` +
367
423
  `but function signature expects ${printTypeValue(expectedOutput)} ` +
368
- `at ${printLocationValue(node.value.location)}`);
424
+ `at loc_id ${node.value.loc_id}`);
369
425
  }
370
426
  // Creating a function is sync (it just captures variables at this stage)
371
427
  return {
@@ -381,7 +437,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
381
437
  // Validate it has a Function type
382
438
  if (node.value.type.type !== "AsyncFunction") {
383
439
  throw new Error(`Expected AsyncFunction type, got ${printTypeValue(node.value.type)} ` +
384
- `at ${printLocationValue(node.value.location)}`);
440
+ `at loc_id ${node.value.loc_id}`);
385
441
  }
386
442
  // Create new context for function body
387
443
  const fnCtx = {};
@@ -390,27 +446,31 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
390
446
  const outerVar = ctx[captureVar.value.name];
391
447
  if (outerVar === undefined) {
392
448
  throw new Error(`Captured variable ${captureVar.value.name} not in scope ` +
393
- `at ${printLocationValue(node.value.location)}`);
449
+ `at loc_id ${node.value.loc_id}`);
394
450
  }
395
451
  if (!isTypeValueEqual(outerVar.type, captureVar.value.type)) {
396
452
  throw new Error(`Captured variable ${captureVar.value.name} has type ${printTypeValue(outerVar.type)} ` +
397
453
  `but expected ${printTypeValue(captureVar.value.type)} ` +
398
- `at ${printLocationValue(node.value.location)}`);
454
+ `at loc_id ${node.value.loc_id}`);
399
455
  }
400
456
  if (outerVar.mutable !== captureVar.value.mutable) {
401
457
  throw new Error(`Captured variable ${captureVar.value.name} mutability mismatch: ` +
402
458
  `context has ${outerVar.mutable ? 'mutable' : 'const'} ` +
403
459
  `but IR expects ${captureVar.value.mutable ? 'mutable' : 'const'} ` +
404
- `at ${printLocationValue(node.value.location)}`);
460
+ `at loc_id ${node.value.loc_id}`);
405
461
  }
406
462
  // Mark the outer variable as captured (it's being closed over by this function)
463
+ const wasAlreadyCaptured = outerVar.captured;
407
464
  outerVar.captured = true;
408
465
  const defVarAnalysis = analysis.get(outerVar.definedBy);
409
- if (!defVarAnalysis) {
466
+ if (defVarAnalysis) {
467
+ defVarAnalysis.captured = true;
468
+ }
469
+ else if (!wasAlreadyCaptured) {
470
+ // Only error if this wasn't already marked as captured (from a synthetic/external context)
410
471
  throw new Error(`Internal error: VariableIR node for captured variable ${captureVar.value.name} not analyzed. ` +
411
472
  `This should never happen - all VariableIR nodes should be analyzed when encountered.`);
412
473
  }
413
- defVarAnalysis.captured = true;
414
474
  fnCtx[captureVar.value.name] = {
415
475
  type: captureVar.value.type,
416
476
  mutable: captureVar.value.mutable,
@@ -440,7 +500,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
440
500
  if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, expectedOutput)) {
441
501
  throw new Error(`AsyncFunction body returns type ${printTypeValue(bodyInfo.value.type)} ` +
442
502
  `but function signature expects ${printTypeValue(expectedOutput)} ` +
443
- `at ${printLocationValue(node.value.location)}`);
503
+ `at loc_id ${node.value.loc_id}`);
444
504
  }
445
505
  // Creating a function is sync (it just captures variables at this stage)
446
506
  return {
@@ -458,13 +518,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
458
518
  // Validate it's a function type
459
519
  if (fnInfo.value.type.type !== "Function") {
460
520
  throw new Error(`Call expects Function type, got ${printTypeValue(fnInfo.value.type)} ` +
461
- `at ${printLocationValue(node.value.location)}`);
521
+ `at loc_id ${node.value.loc_id}`);
462
522
  }
463
523
  // Validate argument count
464
524
  if (fnInfo.value.type.value.inputs.length !== node.value.arguments.length) {
465
525
  throw new Error(`Function expects ${fnInfo.value.type.value.inputs.length} arguments, ` +
466
526
  `got ${node.value.arguments.length} ` +
467
- `at ${printLocationValue(node.value.location)}`);
527
+ `at loc_id ${node.value.loc_id}`);
468
528
  }
469
529
  // Analyze all arguments
470
530
  const analyzedArgs = [];
@@ -482,14 +542,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
482
542
  `Expected type ${printTypeValue(expectedType)} ` +
483
543
  `but got ${printTypeValue(argInfo.value.type)}. ` +
484
544
  `Insert an As node if subtyping is intended. ` +
485
- `at ${printLocationValue(node.value.location)}`);
545
+ `at loc_id ${node.value.loc_id}`);
486
546
  }
487
547
  }
488
548
  // Validate return type matches
489
549
  if (!isTypeValueEqual(node.value.type, fnInfo.value.type.value.output)) {
490
550
  throw new Error(`Function call return type expected to be ${printTypeValue(fnInfo.value.type.value.output)} ` +
491
551
  `but IR has ${printTypeValue(node.value.type)} ` +
492
- `at ${printLocationValue(node.value.location)}`);
552
+ `at loc_id ${node.value.loc_id}`);
493
553
  }
494
554
  // Return analyzed Call with analyzed function and arguments
495
555
  return {
@@ -510,13 +570,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
510
570
  // Validate it's an async function type
511
571
  if (fnInfo.value.type.type !== "AsyncFunction") {
512
572
  throw new Error(`CallAsync expects AsyncFunction type, got ${printTypeValue(fnInfo.value.type)} ` +
513
- `at ${printLocationValue(node.value.location)}`);
573
+ `at loc_id ${node.value.loc_id}`);
514
574
  }
515
575
  // Validate argument count
516
576
  if (fnInfo.value.type.value.inputs.length !== node.value.arguments.length) {
517
577
  throw new Error(`Function expects ${fnInfo.value.type.value.inputs.length} arguments, ` +
518
578
  `got ${node.value.arguments.length} ` +
519
- `at ${printLocationValue(node.value.location)}`);
579
+ `at loc_id ${node.value.loc_id}`);
520
580
  }
521
581
  // Analyze all arguments
522
582
  const analyzedArgs = [];
@@ -531,14 +591,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
531
591
  `Expected type ${printTypeValue(expectedType)} ` +
532
592
  `but got ${printTypeValue(argInfo.value.type)}. ` +
533
593
  `Insert an As node if subtyping is intended. ` +
534
- `at ${printLocationValue(node.value.location)}`);
594
+ `at loc_id ${node.value.loc_id}`);
535
595
  }
536
596
  }
537
597
  // Validate return type matches
538
598
  if (!isTypeValueEqual(node.value.type, fnInfo.value.type.value.output)) {
539
599
  throw new Error(`Function call return type expected to be ${printTypeValue(fnInfo.value.type.value.output)} ` +
540
600
  `but IR has ${printTypeValue(node.value.type)} ` +
541
- `at ${printLocationValue(node.value.location)}`);
601
+ `at loc_id ${node.value.loc_id}`);
542
602
  }
543
603
  // Return analyzed Call with analyzed function and arguments
544
604
  return {
@@ -559,12 +619,12 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
559
619
  const builtin = Builtins[builtinName];
560
620
  if (!builtin) {
561
621
  throw new Error(`Unknown builtin function '${builtinName}' ` +
562
- `at ${printLocationValue(node.value.location)}`);
622
+ `at loc_id ${node.value.loc_id}`);
563
623
  }
564
624
  if (node.value.arguments.length !== builtin.inputs.length) {
565
625
  throw new Error(`Builtin function '${builtinName}' expects ${builtin.inputs.length} arguments, ` +
566
626
  `but got ${node.value.arguments.length} ` +
567
- `at ${printLocationValue(node.value.location)}`);
627
+ `at loc_id ${node.value.loc_id}`);
568
628
  }
569
629
  // Visit all arguments
570
630
  const analyzedArgs = [];
@@ -588,7 +648,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
588
648
  else if (node.type === "Return") {
589
649
  // Validate we're inside a function
590
650
  if (!expectedReturnType) {
591
- throw new Error(`Return statement outside of function at ${printLocationValue(node.value.location)}`);
651
+ throw new Error(`Return statement outside of function at loc_id ${node.value.loc_id}`);
592
652
  }
593
653
  // Analyze the return value expression
594
654
  const valueInfo = visit(node.value.value, ctx, expectedReturnType);
@@ -596,7 +656,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
596
656
  if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, expectedReturnType)) {
597
657
  throw new Error(`Return statement returns type ${printTypeValue(valueInfo.value.type)} ` +
598
658
  `but function signature expects ${printTypeValue(expectedReturnType)} ` +
599
- `at ${printLocationValue(node.value.location)}`);
659
+ `at loc_id ${node.value.loc_id}`);
600
660
  }
601
661
  // Return analyzed Return node with analyzed value
602
662
  return {
@@ -612,7 +672,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
612
672
  // Validate type is Ref
613
673
  if (node.value.type.type !== "Ref") {
614
674
  throw new Error(`NewRef node must have Ref type, got ${printTypeValue(node.value.type)} ` +
615
- `at ${printLocationValue(node.value.location)}`);
675
+ `at loc_id ${node.value.loc_id}`);
616
676
  }
617
677
  const elementType = node.value.type.value;
618
678
  const valueInfo = visit(node.value.value, ctx, expectedReturnType);
@@ -621,14 +681,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
621
681
  if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
622
682
  throw new Error(`Ref value has type ${printTypeValue(valueInfo.value.type)} ` +
623
683
  `but Ref expects ${printTypeValue(elementType)} ` +
624
- `at ${printLocationValue(node.value.location)}`);
684
+ `at loc_id ${node.value.loc_id}`);
625
685
  }
626
686
  }
627
687
  else if (node.type === "NewArray") {
628
688
  // Validate type is Array
629
689
  if (node.value.type.type !== "Array") {
630
690
  throw new Error(`NewArray node must have Array type, got ${printTypeValue(node.value.type)} ` +
631
- `at ${printLocationValue(node.value.location)}`);
691
+ `at loc_id ${node.value.loc_id}`);
632
692
  }
633
693
  const elementType = node.value.type.value;
634
694
  isAsync = false;
@@ -643,7 +703,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
643
703
  if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
644
704
  throw new Error(`Array element ${i} has type ${printTypeValue(valueInfo.value.type)} ` +
645
705
  `but array expects ${printTypeValue(elementType)} ` +
646
- `at ${printLocationValue(node.value.location)}`);
706
+ `at loc_id ${node.value.loc_id}`);
647
707
  }
648
708
  }
649
709
  }
@@ -651,7 +711,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
651
711
  // Validate type is Set
652
712
  if (node.value.type.type !== "Set") {
653
713
  throw new Error(`NewSet node must have Set type, got ${printTypeValue(node.value.type)} ` +
654
- `at ${printLocationValue(node.value.location)}`);
714
+ `at loc_id ${node.value.loc_id}`);
655
715
  }
656
716
  const keyType = node.value.type.value;
657
717
  isAsync = false;
@@ -666,7 +726,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
666
726
  if (keyInfo.value.type.type !== "Never" && !isTypeValueEqual(keyInfo.value.type, keyType)) {
667
727
  throw new Error(`Set element ${i} has type ${printTypeValue(keyInfo.value.type)} ` +
668
728
  `but set expects ${printTypeValue(keyType)} ` +
669
- `at ${printLocationValue(node.value.location)}`);
729
+ `at loc_id ${node.value.loc_id}`);
670
730
  }
671
731
  }
672
732
  }
@@ -674,7 +734,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
674
734
  // Validate type is Dict
675
735
  if (node.value.type.type !== "Dict") {
676
736
  throw new Error(`NewDict node must have Dict type, got ${printTypeValue(node.value.type)} ` +
677
- `at ${printLocationValue(node.value.location)}`);
737
+ `at loc_id ${node.value.loc_id}`);
678
738
  }
679
739
  const keyType = node.value.type.value.key;
680
740
  const valueType = node.value.type.value.value;
@@ -694,13 +754,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
694
754
  if (keyInfo.value.type.type !== "Never" && !isTypeValueEqual(keyInfo.value.type, keyType)) {
695
755
  throw new Error(`Dict key ${i} has type ${printTypeValue(keyInfo.value.type)} ` +
696
756
  `but dict expects ${printTypeValue(keyType)} ` +
697
- `at ${printLocationValue(node.value.location)}`);
757
+ `at loc_id ${node.value.loc_id}`);
698
758
  }
699
759
  // Validate value type exactly matches
700
760
  if (valInfo.value.type.type !== "Never" && !isTypeValueEqual(valInfo.value.type, valueType)) {
701
761
  throw new Error(`Dict value ${i} has type ${printTypeValue(valInfo.value.type)} ` +
702
762
  `but dict expects ${printTypeValue(valueType)} ` +
703
- `at ${printLocationValue(node.value.location)}`);
763
+ `at loc_id ${node.value.loc_id}`);
704
764
  }
705
765
  }
706
766
  }
@@ -710,19 +770,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
710
770
  // Validate it's an Array type (not Never)
711
771
  if (arrayInfo.value.type.type !== "Array") {
712
772
  throw new Error(`ForArray expects Array type, got ${printTypeValue(arrayInfo.value.type)} ` +
713
- `at ${printLocationValue(node.value.location)}`);
773
+ `at loc_id ${node.value.loc_id}`);
714
774
  }
715
775
  const elementType = arrayInfo.value.type.value;
716
776
  // Validate key variable is Integer type
717
777
  if (node.value.key.value.type.type !== "Integer") {
718
778
  throw new Error(`ForArray key must be Integer type, got ${printTypeValue(node.value.key.value.type)} ` +
719
- `at ${printLocationValue(node.value.location)}`);
779
+ `at loc_id ${node.value.loc_id}`);
720
780
  }
721
781
  // Validate value variable matches array element type
722
782
  if (!isTypeValueEqual(node.value.value.value.type, elementType)) {
723
783
  throw new Error(`ForArray value variable has type ${printTypeValue(node.value.value.value.type)} ` +
724
784
  `but array elements have type ${printTypeValue(elementType)} ` +
725
- `at ${printLocationValue(node.value.location)}`);
785
+ `at loc_id ${node.value.loc_id}`);
726
786
  }
727
787
  // Analyze the key and value VariableIR nodes
728
788
  analysis.set(node.value.key, {
@@ -764,14 +824,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
764
824
  // Validate it's a Set type (not Never)
765
825
  if (setInfo.value.type.type !== "Set") {
766
826
  throw new Error(`ForSet expects Set type, got ${printTypeValue(setInfo.value.type)} ` +
767
- `at ${printLocationValue(node.value.location)}`);
827
+ `at loc_id ${node.value.loc_id}`);
768
828
  }
769
829
  const elementType = setInfo.value.type.value;
770
830
  // Validate key variable matches set element type
771
831
  if (!isTypeValueEqual(node.value.key.value.type, elementType)) {
772
832
  throw new Error(`ForSet key variable has type ${printTypeValue(node.value.key.value.type)} ` +
773
833
  `but set elements have type ${printTypeValue(elementType)} ` +
774
- `at ${printLocationValue(node.value.location)}`);
834
+ `at loc_id ${node.value.loc_id}`);
775
835
  }
776
836
  // Analyze the key VariableIR node
777
837
  analysis.set(node.value.key, {
@@ -795,7 +855,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
795
855
  // Validate it's a Dict type (not Never)
796
856
  if (dictInfo.value.type.type !== "Dict") {
797
857
  throw new Error(`ForDict expects Dict type, got ${printTypeValue(dictInfo.value.type)} ` +
798
- `at ${printLocationValue(node.value.location)}`);
858
+ `at loc_id ${node.value.loc_id}`);
799
859
  }
800
860
  const keyType = dictInfo.value.type.value.key;
801
861
  const valueType = dictInfo.value.type.value.value;
@@ -803,13 +863,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
803
863
  if (!isTypeValueEqual(node.value.key.value.type, keyType)) {
804
864
  throw new Error(`ForDict key variable has type ${printTypeValue(node.value.key.value.type)} ` +
805
865
  `but dict keys have type ${printTypeValue(keyType)} ` +
806
- `at ${printLocationValue(node.value.location)}`);
866
+ `at loc_id ${node.value.loc_id}`);
807
867
  }
808
868
  // Validate value variable matches dict value type
809
869
  if (!isTypeValueEqual(node.value.value.value.type, valueType)) {
810
870
  throw new Error(`ForDict value variable has type ${printTypeValue(node.value.value.value.type)} ` +
811
871
  `but dict values have type ${printTypeValue(valueType)} ` +
812
- `at ${printLocationValue(node.value.location)}`);
872
+ `at loc_id ${node.value.loc_id}`);
813
873
  }
814
874
  // Analyze the key and value VariableIR nodes
815
875
  analysis.set(node.value.key, {
@@ -850,7 +910,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
850
910
  }
851
911
  if (predicateInfo.value.type.type !== "Boolean") {
852
912
  throw new Error(`IfElse predicate ${i} must be Boolean type, got ${printTypeValue(predicateInfo.value.type)} ` +
853
- `at ${printLocationValue(node.value.location)}`);
913
+ `at loc_id ${node.value.loc_id}`);
854
914
  }
855
915
  // Visit branch body and validate type
856
916
  const bodyInfo = visit(branch.body, ctx, expectedReturnType);
@@ -865,7 +925,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
865
925
  if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, node.value.type)) {
866
926
  throw new Error(`IfElse branch ${i} returns type ${printTypeValue(bodyInfo.value.type)} ` +
867
927
  `but IfElse expects ${printTypeValue(node.value.type)} ` +
868
- `at ${printLocationValue(node.value.location)}`);
928
+ `at loc_id ${node.value.loc_id}`);
869
929
  }
870
930
  analyzedIfs.push({ predicate: predicateInfo, body: bodyInfo });
871
931
  }
@@ -882,18 +942,18 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
882
942
  if (elseInfo.value.type.type !== "Never" && !isTypeValueEqual(elseInfo.value.type, node.value.type)) {
883
943
  throw new Error(`IfElse else branch returns type ${printTypeValue(elseInfo.value.type)} ` +
884
944
  `but IfElse expects ${printTypeValue(node.value.type)} ` +
885
- `at ${printLocationValue(node.value.location)}`);
945
+ `at loc_id ${node.value.loc_id}`);
886
946
  }
887
947
  // If all branches diverge, IfElse must be Never
888
948
  if (allBranchesNever && node.value.type.type !== "Never") {
889
949
  throw new Error(`IfElse has all branches returning Never, so it must have type Never, ` +
890
950
  `but has type ${printTypeValue(node.value.type)} ` +
891
- `at ${printLocationValue(node.value.location)}`);
951
+ `at loc_id ${node.value.loc_id}`);
892
952
  }
893
953
  // If IfElse is Never, all branches must be Never
894
954
  if (node.value.type.type === "Never" && !allBranchesNever) {
895
955
  throw new Error(`IfElse has type Never but not all branches diverge ` +
896
- `at ${printLocationValue(node.value.location)}`);
956
+ `at loc_id ${node.value.loc_id}`);
897
957
  }
898
958
  // Return analyzed IfElse with analyzed branches
899
959
  return {
@@ -911,7 +971,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
911
971
  const predicateInfo = visit(node.value.predicate, ctx, expectedReturnType);
912
972
  if (predicateInfo.value.type.type !== "Boolean") {
913
973
  throw new Error(`While predicate must be Boolean type, got ${printTypeValue(predicateInfo.value.type)} ` +
914
- `at ${printLocationValue(node.value.location)}`);
974
+ `at loc_id ${node.value.loc_id}`);
915
975
  }
916
976
  // Visit loop body
917
977
  const bodyInfo = visit(node.value.body, ctx, expectedReturnType);
@@ -939,7 +999,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
939
999
  const messageInfo = visit(node.value.message, ctx, expectedReturnType);
940
1000
  if (messageInfo.value.type.type !== "String") {
941
1001
  throw new Error(`Error message must be String type, got ${printTypeValue(messageInfo.value.type)} ` +
942
- `at ${printLocationValue(node.value.location)}`);
1002
+ `at loc_id ${node.value.loc_id}`);
943
1003
  }
944
1004
  // Error always has type Never (throws exception, diverges control flow)
945
1005
  isAsync = messageInfo.value.isAsync; // Error is async if message is async
@@ -950,13 +1010,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
950
1010
  // Validate message variable is String type
951
1011
  if (node.value.message.value.type.type !== "String") {
952
1012
  throw new Error(`TryCatch message variable must be String type, got ${printTypeValue(node.value.message.value.type)} ` +
953
- `at ${printLocationValue(node.value.location)}`);
1013
+ `at loc_id ${node.value.loc_id}`);
954
1014
  }
955
1015
  // Validate stack variable is correct type
956
1016
  const stackType = toEastTypeValue(ArrayType(StructType({ filename: StringType, line: IntegerType, column: IntegerType })));
957
1017
  if (!isTypeValueEqual(node.value.stack.value.type, stackType)) {
958
1018
  throw new Error(`TryCatch stack variable must be ${printTypeValue(stackType)} type, got ${printTypeValue(node.value.stack.value.type)} ` +
959
- `at ${printLocationValue(node.value.location)}`);
1019
+ `at loc_id ${node.value.loc_id}`);
960
1020
  }
961
1021
  // Analyze the message and stack VariableIR nodes
962
1022
  analysis.set(node.value.message, {
@@ -985,19 +1045,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
985
1045
  if (tryInfo.value.type.type !== "Never" && !isTypeValueEqual(tryInfo.value.type, node.value.type)) {
986
1046
  throw new Error(`TryCatch try body returns type ${printTypeValue(tryInfo.value.type)} ` +
987
1047
  `but TryCatch expects ${printTypeValue(node.value.type)} ` +
988
- `at ${printLocationValue(node.value.location)}`);
1048
+ `at loc_id ${node.value.loc_id}`);
989
1049
  }
990
1050
  if (catchInfo.value.type.type !== "Never" && !isTypeValueEqual(catchInfo.value.type, node.value.type)) {
991
1051
  throw new Error(`TryCatch catch body returns type ${printTypeValue(catchInfo.value.type)} ` +
992
1052
  `but TryCatch expects ${printTypeValue(node.value.type)} ` +
993
- `at ${printLocationValue(node.value.location)}`);
1053
+ `at loc_id ${node.value.loc_id}`);
994
1054
  }
995
1055
  // If both bodies diverge, TryCatch must be Never
996
1056
  const bothNever = tryInfo.value.type.type === "Never" && catchInfo.value.type.type === "Never";
997
1057
  if (bothNever && node.value.type.type !== "Never") {
998
1058
  throw new Error(`TryCatch has both try and catch bodies returning Never, so it must have type Never, ` +
999
1059
  `but has type ${printTypeValue(node.value.type)} ` +
1000
- `at ${printLocationValue(node.value.location)}`);
1060
+ `at loc_id ${node.value.loc_id}`);
1001
1061
  }
1002
1062
  // Visit finally body
1003
1063
  const finallyInfo = visit(node.value.finally_body, ctx, expectedReturnType);
@@ -1018,14 +1078,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1018
1078
  // Validate type is Struct
1019
1079
  if (node.value.type.type !== "Struct") {
1020
1080
  throw new Error(`Struct node must have Struct type, got ${printTypeValue(node.value.type)} ` +
1021
- `at ${printLocationValue(node.value.location)}`);
1081
+ `at loc_id ${node.value.loc_id}`);
1022
1082
  }
1023
1083
  const structType = expandTypeValue(node.value.type);
1024
1084
  isAsync = false;
1025
1085
  if (structType.value.length !== node.value.fields.length) {
1026
1086
  throw new Error(`Struct type has ${structType.value.length} fields but struct value has ` +
1027
1087
  `${node.value.fields.length} fields ` +
1028
- `at ${printLocationValue(node.value.location)}`);
1088
+ `at loc_id ${node.value.loc_id}`);
1029
1089
  }
1030
1090
  // Visit all field values and validate types
1031
1091
  for (const [i, field] of node.value.fields.entries()) {
@@ -1037,13 +1097,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1037
1097
  const typeField = structType.value[i];
1038
1098
  if (typeField.name !== field.name) {
1039
1099
  throw new Error(`Struct has field ${typeField.name} at position ${i}, but value does not ` +
1040
- `at ${printLocationValue(node.value.location)}`);
1100
+ `at loc_id ${node.value.loc_id}`);
1041
1101
  }
1042
1102
  // Validate field type exactly matches
1043
1103
  if (!isTypeValueEqual(fieldInfo.value.type, typeField.type)) {
1044
1104
  throw new Error(`Struct field ${field.name} has type ${printTypeValue(fieldInfo.value.type)} ` +
1045
1105
  `but struct type expects ${printTypeValue(typeField.type)} ` +
1046
- `at ${printLocationValue(node.value.location)}`);
1106
+ `at loc_id ${node.value.loc_id}`);
1047
1107
  }
1048
1108
  }
1049
1109
  }
@@ -1053,20 +1113,20 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1053
1113
  // Validate it's a Struct type
1054
1114
  if (structInfo.value.type.type !== "Struct") {
1055
1115
  throw new Error(`GetField expects Struct type, got ${printTypeValue(structInfo.value.type)} ` +
1056
- `at ${printLocationValue(node.value.location)}`);
1116
+ `at loc_id ${node.value.loc_id}`);
1057
1117
  }
1058
1118
  // Find the field in struct type
1059
1119
  const structType = expandTypeValue(structInfo.value.type);
1060
1120
  const field = structType.value.find(f => f.name === node.value.field);
1061
1121
  if (!field) {
1062
1122
  throw new Error(`Struct does not have field ${node.value.field} ` +
1063
- `at ${printLocationValue(node.value.location)}`);
1123
+ `at loc_id ${node.value.loc_id}`);
1064
1124
  }
1065
1125
  // Validate return type matches field type
1066
1126
  if (!isTypeValueEqual(node.value.type, field.type)) {
1067
1127
  throw new Error(`GetField result type ${printTypeValue(node.value.type)} ` +
1068
1128
  `does not match field type ${printTypeValue(field.type)} ` +
1069
- `at ${printLocationValue(node.value.location)}`);
1129
+ `at loc_id ${node.value.loc_id}`);
1070
1130
  }
1071
1131
  isAsync = structInfo.value.isAsync;
1072
1132
  }
@@ -1076,25 +1136,25 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1076
1136
  // Validate type is Variant
1077
1137
  if (node.value.type.type !== "Variant") {
1078
1138
  throw new Error(`Variant node must have Variant type, got ${printTypeValue(node.value.type)} ` +
1079
- `at ${printLocationValue(node.value.location)}`);
1139
+ `at loc_id ${node.value.loc_id}`);
1080
1140
  }
1081
1141
  // Expand recursive types to get well-formed variant type
1082
1142
  const variantType = expandTypeValue(node.value.type);
1083
1143
  if (variantType.type !== "Variant") {
1084
1144
  throw new Error(`Expanded Variant type is not Variant, got ${printTypeValue(variantType)} ` +
1085
- `at ${printLocationValue(node.value.location)}`);
1145
+ `at loc_id ${node.value.loc_id}`);
1086
1146
  }
1087
1147
  // Find the case in variant type
1088
1148
  const caseType = variantType.value.find((c) => c.name === node.value.case);
1089
1149
  if (!caseType) {
1090
1150
  throw new Error(`Variant type does not have case ${node.value.case} ` +
1091
- `at ${printLocationValue(node.value.location)}`);
1151
+ `at loc_id ${node.value.loc_id}`);
1092
1152
  }
1093
1153
  // Validate value type exactly matches case type
1094
1154
  if (!isTypeValueEqual(valueInfo.value.type, caseType.type)) {
1095
1155
  throw new Error(`Variant case ${node.value.case} value has type ${printTypeValue(valueInfo.value.type)} ` +
1096
1156
  `but variant type expects ${printTypeValue(caseType.type)} ` +
1097
- `at ${printLocationValue(node.value.location)}`);
1157
+ `at loc_id ${node.value.loc_id}`);
1098
1158
  }
1099
1159
  isAsync = valueInfo.value.isAsync;
1100
1160
  }
@@ -1104,19 +1164,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1104
1164
  // Validate it's a Variant type
1105
1165
  if (variantInfo.value.type.type !== "Variant") {
1106
1166
  throw new Error(`Match expects Variant type, got ${printTypeValue(variantInfo.value.type)} ` +
1107
- `at ${printLocationValue(node.value.location)}`);
1167
+ `at loc_id ${node.value.loc_id}`);
1108
1168
  }
1109
1169
  // Expand recursive types to get well-formed variant type
1110
1170
  const variantType = expandTypeValue(variantInfo.value.type);
1111
1171
  if (variantType.type !== "Variant") {
1112
1172
  throw new Error(`Expanded Match variant type is not Variant, got ${printTypeValue(variantType)} ` +
1113
- `at ${printLocationValue(node.value.location)}`);
1173
+ `at loc_id ${node.value.loc_id}`);
1114
1174
  }
1115
1175
  // Validate case count matches
1116
1176
  if (variantType.value.length !== node.value.cases.length) {
1117
1177
  throw new Error(`Match has ${node.value.cases.length} cases but variant type has ` +
1118
1178
  `${variantType.value.length} cases ` +
1119
- `at ${printLocationValue(node.value.location)}`);
1179
+ `at loc_id ${node.value.loc_id}`);
1120
1180
  }
1121
1181
  isAsync = variantInfo.value.isAsync;
1122
1182
  let allCasesNever = true;
@@ -1126,13 +1186,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1126
1186
  const typeCase = variantType.value.find((c) => c.name === matchCase.case);
1127
1187
  if (!typeCase) {
1128
1188
  throw new Error(`Match has case ${matchCase.case} but variant type does not ` +
1129
- `at ${printLocationValue(node.value.location)}`);
1189
+ `at loc_id ${node.value.loc_id}`);
1130
1190
  }
1131
1191
  // Validate variable type matches case type
1132
1192
  if (!isTypeValueEqual(matchCase.variable.value.type, typeCase.type)) {
1133
1193
  throw new Error(`Match case ${matchCase.case} variable has type ${printTypeValue(matchCase.variable.value.type)} ` +
1134
1194
  `but variant case has type ${printTypeValue(typeCase.type)} ` +
1135
- `at ${printLocationValue(node.value.location)}`);
1195
+ `at loc_id ${node.value.loc_id}`);
1136
1196
  }
1137
1197
  // Analyze the variable VariableIR node
1138
1198
  analysis.set(matchCase.variable, {
@@ -1159,41 +1219,93 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
1159
1219
  if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, node.value.type)) {
1160
1220
  throw new Error(`Match case ${matchCase.case} returns type ${printTypeValue(bodyInfo.value.type)} ` +
1161
1221
  `but Match expects ${printTypeValue(node.value.type)} ` +
1162
- `at ${printLocationValue(node.value.location)}`);
1222
+ `at loc_id ${node.value.loc_id}`);
1163
1223
  }
1164
1224
  }
1165
1225
  // If all cases diverge, Match must be Never
1166
1226
  if (allCasesNever && node.value.type.type !== "Never") {
1167
1227
  throw new Error(`Match has all cases returning Never, so it must have type Never, ` +
1168
1228
  `but has type ${printTypeValue(node.value.type)} ` +
1169
- `at ${printLocationValue(node.value.location)}`);
1229
+ `at loc_id ${node.value.loc_id}`);
1170
1230
  }
1171
1231
  // isAsync already set from loop above
1172
1232
  }
1173
1233
  else if (node.type === "UnwrapRecursive") {
1174
1234
  // Visit the value expression
1175
1235
  const valueInfo = visit(node.value.value, ctx, expectedReturnType);
1176
- // Validate result type matches expanded type
1177
- if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(node.value.type, valueInfo.value.type)) {
1236
+ // Validate result type matches expanded type.
1237
+ // The value type may be Recursive(wrapper({id, inner})) — unwrap for comparison.
1238
+ const inputType = valueInfo.value.type.type === "Recursive" && valueInfo.value.type.value.type === "wrapper"
1239
+ ? valueInfo.value.type.value.value.inner : valueInfo.value.type;
1240
+ if (inputType.type !== "Never" && !isTypeValueEqual(node.value.type, inputType)) {
1178
1241
  throw new Error(`UnwrapRecursive result type ${printTypeValue(node.value.type)} ` +
1179
- `does not match recursive type ${printTypeValue(valueInfo.value.type)} ` +
1180
- `at ${printLocationValue(node.value.location)}`);
1242
+ `does not match recursive type ${printTypeValue(inputType)} ` +
1243
+ `at loc_id ${node.value.loc_id}`);
1181
1244
  }
1182
1245
  isAsync = valueInfo.value.isAsync;
1183
1246
  }
1184
1247
  else if (node.type === "WrapRecursive") {
1185
1248
  // Visit the value expression
1186
1249
  const valueInfo = visit(node.value.value, ctx, expectedReturnType);
1187
- // Validate value type matches expanded recursive type
1188
- if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, node.value.type)) {
1250
+ // Validate value type matches the inner type of the recursive wrapper.
1251
+ // node.value.type is Recursive(wrapper({id, inner})) — the value has the inner type.
1252
+ const expectedType = node.value.type.type === "Recursive" && node.value.type.value.type === "wrapper"
1253
+ ? node.value.type.value.value.inner : node.value.type;
1254
+ if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, expectedType)) {
1189
1255
  throw new Error(`WrapRecursive value has type ${printTypeValue(valueInfo.value.type)} ` +
1190
- `but expects ${printTypeValue(node.value.type)} ` +
1191
- `at ${printLocationValue(node.value.location)}`);
1256
+ `but expects ${printTypeValue(expectedType)} ` +
1257
+ `at loc_id ${node.value.loc_id}`);
1192
1258
  }
1193
1259
  isAsync = valueInfo.value.isAsync;
1194
1260
  }
1261
+ else if (node.type === "NewVector") {
1262
+ // Validate type is Vector
1263
+ if (node.value.type.type !== "Vector") {
1264
+ throw new Error(`NewVector node must have Vector type, got ${printTypeValue(node.value.type)} ` +
1265
+ `at loc_id ${node.value.loc_id}`);
1266
+ }
1267
+ const elementType = node.value.type.value;
1268
+ isAsync = false;
1269
+ // Visit all element values and validate types
1270
+ for (let i = 0; i < node.value.values.length; i++) {
1271
+ const valueExpr = node.value.values[i];
1272
+ const valueInfo = visit(valueExpr, ctx, expectedReturnType);
1273
+ if (valueInfo.value.isAsync) {
1274
+ isAsync = true;
1275
+ }
1276
+ // Validate element type exactly matches
1277
+ if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
1278
+ throw new Error(`Vector element ${i} has type ${printTypeValue(valueInfo.value.type)} ` +
1279
+ `but vector expects ${printTypeValue(elementType)} ` +
1280
+ `at loc_id ${node.value.loc_id}`);
1281
+ }
1282
+ }
1283
+ }
1284
+ else if (node.type === "NewMatrix") {
1285
+ // Validate type is Matrix
1286
+ if (node.value.type.type !== "Matrix") {
1287
+ throw new Error(`NewMatrix node must have Matrix type, got ${printTypeValue(node.value.type)} ` +
1288
+ `at loc_id ${node.value.loc_id}`);
1289
+ }
1290
+ const elementType = node.value.type.value;
1291
+ isAsync = false;
1292
+ // Visit all element values and validate types
1293
+ for (let i = 0; i < node.value.values.length; i++) {
1294
+ const valueExpr = node.value.values[i];
1295
+ const valueInfo = visit(valueExpr, ctx, expectedReturnType);
1296
+ if (valueInfo.value.isAsync) {
1297
+ isAsync = true;
1298
+ }
1299
+ // Validate element type exactly matches
1300
+ if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
1301
+ throw new Error(`Matrix element ${i} has type ${printTypeValue(valueInfo.value.type)} ` +
1302
+ `but matrix expects ${printTypeValue(elementType)} ` +
1303
+ `at loc_id ${node.value.loc_id}`);
1304
+ }
1305
+ }
1306
+ }
1195
1307
  else {
1196
- throw new Error(`Unhandled IR type: ${node.type} at ${printLocationValue(node.value?.location || { file: "unknown", line: 0, column: 0 })}`);
1308
+ throw new Error(`Unhandled IR type: ${node.type} at loc_id ${node.value?.loc_id ?? -1n}`);
1197
1309
  }
1198
1310
  return {
1199
1311
  ...node,