@scriptc/compiler 0.2.3 → 0.2.5

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 (1124) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +915 -215
  2. package/ambient/scriptc-overrides.d.ts +5 -1
  3. package/ambient/scriptc.d.ts +22 -2
  4. package/dist/backend/build-cache.d.ts +4 -0
  5. package/dist/backend/build-cache.js +16 -2
  6. package/dist/backend/build-cache.js.map +1 -1
  7. package/dist/backend/cycle-analysis.js +17 -5
  8. package/dist/backend/cycle-analysis.js.map +1 -1
  9. package/dist/backend/cycle-analysis.test.js +50 -11
  10. package/dist/backend/cycle-analysis.test.js.map +1 -1
  11. package/dist/backend/debug-symbols.js.map +1 -1
  12. package/dist/backend/executable-features.js +2 -1
  13. package/dist/backend/executable-features.js.map +1 -1
  14. package/dist/backend/external-c.d.ts +13 -6
  15. package/dist/backend/external-c.js +15 -3
  16. package/dist/backend/external-c.js.map +1 -1
  17. package/dist/backend/ffi-callbacks.js +6 -9
  18. package/dist/backend/ffi-callbacks.js.map +1 -1
  19. package/dist/backend/library-identity-markers.js.map +1 -1
  20. package/dist/backend/library-pack.d.ts +1 -1
  21. package/dist/backend/library-pack.js +81 -24
  22. package/dist/backend/library-pack.js.map +1 -1
  23. package/dist/backend/link-plan-core.js +9 -2
  24. package/dist/backend/link-plan-core.js.map +1 -1
  25. package/dist/backend/link-plan.d.ts +1 -1
  26. package/dist/backend/link-plan.js +4 -5
  27. package/dist/backend/link-plan.js.map +1 -1
  28. package/dist/backend/linker.d.ts +1 -1
  29. package/dist/backend/linker.js +42 -23
  30. package/dist/backend/linker.js.map +1 -1
  31. package/dist/backend/literals.js +5 -4
  32. package/dist/backend/literals.js.map +1 -1
  33. package/dist/backend/literals.test.js +30 -5
  34. package/dist/backend/literals.test.js.map +1 -1
  35. package/dist/backend/llvm/blocks.test.js +5 -2
  36. package/dist/backend/llvm/blocks.test.js.map +1 -1
  37. package/dist/backend/llvm/borrowed-inputs.d.ts +15 -0
  38. package/dist/backend/llvm/borrowed-inputs.js +28 -0
  39. package/dist/backend/llvm/borrowed-inputs.js.map +1 -0
  40. package/dist/backend/llvm/borrowed-receivers.js +43 -19
  41. package/dist/backend/llvm/borrowed-receivers.js.map +1 -1
  42. package/dist/backend/llvm/byte-numbers.d.ts +10 -0
  43. package/dist/backend/llvm/byte-numbers.js +240 -0
  44. package/dist/backend/llvm/byte-numbers.js.map +1 -0
  45. package/dist/backend/llvm/bytes-bounds.d.ts +9 -0
  46. package/dist/backend/llvm/bytes-bounds.js +240 -0
  47. package/dist/backend/llvm/bytes-bounds.js.map +1 -0
  48. package/dist/backend/llvm/call-lifetimes.d.ts +10 -0
  49. package/dist/backend/llvm/call-lifetimes.js +83 -20
  50. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  51. package/dist/backend/llvm/call-lifetimes.test.js +203 -18
  52. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  53. package/dist/backend/llvm/checked-value-lifetimes.d.ts +13 -0
  54. package/dist/backend/llvm/checked-value-lifetimes.js +45 -0
  55. package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -0
  56. package/dist/backend/llvm/classes.js +16 -12
  57. package/dist/backend/llvm/classes.js.map +1 -1
  58. package/dist/backend/llvm/common.js +4 -1
  59. package/dist/backend/llvm/common.js.map +1 -1
  60. package/dist/backend/llvm/counted-loops.d.ts +6 -0
  61. package/dist/backend/llvm/counted-loops.js +35 -0
  62. package/dist/backend/llvm/counted-loops.js.map +1 -0
  63. package/dist/backend/llvm/debug-info.js +33 -13
  64. package/dist/backend/llvm/debug-info.js.map +1 -1
  65. package/dist/backend/llvm/debug-info.test.js +28 -6
  66. package/dist/backend/llvm/debug-info.test.js.map +1 -1
  67. package/dist/backend/llvm/dyn.js +68 -22
  68. package/dist/backend/llvm/dyn.js.map +1 -1
  69. package/dist/backend/llvm/emitter.d.ts +34 -12
  70. package/dist/backend/llvm/emitter.js +357 -124
  71. package/dist/backend/llvm/emitter.js.map +1 -1
  72. package/dist/backend/llvm/emitter.test.js +237 -46
  73. package/dist/backend/llvm/emitter.test.js.map +1 -1
  74. package/dist/backend/llvm/expr-async.js +28 -8
  75. package/dist/backend/llvm/expr-async.js.map +1 -1
  76. package/dist/backend/llvm/expr-bytes.d.ts +4 -4
  77. package/dist/backend/llvm/expr-bytes.js +78 -36
  78. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  79. package/dist/backend/llvm/expr-callbacks.js +10 -4
  80. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  81. package/dist/backend/llvm/expr-calls.js +40 -21
  82. package/dist/backend/llvm/expr-calls.js.map +1 -1
  83. package/dist/backend/llvm/expr-containers.d.ts +4 -1
  84. package/dist/backend/llvm/expr-containers.js +157 -76
  85. package/dist/backend/llvm/expr-containers.js.map +1 -1
  86. package/dist/backend/llvm/expr-context.d.ts +11 -0
  87. package/dist/backend/llvm/expr-control.js +27 -8
  88. package/dist/backend/llvm/expr-control.js.map +1 -1
  89. package/dist/backend/llvm/expr-dispatch.js +3 -1
  90. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  91. package/dist/backend/llvm/expr-dynamic.js +50 -33
  92. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  93. package/dist/backend/llvm/expr-island.js +26 -6
  94. package/dist/backend/llvm/expr-island.js.map +1 -1
  95. package/dist/backend/llvm/expr-primitives.js +139 -37
  96. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  97. package/dist/backend/llvm/expr-primitives.test.js +43 -1
  98. package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
  99. package/dist/backend/llvm/expr-records.js +16 -9
  100. package/dist/backend/llvm/expr-records.js.map +1 -1
  101. package/dist/backend/llvm/expr-stream-bridges.js +44 -26
  102. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  103. package/dist/backend/llvm/expr-stream-bridges.test.js +51 -14
  104. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
  105. package/dist/backend/llvm/expr-stream-callbacks.js +34 -14
  106. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  107. package/dist/backend/llvm/integer-values.d.ts +10 -0
  108. package/dist/backend/llvm/integer-values.js +52 -0
  109. package/dist/backend/llvm/integer-values.js.map +1 -0
  110. package/dist/backend/llvm/integer-views.d.ts +7 -0
  111. package/dist/backend/llvm/integer-views.js +83 -0
  112. package/dist/backend/llvm/integer-views.js.map +1 -0
  113. package/dist/backend/llvm/integer-views.test.d.ts +1 -0
  114. package/dist/backend/llvm/integer-views.test.js +69 -0
  115. package/dist/backend/llvm/integer-views.test.js.map +1 -0
  116. package/dist/backend/llvm/lib-abi.js +13 -4
  117. package/dist/backend/llvm/lib-abi.js.map +1 -1
  118. package/dist/backend/llvm/lib-connect.js +7 -1
  119. package/dist/backend/llvm/lib-connect.js.map +1 -1
  120. package/dist/backend/llvm/lib-datagram.js +35 -10
  121. package/dist/backend/llvm/lib-datagram.js.map +1 -1
  122. package/dist/backend/llvm/lib-dispatch.js +36 -15
  123. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  124. package/dist/backend/llvm/lib-filesystem.js +38 -23
  125. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  126. package/dist/backend/llvm/lib-http2.js +60 -15
  127. package/dist/backend/llvm/lib-http2.js.map +1 -1
  128. package/dist/backend/llvm/lib-lookup.js +12 -5
  129. package/dist/backend/llvm/lib-lookup.js.map +1 -1
  130. package/dist/backend/llvm/lib-network.js +97 -31
  131. package/dist/backend/llvm/lib-network.js.map +1 -1
  132. package/dist/backend/llvm/lib-process.js +57 -14
  133. package/dist/backend/llvm/lib-process.js.map +1 -1
  134. package/dist/backend/llvm/lib-shared.js +107 -31
  135. package/dist/backend/llvm/lib-shared.js.map +1 -1
  136. package/dist/backend/llvm/lib-stream.js +33 -14
  137. package/dist/backend/llvm/lib-stream.js.map +1 -1
  138. package/dist/backend/llvm/lib-test.js +21 -7
  139. package/dist/backend/llvm/lib-test.js.map +1 -1
  140. package/dist/backend/llvm/lib-tls.js +69 -20
  141. package/dist/backend/llvm/lib-tls.js.map +1 -1
  142. package/dist/backend/llvm/local-array-reads.d.ts +3 -4
  143. package/dist/backend/llvm/local-array-reads.js +100 -121
  144. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  145. package/dist/backend/llvm/local-array-reads.test.js +379 -71
  146. package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
  147. package/dist/backend/llvm/local-union-storage.d.ts +25 -0
  148. package/dist/backend/llvm/local-union-storage.js +109 -0
  149. package/dist/backend/llvm/local-union-storage.js.map +1 -0
  150. package/dist/backend/llvm/local-union-storage.test.d.ts +1 -0
  151. package/dist/backend/llvm/local-union-storage.test.js +210 -0
  152. package/dist/backend/llvm/local-union-storage.test.js.map +1 -0
  153. package/dist/backend/llvm/map-read-lifetimes.d.ts +6 -2
  154. package/dist/backend/llvm/map-read-lifetimes.js +46 -16
  155. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  156. package/dist/backend/llvm/map-read-lifetimes.test.js +93 -17
  157. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  158. package/dist/backend/llvm/reference-effects.d.ts +23 -0
  159. package/dist/backend/llvm/reference-effects.js +179 -0
  160. package/dist/backend/llvm/reference-effects.js.map +1 -0
  161. package/dist/backend/llvm/reference-effects.test.d.ts +1 -0
  162. package/dist/backend/llvm/reference-effects.test.js +157 -0
  163. package/dist/backend/llvm/reference-effects.test.js.map +1 -0
  164. package/dist/backend/llvm/shapes.d.ts +7 -4
  165. package/dist/backend/llvm/shapes.js +82 -22
  166. package/dist/backend/llvm/shapes.js.map +1 -1
  167. package/dist/backend/llvm/shapes.test.js +3 -1
  168. package/dist/backend/llvm/shapes.test.js.map +1 -1
  169. package/dist/backend/llvm/split.js +4 -4
  170. package/dist/backend/llvm/split.js.map +1 -1
  171. package/dist/backend/llvm/split.test.js +14 -6
  172. package/dist/backend/llvm/split.test.js.map +1 -1
  173. package/dist/backend/llvm/stack-unions.js +14 -5
  174. package/dist/backend/llvm/stack-unions.js.map +1 -1
  175. package/dist/backend/llvm/stack-unions.test.js +172 -32
  176. package/dist/backend/llvm/stack-unions.test.js.map +1 -1
  177. package/dist/backend/llvm/string-construction.d.ts +10 -0
  178. package/dist/backend/llvm/string-construction.js +38 -0
  179. package/dist/backend/llvm/string-construction.js.map +1 -0
  180. package/dist/backend/llvm/string-construction.test.d.ts +1 -0
  181. package/dist/backend/llvm/string-construction.test.js +90 -0
  182. package/dist/backend/llvm/string-construction.test.js.map +1 -0
  183. package/dist/backend/llvm/string-lifetimes.d.ts +2 -2
  184. package/dist/backend/llvm/string-lifetimes.js +19 -11
  185. package/dist/backend/llvm/string-lifetimes.js.map +1 -1
  186. package/dist/backend/llvm/string-lifetimes.test.js +127 -32
  187. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  188. package/dist/backend/llvm/switch-dispatch.d.ts +9 -0
  189. package/dist/backend/llvm/switch-dispatch.js +114 -0
  190. package/dist/backend/llvm/switch-dispatch.js.map +1 -0
  191. package/dist/backend/llvm/switch-dispatch.test.d.ts +1 -0
  192. package/dist/backend/llvm/switch-dispatch.test.js +83 -0
  193. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -0
  194. package/dist/backend/llvm/unsupported.js.map +1 -1
  195. package/dist/backend/llvm/walkers.js +6 -3
  196. package/dist/backend/llvm/walkers.js.map +1 -1
  197. package/dist/backend/mangle.js +9 -3
  198. package/dist/backend/mangle.js.map +1 -1
  199. package/dist/backend/may-throw.js +18 -8
  200. package/dist/backend/may-throw.js.map +1 -1
  201. package/dist/backend/may-throw.test.js +118 -22
  202. package/dist/backend/may-throw.test.js.map +1 -1
  203. package/dist/backend/native/artifact-stamps.d.ts +39 -0
  204. package/dist/backend/native/artifact-stamps.js +371 -0
  205. package/dist/backend/native/artifact-stamps.js.map +1 -0
  206. package/dist/backend/native/cache-warm.d.ts +24 -0
  207. package/dist/backend/native/cache-warm.js +80 -0
  208. package/dist/backend/native/cache-warm.js.map +1 -0
  209. package/dist/backend/native/compiler-fingerprint.d.ts +19 -0
  210. package/dist/backend/native/compiler-fingerprint.js +357 -0
  211. package/dist/backend/native/compiler-fingerprint.js.map +1 -0
  212. package/dist/backend/native/contracts.d.ts +314 -0
  213. package/dist/backend/native/contracts.js +2 -0
  214. package/dist/backend/native/contracts.js.map +1 -0
  215. package/dist/backend/native/dependency-files.d.ts +5 -0
  216. package/dist/backend/native/dependency-files.js +83 -0
  217. package/dist/backend/native/dependency-files.js.map +1 -0
  218. package/dist/backend/native/driver.d.ts +50 -0
  219. package/dist/backend/native/driver.js +294 -0
  220. package/dist/backend/native/driver.js.map +1 -0
  221. package/dist/backend/native/executable.d.ts +18 -0
  222. package/dist/backend/native/executable.js +1267 -0
  223. package/dist/backend/native/executable.js.map +1 -0
  224. package/dist/backend/native/library.d.ts +2 -0
  225. package/dist/backend/native/library.js +614 -0
  226. package/dist/backend/native/library.js.map +1 -0
  227. package/dist/backend/native/linker-fingerprint.d.ts +8 -0
  228. package/dist/backend/native/linker-fingerprint.js +174 -0
  229. package/dist/backend/native/linker-fingerprint.js.map +1 -0
  230. package/dist/backend/native/object-merge.d.ts +2 -0
  231. package/dist/backend/native/object-merge.js +154 -0
  232. package/dist/backend/native/object-merge.js.map +1 -0
  233. package/dist/backend/native/process.d.ts +17 -0
  234. package/dist/backend/native/process.js +42 -0
  235. package/dist/backend/native/process.js.map +1 -0
  236. package/dist/backend/native/program-shards.d.ts +21 -0
  237. package/dist/backend/native/program-shards.js +99 -0
  238. package/dist/backend/native/program-shards.js.map +1 -0
  239. package/dist/backend/native/runtime-inputs.d.ts +12 -0
  240. package/dist/backend/native/runtime-inputs.js +163 -0
  241. package/dist/backend/native/runtime-inputs.js.map +1 -0
  242. package/dist/backend/native/runtime-inputs.test.d.ts +1 -0
  243. package/dist/backend/native/runtime-inputs.test.js +64 -0
  244. package/dist/backend/native/runtime-inputs.test.js.map +1 -0
  245. package/dist/backend/native/runtime-objects.d.ts +16 -0
  246. package/dist/backend/native/runtime-objects.js +122 -0
  247. package/dist/backend/native/runtime-objects.js.map +1 -0
  248. package/dist/backend/native/session.d.ts +12 -0
  249. package/dist/backend/native/session.js +31 -0
  250. package/dist/backend/native/session.js.map +1 -0
  251. package/dist/backend/native/tool-identity.d.ts +37 -0
  252. package/dist/backend/native/tool-identity.js +310 -0
  253. package/dist/backend/native/tool-identity.js.map +1 -0
  254. package/dist/backend/native/trace-paths.d.ts +12 -0
  255. package/dist/backend/native/trace-paths.js +73 -0
  256. package/dist/backend/native/trace-paths.js.map +1 -0
  257. package/dist/backend/native/vendor.d.ts +1 -0
  258. package/dist/backend/native/vendor.js +12 -0
  259. package/dist/backend/native/vendor.js.map +1 -0
  260. package/dist/backend/native-codegen-core.js +2 -1
  261. package/dist/backend/native-codegen-core.js.map +1 -1
  262. package/dist/backend/native-codegen.d.ts +1 -1
  263. package/dist/backend/native-codegen.js +24 -13
  264. package/dist/backend/native-codegen.js.map +1 -1
  265. package/dist/backend/native-codegen.test.js +12 -9
  266. package/dist/backend/native-codegen.test.js.map +1 -1
  267. package/dist/backend/native-link-info-core.js +9 -5
  268. package/dist/backend/native-link-info-core.js.map +1 -1
  269. package/dist/backend/native-link-info.js +14 -5
  270. package/dist/backend/native-link-info.js.map +1 -1
  271. package/dist/backend/native-link-info.test.js +58 -13
  272. package/dist/backend/native-link-info.test.js.map +1 -1
  273. package/dist/backend/native-toolchain.d.ts +17 -450
  274. package/dist/backend/native-toolchain.js +17 -3971
  275. package/dist/backend/native-toolchain.js.map +1 -1
  276. package/dist/backend/native-toolchain.test.js +103 -72
  277. package/dist/backend/native-toolchain.test.js.map +1 -1
  278. package/dist/backend/native-tools.js +27 -8
  279. package/dist/backend/native-tools.js.map +1 -1
  280. package/dist/backend/object-localize.js +17 -14
  281. package/dist/backend/object-localize.js.map +1 -1
  282. package/dist/backend/object-localize.test.js +59 -12
  283. package/dist/backend/object-localize.test.js.map +1 -1
  284. package/dist/backend/runtime-pack-core.js +96 -49
  285. package/dist/backend/runtime-pack-core.js.map +1 -1
  286. package/dist/backend/runtime-pack-native.js +5 -3
  287. package/dist/backend/runtime-pack-native.js.map +1 -1
  288. package/dist/backend/runtime-pack-targets.test.js +87 -15
  289. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  290. package/dist/backend/runtime-pack.d.ts +1 -1
  291. package/dist/backend/runtime-pack.js +11 -12
  292. package/dist/backend/runtime-pack.js.map +1 -1
  293. package/dist/backend/runtime-pack.test.js +40 -24
  294. package/dist/backend/runtime-pack.test.js.map +1 -1
  295. package/dist/backend/source-locations.js.map +1 -1
  296. package/dist/backend/source-locations.test.js +7 -2
  297. package/dist/backend/source-locations.test.js.map +1 -1
  298. package/dist/backend/target-diagnostics.js +44 -14
  299. package/dist/backend/target-diagnostics.js.map +1 -1
  300. package/dist/backend/target-diagnostics.test.js +93 -20
  301. package/dist/backend/target-diagnostics.test.js.map +1 -1
  302. package/dist/backend/targets.js +230 -86
  303. package/dist/backend/targets.js.map +1 -1
  304. package/dist/backend/targets.test.js +32 -18
  305. package/dist/backend/targets.test.js.map +1 -1
  306. package/dist/backend/toolchain-environment.js +5 -1
  307. package/dist/backend/toolchain-environment.js.map +1 -1
  308. package/dist/backend/vendor-archives.d.ts +2 -2
  309. package/dist/backend/vendor-archives.js +84 -35
  310. package/dist/backend/vendor-archives.js.map +1 -1
  311. package/dist/backend/vendor-inputs.js +13 -1
  312. package/dist/backend/vendor-inputs.js.map +1 -1
  313. package/dist/backend/warm-cache.d.ts +1 -1
  314. package/dist/backend/warm-cache.js +33 -9
  315. package/dist/backend/warm-cache.js.map +1 -1
  316. package/dist/cli/command.js +39 -9
  317. package/dist/cli/command.js.map +1 -1
  318. package/dist/cli/output-options.js +14 -4
  319. package/dist/cli/output-options.js.map +1 -1
  320. package/dist/cli/paths.js.map +1 -1
  321. package/dist/cli/wasi-runner.js.map +1 -1
  322. package/dist/compat/fetch-profile.js +36 -35
  323. package/dist/compat/fetch-profile.js.map +1 -1
  324. package/dist/coverage/report.js +16 -17
  325. package/dist/coverage/report.js.map +1 -1
  326. package/dist/coverage/surface-manifest.js +112 -26
  327. package/dist/coverage/surface-manifest.js.map +1 -1
  328. package/dist/diagnostics/diagnostic.js +55 -16
  329. package/dist/diagnostics/diagnostic.js.map +1 -1
  330. package/dist/executable/executable-cache.d.ts +1 -1
  331. package/dist/executable/executable-cache.js +78 -48
  332. package/dist/executable/executable-cache.js.map +1 -1
  333. package/dist/executable/executable-cache.test.js +75 -26
  334. package/dist/executable/executable-cache.test.js.map +1 -1
  335. package/dist/executable/prepare.js +2 -2
  336. package/dist/executable/prepare.js.map +1 -1
  337. package/dist/ffi/ffi-manifest.js +78 -20
  338. package/dist/ffi/ffi-manifest.js.map +1 -1
  339. package/dist/ffi/ffi-manifest.test.js +96 -16
  340. package/dist/ffi/ffi-manifest.test.js.map +1 -1
  341. package/dist/format-integer.js.map +1 -1
  342. package/dist/frontend/analysis.js +12 -2
  343. package/dist/frontend/analysis.js.map +1 -1
  344. package/dist/frontend/arguments-usage.js.map +1 -1
  345. package/dist/frontend/binding-source.js +9 -3
  346. package/dist/frontend/binding-source.js.map +1 -1
  347. package/dist/frontend/builtin-modules.js +46 -2
  348. package/dist/frontend/builtin-modules.js.map +1 -1
  349. package/dist/frontend/cjs-resolve.js +40 -17
  350. package/dist/frontend/cjs-resolve.js.map +1 -1
  351. package/dist/frontend/cjs-syntax.js +31 -10
  352. package/dist/frontend/cjs-syntax.js.map +1 -1
  353. package/dist/frontend/comptime-node.test.js +10 -11
  354. package/dist/frontend/comptime-node.test.js.map +1 -1
  355. package/dist/frontend/dts-paths.js +7 -3
  356. package/dist/frontend/dts-paths.js.map +1 -1
  357. package/dist/frontend/fork-target.js +17 -12
  358. package/dist/frontend/fork-target.js.map +1 -1
  359. package/dist/frontend/function-completion.js +11 -6
  360. package/dist/frontend/function-completion.js.map +1 -1
  361. package/dist/frontend/helper-tokens.js +53 -6
  362. package/dist/frontend/helper-tokens.js.map +1 -1
  363. package/dist/frontend/helper-tokens.test.js +18 -2
  364. package/dist/frontend/helper-tokens.test.js.map +1 -1
  365. package/dist/frontend/inferred-js-diagnostics.js +32 -12
  366. package/dist/frontend/inferred-js-diagnostics.js.map +1 -1
  367. package/dist/frontend/inferred-js-diagnostics.test.js +11 -15
  368. package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -1
  369. package/dist/frontend/input-tracker.js +11 -11
  370. package/dist/frontend/input-tracker.js.map +1 -1
  371. package/dist/frontend/input-tracker.test.js +4 -1
  372. package/dist/frontend/input-tracker.test.js.map +1 -1
  373. package/dist/frontend/lib-contract.js +38 -9
  374. package/dist/frontend/lib-contract.js.map +1 -1
  375. package/dist/frontend/literal-values.js.map +1 -1
  376. package/dist/frontend/literal-values.test.js +28 -8
  377. package/dist/frontend/literal-values.test.js.map +1 -1
  378. package/dist/frontend/lowering/abstract-equality.js +53 -10
  379. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  380. package/dist/frontend/lowering/array-indexed-mutation.d.ts +1 -1
  381. package/dist/frontend/lowering/array-indexed-mutation.js +108 -106
  382. package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
  383. package/dist/frontend/lowering/array-values.js +37 -14
  384. package/dist/frontend/lowering/array-values.js.map +1 -1
  385. package/dist/frontend/lowering/binding-analysis.d.ts +50 -0
  386. package/dist/frontend/lowering/binding-analysis.js +376 -0
  387. package/dist/frontend/lowering/binding-analysis.js.map +1 -0
  388. package/dist/frontend/lowering/builtin-calls.d.ts +9 -0
  389. package/dist/frontend/lowering/builtin-calls.js +60 -0
  390. package/dist/frontend/lowering/builtin-calls.js.map +1 -0
  391. package/dist/frontend/lowering/builtins/arguments.d.ts +43 -0
  392. package/dist/frontend/lowering/builtins/arguments.js +247 -0
  393. package/dist/frontend/lowering/builtins/arguments.js.map +1 -0
  394. package/dist/frontend/lowering/builtins/async-context.d.ts +52 -0
  395. package/dist/frontend/lowering/builtins/async-context.js +436 -0
  396. package/dist/frontend/lowering/builtins/async-context.js.map +1 -0
  397. package/dist/frontend/lowering/builtins/atomics.d.ts +15 -0
  398. package/dist/frontend/lowering/builtins/atomics.js +46 -0
  399. package/dist/frontend/lowering/builtins/atomics.js.map +1 -0
  400. package/dist/frontend/lowering/builtins/callable-aliases.d.ts +13 -0
  401. package/dist/frontend/lowering/builtins/callable-aliases.js +87 -0
  402. package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -0
  403. package/dist/frontend/lowering/builtins/child-process-async.d.ts +18 -0
  404. package/dist/frontend/lowering/builtins/child-process-async.js +245 -0
  405. package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -0
  406. package/dist/frontend/lowering/builtins/child-process-methods.d.ts +21 -0
  407. package/dist/frontend/lowering/builtins/child-process-methods.js +362 -0
  408. package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -0
  409. package/dist/frontend/lowering/builtins/child-process-sync.d.ts +4 -0
  410. package/dist/frontend/lowering/builtins/child-process-sync.js +639 -0
  411. package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -0
  412. package/dist/frontend/lowering/builtins/child-process.d.ts +55 -0
  413. package/dist/frontend/lowering/builtins/child-process.js +669 -0
  414. package/dist/frontend/lowering/builtins/child-process.js.map +1 -0
  415. package/dist/frontend/lowering/builtins/compression.d.ts +7 -0
  416. package/dist/frontend/lowering/builtins/compression.js +115 -0
  417. package/dist/frontend/lowering/builtins/compression.js.map +1 -0
  418. package/dist/frontend/lowering/builtins/console.d.ts +10 -0
  419. package/dist/frontend/lowering/builtins/console.js +38 -0
  420. package/dist/frontend/lowering/builtins/console.js.map +1 -0
  421. package/dist/frontend/lowering/builtins/constants.d.ts +24 -0
  422. package/dist/frontend/lowering/builtins/constants.js +141 -0
  423. package/dist/frontend/lowering/builtins/constants.js.map +1 -0
  424. package/dist/frontend/lowering/builtins/crypto.d.ts +22 -0
  425. package/dist/frontend/lowering/builtins/crypto.js +517 -0
  426. package/dist/frontend/lowering/builtins/crypto.js.map +1 -0
  427. package/dist/frontend/lowering/builtins/dates.d.ts +7 -0
  428. package/dist/frontend/lowering/builtins/dates.js +101 -0
  429. package/dist/frontend/lowering/builtins/dates.js.map +1 -0
  430. package/dist/frontend/lowering/builtins/environment.d.ts +34 -0
  431. package/dist/frontend/lowering/builtins/environment.js +95 -0
  432. package/dist/frontend/lowering/builtins/environment.js.map +1 -0
  433. package/dist/frontend/lowering/builtins/errors.d.ts +14 -0
  434. package/dist/frontend/lowering/builtins/errors.js +83 -0
  435. package/dist/frontend/lowering/builtins/errors.js.map +1 -0
  436. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +32 -0
  437. package/dist/frontend/lowering/builtins/filesystem-calls.js +678 -0
  438. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -0
  439. package/dist/frontend/lowering/builtins/filesystem.d.ts +108 -0
  440. package/dist/frontend/lowering/builtins/filesystem.js +1061 -0
  441. package/dist/frontend/lowering/builtins/filesystem.js.map +1 -0
  442. package/dist/frontend/lowering/builtins/ipc.d.ts +8 -0
  443. package/dist/frontend/lowering/builtins/ipc.js +76 -0
  444. package/dist/frontend/lowering/builtins/ipc.js.map +1 -0
  445. package/dist/frontend/lowering/builtins/json.d.ts +12 -0
  446. package/dist/frontend/lowering/builtins/json.js +387 -0
  447. package/dist/frontend/lowering/builtins/json.js.map +1 -0
  448. package/dist/frontend/lowering/builtins/module-bindings.d.ts +85 -0
  449. package/dist/frontend/lowering/builtins/module-bindings.js +346 -0
  450. package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -0
  451. package/dist/frontend/lowering/builtins/module-calls.d.ts +8 -0
  452. package/dist/frontend/lowering/builtins/module-calls.js +303 -0
  453. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -0
  454. package/dist/frontend/lowering/builtins/module-resolution.d.ts +38 -0
  455. package/dist/frontend/lowering/builtins/module-resolution.js +344 -0
  456. package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -0
  457. package/dist/frontend/lowering/builtins/numbers.d.ts +15 -0
  458. package/dist/frontend/lowering/builtins/numbers.js +124 -0
  459. package/dist/frontend/lowering/builtins/numbers.js.map +1 -0
  460. package/dist/frontend/lowering/builtins/operating-system.d.ts +13 -0
  461. package/dist/frontend/lowering/builtins/operating-system.js +148 -0
  462. package/dist/frontend/lowering/builtins/operating-system.js.map +1 -0
  463. package/dist/frontend/lowering/builtins/performance.d.ts +13 -0
  464. package/dist/frontend/lowering/builtins/performance.js +100 -0
  465. package/dist/frontend/lowering/builtins/performance.js.map +1 -0
  466. package/dist/frontend/lowering/builtins/process.d.ts +50 -0
  467. package/dist/frontend/lowering/builtins/process.js +1138 -0
  468. package/dist/frontend/lowering/builtins/process.js.map +1 -0
  469. package/dist/frontend/lowering/builtins/promises.d.ts +14 -0
  470. package/dist/frontend/lowering/builtins/promises.js +356 -0
  471. package/dist/frontend/lowering/builtins/promises.js.map +1 -0
  472. package/dist/frontend/lowering/builtins/properties.d.ts +11 -0
  473. package/dist/frontend/lowering/builtins/properties.js +186 -0
  474. package/dist/frontend/lowering/builtins/properties.js.map +1 -0
  475. package/dist/frontend/lowering/builtins/querystring.d.ts +19 -0
  476. package/dist/frontend/lowering/builtins/querystring.js +150 -0
  477. package/dist/frontend/lowering/builtins/querystring.js.map +1 -0
  478. package/dist/frontend/lowering/builtins/readline.d.ts +13 -0
  479. package/dist/frontend/lowering/builtins/readline.js +138 -0
  480. package/dist/frontend/lowering/builtins/readline.js.map +1 -0
  481. package/dist/frontend/lowering/builtins/receiver-types.d.ts +5 -0
  482. package/dist/frontend/lowering/builtins/receiver-types.js +15 -0
  483. package/dist/frontend/lowering/builtins/receiver-types.js.map +1 -0
  484. package/dist/frontend/lowering/builtins/reflection.d.ts +13 -0
  485. package/dist/frontend/lowering/builtins/reflection.js +95 -0
  486. package/dist/frontend/lowering/builtins/reflection.js.map +1 -0
  487. package/dist/frontend/lowering/builtins/strings.d.ts +14 -0
  488. package/dist/frontend/lowering/builtins/strings.js +121 -0
  489. package/dist/frontend/lowering/builtins/strings.js.map +1 -0
  490. package/dist/frontend/lowering/builtins/text-codecs.d.ts +29 -0
  491. package/dist/frontend/lowering/builtins/text-codecs.js +590 -0
  492. package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -0
  493. package/dist/frontend/lowering/builtins/timers.d.ts +22 -0
  494. package/dist/frontend/lowering/builtins/timers.js +180 -0
  495. package/dist/frontend/lowering/builtins/timers.js.map +1 -0
  496. package/dist/frontend/lowering/builtins/url.d.ts +37 -0
  497. package/dist/frontend/lowering/builtins/url.js +596 -0
  498. package/dist/frontend/lowering/builtins/url.js.map +1 -0
  499. package/dist/frontend/lowering/builtins/util-types.d.ts +7 -0
  500. package/dist/frontend/lowering/builtins/util-types.js +31 -0
  501. package/dist/frontend/lowering/builtins/util-types.js.map +1 -0
  502. package/dist/frontend/lowering/call-arguments.d.ts +72 -0
  503. package/dist/frontend/lowering/call-arguments.js +618 -0
  504. package/dist/frontend/lowering/call-arguments.js.map +1 -0
  505. package/dist/frontend/lowering/call-signatures.d.ts +115 -0
  506. package/dist/frontend/lowering/call-signatures.js +719 -0
  507. package/dist/frontend/lowering/call-signatures.js.map +1 -0
  508. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  509. package/dist/frontend/lowering/checked-iterable-spread.js +53 -10
  510. package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -1
  511. package/dist/frontend/lowering/checked-promise-all.js +41 -9
  512. package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
  513. package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
  514. package/dist/frontend/lowering/class-callbacks.js +130 -27
  515. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  516. package/dist/frontend/lowering/class-construction.d.ts +1 -1
  517. package/dist/frontend/lowering/class-construction.js +247 -50
  518. package/dist/frontend/lowering/class-construction.js.map +1 -1
  519. package/dist/frontend/lowering/class-descriptors.js +109 -29
  520. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  521. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +6 -1
  522. package/dist/frontend/lowering/class-dynamic-dispatch.js +2471 -465
  523. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  524. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +284 -44
  525. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  526. package/dist/frontend/lowering/class-instance-constructor.js +17 -5
  527. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  528. package/dist/frontend/lowering/class-method-values.js +199 -51
  529. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  530. package/dist/frontend/lowering/class-prototypes.js +345 -86
  531. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  532. package/dist/frontend/lowering/class-runtime-statics.d.ts +1 -1
  533. package/dist/frontend/lowering/class-runtime-statics.js +80 -17
  534. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
  535. package/dist/frontend/lowering/class-static-data.js +76 -16
  536. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  537. package/dist/frontend/lowering/coercions/builders.d.ts +13 -0
  538. package/dist/frontend/lowering/coercions/builders.js +77 -0
  539. package/dist/frontend/lowering/coercions/builders.js.map +1 -0
  540. package/dist/frontend/lowering/coercions/function-adapters.d.ts +58 -0
  541. package/dist/frontend/lowering/coercions/function-adapters.js +430 -0
  542. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -0
  543. package/dist/frontend/lowering/coercions/island.d.ts +37 -0
  544. package/dist/frontend/lowering/coercions/island.js +350 -0
  545. package/dist/frontend/lowering/coercions/island.js.map +1 -0
  546. package/dist/frontend/lowering/coercions/state.d.ts +14 -0
  547. package/dist/frontend/lowering/coercions/state.js +16 -0
  548. package/dist/frontend/lowering/coercions/state.js.map +1 -0
  549. package/dist/frontend/lowering/coercions/structural-plans.d.ts +40 -0
  550. package/dist/frontend/lowering/coercions/structural-plans.js +447 -0
  551. package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -0
  552. package/dist/frontend/lowering/coercions/structural.d.ts +63 -0
  553. package/dist/frontend/lowering/coercions/structural.js +616 -0
  554. package/dist/frontend/lowering/coercions/structural.js.map +1 -0
  555. package/dist/frontend/lowering/coercions/unions.d.ts +65 -0
  556. package/dist/frontend/lowering/coercions/unions.js +318 -0
  557. package/dist/frontend/lowering/coercions/unions.js.map +1 -0
  558. package/dist/frontend/lowering/collection-ingestion.js +359 -67
  559. package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
  560. package/dist/frontend/lowering/containers/array-callbacks.d.ts +92 -0
  561. package/dist/frontend/lowering/containers/array-callbacks.js +1646 -0
  562. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -0
  563. package/dist/frontend/lowering/containers/array-construction.d.ts +42 -0
  564. package/dist/frontend/lowering/containers/array-construction.js +1044 -0
  565. package/dist/frontend/lowering/containers/array-construction.js.map +1 -0
  566. package/dist/frontend/lowering/containers/array-iteration.d.ts +16 -0
  567. package/dist/frontend/lowering/containers/array-iteration.js +95 -0
  568. package/dist/frontend/lowering/containers/array-iteration.js.map +1 -0
  569. package/dist/frontend/lowering/containers/array-methods.d.ts +27 -0
  570. package/dist/frontend/lowering/containers/array-methods.js +1854 -0
  571. package/dist/frontend/lowering/containers/array-methods.js.map +1 -0
  572. package/dist/frontend/lowering/containers/bytes.d.ts +17 -17
  573. package/dist/frontend/lowering/containers/bytes.js +419 -105
  574. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  575. package/dist/frontend/lowering/containers/callback-arguments.d.ts +26 -0
  576. package/dist/frontend/lowering/containers/callback-arguments.js +179 -0
  577. package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -0
  578. package/dist/frontend/lowering/containers/collection-grouping.d.ts +19 -0
  579. package/dist/frontend/lowering/containers/collection-grouping.js +297 -0
  580. package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -0
  581. package/dist/frontend/lowering/containers/collection-methods.d.ts +57 -0
  582. package/dist/frontend/lowering/containers/collection-methods.js +1314 -0
  583. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -0
  584. package/dist/frontend/lowering/containers/dynamic-receivers.d.ts +18 -0
  585. package/dist/frontend/lowering/containers/dynamic-receivers.js +114 -0
  586. package/dist/frontend/lowering/containers/dynamic-receivers.js.map +1 -0
  587. package/dist/frontend/lowering/containers/for-of.d.ts +60 -0
  588. package/dist/frontend/lowering/containers/for-of.js +643 -0
  589. package/dist/frontend/lowering/containers/for-of.js.map +1 -0
  590. package/dist/frontend/lowering/containers/indexed-objects.d.ts +132 -0
  591. package/dist/frontend/lowering/containers/indexed-objects.js +1743 -0
  592. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -0
  593. package/dist/frontend/lowering/containers/iterator-helpers.d.ts +20 -0
  594. package/dist/frontend/lowering/containers/iterator-helpers.js +809 -0
  595. package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -0
  596. package/dist/frontend/lowering/containers/string-and-regexp.js +585 -157
  597. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  598. package/dist/frontend/lowering/containers/string-replacement.js +213 -63
  599. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
  600. package/dist/frontend/lowering/crypto-tables.js +263 -64
  601. package/dist/frontend/lowering/crypto-tables.js.map +1 -1
  602. package/dist/frontend/lowering/deferred-module-initializers.js +172 -68
  603. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
  604. package/dist/frontend/lowering/deferred-module-initializers.test.js +41 -8
  605. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
  606. package/dist/frontend/lowering/error-methods.js +339 -65
  607. package/dist/frontend/lowering/error-methods.js.map +1 -1
  608. package/dist/frontend/lowering/expressions/evaluation-safety.js +3 -2
  609. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
  610. package/dist/frontend/lowering/expressions/global-symbols.js +2 -1
  611. package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -1
  612. package/dist/frontend/lowering/expressions/native-proxy.js +11 -5
  613. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
  614. package/dist/frontend/lowering/expressions/nullish-assignment.js +67 -13
  615. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  616. package/dist/frontend/lowering/expressions/object-literals.js +589 -162
  617. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  618. package/dist/frontend/lowering/expressions/optional-chains.d.ts +1 -1
  619. package/dist/frontend/lowering/expressions/optional-chains.js +68 -17
  620. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  621. package/dist/frontend/lowering/expressions/union-field-write.js +45 -18
  622. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
  623. package/dist/frontend/lowering/function-context.js +5 -1
  624. package/dist/frontend/lowering/function-context.js.map +1 -1
  625. package/dist/frontend/lowering/function-returns.d.ts +67 -0
  626. package/dist/frontend/lowering/function-returns.js +392 -0
  627. package/dist/frontend/lowering/function-returns.js.map +1 -0
  628. package/dist/frontend/lowering/generator-delegation.d.ts +1 -1
  629. package/dist/frontend/lowering/generator-delegation.js +171 -39
  630. package/dist/frontend/lowering/generator-delegation.js.map +1 -1
  631. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -1
  632. package/dist/frontend/lowering/generator-dynamic-dispatch.js +176 -36
  633. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
  634. package/dist/frontend/lowering/generic-functions.d.ts +274 -0
  635. package/dist/frontend/lowering/generic-functions.js +1727 -0
  636. package/dist/frontend/lowering/generic-functions.js.map +1 -0
  637. package/dist/frontend/lowering/import-meta.d.ts +1 -1
  638. package/dist/frontend/lowering/import-meta.js +37 -14
  639. package/dist/frontend/lowering/import-meta.js.map +1 -1
  640. package/dist/frontend/lowering/indexed-comparison.js +6 -2
  641. package/dist/frontend/lowering/indexed-comparison.js.map +1 -1
  642. package/dist/frontend/lowering/iterator-consumption.d.ts +9 -0
  643. package/dist/frontend/lowering/iterator-consumption.js +91 -0
  644. package/dist/frontend/lowering/iterator-consumption.js.map +1 -0
  645. package/dist/frontend/lowering/lib-boundary.js +40 -17
  646. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  647. package/dist/frontend/lowering/lib-boundary.test.js +49 -11
  648. package/dist/frontend/lowering/lib-boundary.test.js.map +1 -1
  649. package/dist/frontend/lowering/lower-array-sort.d.ts +0 -19
  650. package/dist/frontend/lowering/lower-array-sort.js +331 -566
  651. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  652. package/dist/frontend/lowering/lower-assert.js +248 -43
  653. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  654. package/dist/frontend/lowering/lower-async-iteration.js +71 -16
  655. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  656. package/dist/frontend/lowering/lower-builtin-values.js +420 -71
  657. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  658. package/dist/frontend/lowering/lower-calls.d.ts +39 -558
  659. package/dist/frontend/lowering/lower-calls.js +2593 -5667
  660. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  661. package/dist/frontend/lowering/lower-classes.d.ts +243 -242
  662. package/dist/frontend/lowering/lower-classes.js +1704 -727
  663. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  664. package/dist/frontend/lowering/lower-comptime.d.ts +35 -35
  665. package/dist/frontend/lowering/lower-comptime.js +39 -37
  666. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  667. package/dist/frontend/lowering/lower-dgram.js +59 -31
  668. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  669. package/dist/frontend/lowering/lower-enums.js +5 -2
  670. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  671. package/dist/frontend/lowering/lower-event-emitter.js +322 -85
  672. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  673. package/dist/frontend/lowering/lower-expando.js +19 -7
  674. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  675. package/dist/frontend/lowering/lower-exprs.d.ts +194 -194
  676. package/dist/frontend/lowering/lower-exprs.js +3455 -1153
  677. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  678. package/dist/frontend/lowering/lower-functions.d.ts +23 -0
  679. package/dist/frontend/lowering/lower-functions.js +449 -0
  680. package/dist/frontend/lowering/lower-functions.js.map +1 -0
  681. package/dist/frontend/lowering/lower-generators.js +121 -32
  682. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  683. package/dist/frontend/lowering/lower-global-value.js +15 -4
  684. package/dist/frontend/lowering/lower-global-value.js.map +1 -1
  685. package/dist/frontend/lowering/lower-inspect.js +479 -89
  686. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  687. package/dist/frontend/lowering/lower-island.d.ts +79 -79
  688. package/dist/frontend/lowering/lower-island.js +365 -273
  689. package/dist/frontend/lowering/lower-island.js.map +1 -1
  690. package/dist/frontend/lowering/lower-island.test.js +7 -2
  691. package/dist/frontend/lowering/lower-island.test.js.map +1 -1
  692. package/dist/frontend/lowering/lower-mixins.js +17 -8
  693. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  694. package/dist/frontend/lowering/lower-modules.d.ts +94 -94
  695. package/dist/frontend/lowering/lower-modules.js +612 -321
  696. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  697. package/dist/frontend/lowering/lower-modules.test.js +91 -20
  698. package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
  699. package/dist/frontend/lowering/lower-namespaces.js +25 -8
  700. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  701. package/dist/frontend/lowering/lower-node-module.js +115 -34
  702. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  703. package/dist/frontend/lowering/lower-server.js +1210 -290
  704. package/dist/frontend/lowering/lower-server.js.map +1 -1
  705. package/dist/frontend/lowering/lower-stmts.d.ts +148 -148
  706. package/dist/frontend/lowering/lower-stmts.js +2312 -984
  707. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  708. package/dist/frontend/lowering/lower-stmts.test.js +13 -5
  709. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -1
  710. package/dist/frontend/lowering/lower-stream.js +362 -90
  711. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  712. package/dist/frontend/lowering/lower-system-errors.js +30 -8
  713. package/dist/frontend/lowering/lower-system-errors.js.map +1 -1
  714. package/dist/frontend/lowering/lower-test.js +40 -13
  715. package/dist/frontend/lowering/lower-test.js.map +1 -1
  716. package/dist/frontend/lowering/lower-timers.d.ts +31 -0
  717. package/dist/frontend/lowering/lower-timers.js +336 -0
  718. package/dist/frontend/lowering/lower-timers.js.map +1 -0
  719. package/dist/frontend/lowering/lower-url.d.ts +1 -1
  720. package/dist/frontend/lowering/lower-url.js +46 -13
  721. package/dist/frontend/lowering/lower-url.js.map +1 -1
  722. package/dist/frontend/lowering/lowerer.d.ts +21 -351
  723. package/dist/frontend/lowering/lowerer.js +1031 -2704
  724. package/dist/frontend/lowering/lowerer.js.map +1 -1
  725. package/dist/frontend/lowering/lowerer.test.js +85 -17
  726. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  727. package/dist/frontend/lowering/module-namespace-elements.js +43 -8
  728. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
  729. package/dist/frontend/lowering/native-ffi.d.ts +21 -1
  730. package/dist/frontend/lowering/native-ffi.js +487 -18
  731. package/dist/frontend/lowering/native-ffi.js.map +1 -1
  732. package/dist/frontend/lowering/object-enumeration-receiver.js +55 -10
  733. package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -1
  734. package/dist/frontend/lowering/object-factory-new.d.ts +1 -1
  735. package/dist/frontend/lowering/object-factory-new.js +36 -11
  736. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  737. package/dist/frontend/lowering/optional-arguments.js +49 -20
  738. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  739. package/dist/frontend/lowering/pairs-snapshot.js +66 -14
  740. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  741. package/dist/frontend/lowering/runtime-optional-locals.js +3 -1
  742. package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -1
  743. package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -1
  744. package/dist/frontend/lowering/sanitize-class-types.js +4 -1
  745. package/dist/frontend/lowering/sanitize-class-types.js.map +1 -1
  746. package/dist/frontend/lowering/sanitize-class-types.test.js +86 -18
  747. package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -1
  748. package/dist/frontend/lowering/static-this.js +13 -6
  749. package/dist/frontend/lowering/static-this.js.map +1 -1
  750. package/dist/frontend/lowering/string-index.js +32 -10
  751. package/dist/frontend/lowering/string-index.js.map +1 -1
  752. package/dist/frontend/lowering/surfaces.d.ts +42 -42
  753. package/dist/frontend/lowering/surfaces.js +1094 -249
  754. package/dist/frontend/lowering/surfaces.js.map +1 -1
  755. package/dist/frontend/lowering/symbol-fields.js +40 -15
  756. package/dist/frontend/lowering/symbol-fields.js.map +1 -1
  757. package/dist/frontend/lowering/symbol-methods.js.map +1 -1
  758. package/dist/frontend/lowering/text-decoder-encoding.js +236 -24
  759. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  760. package/dist/frontend/lowering/text-decoder-encoding.test.js +84 -12
  761. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
  762. package/dist/frontend/lowering/union-narrow.js +59 -16
  763. package/dist/frontend/lowering/union-narrow.js.map +1 -1
  764. package/dist/frontend/lowering/union-narrow.test.js +24 -7
  765. package/dist/frontend/lowering/union-narrow.test.js.map +1 -1
  766. package/dist/frontend/lowering/union-retag.js +155 -40
  767. package/dist/frontend/lowering/union-retag.js.map +1 -1
  768. package/dist/frontend/lowering/union-retag.test.js +131 -33
  769. package/dist/frontend/lowering/union-retag.test.js.map +1 -1
  770. package/dist/frontend/lowering/unregistered-class-types.js.map +1 -1
  771. package/dist/frontend/lowering/unregistered-class-types.test.js +34 -8
  772. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
  773. package/dist/frontend/module-syntax.js +21 -8
  774. package/dist/frontend/module-syntax.js.map +1 -1
  775. package/dist/frontend/module-syntax.test.js +37 -13
  776. package/dist/frontend/module-syntax.test.js.map +1 -1
  777. package/dist/frontend/npm-fetch-analysis.js +13 -4
  778. package/dist/frontend/npm-fetch-analysis.js.map +1 -1
  779. package/dist/frontend/npm-fetch-analysis.test.js +33 -10
  780. package/dist/frontend/npm-fetch-analysis.test.js.map +1 -1
  781. package/dist/frontend/npm-fetch-node.js.map +1 -1
  782. package/dist/frontend/npm-fetch-syntax.js +4 -9
  783. package/dist/frontend/npm-fetch-syntax.js.map +1 -1
  784. package/dist/frontend/npm-node.js +3 -1
  785. package/dist/frontend/npm-node.js.map +1 -1
  786. package/dist/frontend/npm-static-bundled-cjs.js +88 -29
  787. package/dist/frontend/npm-static-bundled-cjs.js.map +1 -1
  788. package/dist/frontend/npm-static-bundled-cjs.test.js +29 -10
  789. package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -1
  790. package/dist/frontend/npm-static-declaration-syntax.js +148 -56
  791. package/dist/frontend/npm-static-declaration-syntax.js.map +1 -1
  792. package/dist/frontend/npm-static-declarations.d.ts +1 -1
  793. package/dist/frontend/npm-static-declarations.js.map +1 -1
  794. package/dist/frontend/npm-static-declarations.test.js +33 -7
  795. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  796. package/dist/frontend/npm-static-prune.js +26 -12
  797. package/dist/frontend/npm-static-prune.js.map +1 -1
  798. package/dist/frontend/npm-static-prune.test.js +17 -3
  799. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  800. package/dist/frontend/npm-static-rewrite-host.js +2 -3
  801. package/dist/frontend/npm-static-rewrite-host.js.map +1 -1
  802. package/dist/frontend/npm-static-rewrite-syntax.js +64 -21
  803. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
  804. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  805. package/dist/frontend/npm-static-subtyping.js +9 -4
  806. package/dist/frontend/npm-static-subtyping.js.map +1 -1
  807. package/dist/frontend/npm-static-subtyping.test.js +30 -6
  808. package/dist/frontend/npm-static-subtyping.test.js.map +1 -1
  809. package/dist/frontend/npm-static.js +15 -4
  810. package/dist/frontend/npm-static.js.map +1 -1
  811. package/dist/frontend/npm.js +122 -36
  812. package/dist/frontend/npm.js.map +1 -1
  813. package/dist/frontend/npm.test.js +30 -10
  814. package/dist/frontend/npm.test.js.map +1 -1
  815. package/dist/frontend/pipeline-native.js.map +1 -1
  816. package/dist/frontend/pipeline.js +25 -8
  817. package/dist/frontend/pipeline.js.map +1 -1
  818. package/dist/frontend/pipeline.test.js +21 -7
  819. package/dist/frontend/pipeline.test.js.map +1 -1
  820. package/dist/frontend/program-node.js +5 -3
  821. package/dist/frontend/program-node.js.map +1 -1
  822. package/dist/frontend/program.d.ts +2 -2
  823. package/dist/frontend/program.js +234 -101
  824. package/dist/frontend/program.js.map +1 -1
  825. package/dist/frontend/program.test.js +27 -27
  826. package/dist/frontend/program.test.js.map +1 -1
  827. package/dist/frontend/provenance-core.js +8 -4
  828. package/dist/frontend/provenance-core.js.map +1 -1
  829. package/dist/frontend/provenance-registry.js +1 -4
  830. package/dist/frontend/provenance-registry.js.map +1 -1
  831. package/dist/frontend/resolve.js +32 -20
  832. package/dist/frontend/resolve.js.map +1 -1
  833. package/dist/frontend/resolve.test.js +1 -1
  834. package/dist/frontend/resolve.test.js.map +1 -1
  835. package/dist/frontend/runtime-resolve.js +13 -4
  836. package/dist/frontend/runtime-resolve.js.map +1 -1
  837. package/dist/frontend/runtime-resolve.test.js +25 -9
  838. package/dist/frontend/runtime-resolve.test.js.map +1 -1
  839. package/dist/frontend/services-node.js +6 -2
  840. package/dist/frontend/services-node.js.map +1 -1
  841. package/dist/frontend/services-node.test.js +18 -6
  842. package/dist/frontend/services-node.test.js.map +1 -1
  843. package/dist/frontend/services.js +8 -4
  844. package/dist/frontend/services.js.map +1 -1
  845. package/dist/frontend/services.test.js +6 -2
  846. package/dist/frontend/services.test.js.map +1 -1
  847. package/dist/frontend/ts7/api.js +12 -4
  848. package/dist/frontend/ts7/api.js.map +1 -1
  849. package/dist/frontend/ts7/ast-bytes.js +10 -3
  850. package/dist/frontend/ts7/ast-bytes.js.map +1 -1
  851. package/dist/frontend/ts7/ast-bytes.test.js +23 -4
  852. package/dist/frontend/ts7/ast-bytes.test.js.map +1 -1
  853. package/dist/frontend/ts7/ast-guards.test.js +14 -5
  854. package/dist/frontend/ts7/ast-guards.test.js.map +1 -1
  855. package/dist/frontend/ts7/ast-node.d.ts +6 -1
  856. package/dist/frontend/ts7/ast-node.js +484 -164
  857. package/dist/frontend/ts7/ast-node.js.map +1 -1
  858. package/dist/frontend/ts7/ast-node.test.js +109 -36
  859. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  860. package/dist/frontend/ts7/ast-text.js +13 -3
  861. package/dist/frontend/ts7/ast-text.js.map +1 -1
  862. package/dist/frontend/ts7/ast-text.test.js.map +1 -1
  863. package/dist/frontend/ts7/ast-types.js.map +1 -1
  864. package/dist/frontend/ts7/ast-wire.d.ts +1 -1
  865. package/dist/frontend/ts7/ast-wire.js +55 -20
  866. package/dist/frontend/ts7/ast-wire.js.map +1 -1
  867. package/dist/frontend/ts7/ast-wire.test.js +53 -8
  868. package/dist/frontend/ts7/ast-wire.test.js.map +1 -1
  869. package/dist/frontend/ts7/ast.js +47 -28
  870. package/dist/frontend/ts7/ast.js.map +1 -1
  871. package/dist/frontend/ts7/census-check.js +1 -1
  872. package/dist/frontend/ts7/census-check.js.map +1 -1
  873. package/dist/frontend/ts7/checker-cache.js.map +1 -1
  874. package/dist/frontend/ts7/checker.js +5 -3
  875. package/dist/frontend/ts7/checker.js.map +1 -1
  876. package/dist/frontend/ts7/checker.test.js +54 -17
  877. package/dist/frontend/ts7/checker.test.js.map +1 -1
  878. package/dist/frontend/ts7/enums.test.js +9 -4
  879. package/dist/frontend/ts7/enums.test.js.map +1 -1
  880. package/dist/frontend/ts7/native-api.js.map +1 -1
  881. package/dist/frontend/ts7/native-host.js.map +1 -1
  882. package/dist/frontend/ts7/native-process.js +9 -3
  883. package/dist/frontend/ts7/native-process.js.map +1 -1
  884. package/dist/frontend/ts7/program-adapter.js +1 -1
  885. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  886. package/dist/frontend/ts7/program-host.js +7 -4
  887. package/dist/frontend/ts7/program-host.js.map +1 -1
  888. package/dist/frontend/ts7/program-host.test.js +43 -11
  889. package/dist/frontend/ts7/program-host.test.js.map +1 -1
  890. package/dist/frontend/ts7/rpc-api.js +3 -1
  891. package/dist/frontend/ts7/rpc-api.js.map +1 -1
  892. package/dist/frontend/ts7/rpc-client.js +15 -5
  893. package/dist/frontend/ts7/rpc-client.js.map +1 -1
  894. package/dist/frontend/ts7/rpc-client.test.js +26 -8
  895. package/dist/frontend/ts7/rpc-client.test.js.map +1 -1
  896. package/dist/frontend/ts7/rpc-filesystem.js.map +1 -1
  897. package/dist/frontend/ts7/rpc-filesystem.test.js +43 -10
  898. package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -1
  899. package/dist/frontend/ts7/rpc-process.js +16 -6
  900. package/dist/frontend/ts7/rpc-process.js.map +1 -1
  901. package/dist/frontend/ts7/rpc-process.test.js.map +1 -1
  902. package/dist/frontend/ts7/rpc-wire.d.ts +1 -0
  903. package/dist/frontend/ts7/rpc-wire.js +41 -14
  904. package/dist/frontend/ts7/rpc-wire.js.map +1 -1
  905. package/dist/frontend/ts7/rpc-wire.test.js +36 -6
  906. package/dist/frontend/ts7/rpc-wire.test.js.map +1 -1
  907. package/dist/frontend/ts7/semantic-checker.js +209 -68
  908. package/dist/frontend/ts7/semantic-checker.js.map +1 -1
  909. package/dist/frontend/ts7/semantic-checker.test.js +29 -14
  910. package/dist/frontend/ts7/semantic-checker.test.js.map +1 -1
  911. package/dist/frontend/ts7/semantic-json.js +7 -1
  912. package/dist/frontend/ts7/semantic-json.js.map +1 -1
  913. package/dist/frontend/ts7/semantic-json.test.js +17 -3
  914. package/dist/frontend/ts7/semantic-json.test.js.map +1 -1
  915. package/dist/frontend/ts7/semantic-model.js +147 -51
  916. package/dist/frontend/ts7/semantic-model.js.map +1 -1
  917. package/dist/frontend/ts7/semantic-model.test.js +72 -19
  918. package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
  919. package/dist/frontend/ts7/semantic-types.d.ts +2 -2
  920. package/dist/frontend/ts7/session-cache.js +10 -3
  921. package/dist/frontend/ts7/session-cache.js.map +1 -1
  922. package/dist/frontend/ts7/session-cache.test.js +13 -4
  923. package/dist/frontend/ts7/session-cache.test.js.map +1 -1
  924. package/dist/frontend/ts7/session-path.js +25 -10
  925. package/dist/frontend/ts7/session-path.js.map +1 -1
  926. package/dist/frontend/ts7/session-path.test.js +47 -4
  927. package/dist/frontend/ts7/session-path.test.js.map +1 -1
  928. package/dist/frontend/ts7/session-timing.js +22 -3
  929. package/dist/frontend/ts7/session-timing.js.map +1 -1
  930. package/dist/frontend/ts7/session-timing.test.js +12 -3
  931. package/dist/frontend/ts7/session-timing.test.js.map +1 -1
  932. package/dist/frontend/ts7/session.d.ts +1 -0
  933. package/dist/frontend/ts7/session.js +109 -35
  934. package/dist/frontend/ts7/session.js.map +1 -1
  935. package/dist/frontend/ts7/session.test.js +69 -15
  936. package/dist/frontend/ts7/session.test.js.map +1 -1
  937. package/dist/frontend/ts7/source-parser.js +17 -6
  938. package/dist/frontend/ts7/source-parser.js.map +1 -1
  939. package/dist/frontend/ts7/source-parser.test.js +32 -9
  940. package/dist/frontend/ts7/source-parser.test.js.map +1 -1
  941. package/dist/frontend/tsc-codes.js +56 -11
  942. package/dist/frontend/tsc-codes.js.map +1 -1
  943. package/dist/frontend/tsc-codes.test.d.ts +1 -0
  944. package/dist/frontend/tsc-codes.test.js +16 -0
  945. package/dist/frontend/tsc-codes.test.js.map +1 -0
  946. package/dist/frontend/type-mapper.js +547 -206
  947. package/dist/frontend/type-mapper.js.map +1 -1
  948. package/dist/frontend/type-mapper.test.js +108 -33
  949. package/dist/frontend/type-mapper.test.js.map +1 -1
  950. package/dist/frontend/union-discriminants.js +8 -2
  951. package/dist/frontend/union-discriminants.js.map +1 -1
  952. package/dist/frontend/union-discriminants.test.js +77 -20
  953. package/dist/frontend/union-discriminants.test.js.map +1 -1
  954. package/dist/index.d.ts +9 -8
  955. package/dist/index.js +150 -81
  956. package/dist/index.js.map +1 -1
  957. package/dist/ir/analysis.js +97 -38
  958. package/dist/ir/analysis.js.map +1 -1
  959. package/dist/ir/analysis.test.js +91 -15
  960. package/dist/ir/analysis.test.js.map +1 -1
  961. package/dist/ir/api.d.ts +4 -0
  962. package/dist/ir/api.js +6 -0
  963. package/dist/ir/api.js.map +1 -0
  964. package/dist/ir/build.d.ts +7 -0
  965. package/dist/ir/build.js +27 -1
  966. package/dist/ir/build.js.map +1 -1
  967. package/dist/ir/builtin-effects.d.ts +9 -0
  968. package/dist/ir/builtin-effects.js +631 -0
  969. package/dist/ir/builtin-effects.js.map +1 -0
  970. package/dist/ir/builtin-signatures.d.ts +15 -0
  971. package/dist/ir/builtin-signatures.js +3396 -0
  972. package/dist/ir/builtin-signatures.js.map +1 -0
  973. package/dist/ir/byte-numbers.d.ts +20 -0
  974. package/dist/ir/byte-numbers.js +116 -0
  975. package/dist/ir/byte-numbers.js.map +1 -0
  976. package/dist/ir/byte-numbers.test.d.ts +1 -0
  977. package/dist/ir/byte-numbers.test.js +55 -0
  978. package/dist/ir/byte-numbers.test.js.map +1 -0
  979. package/dist/ir/constant-tables.js +13 -5
  980. package/dist/ir/constant-tables.js.map +1 -1
  981. package/dist/ir/constant-tables.test.js +47 -7
  982. package/dist/ir/constant-tables.test.js.map +1 -1
  983. package/dist/ir/control-flow.js +2 -1
  984. package/dist/ir/control-flow.js.map +1 -1
  985. package/dist/ir/control-flow.test.js +35 -11
  986. package/dist/ir/control-flow.test.js.map +1 -1
  987. package/dist/ir/initializer-bindings.d.ts +9 -0
  988. package/dist/ir/initializer-bindings.js +115 -0
  989. package/dist/ir/initializer-bindings.js.map +1 -0
  990. package/dist/ir/initializer-bindings.test.d.ts +1 -0
  991. package/dist/ir/initializer-bindings.test.js +118 -0
  992. package/dist/ir/initializer-bindings.test.js.map +1 -0
  993. package/dist/ir/integer-loop-facts.d.ts +12 -0
  994. package/dist/ir/integer-loop-facts.js +137 -0
  995. package/dist/ir/integer-loop-facts.js.map +1 -0
  996. package/dist/ir/integer-loops.d.ts +19 -0
  997. package/dist/ir/integer-loops.js +172 -11
  998. package/dist/ir/integer-loops.js.map +1 -1
  999. package/dist/ir/integer-loops.test.js +122 -9
  1000. package/dist/ir/integer-loops.test.js.map +1 -1
  1001. package/dist/ir/integer-ranges.d.ts +8 -6
  1002. package/dist/ir/integer-ranges.js +416 -90
  1003. package/dist/ir/integer-ranges.js.map +1 -1
  1004. package/dist/ir/integer-ranges.test.js +239 -10
  1005. package/dist/ir/integer-ranges.test.js.map +1 -1
  1006. package/dist/ir/intrinsic-signatures.d.ts +20 -0
  1007. package/dist/ir/intrinsic-signatures.js +57 -0
  1008. package/dist/ir/intrinsic-signatures.js.map +1 -0
  1009. package/dist/ir/ir.d.ts +14 -2155
  1010. package/dist/ir/ir.js +169 -1394
  1011. package/dist/ir/ir.js.map +1 -1
  1012. package/dist/ir/ir.test.js +98 -77
  1013. package/dist/ir/ir.test.js.map +1 -1
  1014. package/dist/ir/runtime-features.d.ts +221 -0
  1015. package/dist/ir/runtime-features.js +551 -0
  1016. package/dist/ir/runtime-features.js.map +1 -0
  1017. package/dist/ir/runtime-features.test.d.ts +1 -0
  1018. package/dist/ir/runtime-features.test.js +98 -0
  1019. package/dist/ir/runtime-features.test.js.map +1 -0
  1020. package/dist/ir/scalar-records.js +130 -40
  1021. package/dist/ir/scalar-records.js.map +1 -1
  1022. package/dist/ir/scalar-records.test.js +146 -27
  1023. package/dist/ir/scalar-records.test.js.map +1 -1
  1024. package/dist/ir/serialize.js +4 -2
  1025. package/dist/ir/serialize.js.map +1 -1
  1026. package/dist/ir/serialize.test.js +44 -9
  1027. package/dist/ir/serialize.test.js.map +1 -1
  1028. package/dist/ir/traverse.js +156 -43
  1029. package/dist/ir/traverse.js.map +1 -1
  1030. package/dist/ir/traverse.test.js +99 -24
  1031. package/dist/ir/traverse.test.js.map +1 -1
  1032. package/dist/ir/validate.d.ts +1 -31
  1033. package/dist/ir/validate.js +826 -1915
  1034. package/dist/ir/validate.js.map +1 -1
  1035. package/dist/ir/validate.test.js +627 -111
  1036. package/dist/ir/validate.test.js.map +1 -1
  1037. package/dist/library/cache-primitives.js +9 -10
  1038. package/dist/library/cache-primitives.js.map +1 -1
  1039. package/dist/library/cache-reset.test.js +2 -1
  1040. package/dist/library/cache-reset.test.js.map +1 -1
  1041. package/dist/library/compiler-self-identity.js +11 -5
  1042. package/dist/library/compiler-self-identity.js.map +1 -1
  1043. package/dist/library/compiler-self-identity.test.js +10 -3
  1044. package/dist/library/compiler-self-identity.test.js.map +1 -1
  1045. package/dist/library/fence-eval.js +24 -7
  1046. package/dist/library/fence-eval.js.map +1 -1
  1047. package/dist/library/fence-eval.test.js +31 -7
  1048. package/dist/library/fence-eval.test.js.map +1 -1
  1049. package/dist/library/int-infer.js +199 -59
  1050. package/dist/library/int-infer.js.map +1 -1
  1051. package/dist/library/int-infer.test.js +133 -57
  1052. package/dist/library/int-infer.test.js.map +1 -1
  1053. package/dist/library/ir-policy.d.ts +27 -0
  1054. package/dist/library/ir-policy.js +232 -0
  1055. package/dist/library/ir-policy.js.map +1 -0
  1056. package/dist/library/library-cache.js +40 -17
  1057. package/dist/library/library-cache.js.map +1 -1
  1058. package/dist/library/library-cache.test.js +24 -13
  1059. package/dist/library/library-cache.test.js.map +1 -1
  1060. package/dist/library/library-profile.js +68 -13
  1061. package/dist/library/library-profile.js.map +1 -1
  1062. package/dist/library/prepare.js +48 -20
  1063. package/dist/library/prepare.js.map +1 -1
  1064. package/dist/library/semantic-source.js +16 -14
  1065. package/dist/library/semantic-source.js.map +1 -1
  1066. package/dist/library/semantic-source.test.js +9 -14
  1067. package/dist/library/semantic-source.test.js.map +1 -1
  1068. package/dist/library/sidecar-validate.js +53 -12
  1069. package/dist/library/sidecar-validate.js.map +1 -1
  1070. package/dist/library/sidecar.js +85 -24
  1071. package/dist/library/sidecar.js.map +1 -1
  1072. package/dist/library/trap-teaching.js +11 -2
  1073. package/dist/library/trap-teaching.js.map +1 -1
  1074. package/dist/native/cache.js +10 -4
  1075. package/dist/native/cache.js.map +1 -1
  1076. package/dist/native/cli.js +34 -9
  1077. package/dist/native/cli.js.map +1 -1
  1078. package/dist/native/compiler.js +167 -43
  1079. package/dist/native/compiler.js.map +1 -1
  1080. package/dist/native/compiler.test.js +129 -32
  1081. package/dist/native/compiler.test.js.map +1 -1
  1082. package/dist/native/comptime.js +23 -7
  1083. package/dist/native/comptime.js.map +1 -1
  1084. package/dist/native/comptime.test.js +26 -6
  1085. package/dist/native/comptime.test.js.map +1 -1
  1086. package/dist/native/executable-cache.js +77 -27
  1087. package/dist/native/executable-cache.js.map +1 -1
  1088. package/dist/native/executable-cache.test.js +41 -6
  1089. package/dist/native/executable-cache.test.js.map +1 -1
  1090. package/dist/native/file-identity.js +9 -2
  1091. package/dist/native/file-identity.js.map +1 -1
  1092. package/dist/native/file-identity.test.js.map +1 -1
  1093. package/dist/native/library.js +50 -12
  1094. package/dist/native/library.js.map +1 -1
  1095. package/dist/native/prepare.js +119 -34
  1096. package/dist/native/prepare.js.map +1 -1
  1097. package/dist/native/prepare.test.js +22 -6
  1098. package/dist/native/prepare.test.js.map +1 -1
  1099. package/dist/native/runtime-typescript.js +24 -11
  1100. package/dist/native/runtime-typescript.js.map +1 -1
  1101. package/dist/native/runtime-typescript.test.js.map +1 -1
  1102. package/dist/native/sanitizer.js +71 -18
  1103. package/dist/native/sanitizer.js.map +1 -1
  1104. package/dist/native/sanitizer.test.js +77 -20
  1105. package/dist/native/sanitizer.test.js.map +1 -1
  1106. package/dist/native/task.js.map +1 -1
  1107. package/dist/native/task.test.js +7 -2
  1108. package/dist/native/task.test.js.map +1 -1
  1109. package/dist/native/toolchain.js +74 -29
  1110. package/dist/native/toolchain.js.map +1 -1
  1111. package/dist/native/toolchain.test.js +95 -18
  1112. package/dist/native/toolchain.test.js.map +1 -1
  1113. package/dist/startup-cache.d.ts +1 -1
  1114. package/dist/startup-cache.js +1 -1
  1115. package/dist/startup-cache.js.map +1 -1
  1116. package/dist/timing.js.map +1 -1
  1117. package/package.json +20 -20
  1118. package/surface-manifest.json +1 -1
  1119. package/dist/frontend/lowering/lower-builtins.d.ts +0 -601
  1120. package/dist/frontend/lowering/lower-builtins.js +0 -8984
  1121. package/dist/frontend/lowering/lower-builtins.js.map +0 -1
  1122. package/dist/frontend/lowering/lower-containers.d.ts +0 -382
  1123. package/dist/frontend/lowering/lower-containers.js +0 -7366
  1124. package/dist/frontend/lowering/lower-containers.js.map +0 -1
@@ -1,14 +1,15 @@
1
- import { BOOL, DYN, F64, DYN_CLASS_PROPERTIES as PROPERTY_BAG, STRING, VOID, canConvertToDyn, canDynCheckTo, isClassOwnEnumerableFieldName, isDynTypedRefType, isUnitType, typeEquals, typeKey } from "../../ir/ir.js";
1
+ import { dynUndefinedExpr, varRef } from "../../ir/build.js";
2
+ import { BOOL, DYN, F64, DYN_CLASS_PROPERTIES as PROPERTY_BAG, STRING, VOID, canConvertToDyn, canDynCheckTo, isClassOwnEnumerableFieldName, isDynTypedRefType, isUnitType, typeEquals, typeKey, } from "../../ir/ir.js";
2
3
  import { streamTypedRefEligible } from "../../ir/analysis.js";
3
- import { varRef } from "../../ir/build.js";
4
4
  import { everyStmtList, transformExpr, transformStmtList } from "../../ir/traverse.js";
5
- import { dynUndefinedExpr, PoisonError } from "./lowerer.js";
6
- import { implicitDefaultInstance } from "./lower-calls.js";
7
- import { accessorCall, classValueRef, findGenericMethodOn, findGenericStaticOn, findMethodOn, findStaticOn, genericOverrideBelow, upcastTo } from "./lower-classes.js";
8
- import { classPrototypeData, hasClassPrototypeData, reflectClassPrototype } from "./class-prototypes.js";
9
- import { errorPropertyRead, errorPropertyWrite, errorToStringCall, errorToStringMethod, refreshErrorPropertyDispatch, refreshErrorMethodDispatch } from "./error-methods.js";
5
+ import { PoisonError } from "./lowerer.js";
6
+ import { implicitDefaultInstance } from "./generic-functions.js";
7
+ import {} from "./call-signatures.js";
8
+ import { accessorCall, classValueRef, findGenericMethodOn, findGenericStaticOn, findMethodOn, findStaticOn, genericOverrideBelow, upcastTo, } from "./lower-classes.js";
9
+ import { classPrototypeData, hasClassPrototypeData, reflectClassPrototype, } from "./class-prototypes.js";
10
+ import { errorPropertyRead, errorPropertyWrite, errorToStringCall, errorToStringMethod, refreshErrorPropertyDispatch, refreshErrorMethodDispatch, } from "./error-methods.js";
10
11
  import { GeneratorDynamicDispatch } from "./generator-dynamic-dispatch.js";
11
- import { classMethodValue, reflectedClassStaticMethodValue, refreshClassMethodValueSelections } from "./class-method-values.js";
12
+ import { classMethodValue, reflectedClassStaticMethodValue, refreshClassMethodValueSelections, } from "./class-method-values.js";
12
13
  import { classStaticData } from "./class-static-data.js";
13
14
  import { isJsSourceFile } from "../program.js";
14
15
  import * as ts from "../ts7/adapter.js";
@@ -17,15 +18,60 @@ import { isClassCallback } from "./class-callbacks.js";
17
18
  import { refreshDescriptorGuards } from "./class-descriptors.js";
18
19
  import { ClassConstructionDispatch } from "./class-construction.js";
19
20
  import { emitterRooted } from "./lower-event-emitter.js";
20
- const STREAM_METHODS = new Set(["on", "addListener", "once", "prependListener", "prependOnceListener", "off", "removeListener", "read", "pause", "resume", "isPaused", "destroy"]);
21
- const EMITTER_METHODS = new Set(["emit", "on", "addListener", "once", "prependListener", "prependOnceListener", "off", "removeListener"]);
22
- const STREAM_BOOL_PROPERTIES = new Set(["readable", "readableEnded", "writable", "writableEnded", "writableFinished", "writableNeedDrain", "destroyed", "closed", "readableObjectMode", "writableObjectMode", "allowHalfOpen"]);
23
- const STREAM_NUM_PROPERTIES = new Set(["readableLength", "readableHighWaterMark", "writableLength", "writableHighWaterMark", "writableCorked"]);
21
+ const STREAM_METHODS = new Set([
22
+ "on",
23
+ "addListener",
24
+ "once",
25
+ "prependListener",
26
+ "prependOnceListener",
27
+ "off",
28
+ "removeListener",
29
+ "read",
30
+ "pause",
31
+ "resume",
32
+ "isPaused",
33
+ "destroy",
34
+ ]);
35
+ const EMITTER_METHODS = new Set([
36
+ "emit",
37
+ "on",
38
+ "addListener",
39
+ "once",
40
+ "prependListener",
41
+ "prependOnceListener",
42
+ "off",
43
+ "removeListener",
44
+ ]);
45
+ const STREAM_BOOL_PROPERTIES = new Set([
46
+ "readable",
47
+ "readableEnded",
48
+ "writable",
49
+ "writableEnded",
50
+ "writableFinished",
51
+ "writableNeedDrain",
52
+ "destroyed",
53
+ "closed",
54
+ "readableObjectMode",
55
+ "writableObjectMode",
56
+ "allowHalfOpen",
57
+ ]);
58
+ const STREAM_NUM_PROPERTIES = new Set([
59
+ "readableLength",
60
+ "readableHighWaterMark",
61
+ "writableLength",
62
+ "writableHighWaterMark",
63
+ "writableCorked",
64
+ ]);
24
65
  const streamProperty = (name) => STREAM_BOOL_PROPERTIES.has(name) || STREAM_NUM_PROPERTIES.has(name);
25
66
  function symbolMemberKey(lowerer, info, name, loc) {
26
67
  if (name.startsWith("sym:"))
27
- return lowerer.coerceToExpected({ kind: "libCall", fn: "sym.wellKnown",
28
- args: [{ kind: "strLit", value: name.slice(4), type: STRING, loc }], type: SYMBOL_T, loc }, DYN);
68
+ return lowerer.coerceToExpected({
69
+ kind: "libCall",
70
+ fn: "sym.wellKnown",
71
+ args: [{ kind: "strLit", value: name.slice(4), type: STRING, loc }],
72
+ type: SYMBOL_T,
73
+ loc,
74
+ }, DYN);
29
75
  if (info.symbolFields !== undefined) {
30
76
  for (const [symbol, member] of info.symbolFields) {
31
77
  if (member !== name)
@@ -48,39 +94,101 @@ function symbolMemberKey(lowerer, info, name, loc) {
48
94
  }
49
95
  export function classInstanceOf(lowerer, value, info, loc, classValue) {
50
96
  const name = `%dyn.class.${classValue ? "valueInstanceof" : "instanceof"}:${info.def.name}`;
51
- const params = [{ localId: "value", name: "value", type: DYN },
52
- ...(classValue ? [{ localId: "class", name: "class", type: classValue.type }] : [])];
97
+ const params = [
98
+ { localId: "value", name: "value", type: DYN },
99
+ ...(classValue ? [{ localId: "class", name: "class", type: classValue.type }] : []),
100
+ ];
53
101
  if (!lowerer.liftedFns.some((fn) => fn.name === name)) {
54
102
  const candidate = varRef("candidate", DYN, loc);
55
103
  const prototype = classPrototypeData(lowerer, info, loc, classValue ? varRef("class", classValue.type, loc) : undefined);
56
- const body = prototype ? [
57
- { kind: "varDecl", localId: "candidate", init: varRef("value", DYN, loc), loc },
58
- { kind: "while", cond: { kind: "ternary", cond: { kind: "dynTest", test: "nullish", value: candidate, type: BOOL, loc },
59
- then: { kind: "boolLit", value: false, type: BOOL, loc }, else_: { kind: "dynTest", test: "object", value: candidate, type: BOOL, loc }, type: BOOL, loc }, body: [
60
- { kind: "assign", localId: "candidate", value: { kind: "libCall", fn: "dyn.getPrototype", args: [candidate], type: DYN, loc, prototypeIdentityOnly: true }, loc },
61
- { kind: "if", cond: { kind: "dynScalarEq", left: candidate, right: prototype, type: BOOL, loc }, then: [
62
- { kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc },
63
- ], else_: null, loc },
64
- ], loc },
65
- ] : [];
104
+ const body = prototype
105
+ ? [
106
+ { kind: "varDecl", localId: "candidate", init: varRef("value", DYN, loc), loc },
107
+ {
108
+ kind: "while",
109
+ cond: {
110
+ kind: "ternary",
111
+ cond: { kind: "dynTest", test: "nullish", value: candidate, type: BOOL, loc },
112
+ then: { kind: "boolLit", value: false, type: BOOL, loc },
113
+ else_: { kind: "dynTest", test: "object", value: candidate, type: BOOL, loc },
114
+ type: BOOL,
115
+ loc,
116
+ },
117
+ body: [
118
+ {
119
+ kind: "assign",
120
+ localId: "candidate",
121
+ value: {
122
+ kind: "libCall",
123
+ fn: "dyn.getPrototype",
124
+ args: [candidate],
125
+ type: DYN,
126
+ loc,
127
+ prototypeIdentityOnly: true,
128
+ },
129
+ loc,
130
+ },
131
+ {
132
+ kind: "if",
133
+ cond: { kind: "dynScalarEq", left: candidate, right: prototype, type: BOOL, loc },
134
+ then: [
135
+ { kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc },
136
+ ],
137
+ else_: null,
138
+ loc,
139
+ },
140
+ ],
141
+ loc,
142
+ },
143
+ ]
144
+ : [];
66
145
  body.push({ kind: "return", value: { kind: "boolLit", value: false, type: BOOL, loc }, loc });
67
146
  lowerer.liftedFns.push({
68
- name, params, returnType: BOOL,
69
- locals: [...params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })),
70
- ...(prototype ? [{ id: "candidate", name: "candidate", type: DYN, mutable: true }] : [])], body, loc,
147
+ name,
148
+ params,
149
+ returnType: BOOL,
150
+ locals: [
151
+ ...params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })),
152
+ ...(prototype ? [{ id: "candidate", name: "candidate", type: DYN, mutable: true }] : []),
153
+ ],
154
+ body,
155
+ loc,
71
156
  });
72
157
  }
73
- return { kind: "call", callee: name, args: [value, ...(classValue ? [classValue] : [])], type: BOOL, loc };
158
+ return {
159
+ kind: "call",
160
+ callee: name,
161
+ args: [value, ...(classValue ? [classValue] : [])],
162
+ type: BOOL,
163
+ loc,
164
+ };
74
165
  }
75
- export function classPropertiesHelper(lowerer, loc) {
76
- const name = "%dyn.class.properties";
166
+ export function classPropertiesHelper(lowerer, loc, readOnly = false) {
167
+ const name = readOnly ? "%dyn.class.readProperties" : "%dyn.class.properties";
77
168
  const existing = lowerer.liftedFns.find((fn) => fn.name === name);
78
169
  if (existing)
79
170
  return existing;
80
171
  const helper = {
81
- name, params: [{ localId: "p.0", name: "value", type: DYN }], returnType: DYN,
172
+ name,
173
+ params: [{ localId: "p.0", name: "value", type: DYN }],
174
+ returnType: DYN,
82
175
  locals: [{ id: "p.0", name: "value", type: DYN, mutable: false }],
83
- body: [{ kind: "return", value: varRef("p.0", DYN, loc), loc }], loc,
176
+ body: [
177
+ {
178
+ kind: "return",
179
+ value: readOnly
180
+ ? {
181
+ kind: "call",
182
+ callee: classPropertiesHelper(lowerer, loc).name,
183
+ args: [varRef("p.0", DYN, loc)],
184
+ type: DYN,
185
+ loc,
186
+ }
187
+ : varRef("p.0", DYN, loc),
188
+ loc,
189
+ },
190
+ ],
191
+ loc,
84
192
  };
85
193
  lowerer.liftedFns.push(helper);
86
194
  return helper;
@@ -90,12 +198,40 @@ export function classPropertiesHelper(lowerer, loc) {
90
198
  export function classForInHasKey(lowerer, value, key, loc) {
91
199
  const name = "%dyn.class.forInHasKey";
92
200
  if (!lowerer.liftedFns.some((fn) => fn.name === name)) {
93
- lowerer.liftedFns.push({ name, params: [{ localId: "value", name: "value", type: DYN }, { localId: "key", name: "key", type: STRING }], returnType: BOOL,
94
- locals: [{ id: "value", name: "value", type: DYN, mutable: false }, { id: "key", name: "key", type: STRING, mutable: false }],
95
- body: [{ kind: "return", value: { kind: "libCall", fn: "dyn.hasKey", args: [
96
- { kind: "call", callee: classPropertiesHelper(lowerer, loc).name, args: [varRef("value", DYN, loc)], type: DYN, loc },
201
+ lowerer.liftedFns.push({
202
+ name,
203
+ params: [
204
+ { localId: "value", name: "value", type: DYN },
205
+ { localId: "key", name: "key", type: STRING },
206
+ ],
207
+ returnType: BOOL,
208
+ locals: [
209
+ { id: "value", name: "value", type: DYN, mutable: false },
210
+ { id: "key", name: "key", type: STRING, mutable: false },
211
+ ],
212
+ body: [
213
+ {
214
+ kind: "return",
215
+ value: {
216
+ kind: "libCall",
217
+ fn: "dyn.hasKey",
218
+ args: [
219
+ {
220
+ kind: "call",
221
+ callee: classPropertiesHelper(lowerer, loc).name,
222
+ args: [varRef("value", DYN, loc)],
223
+ type: DYN,
224
+ loc,
225
+ },
97
226
  varRef("key", STRING, loc),
98
- ], type: BOOL, loc }, loc }], loc,
227
+ ],
228
+ type: BOOL,
229
+ loc,
230
+ },
231
+ loc,
232
+ },
233
+ ],
234
+ loc,
99
235
  });
100
236
  }
101
237
  return { kind: "call", callee: name, args: [value, key], type: BOOL, loc };
@@ -110,12 +246,24 @@ export function trackClassFieldCreation(lowerer, functions) {
110
246
  const name = "%dyn.class.fieldCreated";
111
247
  const value = varRef("value", DYN, loc), key = varRef("key", DYN, loc);
112
248
  const bag = varRef("bag", DYN, loc);
113
- const created = (receiver, className, field, loc) => ({ kind: "exprStmt", expr: {
114
- kind: "call", callee: name, args: [lowerer.coerceToExpected(receiver, DYN), symbolMemberKey(lowerer, lowerer.classes.get(className), field, loc) ??
115
- lowerer.coerceToExpected({ kind: "strLit", value: field, type: STRING, loc }, DYN)], type: VOID, loc,
116
- }, loc });
117
- const tracked = (className, field) => !!lowerer.classes.get(className)?.def.tracksOwnFields && (isClassOwnEnumerableFieldName(field) ||
118
- symbolMemberKey(lowerer, lowerer.classes.get(className), field, loc) !== null);
249
+ const created = (receiver, className, field, loc) => ({
250
+ kind: "exprStmt",
251
+ expr: {
252
+ kind: "call",
253
+ callee: name,
254
+ args: [
255
+ lowerer.coerceToExpected(receiver, DYN),
256
+ symbolMemberKey(lowerer, lowerer.classes.get(className), field, loc) ??
257
+ lowerer.coerceToExpected({ kind: "strLit", value: field, type: STRING, loc }, DYN),
258
+ ],
259
+ type: VOID,
260
+ loc,
261
+ },
262
+ loc,
263
+ });
264
+ const tracked = (className, field) => !!lowerer.classes.get(className)?.def.tracksOwnFields &&
265
+ (isClassOwnEnumerableFieldName(field) ||
266
+ symbolMemberKey(lowerer, lowerer.classes.get(className), field, loc) !== null);
119
267
  for (const fn of functions) {
120
268
  const instrumented = new WeakSet();
121
269
  const local = (type, loc) => {
@@ -125,41 +273,121 @@ export function trackClassFieldCreation(lowerer, functions) {
125
273
  };
126
274
  fn.body = transformStmtList(fn.body, {
127
275
  stmt: (statement) => {
128
- if (statement.kind !== "fieldSet" || instrumented.has(statement) || !tracked(statement.className, statement.field))
276
+ if (statement.kind !== "fieldSet" ||
277
+ instrumented.has(statement) ||
278
+ !tracked(statement.className, statement.field))
129
279
  return statement;
130
280
  const receiver = local(statement.obj.type, statement.loc);
131
281
  const store = { ...statement, obj: receiver };
132
282
  instrumented.add(store);
133
- return { kind: "block", body: [
283
+ return {
284
+ kind: "block",
285
+ body: [
134
286
  { kind: "varDecl", localId: receiver.localId, init: statement.obj, loc: statement.loc },
135
- store, created(receiver, statement.className, statement.field, statement.loc),
136
- ], loc: statement.loc };
287
+ store,
288
+ created(receiver, statement.className, statement.field, statement.loc),
289
+ ],
290
+ loc: statement.loc,
291
+ };
137
292
  },
138
293
  expr: (expression) => {
139
- if (expression.kind !== "fieldIncDec" || instrumented.has(expression) || !tracked(expression.className, expression.field))
294
+ if (expression.kind !== "fieldIncDec" ||
295
+ instrumented.has(expression) ||
296
+ !tracked(expression.className, expression.field))
140
297
  return expression;
141
298
  const receiver = local(expression.obj.type, expression.loc), result = local(expression.type, expression.loc);
142
299
  const update = { ...expression, obj: receiver };
143
300
  instrumented.add(update);
144
- return { kind: "seqExpr", stmts: [
145
- { kind: "varDecl", localId: receiver.localId, init: expression.obj, loc: expression.loc },
301
+ return {
302
+ kind: "seqExpr",
303
+ stmts: [
304
+ {
305
+ kind: "varDecl",
306
+ localId: receiver.localId,
307
+ init: expression.obj,
308
+ loc: expression.loc,
309
+ },
146
310
  { kind: "varDecl", localId: result.localId, init: update, loc: expression.loc },
147
311
  created(receiver, expression.className, expression.field, expression.loc),
148
- ], result, type: expression.type, loc: expression.loc };
312
+ ],
313
+ result,
314
+ type: expression.type,
315
+ loc: expression.loc,
316
+ };
149
317
  },
150
318
  });
151
319
  }
152
- functions.push({ name, params: [{ localId: "value", name: "value", type: DYN }, { localId: "key", name: "key", type: DYN }], returnType: VOID,
153
- locals: [{ id: "value", name: "value", type: DYN, mutable: false }, { id: "key", name: "key", type: DYN, mutable: false }, { id: "bag", name: "bag", type: DYN, mutable: false }],
320
+ functions.push({
321
+ name,
322
+ params: [
323
+ { localId: "value", name: "value", type: DYN },
324
+ { localId: "key", name: "key", type: DYN },
325
+ ],
326
+ returnType: VOID,
327
+ locals: [
328
+ { id: "value", name: "value", type: DYN, mutable: false },
329
+ { id: "key", name: "key", type: DYN, mutable: false },
330
+ { id: "bag", name: "bag", type: DYN, mutable: false },
331
+ ],
154
332
  body: [
155
- { kind: "varDecl", localId: "bag", init: { kind: "call", callee: classPropertiesHelper(lowerer, loc).name, args: [value], type: DYN, loc }, loc },
156
- { kind: "if", cond: { kind: "unary", op: "!", operand: { kind: "libCall", fn: "dyn.hasOwnComputed", args: [bag, key], type: BOOL, loc }, type: BOOL, loc }, then: [
157
- { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.defineProperty", args: [bag, lowerer.coerceToExpected(key, DYN), { kind: "dynObjLit", fields: [
158
- { key: { kind: "strLit", value: "value", type: STRING, loc }, value: dynUndefinedExpr(loc) },
159
- ...["writable", "enumerable", "configurable"].map((key) => ({ key: { kind: "strLit", value: key, type: STRING, loc }, value: lowerer.coerceToExpected({ kind: "boolLit", value: true, type: BOOL, loc }, DYN) })),
160
- ], type: DYN, loc }], type: DYN, loc }, loc },
161
- ], else_: null, loc },
162
- ], loc, });
333
+ {
334
+ kind: "varDecl",
335
+ localId: "bag",
336
+ init: {
337
+ kind: "call",
338
+ callee: classPropertiesHelper(lowerer, loc).name,
339
+ args: [value],
340
+ type: DYN,
341
+ loc,
342
+ },
343
+ loc,
344
+ },
345
+ {
346
+ kind: "if",
347
+ cond: {
348
+ kind: "unary",
349
+ op: "!",
350
+ operand: { kind: "libCall", fn: "dyn.hasOwnComputed", args: [bag, key], type: BOOL, loc },
351
+ type: BOOL,
352
+ loc,
353
+ },
354
+ then: [
355
+ {
356
+ kind: "exprStmt",
357
+ expr: {
358
+ kind: "libCall",
359
+ fn: "dyn.defineProperty",
360
+ args: [
361
+ bag,
362
+ lowerer.coerceToExpected(key, DYN),
363
+ {
364
+ kind: "dynObjLit",
365
+ fields: [
366
+ {
367
+ key: { kind: "strLit", value: "value", type: STRING, loc },
368
+ value: dynUndefinedExpr(loc),
369
+ },
370
+ ...["writable", "enumerable", "configurable"].map((key) => ({
371
+ key: { kind: "strLit", value: key, type: STRING, loc },
372
+ value: lowerer.coerceToExpected({ kind: "boolLit", value: true, type: BOOL, loc }, DYN),
373
+ })),
374
+ ],
375
+ type: DYN,
376
+ loc,
377
+ },
378
+ ],
379
+ type: DYN,
380
+ loc,
381
+ },
382
+ loc,
383
+ },
384
+ ],
385
+ else_: null,
386
+ loc,
387
+ },
388
+ ],
389
+ loc,
390
+ });
163
391
  }
164
392
  /** Calls on native class capsules keep the instance's compiled methods. The
165
393
  * reachable-body fixed point discovers both the boxed classes and method
@@ -187,6 +415,7 @@ export class ClassDynamicDispatch {
187
415
  bagClasses = new Set();
188
416
  bagInitializers = new Map();
189
417
  typedPropertyBags = new Map();
418
+ readPropertyBags = [];
190
419
  generated = new Set();
191
420
  constructDispatch = null;
192
421
  constructors = new Map();
@@ -208,7 +437,9 @@ export class ClassDynamicDispatch {
208
437
  // entry ahead of every newly inserted branch after rebuilding the tables.
209
438
  for (const fn of this.normalizedDispatches()) {
210
439
  const first = fn.body[0];
211
- if (first?.kind === "assign" && first.value.kind === "call" && first.value.callee === this.normalization?.name)
440
+ if (first?.kind === "assign" &&
441
+ first.value.kind === "call" &&
442
+ first.value.callee === this.normalization?.name)
212
443
  fn.body.shift();
213
444
  }
214
445
  let changed = refreshErrorMethodDispatch(lowerer, functions);
@@ -249,14 +480,16 @@ export class ClassDynamicDispatch {
249
480
  stmt: (statement) => {
250
481
  // Field-creation instrumentation can box a base-constructor receiver
251
482
  // even when only its derived instances otherwise cross the boundary.
252
- if (statement.kind === "fieldSet" && lowerer.classes.get(statement.className)?.def.tracksOwnFields &&
483
+ if (statement.kind === "fieldSet" &&
484
+ lowerer.classes.get(statement.className)?.def.tracksOwnFields &&
253
485
  isClassOwnEnumerableFieldName(statement.field))
254
486
  discover(statement.obj.type);
255
487
  return true;
256
488
  },
257
489
  expr: (expr) => {
258
- if (expr.kind === "jsonStringify" || expr.kind === "libCall" &&
259
- (expr.fn === "json.stringifyValue" || expr.fn === "json.stringifyReplacer")) {
490
+ if (expr.kind === "jsonStringify" ||
491
+ (expr.kind === "libCall" &&
492
+ (expr.fn === "json.stringifyValue" || expr.fn === "json.stringifyReplacer"))) {
260
493
  this.serializesClasses = true;
261
494
  }
262
495
  switch (expr.kind) {
@@ -264,11 +497,15 @@ export class ClassDynamicDispatch {
264
497
  discover(expr.value.type);
265
498
  break;
266
499
  case "fieldIncDec":
267
- if (lowerer.classes.get(expr.className)?.def.tracksOwnFields && isClassOwnEnumerableFieldName(expr.field))
500
+ if (lowerer.classes.get(expr.className)?.def.tracksOwnFields &&
501
+ isClassOwnEnumerableFieldName(expr.field))
268
502
  discover(expr.obj.type);
269
503
  break;
270
504
  case "call":
271
- if (expr.callee === "%dyn.class.properties" && expr.args[0]?.kind === "dynFrom" && isDynTypedRefType(expr.args[0].value.type))
505
+ if ((expr.callee === "%dyn.class.properties" ||
506
+ expr.callee === "%dyn.class.readProperties") &&
507
+ expr.args[0]?.kind === "dynFrom" &&
508
+ isDynTypedRefType(expr.args[0].value.type))
272
509
  rewrite.add(fn);
273
510
  break;
274
511
  case "dynKeyGet":
@@ -280,8 +517,21 @@ export class ClassDynamicDispatch {
280
517
  rewrite.add(fn);
281
518
  break;
282
519
  case "libCall":
283
- if (expr.fn === "bytes.construct" || expr.fn === "dyn.keySet" || expr.fn === "dyn.keySetComputed" || (expr.fn === "dyn.iterator" || expr.fn === "dyn.arrayFromIterator") || expr.fn === "dyn.toString" || expr.fn === "dyn.stringConstructor" ||
284
- expr.fn === "dyn.forInKeys" || expr.fn === "dyn.hasKeyComputed" || expr.fn === "dyn.hasOwnComputed" || expr.fn === "dyn.propertyIsEnumerableComputed" || expr.fn === "dyn.defineProperty" || expr.fn === "dyn.getPrototype" || expr.fn === "dyn.reflectGet" || expr.fn === "dyn.reflectSet")
520
+ if (expr.fn === "bytes.construct" ||
521
+ expr.fn === "dyn.keySet" ||
522
+ expr.fn === "dyn.keySetComputed" ||
523
+ expr.fn === "dyn.iterator" ||
524
+ expr.fn === "dyn.arrayFromIterator" ||
525
+ expr.fn === "dyn.toString" ||
526
+ expr.fn === "dyn.stringConstructor" ||
527
+ expr.fn === "dyn.forInKeys" ||
528
+ expr.fn === "dyn.hasKeyComputed" ||
529
+ expr.fn === "dyn.hasOwnComputed" ||
530
+ expr.fn === "dyn.propertyIsEnumerableComputed" ||
531
+ expr.fn === "dyn.defineProperty" ||
532
+ expr.fn === "dyn.getPrototype" ||
533
+ expr.fn === "dyn.reflectGet" ||
534
+ expr.fn === "dyn.reflectSet")
285
535
  rewrite.add(fn);
286
536
  break;
287
537
  }
@@ -291,7 +541,8 @@ export class ClassDynamicDispatch {
291
541
  if (this.boxed.size === 0 && rewrite.size === 0)
292
542
  return changed;
293
543
  for (const fn of functions) {
294
- if (!fn.name.startsWith("%dyn.class.instanceof:") && !fn.name.startsWith("%dyn.class.valueInstanceof:"))
544
+ if (!fn.name.startsWith("%dyn.class.instanceof:") &&
545
+ !fn.name.startsWith("%dyn.class.valueInstanceof:"))
295
546
  continue;
296
547
  const target = fn.name.slice(fn.name.indexOf(":") + 1);
297
548
  let checked = this.instanceTests.get(fn.name);
@@ -310,11 +561,35 @@ export class ClassDynamicDispatch {
310
561
  const value = varRef("value", DYN, loc);
311
562
  const type = { kind: "object", className };
312
563
  const result = subtype && fn.params[1] && lowerer.classes.get(target)?.localClass
313
- ? { kind: "instanceOfValue", value: { kind: "dynCheck", value, type, loc }, classValue: varRef("class", fn.params[1].type, loc), type: BOOL, loc }
314
- : subtype ? { kind: "boolLit", value: true, type: BOOL, loc }
315
- : { kind: "instanceOf", value: { kind: "dynCheck", value, type, loc }, className: target, type: BOOL, loc };
316
- fn.body.unshift({ kind: "if", cond: { kind: "libCall", fn: "dyn.typedRefIs", args: [value,
317
- { kind: "strLit", value: typeKey(type), type: STRING, loc }], type: BOOL, loc }, then: [{ kind: "return", value: result, loc }], else_: null, loc });
564
+ ? {
565
+ kind: "instanceOfValue",
566
+ value: { kind: "dynCheck", value, type, loc },
567
+ classValue: varRef("class", fn.params[1].type, loc),
568
+ type: BOOL,
569
+ loc,
570
+ }
571
+ : subtype
572
+ ? { kind: "boolLit", value: true, type: BOOL, loc }
573
+ : {
574
+ kind: "instanceOf",
575
+ value: { kind: "dynCheck", value, type, loc },
576
+ className: target,
577
+ type: BOOL,
578
+ loc,
579
+ };
580
+ fn.body.unshift({
581
+ kind: "if",
582
+ cond: {
583
+ kind: "libCall",
584
+ fn: "dyn.typedRefIs",
585
+ args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
586
+ type: BOOL,
587
+ loc,
588
+ },
589
+ then: [{ kind: "return", value: result, loc }],
590
+ else_: null,
591
+ loc,
592
+ });
318
593
  changed = true;
319
594
  }
320
595
  }
@@ -338,11 +613,26 @@ export class ClassDynamicDispatch {
338
613
  const loc = this.prototypeHelper.loc;
339
614
  const type = { kind: "object", className };
340
615
  const value = varRef("value", DYN, loc);
341
- const prototype = reflectClassPrototype(lowerer, info, loc, { kind: "dynCheck", value, type, loc });
616
+ const prototype = reflectClassPrototype(lowerer, info, loc, {
617
+ kind: "dynCheck",
618
+ value,
619
+ type,
620
+ loc,
621
+ });
342
622
  if (prototype)
343
- this.prototypeHelper.body.unshift({ kind: "if", cond: { kind: "libCall", fn: "dyn.typedRefIs", args: [value,
344
- { kind: "strLit", value: typeKey(type), type: STRING, loc }], type: BOOL, loc },
345
- then: [{ kind: "return", value: prototype, loc }], else_: null, loc });
623
+ this.prototypeHelper.body.unshift({
624
+ kind: "if",
625
+ cond: {
626
+ kind: "libCall",
627
+ fn: "dyn.typedRefIs",
628
+ args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
629
+ type: BOOL,
630
+ loc,
631
+ },
632
+ then: [{ kind: "return", value: prototype, loc }],
633
+ else_: null,
634
+ loc,
635
+ });
346
636
  changed = true;
347
637
  }
348
638
  if (this.prototypeIdentityHelper && !this.prototypeIdentityClasses.has(className)) {
@@ -350,30 +640,82 @@ export class ClassDynamicDispatch {
350
640
  const loc = this.prototypeIdentityHelper.loc;
351
641
  const type = { kind: "object", className };
352
642
  const value = varRef("value", DYN, loc);
353
- const prototype = classPrototypeData(lowerer, info, loc, { kind: "dynCheck", value, type, loc });
643
+ const prototype = classPrototypeData(lowerer, info, loc, {
644
+ kind: "dynCheck",
645
+ value,
646
+ type,
647
+ loc,
648
+ });
354
649
  if (prototype)
355
- this.prototypeIdentityHelper.body.unshift({ kind: "if", cond: { kind: "libCall", fn: "dyn.typedRefIs", args: [value,
356
- { kind: "strLit", value: typeKey(type), type: STRING, loc }], type: BOOL, loc },
357
- then: [{ kind: "return", value: prototype, loc }], else_: null, loc });
650
+ this.prototypeIdentityHelper.body.unshift({
651
+ kind: "if",
652
+ cond: {
653
+ kind: "libCall",
654
+ fn: "dyn.typedRefIs",
655
+ args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
656
+ type: BOOL,
657
+ loc,
658
+ },
659
+ then: [{ kind: "return", value: prototype, loc }],
660
+ else_: null,
661
+ loc,
662
+ });
358
663
  changed = true;
359
664
  }
360
- if (this.serializesClasses && !this.jsonPrototypes.has(className) && info.decl && findMethodOn(lowerer, info, "toJSON")) {
665
+ if (this.serializesClasses &&
666
+ !this.jsonPrototypes.has(className) &&
667
+ info.decl &&
668
+ findMethodOn(lowerer, info, "toJSON")) {
361
669
  this.jsonPrototypes.add(className);
362
670
  const loc = this.propertyBag.loc;
363
671
  const method = classMethodValue(lowerer, info.decl, info, "toJSON", loc);
364
672
  const prototype = method ? classPrototypeData(lowerer, info, loc) : null;
365
673
  const helper = lowerer.liftedFns.find((fn) => fn.name === info.def.prototypeDataHelper);
366
674
  const init = helper?.body[0];
367
- if (!info.prototypeReflectionReady && method && prototype && init?.kind === "if" && canConvertToDyn(method.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
368
- const descriptor = { kind: "exprStmt", expr: {
369
- kind: "libCall", fn: "dyn.defineProperty", args: [prototype,
370
- { kind: "dynFrom", value: { kind: "strLit", value: "toJSON", type: STRING, loc }, type: DYN, loc },
371
- { kind: "dynObjLit", fields: [
372
- { key: { kind: "strLit", value: "value", type: STRING, loc }, value: { kind: "dynFrom", value: method, type: DYN, loc } },
373
- ...["writable", "configurable"].map((key) => ({ key: { kind: "strLit", value: key, type: STRING, loc }, value: { kind: "dynFrom", value: { kind: "boolLit", value: true, type: BOOL, loc }, type: DYN, loc } })),
374
- ], type: DYN, loc },
375
- ], type: DYN, loc
376
- }, loc };
675
+ if (!info.prototypeReflectionReady &&
676
+ method &&
677
+ prototype &&
678
+ init?.kind === "if" &&
679
+ canConvertToDyn(method.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
680
+ const descriptor = {
681
+ kind: "exprStmt",
682
+ expr: {
683
+ kind: "libCall",
684
+ fn: "dyn.defineProperty",
685
+ args: [
686
+ prototype,
687
+ {
688
+ kind: "dynFrom",
689
+ value: { kind: "strLit", value: "toJSON", type: STRING, loc },
690
+ type: DYN,
691
+ loc,
692
+ },
693
+ {
694
+ kind: "dynObjLit",
695
+ fields: [
696
+ {
697
+ key: { kind: "strLit", value: "value", type: STRING, loc },
698
+ value: { kind: "dynFrom", value: method, type: DYN, loc },
699
+ },
700
+ ...["writable", "configurable"].map((key) => ({
701
+ key: { kind: "strLit", value: key, type: STRING, loc },
702
+ value: {
703
+ kind: "dynFrom",
704
+ value: { kind: "boolLit", value: true, type: BOOL, loc },
705
+ type: DYN,
706
+ loc,
707
+ },
708
+ })),
709
+ ],
710
+ type: DYN,
711
+ loc,
712
+ },
713
+ ],
714
+ type: DYN,
715
+ loc,
716
+ },
717
+ loc,
718
+ };
377
719
  init.then.push(descriptor);
378
720
  changed = true;
379
721
  }
@@ -387,35 +729,74 @@ export class ClassDynamicDispatch {
387
729
  const name = `%class.instancePrototype:${plan.capsule.def.name}`;
388
730
  const type = { kind: "object", className: plan.capsule.def.name };
389
731
  const loc = this.propertyBag.loc;
390
- const fn = { name, params: [{ localId: "this", name: "this", type }],
391
- locals: [{ id: "this", name: "this", type, mutable: false }], returnType: DYN,
392
- body: [{ kind: "return", value: { kind: "libCall", fn: "dyn.getPrototype",
393
- args: [{ kind: "dynObjLit", fields: [], type: DYN, loc }], type: DYN, loc }, loc }], loc };
732
+ const fn = {
733
+ name,
734
+ params: [{ localId: "this", name: "this", type }],
735
+ locals: [{ id: "this", name: "this", type, mutable: false }],
736
+ returnType: DYN,
737
+ body: [
738
+ {
739
+ kind: "return",
740
+ value: {
741
+ kind: "libCall",
742
+ fn: "dyn.getPrototype",
743
+ args: [{ kind: "dynObjLit", fields: [], type: DYN, loc }],
744
+ type: DYN,
745
+ loc,
746
+ },
747
+ loc,
748
+ },
749
+ ],
750
+ loc,
751
+ };
394
752
  plan.capsule.def.instancePrototypeHelper = name;
395
753
  instancePrototype = { fn, classes: new Set() };
396
754
  this.instancePrototypes.set(plan.capsule.def.name, instancePrototype);
397
755
  this.generated.add(fn);
398
756
  lowerer.liftedFns.push(fn);
399
757
  }
400
- if (instancePrototype && hasClassPrototypeData(info) && !instancePrototype.classes.has(className)) {
758
+ if (instancePrototype &&
759
+ hasClassPrototypeData(info) &&
760
+ !instancePrototype.classes.has(className)) {
401
761
  instancePrototype.classes.add(className);
402
762
  const loc = instancePrototype.fn.loc;
403
763
  const receiver = varRef("this", instancePrototype.fn.params[0].type, loc);
404
- const prototype = classPrototypeData(lowerer, info, loc, info === plan.capsule ? receiver
764
+ const prototype = classPrototypeData(lowerer, info, loc, info === plan.capsule
765
+ ? receiver
405
766
  : { kind: "downcast", value: receiver, type: { kind: "object", className }, loc });
406
- const returned = { kind: "return", value: prototype ?? { kind: "libCall", fn: "dyn.getPrototype",
407
- args: [{ kind: "dynObjLit", fields: [], type: DYN, loc }], type: DYN, loc }, loc };
767
+ const returned = {
768
+ kind: "return",
769
+ value: prototype ?? {
770
+ kind: "libCall",
771
+ fn: "dyn.getPrototype",
772
+ args: [{ kind: "dynObjLit", fields: [], type: DYN, loc }],
773
+ type: DYN,
774
+ loc,
775
+ },
776
+ loc,
777
+ };
408
778
  if (info === plan.capsule)
409
779
  instancePrototype.fn.body[instancePrototype.fn.body.length - 1] = returned;
410
780
  else
411
- instancePrototype.fn.body.unshift({ kind: "if",
412
- cond: { kind: "instanceOf", value: receiver, className, type: BOOL, loc }, then: [returned], else_: null, loc });
781
+ instancePrototype.fn.body.unshift({
782
+ kind: "if",
783
+ cond: { kind: "instanceOf", value: receiver, className, type: BOOL, loc },
784
+ then: [returned],
785
+ else_: null,
786
+ loc,
787
+ });
413
788
  changed = true;
414
789
  }
415
- const needsPrototype = (current) => hasClassPrototypeData(current) || current.subclasses.some((child) => lowerer.classCanBeConstructed(child) && needsPrototype(child));
790
+ const needsPrototype = (current) => hasClassPrototypeData(current) ||
791
+ current.subclasses.some((child) => lowerer.classCanBeConstructed(child) && needsPrototype(child));
416
792
  const prototypeFor = (current, receiver, loc) => {
417
793
  const currentReceiver = receiver.type.kind === "object" && receiver.type.className !== current.def.name
418
- ? { kind: "downcast", value: receiver, type: { kind: "object", className: current.def.name }, loc }
794
+ ? {
795
+ kind: "downcast",
796
+ value: receiver,
797
+ type: { kind: "object", className: current.def.name },
798
+ loc,
799
+ }
419
800
  : receiver;
420
801
  let result = classPrototypeData(lowerer, current, loc, currentReceiver);
421
802
  for (const child of current.subclasses) {
@@ -423,8 +804,20 @@ export class ClassDynamicDispatch {
423
804
  continue;
424
805
  const selected = prototypeFor(child, receiver, loc);
425
806
  if (selected && result)
426
- result = { kind: "ternary", cond: { kind: "instanceOf", value: receiver, className: child.def.name, type: BOOL, loc },
427
- then: selected, else_: result, type: DYN, loc };
807
+ result = {
808
+ kind: "ternary",
809
+ cond: {
810
+ kind: "instanceOf",
811
+ value: receiver,
812
+ className: child.def.name,
813
+ type: BOOL,
814
+ loc,
815
+ },
816
+ then: selected,
817
+ else_: result,
818
+ type: DYN,
819
+ loc,
820
+ };
428
821
  }
429
822
  return result;
430
823
  };
@@ -432,7 +825,13 @@ export class ClassDynamicDispatch {
432
825
  if (existingInit.value.kind === "dynObjLit" && needsPrototype(info)) {
433
826
  const prototype = prototypeFor(info, existingInit.obj, existingInit.loc);
434
827
  if (prototype) {
435
- existingInit.value = { kind: "libCall", fn: "dyn.objCreate", args: [prototype], type: DYN, loc: existingInit.loc };
828
+ existingInit.value = {
829
+ kind: "libCall",
830
+ fn: "dyn.objCreate",
831
+ args: [prototype],
832
+ type: DYN,
833
+ loc: existingInit.loc,
834
+ };
436
835
  changed = true;
437
836
  }
438
837
  }
@@ -455,24 +854,43 @@ export class ClassDynamicDispatch {
455
854
  }
456
855
  const loc = this.propertyBag.loc;
457
856
  const { receiver, condition } = this.propertyReceiver(plan, loc);
458
- const bag = { kind: "fieldGet", obj: receiver, className, field: PROPERTY_BAG, type: DYN, loc };
857
+ const bag = {
858
+ kind: "fieldGet",
859
+ obj: receiver,
860
+ className,
861
+ field: PROPERTY_BAG,
862
+ type: DYN,
863
+ loc,
864
+ };
459
865
  const prototype = needsPrototype(info) ? prototypeFor(info, receiver, loc) : null;
460
866
  const initialize = {
461
- kind: "fieldSet", obj: receiver, className, field: PROPERTY_BAG, value: prototype
867
+ kind: "fieldSet",
868
+ obj: receiver,
869
+ className,
870
+ field: PROPERTY_BAG,
871
+ value: prototype
462
872
  ? { kind: "libCall", fn: "dyn.objCreate", args: [prototype], type: DYN, loc }
463
- : { kind: "dynObjLit", fields: [], type: DYN, loc }, loc,
873
+ : { kind: "dynObjLit", fields: [], type: DYN, loc },
874
+ loc,
464
875
  };
465
876
  const initializers = this.bagInitializers.get(className) ?? [];
466
877
  initializers.push(initialize);
467
878
  this.bagInitializers.set(className, initializers);
468
879
  this.propertyBag.body.unshift({
469
- kind: "if", cond: condition,
880
+ kind: "if",
881
+ cond: condition,
470
882
  then: [
471
- { kind: "if", cond: { kind: "dynTest", test: "undefined", value: bag, type: BOOL, loc }, then: [
472
- initialize,
473
- ], else_: null, loc },
883
+ {
884
+ kind: "if",
885
+ cond: { kind: "dynTest", test: "undefined", value: bag, type: BOOL, loc },
886
+ then: [initialize],
887
+ else_: null,
888
+ loc,
889
+ },
474
890
  { kind: "return", value: bag, loc },
475
- ], else_: null, loc,
891
+ ],
892
+ else_: null,
893
+ loc,
476
894
  });
477
895
  changed = true;
478
896
  }
@@ -489,7 +907,9 @@ export class ClassDynamicDispatch {
489
907
  return [info];
490
908
  if (info.builtinStream)
491
909
  return STREAM_METHODS.has(method) ? [info] : [];
492
- return findMethodOn(lowerer, info, method) || findGenericMethodOn(lowerer, info, method) ? [info] : [];
910
+ return findMethodOn(lowerer, info, method) || findGenericMethodOn(lowerer, info, method)
911
+ ? [info]
912
+ : [];
493
913
  });
494
914
  byMethod.set(method, matching);
495
915
  return matching;
@@ -502,17 +922,20 @@ export class ClassDynamicDispatch {
502
922
  continue;
503
923
  const keyInitializers = new Map();
504
924
  const written = new Set();
505
- everyStmtList(fn.body, { expr: (expression) => {
925
+ everyStmtList(fn.body, {
926
+ expr: (expression) => {
506
927
  if (expression.kind === "incDec" || expression.kind === "assignExpr")
507
928
  written.add(expression.localId);
508
929
  return true;
509
- }, stmt: (statement) => {
930
+ },
931
+ stmt: (statement) => {
510
932
  if (statement.kind === "varDecl" && statement.init)
511
933
  keyInitializers.set(statement.localId, statement.init);
512
934
  if (statement.kind === "assign")
513
935
  written.add(statement.localId);
514
936
  return true;
515
- } });
937
+ },
938
+ });
516
939
  const keyValue = (value) => {
517
940
  const visited = new Set();
518
941
  while (true) {
@@ -524,7 +947,10 @@ export class ClassDynamicDispatch {
524
947
  value = value.args[0];
525
948
  continue;
526
949
  }
527
- if (value.kind === "varRef" && !written.has(value.localId) && !visited.has(value.localId) && keyInitializers.has(value.localId)) {
950
+ if (value.kind === "varRef" &&
951
+ !written.has(value.localId) &&
952
+ !visited.has(value.localId) &&
953
+ keyInitializers.has(value.localId)) {
528
954
  visited.add(value.localId);
529
955
  value = keyInitializers.get(value.localId);
530
956
  continue;
@@ -540,10 +966,16 @@ export class ClassDynamicDispatch {
540
966
  let cast = this.checkedCasts.get(type.className);
541
967
  if (!cast) {
542
968
  const loc = expr.loc;
543
- const fn = { name: `%dyn.class.cast:${type.className}`,
969
+ const fn = {
970
+ name: `%dyn.class.cast:${type.className}`,
544
971
  params: [{ localId: "value", name: "value", type: DYN }],
545
- locals: [{ id: "value", name: "value", type: DYN, mutable: false }], returnType: type,
546
- body: [{ kind: "return", value: { ...expr, value: varRef("value", DYN, loc) }, loc }], loc };
972
+ locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
973
+ returnType: type,
974
+ body: [
975
+ { kind: "return", value: { ...expr, value: varRef("value", DYN, loc) }, loc },
976
+ ],
977
+ loc,
978
+ };
547
979
  cast = { fn, classes: new Set() };
548
980
  this.checkedCasts.set(type.className, cast);
549
981
  this.generated.add(fn);
@@ -552,59 +984,141 @@ export class ClassDynamicDispatch {
552
984
  }
553
985
  return { kind: "call", callee: cast.fn.name, args: [expr.value], type, loc: expr.loc };
554
986
  }
555
- if (expr.kind === "libCall" && expr.fn === "dyn.getPrototype" && expr.args[0]?.kind !== "dynObjLit") {
987
+ if (expr.kind === "libCall" &&
988
+ expr.fn === "dyn.getPrototype" &&
989
+ expr.args[0]?.kind !== "dynObjLit") {
556
990
  if (expr.prototypeIdentityOnly) {
557
991
  if (!this.prototypeIdentityHelper) {
558
992
  const loc = expr.loc;
559
- this.prototypeIdentityHelper = { name: "%dyn.class.prototypeIdentity", params: [{ localId: "value", name: "value", type: DYN }],
560
- locals: [{ id: "value", name: "value", type: DYN, mutable: false }], returnType: DYN, loc,
561
- body: [{ kind: "return", value: { ...expr, args: [varRef("value", DYN, loc)] }, loc }] };
993
+ this.prototypeIdentityHelper = {
994
+ name: "%dyn.class.prototypeIdentity",
995
+ params: [{ localId: "value", name: "value", type: DYN }],
996
+ locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
997
+ returnType: DYN,
998
+ loc,
999
+ body: [
1000
+ { kind: "return", value: { ...expr, args: [varRef("value", DYN, loc)] }, loc },
1001
+ ],
1002
+ };
562
1003
  lowerer.liftedFns.push(this.prototypeIdentityHelper);
563
1004
  this.generated.add(this.prototypeIdentityHelper);
564
1005
  changed = true;
565
1006
  }
566
- return { kind: "call", callee: this.prototypeIdentityHelper.name, args: expr.args, type: DYN, loc: expr.loc };
1007
+ return {
1008
+ kind: "call",
1009
+ callee: this.prototypeIdentityHelper.name,
1010
+ args: expr.args,
1011
+ type: DYN,
1012
+ loc: expr.loc,
1013
+ };
567
1014
  }
568
1015
  if (!this.prototypeHelper) {
569
1016
  const loc = expr.loc;
570
- this.prototypeHelper = { name: "%dyn.class.getPrototype", params: [{ localId: "value", name: "value", type: DYN }],
571
- locals: [{ id: "value", name: "value", type: DYN, mutable: false }], returnType: DYN, loc,
572
- body: [{ kind: "return", value: { ...expr, args: [varRef("value", DYN, loc)] }, loc }] };
1017
+ this.prototypeHelper = {
1018
+ name: "%dyn.class.getPrototype",
1019
+ params: [{ localId: "value", name: "value", type: DYN }],
1020
+ locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
1021
+ returnType: DYN,
1022
+ loc,
1023
+ body: [
1024
+ { kind: "return", value: { ...expr, args: [varRef("value", DYN, loc)] }, loc },
1025
+ ],
1026
+ };
573
1027
  lowerer.liftedFns.push(this.prototypeHelper);
574
1028
  this.generated.add(this.prototypeHelper);
575
1029
  changed = true;
576
1030
  }
577
- return { kind: "call", callee: this.prototypeHelper.name, args: expr.args, type: DYN, loc: expr.loc };
1031
+ return {
1032
+ kind: "call",
1033
+ callee: this.prototypeHelper.name,
1034
+ args: expr.args,
1035
+ type: DYN,
1036
+ loc: expr.loc,
1037
+ };
578
1038
  }
579
- if (expr.kind === "libCall" && (expr.fn === "dyn.toString" || expr.fn === "dyn.stringConstructor") && lowerer.classes.has("%Error")) {
1039
+ if (expr.kind === "libCall" &&
1040
+ (expr.fn === "dyn.toString" || expr.fn === "dyn.stringConstructor") &&
1041
+ lowerer.classes.has("%Error")) {
580
1042
  const key = JSON.stringify([expr.fn, ...expr.args.map((arg) => typeKey(arg.type))]);
581
1043
  let errorString = this.errorStrings.get(key);
582
1044
  if (!errorString) {
583
1045
  const loc = expr.loc;
584
- const params = expr.args.map((arg, i) => ({ localId: `p.${i}`, name: `p${i}`, type: arg.type }));
1046
+ const params = expr.args.map((arg, i) => ({
1047
+ localId: `p.${i}`,
1048
+ name: `p${i}`,
1049
+ type: arg.type,
1050
+ }));
585
1051
  const value = varRef("p.0", DYN, loc);
586
- errorString = { name: `%dyn.error.${expr.fn.slice(4)}.${this.errorStrings.size}`, params, returnType: STRING,
587
- locals: params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })), loc,
1052
+ errorString = {
1053
+ name: `%dyn.error.${expr.fn.slice(4)}.${this.errorStrings.size}`,
1054
+ params,
1055
+ returnType: STRING,
1056
+ locals: params.map((p) => ({
1057
+ id: p.localId,
1058
+ name: p.name,
1059
+ type: p.type,
1060
+ mutable: false,
1061
+ })),
1062
+ loc,
588
1063
  body: [
589
- { kind: "if", cond: { kind: "dynTest", test: "error", value, type: BOOL, loc }, then: [
590
- { kind: "return", value: { kind: "dynCheck", type: STRING, loc, value: {
591
- kind: "dynCall", callee: errorToStringMethod(lowerer, { kind: "dynCheck", value, type: { kind: "object", className: "%Error" }, loc }),
592
- receiver: value, calleeName: "value.toString", args: params.slice(1).map((p) => lowerer.coerceToExpected(varRef(p.localId, p.type, loc), DYN)), type: DYN, loc,
593
- } }, loc },
594
- ], else_: null, loc },
595
- { kind: "return", value: { ...expr, args: params.map((p) => varRef(p.localId, p.type, loc)) }, loc },
596
- ] };
1064
+ {
1065
+ kind: "if",
1066
+ cond: { kind: "dynTest", test: "error", value, type: BOOL, loc },
1067
+ then: [
1068
+ {
1069
+ kind: "return",
1070
+ value: {
1071
+ kind: "dynCheck",
1072
+ type: STRING,
1073
+ loc,
1074
+ value: {
1075
+ kind: "dynCall",
1076
+ callee: errorToStringMethod(lowerer, {
1077
+ kind: "dynCheck",
1078
+ value,
1079
+ type: { kind: "object", className: "%Error" },
1080
+ loc,
1081
+ }),
1082
+ receiver: value,
1083
+ calleeName: "value.toString",
1084
+ args: params
1085
+ .slice(1)
1086
+ .map((p) => lowerer.coerceToExpected(varRef(p.localId, p.type, loc), DYN)),
1087
+ type: DYN,
1088
+ loc,
1089
+ },
1090
+ },
1091
+ loc,
1092
+ },
1093
+ ],
1094
+ else_: null,
1095
+ loc,
1096
+ },
1097
+ {
1098
+ kind: "return",
1099
+ value: { ...expr, args: params.map((p) => varRef(p.localId, p.type, loc)) },
1100
+ loc,
1101
+ },
1102
+ ],
1103
+ };
597
1104
  this.errorStrings.set(key, errorString);
598
1105
  this.generated.add(errorString);
599
1106
  lowerer.liftedFns.push(errorString);
600
1107
  changed = true;
601
1108
  }
602
- return { kind: "call", callee: errorString.name, args: expr.args, type: STRING, loc: expr.loc };
1109
+ return {
1110
+ kind: "call",
1111
+ callee: errorString.name,
1112
+ args: expr.args,
1113
+ type: STRING,
1114
+ loc: expr.loc,
1115
+ };
603
1116
  }
604
- if (expr.kind === "call" && expr.callee === this.propertyBag.name) {
1117
+ if (expr.kind === "call" &&
1118
+ (expr.callee === this.propertyBag.name || expr.callee === "%dyn.class.readProperties")) {
605
1119
  const boxed = expr.args[0];
606
1120
  if (boxed?.kind === "dynFrom" && isDynTypedRefType(boxed.value.type)) {
607
- const helper = this.typedPropertyBag(lowerer, boxed.value.type, expr.loc);
1121
+ const helper = this.typedPropertyBag(lowerer, boxed.value.type, expr.loc, expr.callee === "%dyn.class.readProperties");
608
1122
  if (helper) {
609
1123
  changed = true;
610
1124
  return { ...expr, callee: helper.name, args: [boxed.value] };
@@ -614,71 +1128,191 @@ export class ClassDynamicDispatch {
614
1128
  if (expr.kind === "libCall" && expr.fn === "bytes.construct") {
615
1129
  if (!this.constructDispatch) {
616
1130
  const loc = expr.loc;
617
- const params = [DYN, DYN, STRING].map((type, i) => ({ localId: `p.${i}`, name: `p${i}`, type }));
618
- this.constructDispatch = { name: "%dyn.class.construct", params, returnType: DYN,
619
- locals: params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })),
620
- body: [{ kind: "return", value: { ...expr, args: params.map((p) => varRef(p.localId, p.type, loc)) }, loc }], loc };
1131
+ const params = [DYN, DYN, STRING].map((type, i) => ({
1132
+ localId: `p.${i}`,
1133
+ name: `p${i}`,
1134
+ type,
1135
+ }));
1136
+ this.constructDispatch = {
1137
+ name: "%dyn.class.construct",
1138
+ params,
1139
+ returnType: DYN,
1140
+ locals: params.map((p) => ({
1141
+ id: p.localId,
1142
+ name: p.name,
1143
+ type: p.type,
1144
+ mutable: false,
1145
+ })),
1146
+ body: [
1147
+ {
1148
+ kind: "return",
1149
+ value: { ...expr, args: params.map((p) => varRef(p.localId, p.type, loc)) },
1150
+ loc,
1151
+ },
1152
+ ],
1153
+ loc,
1154
+ };
621
1155
  this.generated.add(this.constructDispatch);
622
1156
  lowerer.liftedFns.push(this.constructDispatch);
623
1157
  changed = true;
624
1158
  }
625
- return { kind: "call", callee: this.constructDispatch.name, args: expr.args, type: DYN, loc: expr.loc };
1159
+ return {
1160
+ kind: "call",
1161
+ callee: this.constructDispatch.name,
1162
+ args: expr.args,
1163
+ type: DYN,
1164
+ loc: expr.loc,
1165
+ };
626
1166
  }
627
1167
  if (expr.kind === "libCall" && expr.fn === "dyn.forInKeys") {
628
1168
  if (!this.enumeration) {
629
1169
  const loc = expr.loc;
630
1170
  const value = varRef("p.0", DYN, loc);
631
- this.enumeration = { name: "%dyn.class.forInKeys", params: [{ localId: "p.0", name: "value", type: DYN }], returnType: DYN,
1171
+ this.enumeration = {
1172
+ name: "%dyn.class.forInKeys",
1173
+ params: [{ localId: "p.0", name: "value", type: DYN }],
1174
+ returnType: DYN,
632
1175
  locals: [{ id: "p.0", name: "value", type: DYN, mutable: false }],
633
- body: [{ kind: "return", value: { ...expr, args: [value] }, loc }], loc };
1176
+ body: [{ kind: "return", value: { ...expr, args: [value] }, loc }],
1177
+ loc,
1178
+ };
634
1179
  this.generated.add(this.enumeration);
635
1180
  lowerer.liftedFns.push(this.enumeration);
636
1181
  changed = true;
637
1182
  }
638
- return { kind: "call", callee: this.enumeration.name, args: expr.args, type: DYN, loc: expr.loc };
1183
+ return {
1184
+ kind: "call",
1185
+ callee: this.enumeration.name,
1186
+ args: expr.args,
1187
+ type: DYN,
1188
+ loc: expr.loc,
1189
+ };
639
1190
  }
640
1191
  if (expr.kind === "libCall" && expr.fn === "dyn.defineProperty") {
641
1192
  const loc = expr.loc;
642
1193
  if (!this.descriptorHelper) {
643
- const params = ["target", "key", "descriptor"].map((name) => ({ localId: name, name, type: DYN }));
1194
+ const params = ["target", "key", "descriptor"].map((name) => ({
1195
+ localId: name,
1196
+ name,
1197
+ type: DYN,
1198
+ }));
644
1199
  const target = varRef("target", DYN, loc);
645
1200
  const key = varRef("key", DYN, loc);
646
1201
  const descriptor = varRef("descriptor", DYN, loc);
647
1202
  this.descriptorHelper = {
648
- name: "%dyn.class.defineProperty", params, returnType: DYN,
649
- locals: params.map((param) => ({ id: param.localId, name: param.name, type: DYN, mutable: false })),
1203
+ name: "%dyn.class.defineProperty",
1204
+ params,
1205
+ returnType: DYN,
1206
+ locals: params.map((param) => ({
1207
+ id: param.localId,
1208
+ name: param.name,
1209
+ type: DYN,
1210
+ mutable: false,
1211
+ })),
650
1212
  body: [
651
- { kind: "if", cond: { kind: "dynTest", test: "symbol", value: key, type: BOOL, loc }, then: [
652
- { kind: "exprStmt", expr: { ...expr, args: [{ kind: "call", callee: this.propertyBag.name, args: [target], type: DYN, loc }, key, descriptor] }, loc },
1213
+ {
1214
+ kind: "if",
1215
+ cond: { kind: "dynTest", test: "symbol", value: key, type: BOOL, loc },
1216
+ then: [
1217
+ {
1218
+ kind: "exprStmt",
1219
+ expr: {
1220
+ ...expr,
1221
+ args: [
1222
+ {
1223
+ kind: "call",
1224
+ callee: this.propertyBag.name,
1225
+ args: [target],
1226
+ type: DYN,
1227
+ loc,
1228
+ },
1229
+ key,
1230
+ descriptor,
1231
+ ],
1232
+ },
1233
+ loc,
1234
+ },
653
1235
  { kind: "return", value: target, loc },
654
- ], else_: null, loc },
1236
+ ],
1237
+ else_: null,
1238
+ loc,
1239
+ },
655
1240
  { kind: "return", value: { ...expr, args: [target, key, descriptor] }, loc },
656
- ], loc,
1241
+ ],
1242
+ loc,
657
1243
  };
658
1244
  this.generated.add(this.descriptorHelper);
659
1245
  lowerer.liftedFns.push(this.descriptorHelper);
660
1246
  changed = true;
661
1247
  }
662
- return { kind: "call", callee: this.descriptorHelper.name, args: expr.args, type: DYN, loc };
1248
+ return {
1249
+ kind: "call",
1250
+ callee: this.descriptorHelper.name,
1251
+ args: expr.args,
1252
+ type: DYN,
1253
+ loc,
1254
+ };
663
1255
  }
664
1256
  if (expr.kind === "dynKeyGet" && expr.value.kind === "dynObjLit")
665
1257
  return expr;
666
1258
  const reflectRead = expr.kind === "libCall" && expr.fn === "dyn.reflectGet" ? expr : null;
667
1259
  const reflectWrite = expr.kind === "libCall" && expr.fn === "dyn.reflectSet" ? expr : null;
668
1260
  const reflect = !!reflectRead || !!reflectWrite;
669
- const computedRead = reflectRead ? { kind: "dynKeyGet", value: reflectRead.args[0], key: reflectRead.args[1], type: DYN, loc: expr.loc }
670
- : expr.kind === "dynKeyGet" && expr.key.kind !== "strLit" ? expr : null;
671
- const computedWrite = reflectWrite ? { ...reflectWrite, fn: "dyn.keySetComputed", args: reflectWrite.args.slice(0, 3), type: VOID }
672
- : expr.kind === "libCall" && (expr.fn === "dyn.keySetComputed" || expr.fn === "dyn.keySet" && expr.args[1]?.kind !== "strLit") ? expr : null;
673
- const computedProbe = expr.kind === "libCall" && ["dyn.hasKeyComputed", "dyn.hasOwnComputed", "dyn.propertyIsEnumerableComputed"].includes(expr.fn) ? expr : null;
1261
+ const computedRead = reflectRead
1262
+ ? {
1263
+ kind: "dynKeyGet",
1264
+ value: reflectRead.args[0],
1265
+ key: reflectRead.args[1],
1266
+ type: DYN,
1267
+ loc: expr.loc,
1268
+ }
1269
+ : expr.kind === "dynKeyGet" && expr.key.kind !== "strLit"
1270
+ ? expr
1271
+ : null;
1272
+ const computedWrite = reflectWrite
1273
+ ? {
1274
+ ...reflectWrite,
1275
+ fn: "dyn.keySetComputed",
1276
+ args: reflectWrite.args.slice(0, 3),
1277
+ type: VOID,
1278
+ }
1279
+ : expr.kind === "libCall" &&
1280
+ (expr.fn === "dyn.keySetComputed" ||
1281
+ (expr.fn === "dyn.keySet" && expr.args[1]?.kind !== "strLit"))
1282
+ ? expr
1283
+ : null;
1284
+ const computedProbe = expr.kind === "libCall" &&
1285
+ [
1286
+ "dyn.hasKeyComputed",
1287
+ "dyn.hasOwnComputed",
1288
+ "dyn.propertyIsEnumerableComputed",
1289
+ ].includes(expr.fn)
1290
+ ? expr
1291
+ : null;
674
1292
  if (computedRead || computedWrite || computedProbe) {
675
- const probe = computedProbe ? computedProbe.fn === "dyn.hasKeyComputed" ? "in" : computedProbe.fn === "dyn.hasOwnComputed" ? "own" : "enumerable" : undefined;
676
- const dynamicKey = reflect || !!computedProbe || computedWrite?.fn === "dyn.keySetComputed" || computedRead?.key.type.kind === "dyn";
1293
+ const probe = computedProbe
1294
+ ? computedProbe.fn === "dyn.hasKeyComputed"
1295
+ ? "in"
1296
+ : computedProbe.fn === "dyn.hasOwnComputed"
1297
+ ? "own"
1298
+ : "enumerable"
1299
+ : undefined;
1300
+ const dynamicKey = reflect ||
1301
+ !!computedProbe ||
1302
+ computedWrite?.fn === "dyn.keySetComputed" ||
1303
+ computedRead?.key.type.kind === "dyn";
677
1304
  const sourceKey = keyValue(computedRead?.key ?? (computedWrite ?? computedProbe).args[1]);
678
1305
  const numericKey = sourceKey.type.kind === "f64" ||
679
- sourceKey.kind === "dynFrom" && sourceKey.value.type.kind === "f64" ||
680
- sourceKey.kind === "toString" && sourceKey.operand.type.kind === "f64";
681
- const key = JSON.stringify([!!computedWrite, computedRead?.optional ?? false, dynamicKey, probe, numericKey, reflect]);
1306
+ (sourceKey.kind === "dynFrom" && sourceKey.value.type.kind === "f64") ||
1307
+ (sourceKey.kind === "toString" && sourceKey.operand.type.kind === "f64");
1308
+ const key = JSON.stringify([
1309
+ !!computedWrite,
1310
+ computedRead?.optional ?? false,
1311
+ dynamicKey,
1312
+ probe,
1313
+ numericKey,
1314
+ reflect,
1315
+ ]);
682
1316
  let dispatch = this.computed.get(key);
683
1317
  if (!dispatch) {
684
1318
  const loc = expr.loc;
@@ -689,75 +1323,314 @@ export class ClassDynamicDispatch {
689
1323
  ...(reflect ? [{ localId: "p.reflectReceiver", name: "receiver", type: DYN }] : []),
690
1324
  ];
691
1325
  const keyLocal = dynamicKey ? "key.string" : "p.key";
692
- const bag = { kind: "call", callee: this.propertyBag.name, args: [varRef("p.0", DYN, loc)], type: DYN, loc };
693
- const reflectionFallback = (target, property) => ({ kind: "libCall", fn: computedWrite ? "dyn.reflectSet" : "dyn.reflectGet",
694
- args: [target, lowerer.coerceToExpected(property, DYN), ...(computedWrite ? [varRef("p.1", DYN, loc)] : []), varRef("p.reflectReceiver", DYN, loc)], type: computedWrite ? BOOL : DYN, loc });
695
- const fallback = reflect ? reflectionFallback(bag, varRef(keyLocal, STRING, loc)) : computedProbe
696
- ? { ...computedProbe, fn: probe === "in" ? "dyn.hasKey" : probe === "own" ? "dyn.hasOwn" : "dyn.propertyIsEnumerable", args: [bag, varRef(keyLocal, STRING, loc)] }
697
- : computedRead
698
- ? { ...computedRead, value: bag, key: varRef(keyLocal, STRING, loc) }
699
- : { ...computedWrite, fn: "dyn.keySet", args: [bag, varRef(keyLocal, STRING, loc), varRef("p.1", DYN, loc)] };
1326
+ const bag = {
1327
+ kind: "call",
1328
+ callee: this.propertyBag.name,
1329
+ args: [varRef("p.0", DYN, loc)],
1330
+ type: DYN,
1331
+ loc,
1332
+ };
1333
+ const reflectionFallback = (target, property) => ({
1334
+ kind: "libCall",
1335
+ fn: computedWrite ? "dyn.reflectSet" : "dyn.reflectGet",
1336
+ args: [
1337
+ target,
1338
+ lowerer.coerceToExpected(property, DYN),
1339
+ ...(computedWrite ? [varRef("p.1", DYN, loc)] : []),
1340
+ varRef("p.reflectReceiver", DYN, loc),
1341
+ ],
1342
+ type: computedWrite ? BOOL : DYN,
1343
+ loc,
1344
+ });
1345
+ const fallback = reflect
1346
+ ? reflectionFallback(bag, varRef(keyLocal, STRING, loc))
1347
+ : computedProbe
1348
+ ? {
1349
+ ...computedProbe,
1350
+ fn: probe === "in"
1351
+ ? "dyn.hasKey"
1352
+ : probe === "own"
1353
+ ? "dyn.hasOwn"
1354
+ : "dyn.propertyIsEnumerable",
1355
+ args: [bag, varRef(keyLocal, STRING, loc)],
1356
+ }
1357
+ : computedRead
1358
+ ? { ...computedRead, value: bag, key: varRef(keyLocal, STRING, loc) }
1359
+ : {
1360
+ ...computedWrite,
1361
+ fn: "dyn.keySet",
1362
+ args: [bag, varRef(keyLocal, STRING, loc), varRef("p.1", DYN, loc)],
1363
+ };
700
1364
  const helper = {
701
- name: `%dyn.class.computed.${this.computed.size}`, params, returnType: reflect && computedWrite || computedProbe ? BOOL : computedWrite ? VOID : DYN,
702
- locals: [...params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })), ...(dynamicKey ? [{ id: keyLocal, name: "key", type: STRING, mutable: false }] : [])],
703
- body: reflect ? [{ kind: "return", value: fallback, loc }] : computedWrite
704
- ? [{ kind: "exprStmt", expr: fallback, loc }, { kind: "return", value: null, loc }]
705
- : [{ kind: "return", value: fallback, loc }], loc,
1365
+ name: `%dyn.class.computed.${this.computed.size}`,
1366
+ params,
1367
+ returnType: (reflect && computedWrite) || computedProbe ? BOOL : computedWrite ? VOID : DYN,
1368
+ locals: [
1369
+ ...params.map((p) => ({
1370
+ id: p.localId,
1371
+ name: p.name,
1372
+ type: p.type,
1373
+ mutable: false,
1374
+ })),
1375
+ ...(dynamicKey
1376
+ ? [{ id: keyLocal, name: "key", type: STRING, mutable: false }]
1377
+ : []),
1378
+ ],
1379
+ body: reflect
1380
+ ? [{ kind: "return", value: fallback, loc }]
1381
+ : computedWrite
1382
+ ? [
1383
+ { kind: "exprStmt", expr: fallback, loc },
1384
+ { kind: "return", value: null, loc },
1385
+ ]
1386
+ : [{ kind: "return", value: fallback, loc }],
1387
+ loc,
706
1388
  };
707
1389
  if (dynamicKey)
708
- helper.body.unshift({ kind: "if", cond: { kind: "dynTest", test: "symbol", value: varRef("p.key", DYN, loc), type: BOOL, loc }, then: reflect ? [
709
- { kind: "return", value: reflectionFallback(bag, varRef("p.key", DYN, loc)), loc },
710
- ] : computedProbe ? [
711
- { kind: "return", value: { ...computedProbe, args: [bag, varRef("p.key", DYN, loc)] }, loc },
712
- ] : computedRead ? [
713
- { kind: "return", value: { ...computedRead, value: bag, key: varRef("p.key", DYN, loc) }, loc },
714
- ] : [
715
- { kind: "exprStmt", expr: { ...computedWrite, args: [bag, varRef("p.key", DYN, loc), varRef("p.1", DYN, loc)] }, loc },
716
- { kind: "return", value: null, loc },
717
- ], else_: null, loc }, { kind: "if", cond: { kind: "dynTest", test: "nullish", value: varRef("p.0", DYN, loc), type: BOOL, loc }, then: [
718
- ...(reflect ? [{ kind: "return", value: reflectionFallback(varRef("p.0", DYN, loc), varRef("p.key", DYN, loc)), loc }] : computedProbe ? [{ kind: "return", value: { ...computedProbe, args: [varRef("p.0", DYN, loc), varRef("p.key", DYN, loc)] }, loc }] : computedRead ? [{ kind: "return", value: { ...computedRead, value: varRef("p.0", DYN, loc), key: varRef("p.key", DYN, loc) }, loc }] : [
719
- { kind: "exprStmt", expr: { ...computedWrite, args: [varRef("p.0", DYN, loc), varRef("p.key", DYN, loc), varRef("p.1", DYN, loc)] }, loc },
720
- { kind: "return", value: null, loc },
721
- ]),
722
- ], else_: null, loc }, { kind: "varDecl", localId: keyLocal, init: { kind: "libCall", fn: "dyn.toStringCoerce", args: [varRef("p.key", DYN, loc)], type: STRING, loc }, loc });
723
- dispatch = { write: !!computedWrite, reflect, fn: helper, classes: new Set(), keyLocal, branchIndex: dynamicKey ? 3 : 0, dynamicKey, numericKey, probe };
1390
+ helper.body.unshift({
1391
+ kind: "if",
1392
+ cond: {
1393
+ kind: "dynTest",
1394
+ test: "symbol",
1395
+ value: varRef("p.key", DYN, loc),
1396
+ type: BOOL,
1397
+ loc,
1398
+ },
1399
+ then: reflect
1400
+ ? [
1401
+ {
1402
+ kind: "return",
1403
+ value: reflectionFallback(bag, varRef("p.key", DYN, loc)),
1404
+ loc,
1405
+ },
1406
+ ]
1407
+ : computedProbe
1408
+ ? [
1409
+ {
1410
+ kind: "return",
1411
+ value: { ...computedProbe, args: [bag, varRef("p.key", DYN, loc)] },
1412
+ loc,
1413
+ },
1414
+ ]
1415
+ : computedRead
1416
+ ? [
1417
+ {
1418
+ kind: "return",
1419
+ value: {
1420
+ ...computedRead,
1421
+ value: bag,
1422
+ key: varRef("p.key", DYN, loc),
1423
+ },
1424
+ loc,
1425
+ },
1426
+ ]
1427
+ : [
1428
+ {
1429
+ kind: "exprStmt",
1430
+ expr: {
1431
+ ...computedWrite,
1432
+ args: [bag, varRef("p.key", DYN, loc), varRef("p.1", DYN, loc)],
1433
+ },
1434
+ loc,
1435
+ },
1436
+ { kind: "return", value: null, loc },
1437
+ ],
1438
+ else_: null,
1439
+ loc,
1440
+ }, {
1441
+ kind: "if",
1442
+ cond: {
1443
+ kind: "dynTest",
1444
+ test: "nullish",
1445
+ value: varRef("p.0", DYN, loc),
1446
+ type: BOOL,
1447
+ loc,
1448
+ },
1449
+ then: [
1450
+ ...(reflect
1451
+ ? [
1452
+ {
1453
+ kind: "return",
1454
+ value: reflectionFallback(varRef("p.0", DYN, loc), varRef("p.key", DYN, loc)),
1455
+ loc,
1456
+ },
1457
+ ]
1458
+ : computedProbe
1459
+ ? [
1460
+ {
1461
+ kind: "return",
1462
+ value: {
1463
+ ...computedProbe,
1464
+ args: [varRef("p.0", DYN, loc), varRef("p.key", DYN, loc)],
1465
+ },
1466
+ loc,
1467
+ },
1468
+ ]
1469
+ : computedRead
1470
+ ? [
1471
+ {
1472
+ kind: "return",
1473
+ value: {
1474
+ ...computedRead,
1475
+ value: varRef("p.0", DYN, loc),
1476
+ key: varRef("p.key", DYN, loc),
1477
+ },
1478
+ loc,
1479
+ },
1480
+ ]
1481
+ : [
1482
+ {
1483
+ kind: "exprStmt",
1484
+ expr: {
1485
+ ...computedWrite,
1486
+ args: [
1487
+ varRef("p.0", DYN, loc),
1488
+ varRef("p.key", DYN, loc),
1489
+ varRef("p.1", DYN, loc),
1490
+ ],
1491
+ },
1492
+ loc,
1493
+ },
1494
+ { kind: "return", value: null, loc },
1495
+ ]),
1496
+ ],
1497
+ else_: null,
1498
+ loc,
1499
+ }, {
1500
+ kind: "varDecl",
1501
+ localId: keyLocal,
1502
+ init: {
1503
+ kind: "libCall",
1504
+ fn: "dyn.toStringCoerce",
1505
+ args: [varRef("p.key", DYN, loc)],
1506
+ type: STRING,
1507
+ loc,
1508
+ },
1509
+ loc,
1510
+ });
1511
+ dispatch = {
1512
+ write: !!computedWrite,
1513
+ reflect,
1514
+ fn: helper,
1515
+ classes: new Set(),
1516
+ keyLocal,
1517
+ branchIndex: dynamicKey ? 3 : 0,
1518
+ dynamicKey,
1519
+ numericKey,
1520
+ probe,
1521
+ };
724
1522
  this.computed.set(key, dispatch);
725
1523
  this.generated.add(helper);
726
1524
  lowerer.liftedFns.push(helper);
727
1525
  changed = true;
728
1526
  }
729
- return { kind: "call", callee: dispatch.fn.name, args: reflect ? (reflectRead ?? reflectWrite).args : computedRead ? [computedRead.value, computedRead.key] : (computedWrite ?? computedProbe).args, type: dispatch.fn.returnType, loc: expr.loc };
1527
+ return {
1528
+ kind: "call",
1529
+ callee: dispatch.fn.name,
1530
+ args: reflect
1531
+ ? (reflectRead ?? reflectWrite).args
1532
+ : computedRead
1533
+ ? [computedRead.value, computedRead.key]
1534
+ : (computedWrite ?? computedProbe).args,
1535
+ type: dispatch.fn.returnType,
1536
+ loc: expr.loc,
1537
+ };
730
1538
  }
731
1539
  const read = expr.kind === "dynKeyGet" && expr.key.kind === "strLit" ? expr : null;
732
- const write = expr.kind === "libCall" && expr.fn === "dyn.keySet" && expr.args[1]?.kind === "strLit" ? expr : null;
733
- const name = read?.key.kind === "strLit" ? read.key.value : write?.args[1]?.kind === "strLit" ? write.args[1].value : null;
1540
+ const write = expr.kind === "libCall" && expr.fn === "dyn.keySet" && expr.args[1]?.kind === "strLit"
1541
+ ? expr
1542
+ : null;
1543
+ const name = read?.key.kind === "strLit"
1544
+ ? read.key.value
1545
+ : write?.args[1]?.kind === "strLit"
1546
+ ? write.args[1].value
1547
+ : null;
734
1548
  if (name !== null) {
735
1549
  const key = JSON.stringify([name, !!write, read?.optional ?? false]);
736
1550
  let dispatch = this.properties.get(key);
737
1551
  if (!dispatch) {
738
1552
  const loc = expr.loc;
739
- const params = (write ? [0, 1] : [0]).map((i) => ({ localId: `p.${i}`, name: `p${i}`, type: DYN }));
740
- const instanceBag = { kind: "call", callee: this.propertyBag.name, args: [varRef("p.0", DYN, loc)], type: DYN, loc };
1553
+ const params = (write ? [0, 1] : [0]).map((i) => ({
1554
+ localId: `p.${i}`,
1555
+ name: `p${i}`,
1556
+ type: DYN,
1557
+ }));
1558
+ const instanceBag = {
1559
+ kind: "call",
1560
+ callee: this.propertyBag.name,
1561
+ args: [varRef("p.0", DYN, loc)],
1562
+ type: DYN,
1563
+ loc,
1564
+ };
741
1565
  const bag = read && !["name", "length", "apply"].includes(name)
742
- ? { kind: "call", callee: this.constructorPropertyBag(lowerer, loc).name, args: [instanceBag], type: DYN, loc }
1566
+ ? {
1567
+ kind: "call",
1568
+ callee: this.constructorPropertyBag(lowerer, loc).name,
1569
+ args: [instanceBag],
1570
+ type: DYN,
1571
+ loc,
1572
+ }
743
1573
  : instanceBag;
744
1574
  const fallback = read
745
- ? { kind: "ternary", cond: { kind: "dynScalarEq", left: bag, right: varRef("p.0", DYN, loc), type: BOOL, loc },
746
- then: { ...read, value: bag }, else_: { kind: "libCall", fn: "dyn.bagGet",
747
- args: [bag, read.key, varRef("p.0", DYN, loc)], type: DYN, loc }, type: DYN, loc }
1575
+ ? {
1576
+ kind: "ternary",
1577
+ cond: {
1578
+ kind: "dynScalarEq",
1579
+ left: bag,
1580
+ right: varRef("p.0", DYN, loc),
1581
+ type: BOOL,
1582
+ loc,
1583
+ },
1584
+ then: { ...read, value: bag },
1585
+ else_: {
1586
+ kind: "libCall",
1587
+ fn: "dyn.bagGet",
1588
+ args: [bag, read.key, varRef("p.0", DYN, loc)],
1589
+ type: DYN,
1590
+ loc,
1591
+ },
1592
+ type: DYN,
1593
+ loc,
1594
+ }
748
1595
  : { ...write, args: [bag, write.args[1], varRef("p.1", DYN, loc)] };
749
1596
  const helper = {
750
- name: `%dyn.class.property.${this.properties.size}`, params, returnType: write ? VOID : DYN,
751
- locals: params.map((p) => ({ id: p.localId, name: p.name, type: DYN, mutable: false })),
1597
+ name: `%dyn.class.property.${this.properties.size}`,
1598
+ params,
1599
+ returnType: write ? VOID : DYN,
1600
+ locals: params.map((p) => ({
1601
+ id: p.localId,
1602
+ name: p.name,
1603
+ type: DYN,
1604
+ mutable: false,
1605
+ })),
752
1606
  body: write
753
- ? [{ kind: "exprStmt", expr: fallback, loc }, { kind: "return", value: null, loc }]
754
- : [{ kind: "return", value: fallback, loc }], loc,
1607
+ ? [
1608
+ { kind: "exprStmt", expr: fallback, loc },
1609
+ { kind: "return", value: null, loc },
1610
+ ]
1611
+ : [{ kind: "return", value: fallback, loc }],
1612
+ loc,
755
1613
  };
756
1614
  if (!write && name === "toString" && lowerer.classes.has("%Error")) {
757
1615
  const value = varRef("p.0", DYN, loc);
758
- helper.body.unshift({ kind: "if", cond: { kind: "dynTest", test: "error", value, type: BOOL, loc }, then: [
759
- { kind: "return", value: errorToStringMethod(lowerer, { kind: "dynCheck", value, type: { kind: "object", className: "%Error" }, loc }), loc },
760
- ], else_: null, loc });
1616
+ helper.body.unshift({
1617
+ kind: "if",
1618
+ cond: { kind: "dynTest", test: "error", value, type: BOOL, loc },
1619
+ then: [
1620
+ {
1621
+ kind: "return",
1622
+ value: errorToStringMethod(lowerer, {
1623
+ kind: "dynCheck",
1624
+ value,
1625
+ type: { kind: "object", className: "%Error" },
1626
+ loc,
1627
+ }),
1628
+ loc,
1629
+ },
1630
+ ],
1631
+ else_: null,
1632
+ loc,
1633
+ });
761
1634
  }
762
1635
  dispatch = { name, write: !!write, fn: helper, classes: new Set() };
763
1636
  this.properties.set(key, dispatch);
@@ -765,47 +1638,133 @@ export class ClassDynamicDispatch {
765
1638
  lowerer.liftedFns.push(helper);
766
1639
  changed = true;
767
1640
  }
768
- return { kind: "call", callee: dispatch.fn.name, args: read ? [read.value] : [write.args[0], write.args[2]], type: dispatch.fn.returnType, loc: expr.loc };
1641
+ return {
1642
+ kind: "call",
1643
+ callee: dispatch.fn.name,
1644
+ args: read ? [read.value] : [write.args[0], write.args[2]],
1645
+ type: dispatch.fn.returnType,
1646
+ loc: expr.loc,
1647
+ };
769
1648
  }
770
- const iterator = expr.kind === "libCall" && (expr.fn === "dyn.iterator" || expr.fn === "dyn.arrayFromIterator") ? expr : null;
1649
+ const iterator = expr.kind === "libCall" &&
1650
+ (expr.fn === "dyn.iterator" || expr.fn === "dyn.arrayFromIterator")
1651
+ ? expr
1652
+ : null;
771
1653
  const invoke = iterator
772
- ? { kind: "dynInvoke", recv: iterator.args[0], method: "sym:iterator", calleeName: "value[Symbol.iterator]", args: [], type: DYN, loc: iterator.loc }
773
- : expr.kind === "dynInvoke" ? expr : null;
774
- const staticCandidates = invoke && [...this.boxedConstructors].some((name) => {
775
- const info = lowerer.classes.get(name);
776
- return info && findStaticOn(lowerer, info, invoke.method)?.method;
777
- });
778
- if (!invoke || candidates(invoke.method).length === 0 && !staticCandidates && !(invoke.method === "toString" && lowerer.classes.has("%Error")))
1654
+ ? {
1655
+ kind: "dynInvoke",
1656
+ recv: iterator.args[0],
1657
+ method: "sym:iterator",
1658
+ calleeName: "value[Symbol.iterator]",
1659
+ args: [],
1660
+ type: DYN,
1661
+ loc: iterator.loc,
1662
+ }
1663
+ : expr.kind === "dynInvoke"
1664
+ ? expr
1665
+ : null;
1666
+ const staticCandidates = invoke &&
1667
+ [...this.boxedConstructors].some((name) => {
1668
+ const info = lowerer.classes.get(name);
1669
+ return info && findStaticOn(lowerer, info, invoke.method)?.method;
1670
+ });
1671
+ if (!invoke ||
1672
+ (candidates(invoke.method).length === 0 &&
1673
+ !staticCandidates &&
1674
+ !(invoke.method === "toString" && lowerer.classes.has("%Error"))))
779
1675
  return expr;
780
- const key = JSON.stringify([invoke.method, invoke.args.length, iterator?.fn, iterator?.args[1]]);
1676
+ const key = JSON.stringify([
1677
+ invoke.method,
1678
+ invoke.args.length,
1679
+ iterator?.fn,
1680
+ iterator?.args[1],
1681
+ ]);
781
1682
  let dispatch = this.dispatches.get(key);
782
1683
  if (!dispatch) {
783
- const params = [invoke.recv, ...invoke.args].map((_, i) => ({ localId: `p.${i}`, name: `p${i}`, type: DYN }));
1684
+ const params = [invoke.recv, ...invoke.args].map((_, i) => ({
1685
+ localId: `p.${i}`,
1686
+ name: `p${i}`,
1687
+ type: DYN,
1688
+ }));
784
1689
  params.splice(1, 0, { localId: "p.callback", name: "callback", type: DYN });
785
- iterator?.args.slice(1).forEach((argument, i) => params.push({ localId: `p.iterator.${i}`, name: `iterator${i}`, type: argument.type }));
1690
+ iterator?.args.slice(1).forEach((argument, i) => params.push({
1691
+ localId: `p.iterator.${i}`,
1692
+ name: `iterator${i}`,
1693
+ type: argument.type,
1694
+ }));
786
1695
  params.push({ localId: "p.calleeName", name: "calleeName", type: STRING });
787
1696
  const callback = {
788
- name: `%dyn.class.callback.${this.dispatches.size}`, params: [params[0]], returnType: DYN,
1697
+ name: `%dyn.class.callback.${this.dispatches.size}`,
1698
+ params: [params[0]],
1699
+ returnType: DYN,
789
1700
  locals: [{ id: "p.0", name: "receiver", type: DYN, mutable: false }],
790
- body: [{ kind: "return", value: dynUndefinedExpr(expr.loc), loc: expr.loc }], loc: expr.loc,
1701
+ body: [{ kind: "return", value: dynUndefinedExpr(expr.loc), loc: expr.loc }],
1702
+ loc: expr.loc,
791
1703
  };
792
1704
  const helper = {
793
- name: `%dyn.class.call.${this.dispatches.size}`, params, returnType: DYN,
794
- locals: params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })),
795
- body: [{ kind: "return", value: iterator
796
- ? { ...iterator, args: [varRef("p.0", DYN, expr.loc), ...iterator.args.slice(1).map((argument, i) => varRef(`p.iterator.${i}`, argument.type, expr.loc))] }
797
- : { ...invoke, calleeNameValue: varRef("p.calleeName", STRING, expr.loc), recv: varRef("p.0", DYN, expr.loc), args: invoke.args.map((_, i) => varRef(`p.${i + 1}`, DYN, expr.loc)) }, loc: expr.loc }],
1705
+ name: `%dyn.class.call.${this.dispatches.size}`,
1706
+ params,
1707
+ returnType: DYN,
1708
+ locals: params.map((p) => ({
1709
+ id: p.localId,
1710
+ name: p.name,
1711
+ type: p.type,
1712
+ mutable: false,
1713
+ })),
1714
+ body: [
1715
+ {
1716
+ kind: "return",
1717
+ value: iterator
1718
+ ? {
1719
+ ...iterator,
1720
+ args: [
1721
+ varRef("p.0", DYN, expr.loc),
1722
+ ...iterator.args
1723
+ .slice(1)
1724
+ .map((argument, i) => varRef(`p.iterator.${i}`, argument.type, expr.loc)),
1725
+ ],
1726
+ }
1727
+ : {
1728
+ ...invoke,
1729
+ calleeNameValue: varRef("p.calleeName", STRING, expr.loc),
1730
+ recv: varRef("p.0", DYN, expr.loc),
1731
+ args: invoke.args.map((_, i) => varRef(`p.${i + 1}`, DYN, expr.loc)),
1732
+ },
1733
+ loc: expr.loc,
1734
+ },
1735
+ ],
798
1736
  loc: expr.loc,
799
1737
  };
800
1738
  if (invoke.method === "toString" && lowerer.classes.has("%Error")) {
801
1739
  const loc = expr.loc;
802
1740
  const value = varRef("p.0", DYN, loc);
803
- helper.body.unshift({ kind: "if", cond: { kind: "dynTest", test: "error", value, type: BOOL, loc }, then: [
804
- { kind: "return", value: {
805
- kind: "dynCall", callee: errorToStringMethod(lowerer, { kind: "dynCheck", value, type: { kind: "object", className: "%Error" }, loc }),
806
- receiver: value, calleeName: invoke.calleeName, calleeNameValue: varRef("p.calleeName", STRING, loc), args: invoke.args.map((_, i) => varRef(`p.${i + 1}`, DYN, loc)), type: DYN, loc,
807
- }, loc },
808
- ], else_: null, loc });
1741
+ helper.body.unshift({
1742
+ kind: "if",
1743
+ cond: { kind: "dynTest", test: "error", value, type: BOOL, loc },
1744
+ then: [
1745
+ {
1746
+ kind: "return",
1747
+ value: {
1748
+ kind: "dynCall",
1749
+ callee: errorToStringMethod(lowerer, {
1750
+ kind: "dynCheck",
1751
+ value,
1752
+ type: { kind: "object", className: "%Error" },
1753
+ loc,
1754
+ }),
1755
+ receiver: value,
1756
+ calleeName: invoke.calleeName,
1757
+ calleeNameValue: varRef("p.calleeName", STRING, loc),
1758
+ args: invoke.args.map((_, i) => varRef(`p.${i + 1}`, DYN, loc)),
1759
+ type: DYN,
1760
+ loc,
1761
+ },
1762
+ loc,
1763
+ },
1764
+ ],
1765
+ else_: null,
1766
+ loc,
1767
+ });
809
1768
  }
810
1769
  dispatch = { source: invoke, fn: helper, callback, classes: new Set() };
811
1770
  this.dispatches.set(key, dispatch);
@@ -815,13 +1774,44 @@ export class ClassDynamicDispatch {
815
1774
  changed = true;
816
1775
  }
817
1776
  // Resolve an own callback before argument effects can replace it.
818
- const local = { id: `%dispatch.receiver.${fn.locals.length}`, name: "receiver", type: DYN, mutable: false };
1777
+ const local = {
1778
+ id: `%dispatch.receiver.${fn.locals.length}`,
1779
+ name: "receiver",
1780
+ type: DYN,
1781
+ mutable: false,
1782
+ };
819
1783
  fn.locals.push(local);
820
1784
  const receiver = varRef(local.id, DYN, expr.loc);
821
- return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: invoke.recv, loc: expr.loc }], result: {
822
- kind: "call", callee: dispatch.fn.name, args: [receiver,
823
- { kind: "call", callee: dispatch.callback.name, args: [receiver], type: DYN, loc: expr.loc }, ...invoke.args, ...(iterator?.args.slice(1) ?? []), invoke.calleeNameValue ?? { kind: "strLit", value: invoke.calleeName, type: STRING, loc: expr.loc }], type: DYN, loc: expr.loc,
824
- }, type: DYN, loc: expr.loc };
1785
+ return {
1786
+ kind: "seqExpr",
1787
+ stmts: [{ kind: "varDecl", localId: local.id, init: invoke.recv, loc: expr.loc }],
1788
+ result: {
1789
+ kind: "call",
1790
+ callee: dispatch.fn.name,
1791
+ args: [
1792
+ receiver,
1793
+ {
1794
+ kind: "call",
1795
+ callee: dispatch.callback.name,
1796
+ args: [receiver],
1797
+ type: DYN,
1798
+ loc: expr.loc,
1799
+ },
1800
+ ...invoke.args,
1801
+ ...(iterator?.args.slice(1) ?? []),
1802
+ invoke.calleeNameValue ?? {
1803
+ kind: "strLit",
1804
+ value: invoke.calleeName,
1805
+ type: STRING,
1806
+ loc: expr.loc,
1807
+ },
1808
+ ],
1809
+ type: DYN,
1810
+ loc: expr.loc,
1811
+ },
1812
+ type: DYN,
1813
+ loc: expr.loc,
1814
+ };
825
1815
  },
826
1816
  });
827
1817
  }
@@ -834,12 +1824,33 @@ export class ClassDynamicDispatch {
834
1824
  const value = varRef("value", DYN, loc);
835
1825
  const sourceType = { kind: "object", className: source };
836
1826
  const object = { kind: "dynCheck", value, type: sourceType, loc };
837
- cast.fn.body.unshift({ kind: "if", cond: { kind: "libCall", fn: "dyn.typedRefIs", args: [value,
838
- { kind: "strLit", value: typeKey(sourceType), type: STRING, loc }], type: BOOL, loc }, then: [
839
- { kind: "if", cond: { kind: "instanceOf", value: object, className: target, type: BOOL, loc }, then: [
840
- { kind: "return", value: { kind: "downcast", value: object, type: cast.fn.returnType, loc }, loc },
841
- ], else_: null, loc },
842
- ], else_: null, loc });
1827
+ cast.fn.body.unshift({
1828
+ kind: "if",
1829
+ cond: {
1830
+ kind: "libCall",
1831
+ fn: "dyn.typedRefIs",
1832
+ args: [value, { kind: "strLit", value: typeKey(sourceType), type: STRING, loc }],
1833
+ type: BOOL,
1834
+ loc,
1835
+ },
1836
+ then: [
1837
+ {
1838
+ kind: "if",
1839
+ cond: { kind: "instanceOf", value: object, className: target, type: BOOL, loc },
1840
+ then: [
1841
+ {
1842
+ kind: "return",
1843
+ value: { kind: "downcast", value: object, type: cast.fn.returnType, loc },
1844
+ loc,
1845
+ },
1846
+ ],
1847
+ else_: null,
1848
+ loc,
1849
+ },
1850
+ ],
1851
+ else_: null,
1852
+ loc,
1853
+ });
843
1854
  changed = true;
844
1855
  }
845
1856
  }
@@ -856,15 +1867,72 @@ export class ClassDynamicDispatch {
856
1867
  dispatch.classes.add(key);
857
1868
  const loc = dispatch.source.loc;
858
1869
  const receiver = varRef("p.0", DYN, loc);
859
- const condition = { kind: "libCall", fn: "dyn.classIs", args: [receiver,
860
- { kind: "strLit", value: typeKey({ kind: "classval", className: name }), type: STRING, loc }], type: BOOL, loc };
861
- dispatch.callback.body.unshift({ kind: "if", cond: condition, then: [{ kind: "return", value: {
862
- kind: "dynObjLit", fields: [{ key: { kind: "strLit", value: "value", type: STRING, loc }, value: lowerer.coerceToExpected(method, DYN) }], type: DYN, loc,
863
- }, loc }], else_: null, loc });
864
- dispatch.fn.body.unshift({ kind: "if", cond: condition, then: [{ kind: "return", value: {
865
- kind: "dynCall", callee: { kind: "dynKeyGet", value: varRef("p.callback", DYN, loc), key: { kind: "strLit", value: "value", type: STRING, loc }, type: DYN, loc },
866
- receiver, calleeName: dispatch.source.calleeName, calleeNameValue: varRef("p.calleeName", STRING, loc), args: dispatch.source.args.map((_, i) => varRef(`p.${i + 1}`, DYN, loc)), type: DYN, loc,
867
- }, loc }], else_: null, loc });
1870
+ const condition = {
1871
+ kind: "libCall",
1872
+ fn: "dyn.classIs",
1873
+ args: [
1874
+ receiver,
1875
+ {
1876
+ kind: "strLit",
1877
+ value: typeKey({ kind: "classval", className: name }),
1878
+ type: STRING,
1879
+ loc,
1880
+ },
1881
+ ],
1882
+ type: BOOL,
1883
+ loc,
1884
+ };
1885
+ dispatch.callback.body.unshift({
1886
+ kind: "if",
1887
+ cond: condition,
1888
+ then: [
1889
+ {
1890
+ kind: "return",
1891
+ value: {
1892
+ kind: "dynObjLit",
1893
+ fields: [
1894
+ {
1895
+ key: { kind: "strLit", value: "value", type: STRING, loc },
1896
+ value: lowerer.coerceToExpected(method, DYN),
1897
+ },
1898
+ ],
1899
+ type: DYN,
1900
+ loc,
1901
+ },
1902
+ loc,
1903
+ },
1904
+ ],
1905
+ else_: null,
1906
+ loc,
1907
+ });
1908
+ dispatch.fn.body.unshift({
1909
+ kind: "if",
1910
+ cond: condition,
1911
+ then: [
1912
+ {
1913
+ kind: "return",
1914
+ value: {
1915
+ kind: "dynCall",
1916
+ callee: {
1917
+ kind: "dynKeyGet",
1918
+ value: varRef("p.callback", DYN, loc),
1919
+ key: { kind: "strLit", value: "value", type: STRING, loc },
1920
+ type: DYN,
1921
+ loc,
1922
+ },
1923
+ receiver,
1924
+ calleeName: dispatch.source.calleeName,
1925
+ calleeNameValue: varRef("p.calleeName", STRING, loc),
1926
+ args: dispatch.source.args.map((_, i) => varRef(`p.${i + 1}`, DYN, loc)),
1927
+ type: DYN,
1928
+ loc,
1929
+ },
1930
+ loc,
1931
+ },
1932
+ ],
1933
+ else_: null,
1934
+ loc,
1935
+ });
868
1936
  changed = true;
869
1937
  }
870
1938
  for (const plan of this.propertyReceivers(lowerer, true)) {
@@ -879,11 +1947,60 @@ export class ClassDynamicDispatch {
879
1947
  const prototypeMethod = lowerer.prototypeMethodAccesses.has(dispatch.source.method);
880
1948
  if (prototypeMethod)
881
1949
  classPrototypeData(lowerer, info, loc);
882
- const bag = { kind: "call", callee: this.propertyBag.name, args: [value], type: DYN, loc };
883
- dispatch.callback.body.unshift({ kind: "if", cond: condition, then: [{ kind: "return", value: { kind: "ternary", cond: prototypeMethod ? { kind: "boolLit", value: true, type: BOOL, loc } : { kind: "libCall", fn: "dyn.hasKey", args: [bag,
884
- { kind: "strLit", value: dispatch.source.method, type: STRING, loc }], type: BOOL, loc }, then: { kind: "dynObjLit", fields: [
885
- { key: { kind: "strLit", value: "value", type: STRING, loc }, value: { kind: "dynKeyGet", value: bag, key: { kind: "strLit", value: dispatch.source.method, type: STRING, loc }, type: DYN, loc } },
886
- ], type: DYN, loc }, else_: dynUndefinedExpr(loc), type: DYN, loc }, loc }], else_: null, loc });
1950
+ const bag = {
1951
+ kind: "call",
1952
+ callee: this.propertyBag.name,
1953
+ args: [value],
1954
+ type: DYN,
1955
+ loc,
1956
+ };
1957
+ dispatch.callback.body.unshift({
1958
+ kind: "if",
1959
+ cond: condition,
1960
+ then: [
1961
+ {
1962
+ kind: "return",
1963
+ value: {
1964
+ kind: "ternary",
1965
+ cond: prototypeMethod
1966
+ ? { kind: "boolLit", value: true, type: BOOL, loc }
1967
+ : {
1968
+ kind: "libCall",
1969
+ fn: "dyn.hasKey",
1970
+ args: [
1971
+ bag,
1972
+ { kind: "strLit", value: dispatch.source.method, type: STRING, loc },
1973
+ ],
1974
+ type: BOOL,
1975
+ loc,
1976
+ },
1977
+ then: {
1978
+ kind: "dynObjLit",
1979
+ fields: [
1980
+ {
1981
+ key: { kind: "strLit", value: "value", type: STRING, loc },
1982
+ value: {
1983
+ kind: "dynKeyGet",
1984
+ value: bag,
1985
+ key: { kind: "strLit", value: dispatch.source.method, type: STRING, loc },
1986
+ type: DYN,
1987
+ loc,
1988
+ },
1989
+ },
1990
+ ],
1991
+ type: DYN,
1992
+ loc,
1993
+ },
1994
+ else_: dynUndefinedExpr(loc),
1995
+ type: DYN,
1996
+ loc,
1997
+ },
1998
+ loc,
1999
+ },
2000
+ ],
2001
+ else_: null,
2002
+ loc,
2003
+ });
887
2004
  }
888
2005
  const before = lowerer.diags.length;
889
2006
  let branch;
@@ -899,7 +2016,11 @@ export class ClassDynamicDispatch {
899
2016
  branch = [fence];
900
2017
  }
901
2018
  dispatch.fn.body.unshift({
902
- kind: "if", cond: condition, then: branch, else_: null, loc,
2019
+ kind: "if",
2020
+ cond: condition,
2021
+ then: branch,
2022
+ else_: null,
2023
+ loc,
903
2024
  });
904
2025
  changed = true;
905
2026
  }
@@ -911,30 +2032,52 @@ export class ClassDynamicDispatch {
911
2032
  const found = info && findStaticOn(lowerer, info, dispatch.name);
912
2033
  const field = found?.field;
913
2034
  const key = `constructor:${name}`;
914
- if (!info || dispatch.name.startsWith("#") || dispatch.classes.has(key) || !found && dispatch.name !== "prototype")
2035
+ if (!info ||
2036
+ dispatch.name.startsWith("#") ||
2037
+ dispatch.classes.has(key) ||
2038
+ (!found && dispatch.name !== "prototype"))
915
2039
  continue;
916
- const method = found?.method && reflectedClassStaticMethodValue(lowerer, found.declarer, dispatch.name);
917
- if (found && !field && !method || findGenericStaticOn(lowerer, info, dispatch.name) && !method)
2040
+ const method = found?.method &&
2041
+ reflectedClassStaticMethodValue(lowerer, found.declarer, dispatch.name);
2042
+ if ((found && !field && !method) ||
2043
+ (findGenericStaticOn(lowerer, info, dispatch.name) && !method))
918
2044
  continue;
919
2045
  const loc = dispatch.fn.loc;
920
- const result = field ? varRef(field.globalId, field.type, loc) : method ??
921
- (dispatch.name === "prototype" ? classPrototypeData(lowerer, info, loc) : null) ??
922
- dynUndefinedExpr(loc);
2046
+ const result = field
2047
+ ? varRef(field.globalId, field.type, loc)
2048
+ : (method ??
2049
+ (dispatch.name === "prototype" ? classPrototypeData(lowerer, info, loc) : null) ??
2050
+ dynUndefinedExpr(loc));
923
2051
  if (dispatch.name === "name" || dispatch.name === "length" || dispatch.name === "apply")
924
2052
  continue;
925
2053
  dispatch.classes.add(key);
926
2054
  const value = varRef("p.0", DYN, loc);
927
2055
  const type = { kind: "classval", className: name };
928
- dispatch.fn.body.unshift({ kind: "if", cond: { kind: "libCall", fn: "dyn.classIs", args: [value,
929
- { kind: "strLit", value: typeKey(type), type: STRING, loc }], type: BOOL, loc }, then: [
930
- { kind: "return", value: lowerer.coerceToExpected(result, DYN), loc },
931
- ], else_: null, loc });
2056
+ dispatch.fn.body.unshift({
2057
+ kind: "if",
2058
+ cond: {
2059
+ kind: "libCall",
2060
+ fn: "dyn.classIs",
2061
+ args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
2062
+ type: BOOL,
2063
+ loc,
2064
+ },
2065
+ then: [{ kind: "return", value: lowerer.coerceToExpected(result, DYN), loc }],
2066
+ else_: null,
2067
+ loc,
2068
+ });
932
2069
  changed = true;
933
2070
  }
934
2071
  for (const plan of this.propertyReceivers(lowerer, true)) {
935
2072
  const { info } = plan;
936
2073
  if (!isClassOwnEnumerableFieldName(dispatch.name) ||
937
- !(info.builtinStream !== undefined && streamProperty(dispatch.name)) && !findMethodOn(lowerer, info, dispatch.name) && !findGenericMethodOn(lowerer, info, dispatch.name) && dispatch.name !== "constructor" && !info.fields.has(dispatch.name) && !findMethodOn(lowerer, info, `get:${dispatch.name}`) && !findMethodOn(lowerer, info, `set:${dispatch.name}`))
2074
+ (!(info.builtinStream !== undefined && streamProperty(dispatch.name)) &&
2075
+ !findMethodOn(lowerer, info, dispatch.name) &&
2076
+ !findGenericMethodOn(lowerer, info, dispatch.name) &&
2077
+ dispatch.name !== "constructor" &&
2078
+ !info.fields.has(dispatch.name) &&
2079
+ !findMethodOn(lowerer, info, `get:${dispatch.name}`) &&
2080
+ !findMethodOn(lowerer, info, `set:${dispatch.name}`)))
938
2081
  continue;
939
2082
  if (dispatch.classes.has(plan.key))
940
2083
  continue;
@@ -955,7 +2098,11 @@ export class ClassDynamicDispatch {
955
2098
  branch = [fence];
956
2099
  }
957
2100
  dispatch.fn.body.unshift({
958
- kind: "if", cond: condition, then: branch, else_: null, loc,
2101
+ kind: "if",
2102
+ cond: condition,
2103
+ then: branch,
2104
+ else_: null,
2105
+ loc,
959
2106
  });
960
2107
  changed = true;
961
2108
  }
@@ -973,11 +2120,27 @@ export class ClassDynamicDispatch {
973
2120
  const helperKey = JSON.stringify([dispatch.fn.name, info.def.name]);
974
2121
  const existingHelper = this.computedClassHelpers.get(helperKey);
975
2122
  const callHelper = (helper) => {
976
- const call = { kind: "call", callee: helper.name,
977
- args: helper.params.map((param) => param.localId === "p.receiver" ? selected.receiver : varRef(param.localId, param.type, loc)), type: helper.returnType, loc };
978
- return { kind: "if", cond: selected.condition, then: dispatch.write && !dispatch.reflect
979
- ? [{ kind: "exprStmt", expr: call, loc }, { kind: "return", value: null, loc }]
980
- : [{ kind: "return", value: call, loc }], else_: null, loc };
2123
+ const call = {
2124
+ kind: "call",
2125
+ callee: helper.name,
2126
+ args: helper.params.map((param) => param.localId === "p.receiver"
2127
+ ? selected.receiver
2128
+ : varRef(param.localId, param.type, loc)),
2129
+ type: helper.returnType,
2130
+ loc,
2131
+ };
2132
+ return {
2133
+ kind: "if",
2134
+ cond: selected.condition,
2135
+ then: dispatch.write && !dispatch.reflect
2136
+ ? [
2137
+ { kind: "exprStmt", expr: call, loc },
2138
+ { kind: "return", value: null, loc },
2139
+ ]
2140
+ : [{ kind: "return", value: call, loc }],
2141
+ else_: null,
2142
+ loc,
2143
+ };
981
2144
  };
982
2145
  if (existingHelper && !dispatch.dynamicKey) {
983
2146
  dispatch.fn.body.splice(dispatch.branchIndex, 0, callHelper(existingHelper));
@@ -985,35 +2148,112 @@ export class ClassDynamicDispatch {
985
2148
  continue;
986
2149
  }
987
2150
  const memberBody = (name) => {
988
- if (dispatch.probe && (name === "message" || name === "name") && lowerer.isSubclassOf(info.def.name, "%Error") && dispatch.probe !== "in")
989
- return [{
990
- kind: "return", value: dispatch.probe === "own"
991
- ? { kind: "fieldGet", obj: lowerer.upcastTo(receiver, "%Error"), className: "%Error", field: `%${name}Present`, type: BOOL, loc }
992
- : { kind: "fieldGet", obj: lowerer.upcastTo(receiver, "%Error"), className: "%Error", field: `%${name}Enumerable`, type: BOOL, loc }, loc,
993
- }];
2151
+ if (dispatch.probe &&
2152
+ (name === "message" || name === "name") &&
2153
+ lowerer.isSubclassOf(info.def.name, "%Error") &&
2154
+ dispatch.probe !== "in")
2155
+ return [
2156
+ {
2157
+ kind: "return",
2158
+ value: dispatch.probe === "own"
2159
+ ? {
2160
+ kind: "fieldGet",
2161
+ obj: lowerer.upcastTo(receiver, "%Error"),
2162
+ className: "%Error",
2163
+ field: `%${name}Present`,
2164
+ type: BOOL,
2165
+ loc,
2166
+ }
2167
+ : {
2168
+ kind: "fieldGet",
2169
+ obj: lowerer.upcastTo(receiver, "%Error"),
2170
+ className: "%Error",
2171
+ field: `%${name}Enumerable`,
2172
+ type: BOOL,
2173
+ loc,
2174
+ },
2175
+ loc,
2176
+ },
2177
+ ];
994
2178
  if (info.builtinStream !== undefined && streamProperty(name) && dispatch.probe)
995
- return [{ kind: "return", value: { kind: "boolLit", value: dispatch.probe === "in", type: BOOL, loc }, loc }];
2179
+ return [
2180
+ {
2181
+ kind: "return",
2182
+ value: { kind: "boolLit", value: dispatch.probe === "in", type: BOOL, loc },
2183
+ loc,
2184
+ },
2185
+ ];
996
2186
  if (!dispatch.probe)
997
- return dispatch.reflect ? this.reflectPropertyBody(lowerer, { ...dispatch, name }, info, receiver) : this.propertyBody(lowerer, { ...dispatch, name }, info, receiver);
2187
+ return dispatch.reflect
2188
+ ? this.reflectPropertyBody(lowerer, { ...dispatch, name }, info, receiver)
2189
+ : this.propertyBody(lowerer, { ...dispatch, name }, info, receiver);
998
2190
  const prototypeMethod = lowerer.prototypeMethodAccesses.has(name);
999
- if (info.fields.has(name) || dispatch.probe === "in" && !prototypeMethod) {
2191
+ if (info.fields.has(name) || (dispatch.probe === "in" && !prototypeMethod)) {
1000
2192
  if (info.fields.has(name) && info.def.tracksOwnFields) {
1001
- const bag = { kind: "call", callee: this.propertyBag.name, args: [lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc };
2193
+ const bag = {
2194
+ kind: "call",
2195
+ callee: this.propertyBag.name,
2196
+ args: [lowerer.coerceToExpected(receiver, DYN)],
2197
+ type: DYN,
2198
+ loc,
2199
+ };
1002
2200
  const symbol = symbolMemberKey(lowerer, info, name, loc);
1003
- const fn = dispatch.probe === "in" ? "dyn.hasKey" : dispatch.probe === "own" ? "dyn.hasOwn" : "dyn.propertyIsEnumerable";
1004
- return [{ kind: "return", value: { kind: "libCall", fn: symbol ? `${fn}Computed` : fn,
1005
- args: [bag, symbol ?? { kind: "strLit", value: name, type: STRING, loc }], type: BOOL, loc }, loc }];
2201
+ const fn = dispatch.probe === "in"
2202
+ ? "dyn.hasKey"
2203
+ : dispatch.probe === "own"
2204
+ ? "dyn.hasOwn"
2205
+ : "dyn.propertyIsEnumerable";
2206
+ return [
2207
+ {
2208
+ kind: "return",
2209
+ value: {
2210
+ kind: "libCall",
2211
+ fn: symbol ? `${fn}Computed` : fn,
2212
+ args: [bag, symbol ?? { kind: "strLit", value: name, type: STRING, loc }],
2213
+ type: BOOL,
2214
+ loc,
2215
+ },
2216
+ loc,
2217
+ },
2218
+ ];
1006
2219
  }
1007
- return [{ kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc }];
2220
+ return [
2221
+ { kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc },
2222
+ ];
1008
2223
  }
1009
2224
  if (prototypeMethod)
1010
2225
  classPrototypeData(lowerer, info, loc, receiver);
1011
- const bag = { kind: "call", callee: this.propertyBag.name,
1012
- args: [lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc };
2226
+ const bag = {
2227
+ kind: "call",
2228
+ callee: this.propertyBag.name,
2229
+ args: [lowerer.coerceToExpected(receiver, DYN)],
2230
+ type: DYN,
2231
+ loc,
2232
+ };
1013
2233
  const symbol = name.startsWith("sym:") || name.startsWith("%symbol:");
1014
- const fn = dispatch.probe === "in" ? "dyn.hasKey" : dispatch.probe === "own" ? "dyn.hasOwn" : "dyn.propertyIsEnumerable";
1015
- return [{ kind: "return", value: { kind: "libCall", fn: symbol ? `${fn}Computed` : fn,
1016
- args: [bag, symbol ? varRef("p.key", DYN, loc) : { kind: "strLit", value: name, type: STRING, loc }], type: BOOL, loc }, loc }];
2234
+ const fn = dispatch.probe === "in"
2235
+ ? "dyn.hasKey"
2236
+ : dispatch.probe === "own"
2237
+ ? "dyn.hasOwn"
2238
+ : "dyn.propertyIsEnumerable";
2239
+ return [
2240
+ {
2241
+ kind: "return",
2242
+ value: {
2243
+ kind: "libCall",
2244
+ fn: symbol ? `${fn}Computed` : fn,
2245
+ args: [
2246
+ bag,
2247
+ symbol
2248
+ ? varRef("p.key", DYN, loc)
2249
+ : { kind: "strLit", value: name, type: STRING, loc },
2250
+ ],
2251
+ type: BOOL,
2252
+ loc,
2253
+ },
2254
+ loc,
2255
+ },
2256
+ ];
1017
2257
  };
1018
2258
  if (dispatch.dynamicKey) {
1019
2259
  const symbols = new Map();
@@ -1026,7 +2266,9 @@ export class ClassDynamicDispatch {
1026
2266
  symbolEntries.push([symbol, name]);
1027
2267
  for (const [symbol, name] of symbolEntries) {
1028
2268
  const declaration = lowerer.checker.valueDeclarationOf(symbol);
1029
- if (declaration && ts.isVariableDeclaration(declaration) && ts.isIdentifier(declaration.name)) {
2269
+ if (declaration &&
2270
+ ts.isVariableDeclaration(declaration) &&
2271
+ ts.isIdentifier(declaration.name)) {
1030
2272
  const global = lowerer.globalsBySymbol.get(symbol);
1031
2273
  if (global)
1032
2274
  symbols.set(name, lowerer.coerceToExpected(varRef(global.id, global.type, loc), DYN));
@@ -1035,21 +2277,60 @@ export class ClassDynamicDispatch {
1035
2277
  for (let owner = info; owner; owner = owner.base) {
1036
2278
  for (const name of [...owner.methods.keys()])
1037
2279
  if (name.startsWith("sym:")) {
1038
- symbols.set(name, { kind: "dynFrom", type: DYN, loc, value: {
1039
- kind: "libCall", fn: "sym.wellKnown", args: [{ kind: "strLit", value: name.slice(4), type: STRING, loc }], type: SYMBOL_T, loc,
1040
- } });
2280
+ symbols.set(name, {
2281
+ kind: "dynFrom",
2282
+ type: DYN,
2283
+ loc,
2284
+ value: {
2285
+ kind: "libCall",
2286
+ fn: "sym.wellKnown",
2287
+ args: [{ kind: "strLit", value: name.slice(4), type: STRING, loc }],
2288
+ type: SYMBOL_T,
2289
+ loc,
2290
+ },
2291
+ });
1041
2292
  }
1042
2293
  }
1043
2294
  const branches = [];
1044
2295
  if (!dispatch.write && !dispatch.reflect && !info.def.tracksOwnFields) {
1045
2296
  const value = varRef("p.0", DYN, loc);
1046
2297
  const key = varRef("p.key", DYN, loc);
1047
- const bag = { kind: "call", callee: this.propertyBag.name, args: [value], type: DYN, loc };
1048
- branches.push({ kind: "if", cond: { kind: "libCall", fn: "dyn.hasOwnComputed", args: [bag, key], type: BOOL, loc }, then: [
1049
- { kind: "return", value: dispatch.probe ? {
1050
- kind: "libCall", fn: dispatch.probe === "enumerable" ? "dyn.propertyIsEnumerableComputed" : "dyn.hasOwnComputed", args: [bag, key], type: BOOL, loc,
1051
- } : { kind: "dynKeyGet", value: bag, key, type: DYN, loc }, loc },
1052
- ], else_: null, loc });
2298
+ const bag = {
2299
+ kind: "call",
2300
+ callee: this.propertyBag.name,
2301
+ args: [value],
2302
+ type: DYN,
2303
+ loc,
2304
+ };
2305
+ branches.push({
2306
+ kind: "if",
2307
+ cond: {
2308
+ kind: "libCall",
2309
+ fn: "dyn.hasOwnComputed",
2310
+ args: [bag, key],
2311
+ type: BOOL,
2312
+ loc,
2313
+ },
2314
+ then: [
2315
+ {
2316
+ kind: "return",
2317
+ value: dispatch.probe
2318
+ ? {
2319
+ kind: "libCall",
2320
+ fn: dispatch.probe === "enumerable"
2321
+ ? "dyn.propertyIsEnumerableComputed"
2322
+ : "dyn.hasOwnComputed",
2323
+ args: [bag, key],
2324
+ type: BOOL,
2325
+ loc,
2326
+ }
2327
+ : { kind: "dynKeyGet", value: bag, key, type: DYN, loc },
2328
+ loc,
2329
+ },
2330
+ ],
2331
+ else_: null,
2332
+ loc,
2333
+ });
1053
2334
  }
1054
2335
  for (const [name, symbol] of symbols) {
1055
2336
  const before = lowerer.diags.length;
@@ -1065,12 +2346,47 @@ export class ClassDynamicDispatch {
1065
2346
  throw error;
1066
2347
  then = [fence];
1067
2348
  }
1068
- branches.push({ kind: "if", cond: { kind: "dynScalarEq", left: varRef("p.key", DYN, loc), right: symbol, type: BOOL, loc }, then, else_: null, loc });
2349
+ branches.push({
2350
+ kind: "if",
2351
+ cond: {
2352
+ kind: "dynScalarEq",
2353
+ left: varRef("p.key", DYN, loc),
2354
+ right: symbol,
2355
+ type: BOOL,
2356
+ loc,
2357
+ },
2358
+ then,
2359
+ else_: null,
2360
+ loc,
2361
+ });
1069
2362
  }
1070
2363
  if (branches.length) {
1071
- dispatch.fn.body.unshift({ kind: "if", cond: selected.condition, then: [
1072
- { kind: "if", cond: { kind: "dynTest", test: "symbol", value: varRef("p.key", DYN, loc), type: BOOL, loc }, then: transformStmtList(branches, { stmt: (statement) => statement, expr: (expression) => expression.kind === "varRef" && expression.localId === "p.receiver" ? selected.receiver : expression }), else_: null, loc },
1073
- ], else_: null, loc });
2364
+ dispatch.fn.body.unshift({
2365
+ kind: "if",
2366
+ cond: selected.condition,
2367
+ then: [
2368
+ {
2369
+ kind: "if",
2370
+ cond: {
2371
+ kind: "dynTest",
2372
+ test: "symbol",
2373
+ value: varRef("p.key", DYN, loc),
2374
+ type: BOOL,
2375
+ loc,
2376
+ },
2377
+ then: transformStmtList(branches, {
2378
+ stmt: (statement) => statement,
2379
+ expr: (expression) => expression.kind === "varRef" && expression.localId === "p.receiver"
2380
+ ? selected.receiver
2381
+ : expression,
2382
+ }),
2383
+ else_: null,
2384
+ loc,
2385
+ },
2386
+ ],
2387
+ else_: null,
2388
+ loc,
2389
+ });
1074
2390
  dispatch.branchIndex++;
1075
2391
  }
1076
2392
  }
@@ -1110,26 +2426,66 @@ export class ClassDynamicDispatch {
1110
2426
  throw error;
1111
2427
  body = [fence];
1112
2428
  }
1113
- branch.push({ kind: "if", cond: {
1114
- kind: "strEq", left: varRef(dispatch.keyLocal, STRING, loc), right: { kind: "strLit", value: name, type: STRING, loc }, negated: false, type: BOOL, loc,
1115
- }, then: body, else_: null, loc });
2429
+ branch.push({
2430
+ kind: "if",
2431
+ cond: {
2432
+ kind: "strEq",
2433
+ left: varRef(dispatch.keyLocal, STRING, loc),
2434
+ right: { kind: "strLit", value: name, type: STRING, loc },
2435
+ negated: false,
2436
+ type: BOOL,
2437
+ loc,
2438
+ },
2439
+ then: body,
2440
+ else_: null,
2441
+ loc,
2442
+ });
1116
2443
  }
1117
2444
  // Keep each class's key table in a separate function. A single
1118
2445
  // function containing every boxed class grows quadratically during
1119
2446
  // LLVM's control-flow optimization for large library workloads.
1120
- const params = [...dispatch.fn.params, { localId: "p.receiver", name: "receiver", type: receiverType }];
2447
+ const params = [
2448
+ ...dispatch.fn.params,
2449
+ { localId: "p.receiver", name: "receiver", type: receiverType },
2450
+ ];
1121
2451
  if (dispatch.keyLocal !== "p.key")
1122
2452
  params.push({ localId: dispatch.keyLocal, name: "key", type: STRING });
1123
2453
  const helper = {
1124
- name: `%dyn.class.keys.${lowerer.liftedFns.length}`, params, returnType: dispatch.fn.returnType,
1125
- locals: params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false })),
1126
- body: [...branch, ...transformStmtList(dispatch.fn.body.slice(dispatch.write ? -2 : -1), { stmt: (statement) => statement,
2454
+ name: `%dyn.class.keys.${lowerer.liftedFns.length}`,
2455
+ params,
2456
+ returnType: dispatch.fn.returnType,
2457
+ locals: params.map((p) => ({
2458
+ id: p.localId,
2459
+ name: p.name,
2460
+ type: p.type,
2461
+ mutable: false,
2462
+ })),
2463
+ body: [
2464
+ ...branch,
2465
+ ...transformStmtList(dispatch.fn.body.slice(dispatch.write ? -2 : -1), {
2466
+ stmt: (statement) => statement,
1127
2467
  expr: (expression) => expression.kind === "dynKeyGet" && expression.key.type.kind === "string"
1128
- ? { kind: "libCall", fn: "dyn.bagGet", args: [expression.value, expression.key, lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc }
2468
+ ? {
2469
+ kind: "libCall",
2470
+ fn: "dyn.bagGet",
2471
+ args: [
2472
+ expression.value,
2473
+ expression.key,
2474
+ lowerer.coerceToExpected(receiver, DYN),
2475
+ ],
2476
+ type: DYN,
2477
+ loc,
2478
+ }
1129
2479
  : expression.kind === "libCall" && expression.fn === "dyn.keySet"
1130
- ? { ...expression, fn: "dyn.bagSet", args: [...expression.args, lowerer.coerceToExpected(receiver, DYN)] }
2480
+ ? {
2481
+ ...expression,
2482
+ fn: "dyn.bagSet",
2483
+ args: [...expression.args, lowerer.coerceToExpected(receiver, DYN)],
2484
+ }
1131
2485
  : expression,
1132
- })], loc,
2486
+ }),
2487
+ ],
2488
+ loc,
1133
2489
  };
1134
2490
  this.generated.add(helper);
1135
2491
  lowerer.liftedFns.push(helper);
@@ -1145,10 +2501,26 @@ export class ClassDynamicDispatch {
1145
2501
  this.enumerationClasses.add(plan.key);
1146
2502
  const loc = this.enumeration.loc;
1147
2503
  const { condition } = this.propertyReceiver(plan, loc);
1148
- const bag = { kind: "call", callee: this.propertyBag.name, args: [varRef("p.0", DYN, loc)], type: DYN, loc };
1149
- this.enumeration.body.unshift({ kind: "if", cond: condition, then: [
1150
- { kind: "return", value: { kind: "libCall", fn: "dyn.forInKeys", args: [bag], type: DYN, loc }, loc },
1151
- ], else_: null, loc });
2504
+ const bag = {
2505
+ kind: "call",
2506
+ callee: this.propertyBag.name,
2507
+ args: [varRef("p.0", DYN, loc)],
2508
+ type: DYN,
2509
+ loc,
2510
+ };
2511
+ this.enumeration.body.unshift({
2512
+ kind: "if",
2513
+ cond: condition,
2514
+ then: [
2515
+ {
2516
+ kind: "return",
2517
+ value: { kind: "libCall", fn: "dyn.forInKeys", args: [bag], type: DYN, loc },
2518
+ loc,
2519
+ },
2520
+ ],
2521
+ else_: null,
2522
+ loc,
2523
+ });
1152
2524
  changed = true;
1153
2525
  }
1154
2526
  if (this.constructDispatch)
@@ -1166,7 +2538,13 @@ export class ClassDynamicDispatch {
1166
2538
  supported = false;
1167
2539
  break;
1168
2540
  }
1169
- const value = { kind: "dynKeyGet", value: input, key: { kind: "strLit", value: String(i), type: STRING, loc }, type: DYN, loc };
2541
+ const value = {
2542
+ kind: "dynKeyGet",
2543
+ value: input,
2544
+ key: { kind: "strLit", value: String(i), type: STRING, loc },
2545
+ type: DYN,
2546
+ loc,
2547
+ };
1170
2548
  const arg = lowerer.coerceToExpected(value, param.type);
1171
2549
  if (!typeEquals(arg.type, param.type)) {
1172
2550
  supported = false;
@@ -1177,11 +2555,26 @@ export class ClassDynamicDispatch {
1177
2555
  if (!supported || !info.decl)
1178
2556
  continue;
1179
2557
  const cls = classValueRef(lowerer, info, info.decl);
1180
- const result = { kind: "new", className: name, args, type: { kind: "object", className: name }, loc };
1181
- this.constructDispatch.body.unshift({ kind: "if", cond: { kind: "dynScalarEq", left: callee,
1182
- right: lowerer.coerceToExpected(cls, DYN), type: BOOL, loc }, then: [
1183
- { kind: "return", value: lowerer.coerceToExpected(result, DYN), loc },
1184
- ], else_: null, loc });
2558
+ const result = {
2559
+ kind: "new",
2560
+ className: name,
2561
+ args,
2562
+ type: { kind: "object", className: name },
2563
+ loc,
2564
+ };
2565
+ this.constructDispatch.body.unshift({
2566
+ kind: "if",
2567
+ cond: {
2568
+ kind: "dynScalarEq",
2569
+ left: callee,
2570
+ right: lowerer.coerceToExpected(cls, DYN),
2571
+ type: BOOL,
2572
+ loc,
2573
+ },
2574
+ then: [{ kind: "return", value: lowerer.coerceToExpected(result, DYN), loc }],
2575
+ else_: null,
2576
+ loc,
2577
+ });
1185
2578
  changed = true;
1186
2579
  }
1187
2580
  if (this.staticPropertyBag)
@@ -1197,8 +2590,27 @@ export class ClassDynamicDispatch {
1197
2590
  continue;
1198
2591
  this.staticBagClasses.add(name);
1199
2592
  const value = varRef("value", DYN, loc);
1200
- this.staticPropertyBag.body.unshift({ kind: "if", cond: { kind: "libCall", fn: "dyn.classIs", args: [value,
1201
- { kind: "strLit", value: typeKey({ kind: "classval", className: name }), type: STRING, loc }], type: BOOL, loc }, then: [{ kind: "return", value: bag, loc }], else_: null, loc });
2593
+ this.staticPropertyBag.body.unshift({
2594
+ kind: "if",
2595
+ cond: {
2596
+ kind: "libCall",
2597
+ fn: "dyn.classIs",
2598
+ args: [
2599
+ value,
2600
+ {
2601
+ kind: "strLit",
2602
+ value: typeKey({ kind: "classval", className: name }),
2603
+ type: STRING,
2604
+ loc,
2605
+ },
2606
+ ],
2607
+ type: BOOL,
2608
+ loc,
2609
+ },
2610
+ then: [{ kind: "return", value: bag, loc }],
2611
+ else_: null,
2612
+ loc,
2613
+ });
1202
2614
  changed = true;
1203
2615
  }
1204
2616
  changed = this.normalizeDispatches(lowerer) || changed;
@@ -1209,46 +2621,90 @@ export class ClassDynamicDispatch {
1209
2621
  /** A known native class can access its shared bag directly. Keep the
1210
2622
  * receiver as an owned parameter so calls and temporary instances retain
1211
2623
  * their ordinary evaluation and lifetime rules without a boxed capsule. */
1212
- typedPropertyBag(lowerer, type, loc) {
2624
+ typedPropertyBag(lowerer, type, loc, readOnly) {
1213
2625
  // A superclass constructor can be the first code to access this bag.
1214
2626
  // Its receiver still needs the actual subclass's prototype.
1215
2627
  if (lowerer.classes.get(type.className)?.subclasses.length)
1216
2628
  return null;
1217
- const existing = this.typedPropertyBags.get(type.className);
2629
+ const key = `${type.className}:${readOnly}`;
2630
+ const existing = this.typedPropertyBags.get(key);
1218
2631
  if (existing)
1219
2632
  return existing;
1220
2633
  const initializers = this.bagInitializers.get(type.className);
1221
2634
  if (!initializers)
1222
2635
  return null;
1223
2636
  const receiver = varRef("p.0", type, loc);
1224
- const bag = { kind: "fieldGet", obj: receiver, className: type.className, field: PROPERTY_BAG, type: DYN, loc };
1225
- const initialize = { ...initializers[0], obj: receiver,
1226
- value: transformExpr(initializers[0].value, { stmt: (stmt) => stmt, expr: (expr) => expr.kind === "dynCheck" && expr.value.kind === "varRef" && expr.value.localId === "p.0" ? receiver : expr }), loc };
2637
+ const bag = {
2638
+ kind: "fieldGet",
2639
+ obj: receiver,
2640
+ className: type.className,
2641
+ field: PROPERTY_BAG,
2642
+ type: DYN,
2643
+ loc,
2644
+ };
2645
+ const initialize = {
2646
+ ...initializers[0],
2647
+ obj: receiver,
2648
+ value: transformExpr(initializers[0].value, {
2649
+ stmt: (stmt) => stmt,
2650
+ expr: (expr) => expr.kind === "dynCheck" && expr.value.kind === "varRef" && expr.value.localId === "p.0"
2651
+ ? receiver
2652
+ : expr,
2653
+ }),
2654
+ loc,
2655
+ };
1227
2656
  const helper = {
1228
- name: `%class.properties:${type.className}`, params: [{ localId: "p.0", name: "value", type }], returnType: DYN,
1229
- locals: [{ id: "p.0", name: "value", type, mutable: false }], loc,
2657
+ name: `%class.${readOnly ? "readProperties" : "properties"}:${type.className}`,
2658
+ params: [{ localId: "p.0", name: "value", type }],
2659
+ returnType: DYN,
2660
+ locals: [{ id: "p.0", name: "value", type, mutable: false }],
2661
+ loc,
1230
2662
  body: [
1231
- { kind: "if", cond: { kind: "dynTest", test: "undefined", value: bag, type: BOOL, loc }, then: [initialize], else_: null, loc },
2663
+ {
2664
+ kind: "if",
2665
+ cond: { kind: "dynTest", test: "undefined", value: bag, type: BOOL, loc },
2666
+ then: [initialize],
2667
+ else_: null,
2668
+ loc,
2669
+ },
1232
2670
  { kind: "return", value: bag, loc },
1233
2671
  ],
1234
2672
  };
1235
2673
  initializers.push(initialize);
1236
- this.typedPropertyBags.set(type.className, helper);
2674
+ this.typedPropertyBags.set(key, helper);
2675
+ if (readOnly)
2676
+ this.readPropertyBags.push({ helper, initialize });
1237
2677
  this.generated.add(helper);
1238
2678
  lowerer.liftedFns.push(helper);
1239
2679
  return helper;
1240
2680
  }
2681
+ /** Prototype state may appear in a later reachable body. Only after the
2682
+ * dispatch worklist closes can an empty bag initializer be omitted; a
2683
+ * prototype-backed bag must still be initialized before inherited reads. */
2684
+ finalize() {
2685
+ for (const { helper, initialize } of this.readPropertyBags) {
2686
+ if (initialize.value.kind === "dynObjLit" && initialize.value.fields?.length === 0)
2687
+ helper.body.shift();
2688
+ }
2689
+ }
1241
2690
  normalizedDispatches() {
1242
- return [...(this.propertyBag ? [this.propertyBag] : []),
2691
+ return [
2692
+ ...(this.propertyBag ? [this.propertyBag] : []),
1243
2693
  ...[...this.properties.values()].map((dispatch) => dispatch.fn),
1244
2694
  ...[...this.computed.values()].map((dispatch) => dispatch.fn),
1245
- ...[...this.dispatches.values()].flatMap((dispatch) => [dispatch.fn, dispatch.callback])];
2695
+ ...[...this.dispatches.values()].flatMap((dispatch) => [dispatch.fn, dispatch.callback]),
2696
+ ];
1246
2697
  }
1247
2698
  constructorPropertyBag(lowerer, loc) {
1248
2699
  if (!this.staticPropertyBag) {
1249
- this.staticPropertyBag = { name: "%dyn.class.staticProperties", params: [{ localId: "value", name: "value", type: DYN }], returnType: DYN,
2700
+ this.staticPropertyBag = {
2701
+ name: "%dyn.class.staticProperties",
2702
+ params: [{ localId: "value", name: "value", type: DYN }],
2703
+ returnType: DYN,
1250
2704
  locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
1251
- body: [{ kind: "return", value: varRef("value", DYN, loc), loc }], loc };
2705
+ body: [{ kind: "return", value: varRef("value", DYN, loc), loc }],
2706
+ loc,
2707
+ };
1252
2708
  lowerer.liftedFns.push(this.staticPropertyBag);
1253
2709
  this.generated.add(this.staticPropertyBag);
1254
2710
  }
@@ -1277,12 +2733,21 @@ export class ClassDynamicDispatch {
1277
2733
  }
1278
2734
  if (!entries.length && !this.normalization)
1279
2735
  return false;
1280
- const key = JSON.stringify(entries.map(({ capsule, children }) => [capsule.def.name, children.map((child) => child.def.name)]));
2736
+ const key = JSON.stringify(entries.map(({ capsule, children }) => [
2737
+ capsule.def.name,
2738
+ children.map((child) => child.def.name),
2739
+ ]));
1281
2740
  let changed = key !== this.normalizationKey;
1282
2741
  if (!this.normalization) {
1283
2742
  const loc = this.propertyBag.loc;
1284
- this.normalization = { name: "%dyn.class.normalize", params: [{ localId: "value", name: "value", type: DYN }], returnType: DYN,
1285
- locals: [{ id: "value", name: "value", type: DYN, mutable: false }], body: [], loc };
2743
+ this.normalization = {
2744
+ name: "%dyn.class.normalize",
2745
+ params: [{ localId: "value", name: "value", type: DYN }],
2746
+ returnType: DYN,
2747
+ locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
2748
+ body: [],
2749
+ loc,
2750
+ };
1286
2751
  lowerer.liftedFns.push(this.normalization);
1287
2752
  this.generated.add(this.normalization);
1288
2753
  changed = true;
@@ -1294,20 +2759,64 @@ export class ClassDynamicDispatch {
1294
2759
  this.normalization.body = entries.map(({ capsule, children }) => {
1295
2760
  const type = { kind: "object", className: capsule.def.name };
1296
2761
  const receiver = { kind: "dynCheck", value, type, loc };
1297
- return { kind: "if", cond: { kind: "libCall", fn: "dyn.typedRefIs", args: [value,
1298
- { kind: "strLit", value: typeKey(type), type: STRING, loc }], type: BOOL, loc }, then: children.map((child) => ({
1299
- kind: "if", cond: { kind: "instanceOf", value: receiver, className: child.def.name, type: BOOL, loc }, then: [{
1300
- kind: "return", value: { kind: "dynFrom", value: { kind: "downcast", value: receiver,
1301
- type: { kind: "object", className: child.def.name }, loc }, type: DYN, loc }, loc,
1302
- }], else_: null, loc,
1303
- })), else_: null, loc };
2762
+ return {
2763
+ kind: "if",
2764
+ cond: {
2765
+ kind: "libCall",
2766
+ fn: "dyn.typedRefIs",
2767
+ args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
2768
+ type: BOOL,
2769
+ loc,
2770
+ },
2771
+ then: children.map((child) => ({
2772
+ kind: "if",
2773
+ cond: {
2774
+ kind: "instanceOf",
2775
+ value: receiver,
2776
+ className: child.def.name,
2777
+ type: BOOL,
2778
+ loc,
2779
+ },
2780
+ then: [
2781
+ {
2782
+ kind: "return",
2783
+ value: {
2784
+ kind: "dynFrom",
2785
+ value: {
2786
+ kind: "downcast",
2787
+ value: receiver,
2788
+ type: { kind: "object", className: child.def.name },
2789
+ loc,
2790
+ },
2791
+ type: DYN,
2792
+ loc,
2793
+ },
2794
+ loc,
2795
+ },
2796
+ ],
2797
+ else_: null,
2798
+ loc,
2799
+ })),
2800
+ else_: null,
2801
+ loc,
2802
+ };
1304
2803
  });
1305
2804
  this.normalization.body.push({ kind: "return", value, loc });
1306
2805
  }
1307
2806
  for (const fn of this.normalizedDispatches()) {
1308
2807
  fn.locals.find((local) => local.id === "p.0").mutable = true;
1309
- fn.body.unshift({ kind: "assign", localId: "p.0", value: { kind: "call", callee: this.normalization.name,
1310
- args: [varRef("p.0", DYN, fn.loc)], type: DYN, loc: fn.loc }, loc: fn.loc });
2808
+ fn.body.unshift({
2809
+ kind: "assign",
2810
+ localId: "p.0",
2811
+ value: {
2812
+ kind: "call",
2813
+ callee: this.normalization.name,
2814
+ args: [varRef("p.0", DYN, fn.loc)],
2815
+ type: DYN,
2816
+ loc: fn.loc,
2817
+ },
2818
+ loc: fn.loc,
2819
+ });
1311
2820
  }
1312
2821
  return changed;
1313
2822
  }
@@ -1338,13 +2847,20 @@ export class ClassDynamicDispatch {
1338
2847
  const seen = new Set();
1339
2848
  for (const name of this.boxed) {
1340
2849
  const capsule = lowerer.classes.get(name);
1341
- if (!capsule || (capsule.builtinEmitter || capsule.builtinStream) && !streams || capsule.builtinError)
2850
+ if (!capsule ||
2851
+ ((capsule.builtinEmitter || capsule.builtinStream) && !streams) ||
2852
+ capsule.builtinError)
1342
2853
  continue;
1343
2854
  const canonical = normalize && !capsule.builtinStream && !capsule.builtinEmitter;
1344
2855
  const visit = (info) => {
1345
- if ((!canonical || !seen.has(info.def.name)) && (info === capsule || lowerer.classCanBeConstructed(info))) {
2856
+ if ((!canonical || !seen.has(info.def.name)) &&
2857
+ (info === capsule || lowerer.classCanBeConstructed(info))) {
1346
2858
  seen.add(info.def.name);
1347
- plans.push({ info, capsule: canonical ? info : capsule, key: canonical ? info.def.name : JSON.stringify([name, info.def.name]) });
2859
+ plans.push({
2860
+ info,
2861
+ capsule: canonical ? info : capsule,
2862
+ key: canonical ? info.def.name : JSON.stringify([name, info.def.name]),
2863
+ });
1348
2864
  }
1349
2865
  for (const child of info.subclasses)
1350
2866
  visit(child);
@@ -1357,14 +2873,36 @@ export class ClassDynamicDispatch {
1357
2873
  const value = varRef("p.0", DYN, loc);
1358
2874
  const type = { kind: "object", className: plan.capsule.def.name };
1359
2875
  const checked = { kind: "dynCheck", value, type, loc };
1360
- const matches = { kind: "libCall", fn: "dyn.typedRefIs", args: [value,
1361
- { kind: "strLit", value: typeKey(type), type: STRING, loc }], type: BOOL, loc };
2876
+ const matches = {
2877
+ kind: "libCall",
2878
+ fn: "dyn.typedRefIs",
2879
+ args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
2880
+ type: BOOL,
2881
+ loc,
2882
+ };
1362
2883
  if (plan.info === plan.capsule)
1363
2884
  return { receiver: checked, condition: matches };
1364
2885
  return {
1365
- receiver: { kind: "downcast", value: checked, type: { kind: "object", className: plan.info.def.name }, loc },
1366
- condition: { kind: "ternary", cond: matches, then: { kind: "instanceOf", value: checked,
1367
- className: plan.info.def.name, type: BOOL, loc }, else_: { kind: "boolLit", value: false, type: BOOL, loc }, type: BOOL, loc },
2886
+ receiver: {
2887
+ kind: "downcast",
2888
+ value: checked,
2889
+ type: { kind: "object", className: plan.info.def.name },
2890
+ loc,
2891
+ },
2892
+ condition: {
2893
+ kind: "ternary",
2894
+ cond: matches,
2895
+ then: {
2896
+ kind: "instanceOf",
2897
+ value: checked,
2898
+ className: plan.info.def.name,
2899
+ type: BOOL,
2900
+ loc,
2901
+ },
2902
+ else_: { kind: "boolLit", value: false, type: BOOL, loc },
2903
+ type: BOOL,
2904
+ loc,
2905
+ },
1368
2906
  };
1369
2907
  }
1370
2908
  reflectPropertyBody(lowerer, dispatch, info, receiver) {
@@ -1376,17 +2914,53 @@ export class ClassDynamicDispatch {
1376
2914
  const field = info.fields.get(name);
1377
2915
  const member = `${write ? "set" : "get"}:${name}`;
1378
2916
  const accessor = field ? null : findMethodOn(lowerer, info, member);
1379
- const bag = { kind: "call", callee: this.propertyBag.name, args: [instance], type: DYN, loc };
1380
- const fallback = { kind: "libCall", fn: write ? "dyn.reflectSet" : "dyn.reflectGet",
1381
- args: [bag, lowerer.coerceToExpected(key, DYN), ...(write ? [varRef("p.1", DYN, loc)] : []), actualReceiver], type: write ? BOOL : DYN, loc };
2917
+ const bag = {
2918
+ kind: "call",
2919
+ callee: this.propertyBag.name,
2920
+ args: [instance],
2921
+ type: DYN,
2922
+ loc,
2923
+ };
2924
+ const fallback = {
2925
+ kind: "libCall",
2926
+ fn: write ? "dyn.reflectSet" : "dyn.reflectGet",
2927
+ args: [
2928
+ bag,
2929
+ lowerer.coerceToExpected(key, DYN),
2930
+ ...(write ? [varRef("p.1", DYN, loc)] : []),
2931
+ actualReceiver,
2932
+ ],
2933
+ type: write ? BOOL : DYN,
2934
+ loc,
2935
+ };
1382
2936
  if (accessor && info.decl) {
1383
2937
  const method = classMethodValue(lowerer, info.decl, info, member, loc);
1384
2938
  if (method) {
1385
- const call = { kind: "libCall", fn: "dyn.reflectApply", args: [lowerer.coerceToExpected(method, DYN), actualReceiver,
1386
- { kind: "dynArrLit", elems: write ? [varRef("p.1", DYN, loc)] : [], type: DYN, loc }], type: DYN, loc };
2939
+ const call = {
2940
+ kind: "libCall",
2941
+ fn: "dyn.reflectApply",
2942
+ args: [
2943
+ lowerer.coerceToExpected(method, DYN),
2944
+ actualReceiver,
2945
+ { kind: "dynArrLit", elems: write ? [varRef("p.1", DYN, loc)] : [], type: DYN, loc },
2946
+ ],
2947
+ type: DYN,
2948
+ loc,
2949
+ };
1387
2950
  return [
1388
- { kind: "if", cond: { kind: "libCall", fn: "dyn.hasOwn", args: [bag, key], type: BOOL, loc }, then: [{ kind: "return", value: fallback, loc }], else_: null, loc },
1389
- ...(write ? [{ kind: "exprStmt", expr: call, loc }, { kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc }] : [{ kind: "return", value: call, loc }]),
2951
+ {
2952
+ kind: "if",
2953
+ cond: { kind: "libCall", fn: "dyn.hasOwn", args: [bag, key], type: BOOL, loc },
2954
+ then: [{ kind: "return", value: fallback, loc }],
2955
+ else_: null,
2956
+ loc,
2957
+ },
2958
+ ...(write
2959
+ ? [
2960
+ { kind: "exprStmt", expr: call, loc },
2961
+ { kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc },
2962
+ ]
2963
+ : [{ kind: "return", value: call, loc }]),
1390
2964
  ];
1391
2965
  }
1392
2966
  }
@@ -1397,14 +2971,53 @@ export class ClassDynamicDispatch {
1397
2971
  }
1398
2972
  const body = this.propertyBody(lowerer, dispatch, info, receiver);
1399
2973
  if (!write)
1400
- return transformStmtList(body, { stmt: (statement) => statement, expr: (expression) => expression.kind === "libCall" && expression.fn === "dyn.bagGet"
1401
- ? { ...expression, fn: "dyn.reflectGet", args: [expression.args[0], lowerer.coerceToExpected(expression.args[1], DYN), actualReceiver] } : expression });
2974
+ return transformStmtList(body, {
2975
+ stmt: (statement) => statement,
2976
+ expr: (expression) => expression.kind === "libCall" && expression.fn === "dyn.bagGet"
2977
+ ? {
2978
+ ...expression,
2979
+ fn: "dyn.reflectGet",
2980
+ args: [
2981
+ expression.args[0],
2982
+ lowerer.coerceToExpected(expression.args[1], DYN),
2983
+ actualReceiver,
2984
+ ],
2985
+ }
2986
+ : expression,
2987
+ });
1402
2988
  return [
1403
- { kind: "if", cond: { kind: "dynScalarEq", left: instance, right: actualReceiver, negated: true, type: BOOL, loc }, then: [{ kind: "return", value: {
1404
- kind: "libCall", fn: "dyn.reflectDefine", args: [actualReceiver, lowerer.coerceToExpected(key, DYN), varRef("p.1", DYN, loc)], type: BOOL, loc,
1405
- }, loc }], else_: null, loc },
1406
- ...transformStmtList(body, { stmt: (statement) => statement.kind === "return" && !statement.value
1407
- ? { ...statement, value: { kind: "boolLit", value: true, type: BOOL, loc } } : statement, expr: (expression) => expression }),
2989
+ {
2990
+ kind: "if",
2991
+ cond: {
2992
+ kind: "dynScalarEq",
2993
+ left: instance,
2994
+ right: actualReceiver,
2995
+ negated: true,
2996
+ type: BOOL,
2997
+ loc,
2998
+ },
2999
+ then: [
3000
+ {
3001
+ kind: "return",
3002
+ value: {
3003
+ kind: "libCall",
3004
+ fn: "dyn.reflectDefine",
3005
+ args: [actualReceiver, lowerer.coerceToExpected(key, DYN), varRef("p.1", DYN, loc)],
3006
+ type: BOOL,
3007
+ loc,
3008
+ },
3009
+ loc,
3010
+ },
3011
+ ],
3012
+ else_: null,
3013
+ loc,
3014
+ },
3015
+ ...transformStmtList(body, {
3016
+ stmt: (statement) => statement.kind === "return" && !statement.value
3017
+ ? { ...statement, value: { kind: "boolLit", value: true, type: BOOL, loc } }
3018
+ : statement,
3019
+ expr: (expression) => expression,
3020
+ }),
1408
3021
  ];
1409
3022
  }
1410
3023
  propertyBody(lowerer, dispatch, info, receiver) {
@@ -1412,27 +3025,92 @@ export class ClassDynamicDispatch {
1412
3025
  const loc = dispatch.fn.loc;
1413
3026
  if (info.builtinStream !== undefined && streamProperty(name)) {
1414
3027
  if (write)
1415
- return [{ kind: "runtimeFence", code: "SC2020", message: `writing stream property '${name}' through an untyped value is not supported`, loc }];
1416
- return [{ kind: "return", value: lowerer.coerceToExpected({ kind: "libCall", fn: "stream.prop", args: [receiver, { kind: "strLit", value: name, type: STRING, loc }], type: STREAM_BOOL_PROPERTIES.has(name) ? BOOL : F64, loc }, DYN), loc }];
3028
+ return [
3029
+ {
3030
+ kind: "runtimeFence",
3031
+ code: "SC2020",
3032
+ message: `writing stream property '${name}' through an untyped value is not supported`,
3033
+ loc,
3034
+ },
3035
+ ];
3036
+ return [
3037
+ {
3038
+ kind: "return",
3039
+ value: lowerer.coerceToExpected({
3040
+ kind: "libCall",
3041
+ fn: "stream.prop",
3042
+ args: [receiver, { kind: "strLit", value: name, type: STRING, loc }],
3043
+ type: STREAM_BOOL_PROPERTIES.has(name) ? BOOL : F64,
3044
+ loc,
3045
+ }, DYN),
3046
+ loc,
3047
+ },
3048
+ ];
1417
3049
  }
1418
3050
  if ((name === "message" || name === "name") && lowerer.isSubclassOf(info.def.name, "%Error"))
1419
3051
  return write
1420
- ? [errorPropertyWrite(lowerer, receiver, lowerer.coerceToExpected(varRef("p.1", DYN, loc), STRING), name), { kind: "return", value: null, loc }]
1421
- : [{ kind: "return", value: lowerer.coerceToExpected(errorPropertyRead(lowerer, receiver, name), DYN), loc }];
3052
+ ? [
3053
+ errorPropertyWrite(lowerer, receiver, lowerer.coerceToExpected(varRef("p.1", DYN, loc), STRING), name),
3054
+ { kind: "return", value: null, loc },
3055
+ ]
3056
+ : [
3057
+ {
3058
+ kind: "return",
3059
+ value: lowerer.coerceToExpected(errorPropertyRead(lowerer, receiver, name), DYN),
3060
+ loc,
3061
+ },
3062
+ ];
1422
3063
  const field = info.fields.get(name);
1423
3064
  const member = `${write ? "set" : "get"}:${name}`;
1424
3065
  const accessor = field ? null : findMethodOn(lowerer, info, member);
1425
- const fence = () => [{ kind: "runtimeFence", code: "SC2020", message: `${write ? "writing" : "reading"} '${name}' on this native class through an untyped value is not supported yet`, loc }];
3066
+ const fence = () => [
3067
+ {
3068
+ kind: "runtimeFence",
3069
+ code: "SC2020",
3070
+ message: `${write ? "writing" : "reading"} '${name}' on this native class through an untyped value is not supported yet`,
3071
+ loc,
3072
+ },
3073
+ ];
1426
3074
  const getRecord = (id) => lowerer.shapes.get(id);
1427
3075
  const getUnion = (id) => lowerer.unions.get(id);
1428
3076
  if (!write) {
1429
- if (name === "constructor" && !field && !accessor && info.decl && !info.generic && !info.localClass && !info.classDecorators) {
3077
+ if (name === "constructor" &&
3078
+ !field &&
3079
+ !accessor &&
3080
+ info.decl &&
3081
+ !info.generic &&
3082
+ !info.localClass &&
3083
+ !info.classDecorators) {
1430
3084
  this.constructors.set(info.def.name, info);
1431
3085
  const cls = lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN);
1432
- const bag = { kind: "call", callee: this.propertyBag.name, args: [lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc };
3086
+ const bag = {
3087
+ kind: "call",
3088
+ callee: this.propertyBag.name,
3089
+ args: [lowerer.coerceToExpected(receiver, DYN)],
3090
+ type: DYN,
3091
+ loc,
3092
+ };
1433
3093
  const key = { kind: "strLit", value: name, type: STRING, loc };
1434
- return [{ kind: "return", value: { kind: "ternary", cond: { kind: "libCall", fn: "dyn.hasKey", args: [bag, key], type: BOOL, loc },
1435
- then: { kind: "libCall", fn: "dyn.bagGet", args: [bag, key, lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc }, else_: cls, type: DYN, loc }, loc }];
3094
+ return [
3095
+ {
3096
+ kind: "return",
3097
+ value: {
3098
+ kind: "ternary",
3099
+ cond: { kind: "libCall", fn: "dyn.hasKey", args: [bag, key], type: BOOL, loc },
3100
+ then: {
3101
+ kind: "libCall",
3102
+ fn: "dyn.bagGet",
3103
+ args: [bag, key, lowerer.coerceToExpected(receiver, DYN)],
3104
+ type: DYN,
3105
+ loc,
3106
+ },
3107
+ else_: cls,
3108
+ type: DYN,
3109
+ loc,
3110
+ },
3111
+ loc,
3112
+ },
3113
+ ];
1436
3114
  }
1437
3115
  if (name === "toString" && findMethodOn(lowerer, info, name)?.declarer.builtinError) {
1438
3116
  return [{ kind: "return", value: errorToStringMethod(lowerer, receiver), loc }];
@@ -1444,34 +3122,78 @@ export class ClassDynamicDispatch {
1444
3122
  // those speculative branches. Direct typed references still reach
1445
3123
  // the ordinary graph-wide async_free diagnostic.
1446
3124
  if (this.asyncFree && (declared?.sig.gen || declared?.sig.async)) {
1447
- return [{ kind: "runtimeFence", code: "SC4005", message: `reading async or generator method '${name}' through an untyped library lookup is not supported`, loc }];
3125
+ return [
3126
+ {
3127
+ kind: "runtimeFence",
3128
+ code: "SC4005",
3129
+ message: `reading async or generator method '${name}' through an untyped library lookup is not supported`,
3130
+ loc,
3131
+ },
3132
+ ];
1448
3133
  }
1449
3134
  const generic = findGenericMethodOn(lowerer, info, name);
1450
3135
  // A computed lookup has branches for every visible name. Generic
1451
3136
  // methods need a concrete specialization before they can escape;
1452
3137
  // refuse only if this runtime branch is selected.
1453
- if (generic && (!generic.info.implicitParams || !generic.declarer.decl ||
1454
- lowerer.overrideBelow(info, name) || genericOverrideBelow(lowerer, info, name)))
3138
+ if (generic &&
3139
+ (!generic.info.implicitParams ||
3140
+ !generic.declarer.decl ||
3141
+ lowerer.overrideBelow(info, name) ||
3142
+ genericOverrideBelow(info, name)))
1455
3143
  return fence();
1456
3144
  const method = classMethodValue(lowerer, info.decl, info, name, loc);
1457
3145
  if (method && canConvertToDyn(method.type, getRecord, getUnion)) {
1458
3146
  // A capsule may have the base ABI even when its native object is
1459
3147
  // a subclass (for example an inherited iterator returning this).
1460
3148
  // Select the method declaration at extraction, before detaching it.
1461
- const overrides = [...lowerer.classes.values()].filter((candidate) => candidate !== info && lowerer.classCanBeConstructed(candidate) && lowerer.isSubclassOf(candidate.def.name, info.def.name) &&
3149
+ const overrides = [...lowerer.classes.values()].filter((candidate) => candidate !== info &&
3150
+ lowerer.classCanBeConstructed(candidate) &&
3151
+ lowerer.isSubclassOf(candidate.def.name, info.def.name) &&
1462
3152
  (candidate.methods.has(name) || candidate.genericMethods?.has(name)));
1463
- overrides.sort((a, b) => lowerer.isSubclassOf(a.def.name, b.def.name) ? -1 : lowerer.isSubclassOf(b.def.name, a.def.name) ? 1 : 0);
3153
+ overrides.sort((a, b) => lowerer.isSubclassOf(a.def.name, b.def.name)
3154
+ ? -1
3155
+ : lowerer.isSubclassOf(b.def.name, a.def.name)
3156
+ ? 1
3157
+ : 0);
1464
3158
  const body = [];
1465
3159
  const symbol = symbolMemberKey(lowerer, info, name, loc);
1466
- if (symbol || isClassOwnEnumerableFieldName(name) && !name.startsWith("sym:")) {
3160
+ if (symbol || (isClassOwnEnumerableFieldName(name) && !name.startsWith("sym:"))) {
1467
3161
  const prototypeMethod = lowerer.prototypeMethodAccesses.has(name);
1468
3162
  if (prototypeMethod)
1469
3163
  classPrototypeData(lowerer, info, loc, receiver);
1470
- const bag = { kind: "call", callee: this.propertyBag.name,
1471
- args: [lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc };
3164
+ const bag = {
3165
+ kind: "call",
3166
+ callee: this.propertyBag.name,
3167
+ args: [lowerer.coerceToExpected(receiver, DYN)],
3168
+ type: DYN,
3169
+ loc,
3170
+ };
1472
3171
  const key = symbol ?? { kind: "strLit", value: name, type: STRING, loc };
1473
- body.push({ kind: "if", cond: { kind: "libCall", fn: symbol ? "dyn.hasOwnComputed" : "dyn.hasKey", args: [bag, key], type: BOOL, loc },
1474
- then: [{ kind: "return", value: { kind: "libCall", fn: symbol ? "dyn.reflectGet" : "dyn.bagGet", args: [bag, key, lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc }, loc }], else_: null, loc });
3172
+ body.push({
3173
+ kind: "if",
3174
+ cond: {
3175
+ kind: "libCall",
3176
+ fn: symbol ? "dyn.hasOwnComputed" : "dyn.hasKey",
3177
+ args: [bag, key],
3178
+ type: BOOL,
3179
+ loc,
3180
+ },
3181
+ then: [
3182
+ {
3183
+ kind: "return",
3184
+ value: {
3185
+ kind: "libCall",
3186
+ fn: symbol ? "dyn.reflectGet" : "dyn.bagGet",
3187
+ args: [bag, key, lowerer.coerceToExpected(receiver, DYN)],
3188
+ type: DYN,
3189
+ loc,
3190
+ },
3191
+ loc,
3192
+ },
3193
+ ],
3194
+ else_: null,
3195
+ loc,
3196
+ });
1475
3197
  if (prototypeMethod) {
1476
3198
  body.push({ kind: "return", value: dynUndefinedExpr(loc), loc });
1477
3199
  return body;
@@ -1480,19 +3202,58 @@ export class ClassDynamicDispatch {
1480
3202
  for (const candidate of overrides) {
1481
3203
  const selected = classMethodValue(lowerer, info.decl, candidate, name, loc);
1482
3204
  const branch = selected && canConvertToDyn(selected.type, getRecord, getUnion)
1483
- ? [{ kind: "return", value: { kind: "dynFrom", value: selected, type: DYN, loc }, loc }]
3205
+ ? [
3206
+ {
3207
+ kind: "return",
3208
+ value: { kind: "dynFrom", value: selected, type: DYN, loc },
3209
+ loc,
3210
+ },
3211
+ ]
1484
3212
  : fence();
1485
- body.push({ kind: "if", cond: { kind: "instanceOf", value: receiver, className: candidate.def.name, type: BOOL, loc }, then: branch, else_: null, loc });
3213
+ body.push({
3214
+ kind: "if",
3215
+ cond: {
3216
+ kind: "instanceOf",
3217
+ value: receiver,
3218
+ className: candidate.def.name,
3219
+ type: BOOL,
3220
+ loc,
3221
+ },
3222
+ then: branch,
3223
+ else_: null,
3224
+ loc,
3225
+ });
1486
3226
  }
1487
- body.push({ kind: "return", value: { kind: "dynFrom", value: method, type: DYN, loc }, loc });
3227
+ body.push({
3228
+ kind: "return",
3229
+ value: { kind: "dynFrom", value: method, type: DYN, loc },
3230
+ loc,
3231
+ });
1488
3232
  return body;
1489
3233
  }
1490
3234
  }
1491
3235
  if (!field && !accessor) {
1492
3236
  const instance = lowerer.coerceToExpected(receiver, DYN);
1493
- const bag = { kind: "call", callee: this.propertyBag.name, args: [instance], type: DYN, loc };
1494
- return [{ kind: "return", value: { kind: "libCall", fn: "dyn.bagGet", args: [bag,
1495
- { kind: "strLit", value: name, type: STRING, loc }, instance], type: DYN, loc }, loc }];
3237
+ const bag = {
3238
+ kind: "call",
3239
+ callee: this.propertyBag.name,
3240
+ args: [instance],
3241
+ type: DYN,
3242
+ loc,
3243
+ };
3244
+ return [
3245
+ {
3246
+ kind: "return",
3247
+ value: {
3248
+ kind: "libCall",
3249
+ fn: "dyn.bagGet",
3250
+ args: [bag, { kind: "strLit", value: name, type: STRING, loc }, instance],
3251
+ type: DYN,
3252
+ loc,
3253
+ },
3254
+ loc,
3255
+ },
3256
+ ];
1496
3257
  }
1497
3258
  const type = field ?? accessor.sig.ret;
1498
3259
  if (!canConvertToDyn(type, getRecord, getUnion))
@@ -1506,39 +3267,136 @@ export class ClassDynamicDispatch {
1506
3267
  if (boxed.kind === "dynFrom" && mutable(boxed.value.type))
1507
3268
  boxed.liveRef = true;
1508
3269
  if (accessor) {
1509
- const bag = { kind: "call", callee: this.propertyBag.name,
1510
- args: [lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc };
3270
+ const bag = {
3271
+ kind: "call",
3272
+ callee: this.propertyBag.name,
3273
+ args: [lowerer.coerceToExpected(receiver, DYN)],
3274
+ type: DYN,
3275
+ loc,
3276
+ };
1511
3277
  const key = { kind: "strLit", value: name, type: STRING, loc };
1512
- return [{ kind: "if", cond: { kind: "libCall", fn: "dyn.hasOwn", args: [bag, key], type: BOOL, loc },
1513
- then: [{ kind: "return", value: { kind: "libCall", fn: "dyn.bagGet", args: [bag, key, lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc }, loc }], else_: null, loc },
1514
- { kind: "return", value: boxed, loc }];
3278
+ return [
3279
+ {
3280
+ kind: "if",
3281
+ cond: { kind: "libCall", fn: "dyn.hasOwn", args: [bag, key], type: BOOL, loc },
3282
+ then: [
3283
+ {
3284
+ kind: "return",
3285
+ value: {
3286
+ kind: "libCall",
3287
+ fn: "dyn.bagGet",
3288
+ args: [bag, key, lowerer.coerceToExpected(receiver, DYN)],
3289
+ type: DYN,
3290
+ loc,
3291
+ },
3292
+ loc,
3293
+ },
3294
+ ],
3295
+ else_: null,
3296
+ loc,
3297
+ },
3298
+ { kind: "return", value: boxed, loc },
3299
+ ];
1515
3300
  }
1516
3301
  if (field && info.def.tracksOwnFields) {
1517
3302
  const instance = lowerer.coerceToExpected(receiver, DYN);
1518
- const bag = { kind: "call", callee: this.propertyBag.name, args: [instance], type: DYN, loc };
3303
+ const bag = {
3304
+ kind: "call",
3305
+ callee: this.propertyBag.name,
3306
+ args: [instance],
3307
+ type: DYN,
3308
+ loc,
3309
+ };
1519
3310
  const symbol = symbolMemberKey(lowerer, info, name, loc);
1520
3311
  const key = symbol ?? { kind: "strLit", value: name, type: STRING, loc };
1521
- return [{ kind: "return", value: { kind: "ternary", cond: { kind: "libCall", fn: symbol ? "dyn.hasOwnComputed" : "dyn.hasOwn", args: [bag, key], type: BOOL, loc },
1522
- then: boxed, else_: { kind: "libCall", fn: symbol ? "dyn.reflectGet" : "dyn.bagGet", args: [bag, key, instance], type: DYN, loc }, type: DYN, loc }, loc }];
3312
+ return [
3313
+ {
3314
+ kind: "return",
3315
+ value: {
3316
+ kind: "ternary",
3317
+ cond: {
3318
+ kind: "libCall",
3319
+ fn: symbol ? "dyn.hasOwnComputed" : "dyn.hasOwn",
3320
+ args: [bag, key],
3321
+ type: BOOL,
3322
+ loc,
3323
+ },
3324
+ then: boxed,
3325
+ else_: {
3326
+ kind: "libCall",
3327
+ fn: symbol ? "dyn.reflectGet" : "dyn.bagGet",
3328
+ args: [bag, key, instance],
3329
+ type: DYN,
3330
+ loc,
3331
+ },
3332
+ type: DYN,
3333
+ loc,
3334
+ },
3335
+ loc,
3336
+ },
3337
+ ];
1523
3338
  }
1524
3339
  return [{ kind: "return", value: boxed, loc }];
1525
3340
  }
1526
- if (!field && !accessor && isClassOwnEnumerableFieldName(name) && !name.startsWith("sym:") && !findMethodOn(lowerer, info, `get:${name}`)) {
1527
- const bag = { kind: "call", callee: this.propertyBag.name,
1528
- args: [lowerer.coerceToExpected(receiver, DYN)], type: DYN, loc };
1529
- return [{ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.bagSet", args: [bag,
1530
- { kind: "strLit", value: name, type: STRING, loc }, varRef("p.1", DYN, loc), lowerer.coerceToExpected(receiver, DYN)], type: VOID, loc }, loc },
1531
- { kind: "return", value: null, loc }];
3341
+ if (!field &&
3342
+ !accessor &&
3343
+ isClassOwnEnumerableFieldName(name) &&
3344
+ !name.startsWith("sym:") &&
3345
+ !findMethodOn(lowerer, info, `get:${name}`)) {
3346
+ const bag = {
3347
+ kind: "call",
3348
+ callee: this.propertyBag.name,
3349
+ args: [lowerer.coerceToExpected(receiver, DYN)],
3350
+ type: DYN,
3351
+ loc,
3352
+ };
3353
+ return [
3354
+ {
3355
+ kind: "exprStmt",
3356
+ expr: {
3357
+ kind: "libCall",
3358
+ fn: "dyn.bagSet",
3359
+ args: [
3360
+ bag,
3361
+ { kind: "strLit", value: name, type: STRING, loc },
3362
+ varRef("p.1", DYN, loc),
3363
+ lowerer.coerceToExpected(receiver, DYN),
3364
+ ],
3365
+ type: VOID,
3366
+ loc,
3367
+ },
3368
+ loc,
3369
+ },
3370
+ { kind: "return", value: null, loc },
3371
+ ];
1532
3372
  }
1533
3373
  if (!field && !accessor)
1534
- return [{ kind: "throw", value: {
1535
- kind: "libCall", fn: "error.new", args: [{
1536
- kind: "strLit", value: `Cannot set property ${name} of #<${info.def.jsName ?? info.def.name}> which has only a getter`, type: STRING, loc,
1537
- }], type: { kind: "object", className: "%TypeError" }, loc,
1538
- }, loc }];
3374
+ return [
3375
+ {
3376
+ kind: "throw",
3377
+ value: {
3378
+ kind: "libCall",
3379
+ fn: "error.new",
3380
+ args: [
3381
+ {
3382
+ kind: "strLit",
3383
+ value: `Cannot set property ${name} of #<${info.def.jsName ?? info.def.name}> which has only a getter`,
3384
+ type: STRING,
3385
+ loc,
3386
+ },
3387
+ ],
3388
+ type: { kind: "object", className: "%TypeError" },
3389
+ loc,
3390
+ },
3391
+ loc,
3392
+ },
3393
+ ];
1539
3394
  const type = field ?? accessor.sig.params[0].type;
1540
- const checkable = (t) => isDynTypedRefType(t) || isUnitType(t) ||
1541
- (t.kind === "union" ? getUnion(t.unionId)?.arms.every(checkable) ?? false : canDynCheckTo(t, getRecord, getUnion));
3395
+ const checkable = (t) => isDynTypedRefType(t) ||
3396
+ isUnitType(t) ||
3397
+ (t.kind === "union"
3398
+ ? (getUnion(t.unionId)?.arms.every(checkable) ?? false)
3399
+ : canDynCheckTo(t, getRecord, getUnion));
1542
3400
  if (!checkable(type))
1543
3401
  return fence();
1544
3402
  const value = lowerer.coerceToExpected(varRef("p.1", DYN, loc), type);
@@ -1546,47 +3404,143 @@ export class ClassDynamicDispatch {
1546
3404
  return fence();
1547
3405
  const store = field
1548
3406
  ? { kind: "fieldSet", obj: receiver, className: info.def.name, field: name, value, loc }
1549
- : { kind: "exprStmt", expr: accessorCall(lowerer, info.def.name, member, receiver, [value], VOID, loc), loc };
3407
+ : {
3408
+ kind: "exprStmt",
3409
+ expr: accessorCall(lowerer, info.def.name, member, receiver, [value], VOID, loc),
3410
+ loc,
3411
+ };
1550
3412
  return [store, { kind: "return", value: null, loc }];
1551
3413
  }
1552
3414
  methodBody(lowerer, dispatch, info, receiver) {
1553
3415
  const { method, loc } = dispatch.source;
1554
- const fence = () => [{ kind: "runtimeFence", code: "SC2020", message: `calling '${method}' on this native class through an untyped value is not supported yet`, loc }];
1555
- if (info.builtinStream || emitterRooted(lowerer, info) && EMITTER_METHODS.has(method) && !findMethodOn(lowerer, info, method)) {
3416
+ const fence = () => [
3417
+ {
3418
+ kind: "runtimeFence",
3419
+ code: "SC2020",
3420
+ message: `calling '${method}' on this native class through an untyped value is not supported yet`,
3421
+ loc,
3422
+ },
3423
+ ];
3424
+ if (info.builtinStream ||
3425
+ (emitterRooted(lowerer, info) &&
3426
+ EMITTER_METHODS.has(method) &&
3427
+ !findMethodOn(lowerer, info, method))) {
1556
3428
  const incoming = dispatch.source.args.map((_, i) => varRef(`p.${i + 1}`, DYN, loc));
1557
- const registering = ["on", "addListener", "once", "prependListener", "prependOnceListener"].includes(method);
3429
+ const registering = [
3430
+ "on",
3431
+ "addListener",
3432
+ "once",
3433
+ "prependListener",
3434
+ "prependOnceListener",
3435
+ ].includes(method);
1558
3436
  const removing = method === "off" || method === "removeListener";
1559
- const ret = (value) => [{ kind: "return", value: lowerer.coerceToExpected(value, DYN), loc }];
3437
+ const ret = (value) => [
3438
+ { kind: "return", value: lowerer.coerceToExpected(value, DYN), loc },
3439
+ ];
1560
3440
  if (method === "emit") {
1561
3441
  if (!incoming.length)
1562
3442
  return fence();
1563
- return ret({ kind: "libCall", fn: "emitter.emitFlex", args: [receiver,
1564
- lowerer.coerceToExpected(incoming[0], STRING), ...incoming.slice(1)], type: BOOL, loc });
3443
+ return ret({
3444
+ kind: "libCall",
3445
+ fn: "emitter.emitFlex",
3446
+ args: [receiver, lowerer.coerceToExpected(incoming[0], STRING), ...incoming.slice(1)],
3447
+ type: BOOL,
3448
+ loc,
3449
+ });
1565
3450
  }
1566
3451
  if (registering || removing) {
1567
3452
  if (incoming.length < 2)
1568
3453
  return fence();
1569
3454
  const event = lowerer.coerceToExpected(incoming[0], STRING);
1570
3455
  const cb = incoming[1];
1571
- return [{ kind: "exprStmt", expr: { kind: "libCall", fn: "emitter.checkListener", args: [cb], type: VOID, loc }, loc }, ...ret({ kind: "libCall", fn: registering ? info.builtinStream ? "stream.onDyn" : "emitter.onFlex" : "emitter.offDyn", args: [receiver, event, cb, ...(registering ? [
1572
- { kind: "boolLit", value: method === "once" || method === "prependOnceListener", type: BOOL, loc },
1573
- { kind: "boolLit", value: method.startsWith("prepend"), type: BOOL, loc },
1574
- ] : [])], type: receiver.type, loc })];
3456
+ return [
3457
+ {
3458
+ kind: "exprStmt",
3459
+ expr: { kind: "libCall", fn: "emitter.checkListener", args: [cb], type: VOID, loc },
3460
+ loc,
3461
+ },
3462
+ ...ret({
3463
+ kind: "libCall",
3464
+ fn: registering
3465
+ ? info.builtinStream
3466
+ ? "stream.onDyn"
3467
+ : "emitter.onFlex"
3468
+ : "emitter.offDyn",
3469
+ args: [
3470
+ receiver,
3471
+ event,
3472
+ cb,
3473
+ ...(registering
3474
+ ? [
3475
+ {
3476
+ kind: "boolLit",
3477
+ value: method === "once" || method === "prependOnceListener",
3478
+ type: BOOL,
3479
+ loc,
3480
+ },
3481
+ {
3482
+ kind: "boolLit",
3483
+ value: method.startsWith("prepend"),
3484
+ type: BOOL,
3485
+ loc,
3486
+ },
3487
+ ]
3488
+ : []),
3489
+ ],
3490
+ type: receiver.type,
3491
+ loc,
3492
+ }),
3493
+ ];
1575
3494
  }
1576
3495
  if (method === "read")
1577
- return ret({ kind: "libCall", fn: "readable.readDyn", args: [receiver, incoming[0] ?? dynUndefinedExpr(loc)], type: DYN, loc });
3496
+ return ret({
3497
+ kind: "libCall",
3498
+ fn: "readable.readDyn",
3499
+ args: [receiver, incoming[0] ?? dynUndefinedExpr(loc)],
3500
+ type: DYN,
3501
+ loc,
3502
+ });
1578
3503
  if (method === "pause" || method === "resume" || method === "isPaused")
1579
- return ret({ kind: "libCall", fn: method === "pause" ? "readable.pause" : method === "resume" ? "readable.resume" : "readable.isPaused", args: [receiver], type: method === "isPaused" ? BOOL : receiver.type, loc });
3504
+ return ret({
3505
+ kind: "libCall",
3506
+ fn: method === "pause"
3507
+ ? "readable.pause"
3508
+ : method === "resume"
3509
+ ? "readable.resume"
3510
+ : "readable.isPaused",
3511
+ args: [receiver],
3512
+ type: method === "isPaused" ? BOOL : receiver.type,
3513
+ loc,
3514
+ });
1580
3515
  if (method === "destroy" && (!incoming.length || incoming[0]?.kind === "unitLit"))
1581
- return ret({ kind: "libCall", fn: "stream.destroy", args: [receiver], type: receiver.type, loc });
3516
+ return ret({
3517
+ kind: "libCall",
3518
+ fn: "stream.destroy",
3519
+ args: [receiver],
3520
+ type: receiver.type,
3521
+ loc,
3522
+ });
1582
3523
  return fence();
1583
3524
  }
1584
3525
  const methodInfo = findMethodOn(lowerer, info, method);
1585
3526
  if (this.asyncFree && (methodInfo?.sig.gen || methodInfo?.sig.async)) {
1586
- return [{ kind: "runtimeFence", code: "SC4005", message: `calling async or generator method '${method}' through an untyped library value is not supported`, loc }];
3527
+ return [
3528
+ {
3529
+ kind: "runtimeFence",
3530
+ code: "SC4005",
3531
+ message: `calling async or generator method '${method}' through an untyped library value is not supported`,
3532
+ loc,
3533
+ },
3534
+ ];
1587
3535
  }
1588
3536
  if (methodInfo?.declarer.builtinError && method === "toString") {
1589
- return [{ kind: "return", value: { kind: "dynFrom", value: errorToStringCall(lowerer, receiver), type: DYN, loc }, loc }];
3537
+ return [
3538
+ {
3539
+ kind: "return",
3540
+ value: { kind: "dynFrom", value: errorToStringCall(lowerer, receiver), type: DYN, loc },
3541
+ loc,
3542
+ },
3543
+ ];
1590
3544
  }
1591
3545
  const generic = methodInfo ? null : findGenericMethodOn(lowerer, info, method);
1592
3546
  let params;
@@ -1601,8 +3555,10 @@ export class ClassDynamicDispatch {
1601
3555
  callee = `%${owner.def.name}.${method}`;
1602
3556
  virtual = lowerer.overrideBelow(owner, method) || methodInfo.sig.abstract === true;
1603
3557
  }
1604
- else if (generic?.info.implicitParams && generic.declarer.decl &&
1605
- !lowerer.overrideBelow(info, method) && !genericOverrideBelow(lowerer, info, method)) {
3558
+ else if (generic?.info.implicitParams &&
3559
+ generic.declarer.decl &&
3560
+ !lowerer.overrideBelow(info, method) &&
3561
+ !genericOverrideBelow(info, method)) {
1606
3562
  owner = generic.declarer;
1607
3563
  // A failed eager specialization leaves a signature in the instance
1608
3564
  // cache, but no body. Later dispatch arities must retain the fence
@@ -1621,13 +3577,20 @@ export class ClassDynamicDispatch {
1621
3577
  let index = 0;
1622
3578
  for (const param of params) {
1623
3579
  if ((param.mode === "dynRest" || param.mode === "arguments") && param.type.kind === "dyn") {
1624
- args.push({ kind: "dynArrLit", elems: param.mode === "arguments" ? incoming : incoming.slice(index), type: DYN, loc });
3580
+ args.push({
3581
+ kind: "dynArrLit",
3582
+ elems: param.mode === "arguments" ? incoming : incoming.slice(index),
3583
+ type: DYN,
3584
+ loc,
3585
+ });
1625
3586
  index = incoming.length;
1626
3587
  continue;
1627
3588
  }
1628
3589
  if (param.mode === "rest" && param.type.kind === "array") {
1629
3590
  const element = param.type.elem;
1630
- const elems = incoming.slice(index).map((value) => lowerer.coerceToExpected(value, element));
3591
+ const elems = incoming
3592
+ .slice(index)
3593
+ .map((value) => lowerer.coerceToExpected(value, element));
1631
3594
  if (elems.some((value) => !typeEquals(value.type, element)))
1632
3595
  return fence();
1633
3596
  args.push({ kind: "arrayLit", elems, type: param.type, loc });
@@ -1643,8 +3606,21 @@ export class ClassDynamicDispatch {
1643
3606
  args.push(converted);
1644
3607
  }
1645
3608
  const call = virtual
1646
- ? { kind: "virtualCall", className: owner.def.name, method, args: [upcastTo(lowerer, receiver, owner.def.name), ...args], type: result, loc }
1647
- : { kind: "call", callee, args: [upcastTo(lowerer, receiver, owner.def.name), ...args], type: result, loc };
3609
+ ? {
3610
+ kind: "virtualCall",
3611
+ className: owner.def.name,
3612
+ method,
3613
+ args: [upcastTo(lowerer, receiver, owner.def.name), ...args],
3614
+ type: result,
3615
+ loc,
3616
+ }
3617
+ : {
3618
+ kind: "call",
3619
+ callee,
3620
+ args: [upcastTo(lowerer, receiver, owner.def.name), ...args],
3621
+ type: result,
3622
+ loc,
3623
+ };
1648
3624
  let body;
1649
3625
  if (result.kind === "void")
1650
3626
  body = [
@@ -1665,11 +3641,41 @@ export class ClassDynamicDispatch {
1665
3641
  }
1666
3642
  if (isClassCallback(lowerer, info, method)) {
1667
3643
  const descriptor = varRef("p.callback", DYN, loc);
1668
- body.unshift({ kind: "if", cond: { kind: "dynTest", test: "undefined", negated: true, value: descriptor, type: BOOL, loc }, then: [
1669
- { kind: "return", value: { kind: "dynCall", callee: { kind: "dynKeyGet", value: descriptor,
1670
- key: { kind: "strLit", value: "value", type: STRING, loc }, type: DYN, loc }, receiver: varRef("p.0", DYN, loc),
1671
- args: incoming, calleeName: dispatch.source.calleeName, calleeNameValue: varRef("p.calleeName", STRING, loc), type: DYN, loc }, loc },
1672
- ], else_: null, loc });
3644
+ body.unshift({
3645
+ kind: "if",
3646
+ cond: {
3647
+ kind: "dynTest",
3648
+ test: "undefined",
3649
+ negated: true,
3650
+ value: descriptor,
3651
+ type: BOOL,
3652
+ loc,
3653
+ },
3654
+ then: [
3655
+ {
3656
+ kind: "return",
3657
+ value: {
3658
+ kind: "dynCall",
3659
+ callee: {
3660
+ kind: "dynKeyGet",
3661
+ value: descriptor,
3662
+ key: { kind: "strLit", value: "value", type: STRING, loc },
3663
+ type: DYN,
3664
+ loc,
3665
+ },
3666
+ receiver: varRef("p.0", DYN, loc),
3667
+ args: incoming,
3668
+ calleeName: dispatch.source.calleeName,
3669
+ calleeNameValue: varRef("p.calleeName", STRING, loc),
3670
+ type: DYN,
3671
+ loc,
3672
+ },
3673
+ loc,
3674
+ },
3675
+ ],
3676
+ else_: null,
3677
+ loc,
3678
+ });
1673
3679
  }
1674
3680
  return body;
1675
3681
  }