@scriptc/compiler 0.3.1 → 0.3.3

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 (492) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +832 -55
  2. package/dist/backend/cycle-analysis.js +6 -1
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/executable-features.js +1 -0
  5. package/dist/backend/executable-features.js.map +1 -1
  6. package/dist/backend/literals.d.ts +7 -0
  7. package/dist/backend/literals.js +32 -0
  8. package/dist/backend/literals.js.map +1 -1
  9. package/dist/backend/literals.test.js +17 -1
  10. package/dist/backend/literals.test.js.map +1 -1
  11. package/dist/backend/llvm/alloc.d.ts +15 -4
  12. package/dist/backend/llvm/alloc.js +63 -25
  13. package/dist/backend/llvm/alloc.js.map +1 -1
  14. package/dist/backend/llvm/alloc.test.js +62 -2
  15. package/dist/backend/llvm/alloc.test.js.map +1 -1
  16. package/dist/backend/llvm/appended-array-literals.d.ts +2 -0
  17. package/dist/backend/llvm/appended-array-literals.js +109 -0
  18. package/dist/backend/llvm/appended-array-literals.js.map +1 -0
  19. package/dist/backend/llvm/appended-array-literals.test.d.ts +1 -0
  20. package/dist/backend/llvm/appended-array-literals.test.js +90 -0
  21. package/dist/backend/llvm/appended-array-literals.test.js.map +1 -0
  22. package/dist/backend/llvm/array-search.d.ts +8 -0
  23. package/dist/backend/llvm/array-search.js +52 -0
  24. package/dist/backend/llvm/array-search.js.map +1 -0
  25. package/dist/backend/llvm/array-search.test.d.ts +1 -0
  26. package/dist/backend/llvm/array-search.test.js +72 -0
  27. package/dist/backend/llvm/array-search.test.js.map +1 -0
  28. package/dist/backend/llvm/call-lifetimes.d.ts +11 -1
  29. package/dist/backend/llvm/call-lifetimes.js +74 -4
  30. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  31. package/dist/backend/llvm/call-lifetimes.test.js +54 -0
  32. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  33. package/dist/backend/llvm/classes.js +97 -38
  34. package/dist/backend/llvm/classes.js.map +1 -1
  35. package/dist/backend/llvm/classes.test.js +2 -2
  36. package/dist/backend/llvm/common.d.ts +1 -1
  37. package/dist/backend/llvm/common.js +1 -1
  38. package/dist/backend/llvm/dense-array-access.d.ts +5 -0
  39. package/dist/backend/llvm/dense-array-access.js +18 -13
  40. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  41. package/dist/backend/llvm/dense-array-access.test.js +15 -2
  42. package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
  43. package/dist/backend/llvm/dyn.d.ts +6 -0
  44. package/dist/backend/llvm/dyn.js +84 -11
  45. package/dist/backend/llvm/dyn.js.map +1 -1
  46. package/dist/backend/llvm/emitter.d.ts +108 -16
  47. package/dist/backend/llvm/emitter.js +598 -108
  48. package/dist/backend/llvm/emitter.js.map +1 -1
  49. package/dist/backend/llvm/emitter.test.js +26 -3
  50. package/dist/backend/llvm/emitter.test.js.map +1 -1
  51. package/dist/backend/llvm/expr-async.js +174 -7
  52. package/dist/backend/llvm/expr-async.js.map +1 -1
  53. package/dist/backend/llvm/expr-bytes.js +11 -0
  54. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  55. package/dist/backend/llvm/expr-callbacks.d.ts +8 -0
  56. package/dist/backend/llvm/expr-callbacks.js +96 -2
  57. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  58. package/dist/backend/llvm/expr-calls.d.ts +12 -1
  59. package/dist/backend/llvm/expr-calls.js +133 -54
  60. package/dist/backend/llvm/expr-calls.js.map +1 -1
  61. package/dist/backend/llvm/expr-containers.d.ts +7 -0
  62. package/dist/backend/llvm/expr-containers.js +80 -22
  63. package/dist/backend/llvm/expr-containers.js.map +1 -1
  64. package/dist/backend/llvm/expr-context.d.ts +2 -0
  65. package/dist/backend/llvm/expr-control.d.ts +8 -0
  66. package/dist/backend/llvm/expr-control.js +103 -69
  67. package/dist/backend/llvm/expr-control.js.map +1 -1
  68. package/dist/backend/llvm/expr-dynamic.js +21 -10
  69. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  70. package/dist/backend/llvm/expr-primitives.d.ts +7 -0
  71. package/dist/backend/llvm/expr-primitives.js +53 -51
  72. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  73. package/dist/backend/llvm/expr-records.js +19 -5
  74. package/dist/backend/llvm/expr-records.js.map +1 -1
  75. package/dist/backend/llvm/expr-stream-bridges.d.ts +8 -0
  76. package/dist/backend/llvm/expr-stream-bridges.js +111 -39
  77. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  78. package/dist/backend/llvm/expr-stream-bridges.test.js +49 -1
  79. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
  80. package/dist/backend/llvm/expr-stream-callbacks.d.ts +13 -2
  81. package/dist/backend/llvm/expr-stream-callbacks.js +80 -5
  82. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  83. package/dist/backend/llvm/inline-unions.d.ts +48 -0
  84. package/dist/backend/llvm/inline-unions.js +134 -0
  85. package/dist/backend/llvm/inline-unions.js.map +1 -0
  86. package/dist/backend/llvm/inline-unions.test.d.ts +1 -0
  87. package/dist/backend/llvm/inline-unions.test.js +124 -0
  88. package/dist/backend/llvm/inline-unions.test.js.map +1 -0
  89. package/dist/backend/llvm/int32-abi.d.ts +18 -2
  90. package/dist/backend/llvm/int32-abi.js +23 -2
  91. package/dist/backend/llvm/int32-abi.js.map +1 -1
  92. package/dist/backend/llvm/int32-abi.test.js +75 -1
  93. package/dist/backend/llvm/int32-abi.test.js.map +1 -1
  94. package/dist/backend/llvm/integer-remainder.d.ts +28 -5
  95. package/dist/backend/llvm/integer-remainder.js +80 -9
  96. package/dist/backend/llvm/integer-remainder.js.map +1 -1
  97. package/dist/backend/llvm/lib-dispatch.js +170 -28
  98. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  99. package/dist/backend/llvm/lib-filesystem.js +181 -5
  100. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  101. package/dist/backend/llvm/lib-network.js +9 -6
  102. package/dist/backend/llvm/lib-network.js.map +1 -1
  103. package/dist/backend/llvm/lib-process.js +2 -2
  104. package/dist/backend/llvm/lib-process.js.map +1 -1
  105. package/dist/backend/llvm/lib-shared.js +208 -9
  106. package/dist/backend/llvm/lib-shared.js.map +1 -1
  107. package/dist/backend/llvm/lib-stream.js +97 -0
  108. package/dist/backend/llvm/lib-stream.js.map +1 -1
  109. package/dist/backend/llvm/local-array-reads.js +12 -6
  110. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  111. package/dist/backend/llvm/local-array-reads.test.js +6 -3
  112. package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
  113. package/dist/backend/llvm/local-union-storage.d.ts +26 -2
  114. package/dist/backend/llvm/local-union-storage.js +132 -12
  115. package/dist/backend/llvm/local-union-storage.js.map +1 -1
  116. package/dist/backend/llvm/local-union-storage.test.js +107 -1
  117. package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
  118. package/dist/backend/llvm/loop-array-borrows.d.ts +8 -2
  119. package/dist/backend/llvm/loop-array-borrows.js +93 -13
  120. package/dist/backend/llvm/loop-array-borrows.js.map +1 -1
  121. package/dist/backend/llvm/map-number-lookup.d.ts +20 -0
  122. package/dist/backend/llvm/map-number-lookup.js +66 -0
  123. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  124. package/dist/backend/llvm/map-number-lookup.test.d.ts +1 -0
  125. package/dist/backend/llvm/map-number-lookup.test.js +102 -0
  126. package/dist/backend/llvm/map-number-lookup.test.js.map +1 -0
  127. package/dist/backend/llvm/map-read-lifetimes.js +1 -0
  128. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  129. package/dist/backend/llvm/publish.d.ts +4 -0
  130. package/dist/backend/llvm/publish.js +3 -1
  131. package/dist/backend/llvm/publish.js.map +1 -1
  132. package/dist/backend/llvm/record-results.d.ts +29 -0
  133. package/dist/backend/llvm/record-results.js +260 -0
  134. package/dist/backend/llvm/record-results.js.map +1 -0
  135. package/dist/backend/llvm/reference-effects.js +15 -0
  136. package/dist/backend/llvm/reference-effects.js.map +1 -1
  137. package/dist/backend/llvm/reference-writes.js +29 -9
  138. package/dist/backend/llvm/reference-writes.js.map +1 -1
  139. package/dist/backend/llvm/regions.d.ts +68 -0
  140. package/dist/backend/llvm/regions.js +314 -0
  141. package/dist/backend/llvm/regions.js.map +1 -0
  142. package/dist/backend/llvm/regions.test.d.ts +1 -0
  143. package/dist/backend/llvm/regions.test.js +173 -0
  144. package/dist/backend/llvm/regions.test.js.map +1 -0
  145. package/dist/backend/llvm/serialized-ir-emission.test.js +2 -0
  146. package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -1
  147. package/dist/backend/llvm/shapes.d.ts +86 -13
  148. package/dist/backend/llvm/shapes.js +208 -54
  149. package/dist/backend/llvm/shapes.js.map +1 -1
  150. package/dist/backend/llvm/shapes.test.js +68 -9
  151. package/dist/backend/llvm/shapes.test.js.map +1 -1
  152. package/dist/backend/llvm/split-loops.js +1 -1
  153. package/dist/backend/llvm/split-loops.js.map +1 -1
  154. package/dist/backend/llvm/stack-objects.d.ts +29 -0
  155. package/dist/backend/llvm/stack-objects.js +142 -0
  156. package/dist/backend/llvm/stack-objects.js.map +1 -0
  157. package/dist/backend/llvm/stack-objects.test.d.ts +1 -0
  158. package/dist/backend/llvm/stack-objects.test.js +255 -0
  159. package/dist/backend/llvm/stack-objects.test.js.map +1 -0
  160. package/dist/backend/llvm/string-reads.d.ts +4 -1
  161. package/dist/backend/llvm/string-reads.js +89 -9
  162. package/dist/backend/llvm/string-reads.js.map +1 -1
  163. package/dist/backend/llvm/switch-dispatch.js +5 -4
  164. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  165. package/dist/backend/llvm/walkers.d.ts +13 -0
  166. package/dist/backend/llvm/walkers.js +108 -10
  167. package/dist/backend/llvm/walkers.js.map +1 -1
  168. package/dist/backend/may-throw.js +10 -4
  169. package/dist/backend/may-throw.js.map +1 -1
  170. package/dist/backend/native/contracts.d.ts +7 -2
  171. package/dist/backend/native/executable.js +28 -2
  172. package/dist/backend/native/executable.js.map +1 -1
  173. package/dist/backend/native/library.js +1 -1
  174. package/dist/backend/native/library.js.map +1 -1
  175. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  176. package/dist/backend/native/runtime-inputs.js +3 -0
  177. package/dist/backend/native/runtime-inputs.js.map +1 -1
  178. package/dist/backend/native-link-info-core.d.ts +1 -0
  179. package/dist/backend/native-link-info-core.js.map +1 -1
  180. package/dist/backend/native-toolchain.test.js +1 -1
  181. package/dist/backend/native-toolchain.test.js.map +1 -1
  182. package/dist/backend/runtime-abi.d.ts +2 -2
  183. package/dist/backend/runtime-abi.js +2 -2
  184. package/dist/backend/runtime-pack-core.d.ts +1 -0
  185. package/dist/backend/runtime-pack-core.js +1 -0
  186. package/dist/backend/runtime-pack-core.js.map +1 -1
  187. package/dist/backend/runtime-pack-targets.test.js +1 -1
  188. package/dist/backend/runtime-pack.test.js +1 -1
  189. package/dist/backend/target-diagnostics.js +17 -0
  190. package/dist/backend/target-diagnostics.js.map +1 -1
  191. package/dist/backend/target-diagnostics.test.js +16 -0
  192. package/dist/backend/target-diagnostics.test.js.map +1 -1
  193. package/dist/compat/fetch-profile.js +4 -4
  194. package/dist/compat/fetch-profile.js.map +1 -1
  195. package/dist/contracts/check.js +2 -0
  196. package/dist/contracts/check.js.map +1 -1
  197. package/dist/coverage/report.js +1 -1
  198. package/dist/coverage/report.js.map +1 -1
  199. package/dist/diagnostics/diagnostic.d.ts +6 -5
  200. package/dist/diagnostics/diagnostic.js +7 -6
  201. package/dist/diagnostics/diagnostic.js.map +1 -1
  202. package/dist/executable/executable-cache.d.ts +1 -0
  203. package/dist/executable/executable-cache.js.map +1 -1
  204. package/dist/frontend/builtin-modules.d.ts +1 -1
  205. package/dist/frontend/builtin-modules.js +1 -0
  206. package/dist/frontend/builtin-modules.js.map +1 -1
  207. package/dist/frontend/comptime-node.js +2 -2
  208. package/dist/frontend/comptime-node.js.map +1 -1
  209. package/dist/frontend/experimental-import.d.ts +12 -0
  210. package/dist/frontend/experimental-import.js +63 -0
  211. package/dist/frontend/experimental-import.js.map +1 -0
  212. package/dist/frontend/lowering/binding-analysis.d.ts +1 -1
  213. package/dist/frontend/lowering/binding-analysis.js +1 -1
  214. package/dist/frontend/lowering/builtin-calls.d.ts +6 -1
  215. package/dist/frontend/lowering/builtin-calls.js +36 -0
  216. package/dist/frontend/lowering/builtin-calls.js.map +1 -1
  217. package/dist/frontend/lowering/builtins/arguments.d.ts +4 -0
  218. package/dist/frontend/lowering/builtins/arguments.js +8 -4
  219. package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
  220. package/dist/frontend/lowering/builtins/blob.d.ts +20 -0
  221. package/dist/frontend/lowering/builtins/blob.js +167 -0
  222. package/dist/frontend/lowering/builtins/blob.js.map +1 -0
  223. package/dist/frontend/lowering/builtins/child-process-async.d.ts +2 -2
  224. package/dist/frontend/lowering/builtins/child-process-async.js +2 -2
  225. package/dist/frontend/lowering/builtins/child-process-methods.js +1 -1
  226. package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
  227. package/dist/frontend/lowering/builtins/child-process-sync.js +1 -1
  228. package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
  229. package/dist/frontend/lowering/builtins/compression.js +3 -2
  230. package/dist/frontend/lowering/builtins/compression.js.map +1 -1
  231. package/dist/frontend/lowering/builtins/console.d.ts +16 -6
  232. package/dist/frontend/lowering/builtins/console.js +33 -9
  233. package/dist/frontend/lowering/builtins/console.js.map +1 -1
  234. package/dist/frontend/lowering/builtins/crypto.js +415 -120
  235. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  236. package/dist/frontend/lowering/builtins/errors.js +20 -0
  237. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  238. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +10 -0
  239. package/dist/frontend/lowering/builtins/filesystem-calls.js +89 -1
  240. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  241. package/dist/frontend/lowering/builtins/filesystem.d.ts +16 -7
  242. package/dist/frontend/lowering/builtins/filesystem.js +97 -15
  243. package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
  244. package/dist/frontend/lowering/builtins/fs-glob.d.ts +23 -0
  245. package/dist/frontend/lowering/builtins/fs-glob.js +224 -0
  246. package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -0
  247. package/dist/frontend/lowering/builtins/json.d.ts +2 -2
  248. package/dist/frontend/lowering/builtins/json.js +13 -4
  249. package/dist/frontend/lowering/builtins/json.js.map +1 -1
  250. package/dist/frontend/lowering/builtins/key-object.d.ts +13 -0
  251. package/dist/frontend/lowering/builtins/key-object.js +56 -0
  252. package/dist/frontend/lowering/builtins/key-object.js.map +1 -0
  253. package/dist/frontend/lowering/builtins/module-calls.js +60 -12
  254. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  255. package/dist/frontend/lowering/builtins/numbers.d.ts +1 -0
  256. package/dist/frontend/lowering/builtins/numbers.js +17 -0
  257. package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
  258. package/dist/frontend/lowering/builtins/operating-system.d.ts +18 -0
  259. package/dist/frontend/lowering/builtins/operating-system.js +361 -1
  260. package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
  261. package/dist/frontend/lowering/builtins/performance.d.ts +25 -3
  262. package/dist/frontend/lowering/builtins/performance.js +340 -5
  263. package/dist/frontend/lowering/builtins/performance.js.map +1 -1
  264. package/dist/frontend/lowering/builtins/process.d.ts +2 -2
  265. package/dist/frontend/lowering/builtins/process.js +122 -17
  266. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  267. package/dist/frontend/lowering/builtins/promises.js +109 -2
  268. package/dist/frontend/lowering/builtins/promises.js.map +1 -1
  269. package/dist/frontend/lowering/builtins/properties.d.ts +0 -7
  270. package/dist/frontend/lowering/builtins/properties.js +39 -11
  271. package/dist/frontend/lowering/builtins/properties.js.map +1 -1
  272. package/dist/frontend/lowering/builtins/readline.d.ts +23 -8
  273. package/dist/frontend/lowering/builtins/readline.js +266 -90
  274. package/dist/frontend/lowering/builtins/readline.js.map +1 -1
  275. package/dist/frontend/lowering/builtins/text-codecs.d.ts +3 -4
  276. package/dist/frontend/lowering/builtins/text-codecs.js +3 -4
  277. package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
  278. package/dist/frontend/lowering/builtins/url.d.ts +8 -0
  279. package/dist/frontend/lowering/builtins/url.js +36 -0
  280. package/dist/frontend/lowering/builtins/url.js.map +1 -1
  281. package/dist/frontend/lowering/call-arguments.js +1 -1
  282. package/dist/frontend/lowering/call-arguments.js.map +1 -1
  283. package/dist/frontend/lowering/call-signatures.js +20 -2
  284. package/dist/frontend/lowering/call-signatures.js.map +1 -1
  285. package/dist/frontend/lowering/checked-promise-all.d.ts +10 -3
  286. package/dist/frontend/lowering/checked-promise-all.js +52 -6
  287. package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
  288. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +8 -3
  289. package/dist/frontend/lowering/class-dynamic-dispatch.js +159 -32
  290. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  291. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +1 -0
  292. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  293. package/dist/frontend/lowering/class-protocol-dispatch.d.ts +45 -0
  294. package/dist/frontend/lowering/class-protocol-dispatch.js +516 -0
  295. package/dist/frontend/lowering/class-protocol-dispatch.js.map +1 -0
  296. package/dist/frontend/lowering/coercions/structural-plans.js +2 -1
  297. package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
  298. package/dist/frontend/lowering/coercions/structural.js +3 -3
  299. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  300. package/dist/frontend/lowering/collation-repertoire.js +6 -5
  301. package/dist/frontend/lowering/collation-repertoire.js.map +1 -1
  302. package/dist/frontend/lowering/containers/array-callbacks.js +33 -6
  303. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  304. package/dist/frontend/lowering/containers/array-construction.js +8 -4
  305. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  306. package/dist/frontend/lowering/containers/array-methods.d.ts +0 -7
  307. package/dist/frontend/lowering/containers/array-methods.js +43 -2
  308. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  309. package/dist/frontend/lowering/containers/array-pipelines.js +1 -1
  310. package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
  311. package/dist/frontend/lowering/containers/bytes.js +38 -26
  312. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  313. package/dist/frontend/lowering/containers/for-of.d.ts +1 -1
  314. package/dist/frontend/lowering/containers/for-of.js +5 -1
  315. package/dist/frontend/lowering/containers/for-of.js.map +1 -1
  316. package/dist/frontend/lowering/containers/indexed-objects.js +1 -1
  317. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  318. package/dist/frontend/lowering/containers/string-and-regexp.js +91 -0
  319. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  320. package/dist/frontend/lowering/crypto-tables.d.ts +3 -3
  321. package/dist/frontend/lowering/crypto-tables.js +77 -12
  322. package/dist/frontend/lowering/crypto-tables.js.map +1 -1
  323. package/dist/frontend/lowering/cycle-initialization.d.ts +18 -2
  324. package/dist/frontend/lowering/cycle-initialization.js +166 -12
  325. package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
  326. package/dist/frontend/lowering/deferred-module-initializers.js +7 -2
  327. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
  328. package/dist/frontend/lowering/deferred-module-initializers.test.js +28 -0
  329. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
  330. package/dist/frontend/lowering/expressions/nullish-assignment.js +10 -0
  331. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  332. package/dist/frontend/lowering/expressions/object-literals.js +21 -68
  333. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  334. package/dist/frontend/lowering/generator-delegation.d.ts +8 -0
  335. package/dist/frontend/lowering/generator-delegation.js +231 -10
  336. package/dist/frontend/lowering/generator-delegation.js.map +1 -1
  337. package/dist/frontend/lowering/generic-functions.d.ts +2 -2
  338. package/dist/frontend/lowering/generic-functions.js +2 -2
  339. package/dist/frontend/lowering/generic-functions.js.map +1 -1
  340. package/dist/frontend/lowering/http2-constants.js +1 -1
  341. package/dist/frontend/lowering/lifetime-regions.d.ts +11 -0
  342. package/dist/frontend/lowering/lifetime-regions.js +216 -0
  343. package/dist/frontend/lowering/lifetime-regions.js.map +1 -0
  344. package/dist/frontend/lowering/lower-array-sort.d.ts +40 -3
  345. package/dist/frontend/lowering/lower-array-sort.js +661 -194
  346. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  347. package/dist/frontend/lowering/lower-array-sort.test.js +103 -4
  348. package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -1
  349. package/dist/frontend/lowering/lower-assert.js +2 -2
  350. package/dist/frontend/lowering/lower-async-iteration.d.ts +6 -3
  351. package/dist/frontend/lowering/lower-async-iteration.js +248 -2
  352. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  353. package/dist/frontend/lowering/lower-calls.js +173 -111
  354. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  355. package/dist/frontend/lowering/lower-classes.d.ts +12 -5
  356. package/dist/frontend/lowering/lower-classes.js +156 -11
  357. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  358. package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
  359. package/dist/frontend/lowering/lower-comptime.js +4 -4
  360. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  361. package/dist/frontend/lowering/lower-console.d.ts +13 -0
  362. package/dist/frontend/lowering/lower-console.js +460 -4
  363. package/dist/frontend/lowering/lower-console.js.map +1 -1
  364. package/dist/frontend/lowering/lower-event-emitter.d.ts +6 -0
  365. package/dist/frontend/lowering/lower-event-emitter.js +124 -38
  366. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  367. package/dist/frontend/lowering/lower-event-target.d.ts +63 -0
  368. package/dist/frontend/lowering/lower-event-target.js +362 -0
  369. package/dist/frontend/lowering/lower-event-target.js.map +1 -0
  370. package/dist/frontend/lowering/lower-expando.js +2 -2
  371. package/dist/frontend/lowering/lower-exprs.js +247 -42
  372. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  373. package/dist/frontend/lowering/lower-generators.d.ts +15 -7
  374. package/dist/frontend/lowering/lower-generators.js +183 -99
  375. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  376. package/dist/frontend/lowering/lower-inspect.d.ts +8 -1
  377. package/dist/frontend/lowering/lower-inspect.js +247 -28
  378. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  379. package/dist/frontend/lowering/lower-mixins.js +1 -1
  380. package/dist/frontend/lowering/lower-modules.d.ts +1 -1
  381. package/dist/frontend/lowering/lower-modules.js +27 -17
  382. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  383. package/dist/frontend/lowering/lower-namespaces.d.ts +2 -2
  384. package/dist/frontend/lowering/lower-namespaces.js +2 -2
  385. package/dist/frontend/lowering/lower-server.js +39 -14
  386. package/dist/frontend/lowering/lower-server.js.map +1 -1
  387. package/dist/frontend/lowering/lower-stdlib.d.ts +11 -1
  388. package/dist/frontend/lowering/lower-stdlib.js +45 -4
  389. package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
  390. package/dist/frontend/lowering/lower-stmts.d.ts +2 -2
  391. package/dist/frontend/lowering/lower-stmts.js +112 -23
  392. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  393. package/dist/frontend/lowering/lower-stream.js +234 -22
  394. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  395. package/dist/frontend/lowering/lower-timers.js +1 -1
  396. package/dist/frontend/lowering/lowerer.d.ts +45 -6
  397. package/dist/frontend/lowering/lowerer.js +360 -48
  398. package/dist/frontend/lowering/lowerer.js.map +1 -1
  399. package/dist/frontend/lowering/native-ffi.js +2 -2
  400. package/dist/frontend/lowering/native-ffi.js.map +1 -1
  401. package/dist/frontend/lowering/regex-span-reads.d.ts +12 -0
  402. package/dist/frontend/lowering/regex-span-reads.js +164 -0
  403. package/dist/frontend/lowering/regex-span-reads.js.map +1 -0
  404. package/dist/frontend/lowering/runtime-optional-records.d.ts +115 -0
  405. package/dist/frontend/lowering/runtime-optional-records.js +715 -0
  406. package/dist/frontend/lowering/runtime-optional-records.js.map +1 -0
  407. package/dist/frontend/lowering/runtime-optional-records.test.d.ts +1 -0
  408. package/dist/frontend/lowering/runtime-optional-records.test.js +175 -0
  409. package/dist/frontend/lowering/runtime-optional-records.test.js.map +1 -0
  410. package/dist/frontend/lowering/surfaces.d.ts +7 -3
  411. package/dist/frontend/lowering/surfaces.js +385 -32
  412. package/dist/frontend/lowering/surfaces.js.map +1 -1
  413. package/dist/frontend/lowering/var-hoisting.d.ts +3 -0
  414. package/dist/frontend/lowering/var-hoisting.js +261 -0
  415. package/dist/frontend/lowering/var-hoisting.js.map +1 -0
  416. package/dist/frontend/module-syntax.d.ts +1 -1
  417. package/dist/frontend/module-syntax.js +1 -1
  418. package/dist/frontend/npm-static-prune.js +1 -1
  419. package/dist/frontend/npm-static-prune.js.map +1 -1
  420. package/dist/frontend/npm-static-rewrite-syntax.js +4 -3
  421. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
  422. package/dist/frontend/pipeline.js +6 -4
  423. package/dist/frontend/pipeline.js.map +1 -1
  424. package/dist/frontend/program.d.ts +6 -5
  425. package/dist/frontend/program.js +42 -22
  426. package/dist/frontend/program.js.map +1 -1
  427. package/dist/frontend/program.test.js +13 -0
  428. package/dist/frontend/program.test.js.map +1 -1
  429. package/dist/frontend/resolve.js +1 -1
  430. package/dist/frontend/ts7/adapter.js +1 -1
  431. package/dist/frontend/ts7/ast-bytes.d.ts +1 -1
  432. package/dist/frontend/ts7/ast-bytes.js +1 -1
  433. package/dist/frontend/ts7/semantic-json.d.ts +1 -1
  434. package/dist/frontend/ts7/semantic-json.js +1 -1
  435. package/dist/frontend/ts7/semantic-json.js.map +1 -1
  436. package/dist/frontend/ts7/world-check.js +1 -1
  437. package/dist/frontend/tsc-codes.js +2 -2
  438. package/dist/frontend/tsc-codes.js.map +1 -1
  439. package/dist/frontend/type-mapper.d.ts +28 -1
  440. package/dist/frontend/type-mapper.js +288 -30
  441. package/dist/frontend/type-mapper.js.map +1 -1
  442. package/dist/index.js +6 -4
  443. package/dist/index.js.map +1 -1
  444. package/dist/ir/analysis.d.ts +12 -6
  445. package/dist/ir/analysis.js +26 -10
  446. package/dist/ir/analysis.js.map +1 -1
  447. package/dist/ir/analysis.test.js +15 -3
  448. package/dist/ir/analysis.test.js.map +1 -1
  449. package/dist/ir/builtin-effects.js +108 -2
  450. package/dist/ir/builtin-effects.js.map +1 -1
  451. package/dist/ir/builtin-signatures.d.ts +1 -1
  452. package/dist/ir/builtin-signatures.js +436 -53
  453. package/dist/ir/builtin-signatures.js.map +1 -1
  454. package/dist/ir/function-references.test.js +1 -0
  455. package/dist/ir/function-references.test.js.map +1 -1
  456. package/dist/ir/int32-slots.js +2 -0
  457. package/dist/ir/int32-slots.js.map +1 -1
  458. package/dist/ir/intrinsic-signatures.js +2 -0
  459. package/dist/ir/intrinsic-signatures.js.map +1 -1
  460. package/dist/ir/ir.d.ts +129 -36
  461. package/dist/ir/ir.js +42 -1
  462. package/dist/ir/ir.js.map +1 -1
  463. package/dist/ir/runtime-features.d.ts +1 -0
  464. package/dist/ir/runtime-features.js +116 -5
  465. package/dist/ir/runtime-features.js.map +1 -1
  466. package/dist/ir/scalar-records.js +1 -2
  467. package/dist/ir/scalar-records.js.map +1 -1
  468. package/dist/ir/serialize.js +1 -1
  469. package/dist/ir/serialize.js.map +1 -1
  470. package/dist/ir/traverse.js +1 -0
  471. package/dist/ir/traverse.js.map +1 -1
  472. package/dist/ir/validate.js +250 -34
  473. package/dist/ir/validate.js.map +1 -1
  474. package/dist/ir/validate.test.js +125 -0
  475. package/dist/ir/validate.test.js.map +1 -1
  476. package/dist/library/fence-eval.d.ts +1 -1
  477. package/dist/library/fence-eval.js +5 -4
  478. package/dist/library/fence-eval.js.map +1 -1
  479. package/dist/library/ir-policy.js +11 -4
  480. package/dist/library/ir-policy.js.map +1 -1
  481. package/dist/library/library-profile.js +13 -13
  482. package/dist/library/library-profile.js.map +1 -1
  483. package/dist/library/prepare.js +1 -1
  484. package/dist/library/prepare.js.map +1 -1
  485. package/dist/library/sidecar.js +3 -3
  486. package/dist/library/sidecar.js.map +1 -1
  487. package/dist/native/prepare.js +3 -2
  488. package/dist/native/prepare.js.map +1 -1
  489. package/dist/native/sanitizer.test.js +1 -0
  490. package/dist/native/sanitizer.test.js.map +1 -1
  491. package/package.json +20 -20
  492. package/surface-manifest.json +537 -142
@@ -1,4 +1,4 @@
1
- import { BOOL, BYTES_U8, F64, VOID, arrayOf, funcOf, } from "../../ir/ir.js";
1
+ import { BOOL, F64, VOID, UNDEFINED_T, arrayOf, funcOf, } from "../../ir/ir.js";
2
2
  import { numLit } from "../../ir/build.js";
3
3
  import { transformStmtList } from "../../ir/traverse.js";
4
4
  /** Small IR vocabulary shared by the array and byte sort helpers. */
@@ -118,147 +118,603 @@ function distinctNodes(body) {
118
118
  stmt: (node) => (node.kind === "break" ? { ...node } : node),
119
119
  });
120
120
  }
121
- /** Stable natural merge sort over an owned snapshot. Strict descending runs
122
- * can be reversed without reversing ties. Short runs use bounded binary
123
- * insertion; merge passes then consume pairs of complete runs. The boundary
124
- * table compacts in place, and a single run needs no scratch buffer at all.
125
- * Comparator scheduling is intentionally unspecified, as for the previous
126
- * bottom-up sorter. Every callback still uses ordinary IR exception/ownership
127
- * handling; the caller's array is only written after sorting succeeds. */
128
- function stableSort(b, src, n, greater) {
121
+ /** V8's TimSort (third_party/v8/builtins/array-sort.tq) over the first `n`
122
+ * slots of an owned snapshot, step for step like the runtime's
123
+ * (scr_array.c): the same minimum run length, run detection, binary
124
+ * insertion, run-stack invariants, galloping merges and adaptive gallop
125
+ * threshold. Every comparison is `less(x, y)`, the comparator's
126
+ * `f(x, y) < 0`, so the comparator sees Node's calls in Node's order. Every
127
+ * callback still uses ordinary IR exception/ownership handling; the
128
+ * caller's array is only written after sorting succeeds. */
129
+ function timSort(b, src, n, less) {
130
+ return [b.branch(b.lt(b.num(1), n), timSortBody(b, src, n, less))];
131
+ }
132
+ function timSortBody(b, src, n, less) {
129
133
  const elem = src.type.kind === "array" ? src.type.elem : F64;
130
- const dst = b.local("dst", src.type);
131
- const tmp = b.local("tmp", src.type);
132
- const runs = b.local("runs", arrayOf(F64));
133
- const runCount = b.local("runCount");
134
- const start = b.local("start");
135
- const end = b.local("end");
136
- const descending = b.local("descending", BOOL);
137
- const left = b.local("left");
138
- const right = b.local("right");
139
- const pivot = b.local("pivot", elem);
140
- const low = b.local("low");
141
- const high = b.local("high");
142
- const center = b.local("center");
143
- const limit = b.local("limit");
144
- const i = b.local("i");
145
- const j = b.local("j");
146
- const k = b.local("k");
147
- const mid = b.local("mid");
148
- const run = b.local("run");
149
- const nextRun = b.local("nextRun");
150
- const vLeft = b.local("vLeft", elem);
151
- const vRight = b.local("vRight", elem);
152
- const boundaryLeft = b.local("boundaryLeft", elem);
153
- const boundaryRight = b.local("boundaryRight", elem);
134
+ const loc = b.loc;
135
+ let labels = 0;
136
+ const local = (name, type = F64) => b.local(name, type);
154
137
  const zero = b.num(0), one = b.num(1), two = b.num(2);
155
- const at = (index) => b.at(src, index);
156
- const copy = (index, stop) => b.while(b.lt(index, stop), [b.set(dst, k, at(index)), b.step(index), b.step(k)]);
157
- const merge = [
158
- b.bind(vLeft, at(i)),
159
- b.bind(vRight, at(j)),
160
- b.while({
161
- kind: "logical",
162
- op: "&&",
163
- left: b.lt(i, mid),
164
- right: b.lt(j, right),
165
- type: BOOL,
166
- loc: b.loc,
167
- }, [
168
- b.branch(greater(vLeft, vRight), [b.set(dst, k, vRight), b.step(j), b.branch(b.lt(j, right), [b.assign(vRight, at(j))])], [b.set(dst, k, vLeft), b.step(i), b.branch(b.lt(i, mid), [b.assign(vLeft, at(i))])]),
169
- b.step(k),
138
+ const at = (arr, index) => b.at(arr, index);
139
+ const ge = (left, right) => b.not(b.lt(left, right));
140
+ const le = (left, right) => b.not(b.lt(right, left));
141
+ const and = (left, right) => ({
142
+ kind: "logical",
143
+ op: "&&",
144
+ left,
145
+ right,
146
+ type: BOOL,
147
+ loc,
148
+ });
149
+ const or = (left, right) => ({
150
+ kind: "logical",
151
+ op: "||",
152
+ left,
153
+ right,
154
+ type: BOOL,
155
+ loc,
156
+ });
157
+ const truth = { kind: "boolLit", value: true, type: BOOL, loc };
158
+ const forever = (body) => b.while(truth, body);
159
+ const brk = (label) => ({ kind: "break", ...(label ? { label } : {}), loc });
160
+ const block = (label, body) => ({
161
+ kind: "block",
162
+ body,
163
+ labels: [label],
164
+ loc,
165
+ });
166
+ const half = (low, high) => b.add(low, {
167
+ kind: "libCall",
168
+ fn: "math.floor",
169
+ args: [{ kind: "bin", op: "/", left: b.sub(high, low), right: two, type: F64, loc }],
170
+ type: F64,
171
+ loc,
172
+ });
173
+ const min = (x, y) => b.choose(b.lt(x, y), x, y);
174
+ /** Copies `count` slots between arrays (or within one, front to back). */
175
+ const copyForward = (from, fromAt, to, toAt, count) => [
176
+ b.assign(cp, zero),
177
+ b.while(b.lt(cp, count), [b.set(to, b.add(toAt, cp), at(from, b.add(fromAt, cp))), b.step(cp)]),
178
+ ];
179
+ /** Copies `count` slots within `src` back to front (overlap to the right). */
180
+ const copyBackward = (fromAt, toAt, count) => [
181
+ b.assign(cp, count),
182
+ b.while(b.lt(zero, cp), [
183
+ b.step(cp, -1),
184
+ b.set(src, b.add(toAt, cp), at(src, b.add(fromAt, cp))),
170
185
  ]),
171
- copy(i, mid),
172
- copy(j, right),
173
186
  ];
174
- return [
175
- b.bind(runs, { kind: "arrayLit", elems: [zero], type: runs.type, loc: b.loc }),
176
- b.bind(runCount, one),
177
- b.bind(start, zero),
178
- b.while(b.lt(start, n), [
179
- b.bind(end, b.add(start, one)),
180
- b.branch(b.lt(end, n), [
181
- b.bind(descending, greater(at(start), at(end))),
182
- b.step(end),
183
- b.while(b.lt(end, n), [
184
- b.branch(b.choose(descending, greater(at(b.sub(end, one)), at(end)), b.not(greater(at(b.sub(end, one)), at(end)))), [b.step(end)], [{ kind: "break", loc: b.loc }]),
187
+ const minGallop = local("minGallop");
188
+ const runBase = local("runBase", arrayOf(F64));
189
+ const runLen = local("runLen", arrayOf(F64));
190
+ const runs = local("runs");
191
+ const cp = local("copyIndex");
192
+ // Gallop search state; searches never nest.
193
+ const gLast = local("gallopLast");
194
+ const gOfs = local("gallopOffset");
195
+ const gMax = local("gallopMax");
196
+ const gMid = local("gallopMid");
197
+ const gTmp = local("gallopTmp");
198
+ const gBase = local("gallopBase");
199
+ const gLength = local("gallopLength");
200
+ const gHint = local("gallopHint");
201
+ const gKey = local("gallopKey", elem);
202
+ /** gallopLeft/gallopRight: assigns `out` the offset k in [0, length] of
203
+ * `key` in arr[base .. base + length), starting the search at `hint`. */
204
+ const gallop = (right, out, arr, key, base, lengthExpr, hintExpr) => {
205
+ // gallopLeft tests arr[i] < key; gallopRight tests key < arr[i].
206
+ const probe = (index) => right ? less(gKey, at(arr, b.add(gBase, index))) : less(at(arr, b.add(gBase, index)), gKey);
207
+ // Whether the search moves right (toward higher indices) from the hint.
208
+ const towardHigh = right ? b.not(probe(gHint)) : probe(gHint);
209
+ const advance = () => [b.assign(gLast, gOfs), b.assign(gOfs, b.add(b.add(gOfs, gOfs), one))];
210
+ const length = gLength, hint = gHint;
211
+ const body = [
212
+ b.bind(gKey, key),
213
+ b.assign(gBase, base),
214
+ b.assign(gLength, lengthExpr),
215
+ b.assign(gHint, hintExpr),
216
+ b.assign(gLast, zero),
217
+ b.assign(gOfs, one),
218
+ b.branch(towardHigh, [
219
+ b.assign(gMax, b.sub(length, hint)),
220
+ b.while(b.lt(gOfs, gMax), [
221
+ // Stop at the first element the key does not pass.
222
+ b.branch(right ? probe(b.add(hint, gOfs)) : b.not(probe(b.add(hint, gOfs))), [brk()]),
223
+ ...advance(),
185
224
  ]),
186
- b.branch(descending, [
187
- b.bind(left, start),
188
- b.bind(right, b.sub(end, one)),
189
- b.while(b.lt(left, right), [
190
- b.bind(vLeft, at(left)),
191
- b.bind(vRight, at(right)),
192
- b.set(src, left, vRight),
193
- b.set(src, right, vLeft),
194
- b.step(left),
195
- b.step(right, -1),
225
+ b.branch(b.lt(gMax, gOfs), [b.assign(gOfs, gMax)]),
226
+ b.assign(gLast, b.add(gLast, hint)),
227
+ b.assign(gOfs, b.add(gOfs, hint)),
228
+ ], [
229
+ b.assign(gMax, b.add(hint, one)),
230
+ b.while(b.lt(gOfs, gMax), [
231
+ b.branch(right ? b.not(probe(b.sub(hint, gOfs))) : probe(b.sub(hint, gOfs)), [brk()]),
232
+ ...advance(),
233
+ ]),
234
+ b.branch(b.lt(gMax, gOfs), [b.assign(gOfs, gMax)]),
235
+ b.assign(gTmp, gLast),
236
+ b.assign(gLast, b.sub(hint, gOfs)),
237
+ b.assign(gOfs, b.sub(hint, gTmp)),
238
+ ]),
239
+ b.step(gLast),
240
+ b.while(b.lt(gLast, gOfs), [
241
+ b.assign(gMid, half(gLast, gOfs)),
242
+ b.branch(probe(gMid), right ? [b.assign(gOfs, gMid)] : [b.assign(gLast, b.add(gMid, one))], right ? [b.assign(gLast, b.add(gMid, one))] : [b.assign(gOfs, gMid)]),
243
+ ]),
244
+ b.assign(out, gOfs),
245
+ ];
246
+ return [{ kind: "block", body, loc }];
247
+ };
248
+ // Merge state (merges never nest).
249
+ const tmp = local("mergeTmp", src.type);
250
+ const baseA = local("baseA");
251
+ const lenA = local("lenA");
252
+ const baseB = local("baseB");
253
+ const lenB = local("lenB");
254
+ const dest = local("dest");
255
+ const cursorT = local("cursorT");
256
+ const cursorX = local("cursorX");
257
+ const winsA = local("winsA");
258
+ const winsB = local("winsB");
259
+ const firstPass = local("firstPass", BOOL);
260
+ const k = local("mergeK");
261
+ const takeTmp = (count, from) => [
262
+ b.bind(tmp, b.allocate(src.type, count)),
263
+ ...copyForward(src, from, tmp, zero, count),
264
+ ];
265
+ const lowerGallop = (value) => b.assign(minGallop, b.choose(b.lt(one, value), b.sub(value, one), one));
266
+ const enoughWins = () => or(or(ge(winsA, b.num(7)), ge(winsB, b.num(7))), firstPass);
267
+ const mergeLow = () => {
268
+ const id = labels++;
269
+ const succeed = `ts.low${id}.succeed`, copyB = `ts.low${id}.copyB`, exit = `ts.low${id}.exit`;
270
+ const moveB = [b.set(src, dest, at(src, cursorX)), b.step(dest), b.step(cursorX)];
271
+ const moveT = [b.set(src, dest, at(tmp, cursorT)), b.step(dest), b.step(cursorT)];
272
+ return [
273
+ ...takeTmp(lenA, baseA),
274
+ b.assign(dest, baseA),
275
+ b.assign(cursorT, zero),
276
+ b.assign(cursorX, baseB),
277
+ ...moveB,
278
+ block(exit, [
279
+ block(copyB, [
280
+ block(succeed, [
281
+ b.step(lenB, -1),
282
+ b.branch(b.eq(lenB, zero), [brk(succeed)]),
283
+ b.branch(b.eq(lenA, one), [brk(copyB)]),
284
+ forever([
285
+ b.assign(winsA, zero),
286
+ b.assign(winsB, zero),
287
+ forever([
288
+ b.branch(less(at(src, cursorX), at(tmp, cursorT)), [
289
+ ...moveB,
290
+ b.step(winsB),
291
+ b.step(lenB, -1),
292
+ b.assign(winsA, zero),
293
+ b.branch(b.eq(lenB, zero), [brk(succeed)]),
294
+ b.branch(ge(winsB, minGallop), [brk()]),
295
+ ], [
296
+ ...moveT,
297
+ b.step(winsA),
298
+ b.step(lenA, -1),
299
+ b.assign(winsB, zero),
300
+ b.branch(b.eq(lenA, one), [brk(copyB)]),
301
+ b.branch(ge(winsA, minGallop), [brk()]),
302
+ ]),
303
+ ]),
304
+ b.step(minGallop),
305
+ b.assign(firstPass, truth),
306
+ b.while(enoughWins(), [
307
+ b.assign(firstPass, { kind: "boolLit", value: false, type: BOOL, loc }),
308
+ lowerGallop(minGallop),
309
+ ...gallop(true, winsA, tmp, at(src, cursorX), cursorT, lenA, zero),
310
+ b.branch(b.lt(zero, winsA), [
311
+ ...copyForward(tmp, cursorT, src, dest, winsA),
312
+ b.assign(dest, b.add(dest, winsA)),
313
+ b.assign(cursorT, b.add(cursorT, winsA)),
314
+ b.assign(lenA, b.sub(lenA, winsA)),
315
+ b.branch(b.eq(lenA, one), [brk(copyB)]),
316
+ b.branch(b.eq(lenA, zero), [brk(succeed)]),
317
+ ]),
318
+ ...moveB,
319
+ b.step(lenB, -1),
320
+ b.branch(b.eq(lenB, zero), [brk(succeed)]),
321
+ ...gallop(false, winsB, src, at(tmp, cursorT), cursorX, lenB, zero),
322
+ b.branch(b.lt(zero, winsB), [
323
+ ...copyForward(src, cursorX, src, dest, winsB),
324
+ b.assign(dest, b.add(dest, winsB)),
325
+ b.assign(cursorX, b.add(cursorX, winsB)),
326
+ b.assign(lenB, b.sub(lenB, winsB)),
327
+ b.branch(b.eq(lenB, zero), [brk(succeed)]),
328
+ ]),
329
+ ...moveT,
330
+ b.step(lenA, -1),
331
+ b.branch(b.eq(lenA, one), [brk(copyB)]),
332
+ ]),
333
+ b.step(minGallop),
334
+ ]),
196
335
  ]),
336
+ // succeed
337
+ ...copyForward(tmp, cursorT, src, dest, lenA),
338
+ brk(exit),
197
339
  ]),
340
+ // copyB: the last element of run A belongs at the end of the merge.
341
+ ...copyForward(src, cursorX, src, dest, lenB),
342
+ b.set(src, b.add(dest, lenB), at(tmp, cursorT)),
198
343
  ]),
199
- // Bound insertion movement while avoiding tiny merge runs.
200
- b.bind(limit, b.choose(b.lt(b.add(start, b.num(16)), n), b.add(start, b.num(16)), n)),
201
- b.while(b.lt(end, limit), [
202
- b.bind(pivot, at(end)),
203
- b.bind(low, start),
204
- b.bind(high, end),
205
- b.while(b.lt(low, high), [
206
- b.bind(center, {
207
- kind: "libCall",
208
- fn: "math.floor",
209
- args: [
210
- { kind: "bin", op: "/", left: b.add(low, high), right: two, type: F64, loc: b.loc },
211
- ],
212
- type: F64,
213
- loc: b.loc,
214
- }),
215
- // Insert after equal values to preserve their original order.
216
- b.branch(greater(at(center), pivot), [b.assign(high, center)], [b.assign(low, b.add(center, one))]),
344
+ ];
345
+ };
346
+ const mergeHigh = () => {
347
+ const id = labels++;
348
+ const succeed = `ts.high${id}.succeed`, copyA = `ts.high${id}.copyA`, exit = `ts.high${id}.exit`;
349
+ // dest, cursorX (run A) and cursorT index their next slot.
350
+ const moveA = [b.set(src, dest, at(src, cursorX)), b.step(dest, -1), b.step(cursorX, -1)];
351
+ const moveT = [b.set(src, dest, at(tmp, cursorT)), b.step(dest, -1), b.step(cursorT, -1)];
352
+ return [
353
+ ...takeTmp(lenB, baseB),
354
+ b.assign(dest, b.sub(b.add(baseB, lenB), one)),
355
+ b.assign(cursorT, b.sub(lenB, one)),
356
+ b.assign(cursorX, b.sub(b.add(baseA, lenA), one)),
357
+ ...moveA,
358
+ block(exit, [
359
+ block(copyA, [
360
+ block(succeed, [
361
+ b.step(lenA, -1),
362
+ b.branch(b.eq(lenA, zero), [brk(succeed)]),
363
+ b.branch(b.eq(lenB, one), [brk(copyA)]),
364
+ forever([
365
+ b.assign(winsA, zero),
366
+ b.assign(winsB, zero),
367
+ forever([
368
+ b.branch(less(at(tmp, cursorT), at(src, cursorX)), [
369
+ ...moveA,
370
+ b.step(winsA),
371
+ b.step(lenA, -1),
372
+ b.assign(winsB, zero),
373
+ b.branch(b.eq(lenA, zero), [brk(succeed)]),
374
+ b.branch(ge(winsA, minGallop), [brk()]),
375
+ ], [
376
+ ...moveT,
377
+ b.step(winsB),
378
+ b.step(lenB, -1),
379
+ b.assign(winsA, zero),
380
+ b.branch(b.eq(lenB, one), [brk(copyA)]),
381
+ b.branch(ge(winsB, minGallop), [brk()]),
382
+ ]),
383
+ ]),
384
+ b.step(minGallop),
385
+ b.assign(firstPass, truth),
386
+ b.while(enoughWins(), [
387
+ b.assign(firstPass, { kind: "boolLit", value: false, type: BOOL, loc }),
388
+ lowerGallop(minGallop),
389
+ ...gallop(true, k, src, at(tmp, cursorT), baseA, lenA, b.sub(lenA, one)),
390
+ b.assign(winsA, b.sub(lenA, k)),
391
+ b.branch(b.lt(zero, winsA), [
392
+ b.assign(dest, b.sub(dest, winsA)),
393
+ b.assign(cursorX, b.sub(cursorX, winsA)),
394
+ ...copyBackward(b.add(cursorX, one), b.add(dest, one), winsA),
395
+ b.assign(lenA, b.sub(lenA, winsA)),
396
+ b.branch(b.eq(lenA, zero), [brk(succeed)]),
397
+ ]),
398
+ ...moveT,
399
+ b.step(lenB, -1),
400
+ b.branch(b.eq(lenB, one), [brk(copyA)]),
401
+ ...gallop(false, k, tmp, at(src, cursorX), zero, lenB, b.sub(lenB, one)),
402
+ b.assign(winsB, b.sub(lenB, k)),
403
+ b.branch(b.lt(zero, winsB), [
404
+ b.assign(dest, b.sub(dest, winsB)),
405
+ b.assign(cursorT, b.sub(cursorT, winsB)),
406
+ ...copyForward(tmp, b.add(cursorT, one), src, b.add(dest, one), winsB),
407
+ b.assign(lenB, b.sub(lenB, winsB)),
408
+ b.branch(b.eq(lenB, one), [brk(copyA)]),
409
+ b.branch(b.eq(lenB, zero), [brk(succeed)]),
410
+ ]),
411
+ ...moveA,
412
+ b.step(lenA, -1),
413
+ b.branch(b.eq(lenA, zero), [brk(succeed)]),
414
+ ]),
415
+ b.step(minGallop),
416
+ ]),
417
+ ]),
418
+ // succeed
419
+ ...copyForward(tmp, zero, src, b.sub(dest, b.sub(lenB, one)), lenB),
420
+ brk(exit),
217
421
  ]),
218
- b.bind(i, end),
219
- b.while(b.lt(low, i), [b.set(src, i, at(b.sub(i, one))), b.step(i, -1)]),
220
- b.set(src, low, pivot),
221
- b.step(end),
422
+ // copyA: the first element of run B belongs at the front of the merge.
423
+ b.assign(dest, b.sub(dest, lenA)),
424
+ b.assign(cursorX, b.sub(cursorX, lenA)),
425
+ ...copyBackward(b.add(cursorX, one), b.add(dest, one), lenA),
426
+ b.set(src, dest, at(tmp, cursorT)),
222
427
  ]),
223
- b.set(runs, runCount, end),
224
- b.step(runCount),
225
- b.assign(start, end),
226
- ]),
227
- b.branch(b.lt(two, runCount), [
228
- b.bind(dst, b.allocate(src.type, n)),
229
- b.while(b.lt(two, runCount), [
230
- b.bind(run, zero),
231
- b.bind(nextRun, one),
232
- b.while(b.lt(b.add(run, one), runCount), [
233
- b.bind(start, b.at(runs, run)),
234
- b.bind(mid, b.at(runs, b.add(run, one))),
235
- b.bind(right, b.choose(b.lt(b.add(run, two), runCount), b.at(runs, b.add(run, two)), n)),
236
- b.bind(i, start),
237
- b.bind(j, mid),
238
- b.bind(k, start),
239
- b.branch(b.lt(mid, right), [
240
- b.bind(boundaryLeft, at(b.sub(mid, one))),
241
- b.bind(boundaryRight, at(mid)),
242
- b.branch(greater(boundaryLeft, boundaryRight), merge, [copy(i, right)]),
243
- ], [copy(i, right)]),
244
- b.set(runs, nextRun, right),
245
- b.step(nextRun),
246
- b.step(run, 2),
428
+ ];
429
+ };
430
+ const mergeAt = (i) => {
431
+ const merged = local(`mergeAt${labels++}`);
432
+ const id = `ts.at${labels++}`;
433
+ return [
434
+ b.bind(merged, i),
435
+ b.assign(baseA, at(runBase, merged)),
436
+ b.assign(lenA, at(runLen, merged)),
437
+ b.assign(baseB, at(runBase, b.add(merged, one))),
438
+ b.assign(lenB, at(runLen, b.add(merged, one))),
439
+ b.set(runLen, merged, b.add(lenA, lenB)),
440
+ b.branch(b.eq(b.add(merged, b.num(3)), runs), [
441
+ b.set(runBase, b.add(merged, one), at(runBase, b.add(merged, two))),
442
+ b.set(runLen, b.add(merged, one), at(runLen, b.add(merged, two))),
443
+ ]),
444
+ b.step(runs, -1),
445
+ block(id, [
446
+ ...gallop(true, k, src, at(src, baseB), baseA, lenA, zero),
447
+ b.assign(baseA, b.add(baseA, k)),
448
+ b.assign(lenA, b.sub(lenA, k)),
449
+ b.branch(b.eq(lenA, zero), [brk(id)]),
450
+ ...gallop(false, lenB, src, at(src, b.sub(b.add(baseA, lenA), one)), baseB, lenB, b.sub(lenB, one)),
451
+ b.branch(b.eq(lenB, zero), [brk(id)]),
452
+ b.branch(le(lenA, lenB), mergeLow(), mergeHigh()),
453
+ ]),
454
+ ];
455
+ };
456
+ const invariant = (m) => or(b.lt(m, two), b.lt(b.add(at(runLen, b.sub(m, one)), at(runLen, m)), at(runLen, b.sub(m, two))));
457
+ const top = local("top");
458
+ const low = local("low");
459
+ const remaining = local("remaining");
460
+ const minRun = local("minRun");
461
+ const minRunOdd = local("minRunOdd");
462
+ const runEnd = local("runEnd");
463
+ const descending = local("descending", BOOL);
464
+ const previous = local("previous", elem);
465
+ const pivot = local("pivot", elem);
466
+ const left = local("left");
467
+ const right = local("right");
468
+ const mid = local("mid");
469
+ const pos = local("insert");
470
+ const forced = local("forced");
471
+ const vl = local("swapLeft", elem);
472
+ const vr = local("swapRight", elem);
473
+ const length = local("runLength");
474
+ const scan = local("scan");
475
+ const half2 = (value) => ({
476
+ kind: "libCall",
477
+ fn: "math.floor",
478
+ args: [{ kind: "bin", op: "/", left: value, right: two, type: F64, loc }],
479
+ type: F64,
480
+ loc,
481
+ });
482
+ const countRun = [
483
+ b.assign(scan, b.add(low, one)),
484
+ b.assign(runEnd, b.add(low, remaining)),
485
+ b.branch(b.eq(scan, runEnd), [b.assign(length, one)], [
486
+ b.assign(length, two),
487
+ b.assign(descending, less(at(src, scan), at(src, low))),
488
+ b.bind(previous, at(src, scan)),
489
+ b.step(scan),
490
+ b.while(b.lt(scan, runEnd), [
491
+ b.branch(b.choose(descending, b.not(less(at(src, scan), previous)), less(at(src, scan), previous)), [brk()]),
492
+ b.assign(previous, at(src, scan)),
493
+ b.step(length),
494
+ b.step(scan),
495
+ ]),
496
+ b.branch(descending, [
497
+ b.assign(left, low),
498
+ b.assign(right, b.sub(b.add(low, length), one)),
499
+ b.while(b.lt(left, right), [
500
+ b.bind(vl, at(src, left)),
501
+ b.bind(vr, at(src, right)),
502
+ b.set(src, left, vr),
503
+ b.set(src, right, vl),
504
+ b.step(left),
505
+ b.step(right, -1),
247
506
  ]),
248
- b.assign(runCount, nextRun),
249
- b.bind(tmp, src),
250
- b.assign(src, dst),
251
- b.assign(dst, tmp),
252
507
  ]),
253
508
  ]),
254
509
  ];
510
+ const insertion = [
511
+ b.assign(forced, min(minRun, remaining)),
512
+ // [low, low + length) is sorted; insert each later element.
513
+ b.assign(pos, b.add(low, length)),
514
+ b.while(b.lt(pos, b.add(low, forced)), [
515
+ b.assign(left, low),
516
+ b.assign(right, pos),
517
+ b.bind(pivot, at(src, pos)),
518
+ b.while(b.lt(left, right), [
519
+ b.assign(mid, half(left, right)),
520
+ b.branch(less(pivot, at(src, mid)), [b.assign(right, mid)], [b.assign(left, b.add(mid, one))]),
521
+ ]),
522
+ ...copyBackward(left, b.add(left, one), b.sub(pos, left)),
523
+ b.set(src, left, pivot),
524
+ b.step(pos),
525
+ ]),
526
+ b.assign(length, forced),
527
+ ];
528
+ const collapse = b.while(b.lt(one, runs), [
529
+ b.assign(top, b.sub(runs, two)),
530
+ b.branch(or(b.not(invariant(b.add(top, one))), b.not(invariant(top))), [
531
+ b.branch(b.lt(at(runLen, b.sub(top, one)), at(runLen, b.add(top, one))), [b.step(top, -1)]),
532
+ ...mergeAt(top),
533
+ ], [b.branch(le(at(runLen, top), at(runLen, b.add(top, one))), [...mergeAt(top)], [brk()])]),
534
+ ]);
535
+ const forceCollapse = b.while(b.lt(one, runs), [
536
+ b.assign(top, b.sub(runs, two)),
537
+ b.branch(and(b.lt(zero, top), b.lt(at(runLen, b.sub(top, one)), at(runLen, b.add(top, one)))), [
538
+ b.step(top, -1),
539
+ ]),
540
+ ...mergeAt(top),
541
+ ]);
542
+ const scalars = [
543
+ cp,
544
+ gLast,
545
+ gOfs,
546
+ gMax,
547
+ gMid,
548
+ gTmp,
549
+ gBase,
550
+ gLength,
551
+ gHint,
552
+ baseA,
553
+ lenA,
554
+ baseB,
555
+ lenB,
556
+ dest,
557
+ cursorT,
558
+ cursorX,
559
+ winsA,
560
+ winsB,
561
+ k,
562
+ top,
563
+ low,
564
+ remaining,
565
+ minRun,
566
+ minRunOdd,
567
+ runEnd,
568
+ left,
569
+ right,
570
+ mid,
571
+ pos,
572
+ forced,
573
+ length,
574
+ scan,
575
+ ];
576
+ return [
577
+ ...scalars.map((local) => b.bind(local, zero)),
578
+ b.bind(firstPass, { kind: "boolLit", value: false, type: BOOL, loc }),
579
+ b.bind(descending, { kind: "boolLit", value: false, type: BOOL, loc }),
580
+ b.bind(minGallop, b.num(7)),
581
+ b.bind(runBase, { kind: "arrayLit", elems: [], type: runBase.type, loc }),
582
+ b.bind(runLen, { kind: "arrayLit", elems: [], type: runLen.type, loc }),
583
+ b.bind(runs, zero),
584
+ b.bind(minRun, n),
585
+ b.bind(minRunOdd, zero),
586
+ b.while(ge(minRun, b.num(64)), [
587
+ b.branch(b.not(b.eq(b.sub(minRun, b.add(half2(minRun), half2(minRun))), zero)), [
588
+ b.assign(minRunOdd, one),
589
+ ]),
590
+ b.assign(minRun, half2(minRun)),
591
+ ]),
592
+ b.assign(minRun, b.add(minRun, minRunOdd)),
593
+ b.bind(low, zero),
594
+ b.bind(remaining, n),
595
+ b.while(b.lt(zero, remaining), [
596
+ ...countRun,
597
+ b.branch(b.lt(length, minRun), insertion),
598
+ b.set(runBase, runs, low),
599
+ b.set(runLen, runs, length),
600
+ b.step(runs),
601
+ collapse,
602
+ b.assign(low, b.add(low, length)),
603
+ b.assign(remaining, b.sub(remaining, length)),
604
+ ]),
605
+ forceCollapse,
606
+ ];
255
607
  }
256
- export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc, native = false) {
608
+ /** Recognizes the lifted body of a capture-free numeric comparator:
609
+ * `(a, b) => a - b`, `b - a`, `a < b ? -1 : a > b ? 1 : 0` (either test
610
+ * first, either sign), or any of them over one number field of both
611
+ * parameters (`a.k - b.k`). Such a comparator runs no user code, cannot
612
+ * throw, and is consistent over numbers other than NaN, so the runtime may
613
+ * order the elements by their keys without calling it. */
614
+ export function recognizeKeyComparator(fn) {
615
+ if (fn.params.length !== 2 || fn.async || fn.generator || (fn.captures?.length ?? 0) > 0)
616
+ return null;
617
+ const [first, second] = fn.params;
618
+ const ret = fn.body.length === 1 ? fn.body[0] : null;
619
+ if (ret?.kind !== "return" || !ret.value)
620
+ return null;
621
+ let read;
622
+ // Which parameter an operand reads; every operand must read the same key.
623
+ const operand = (e) => {
624
+ if (e.type.kind !== "f64")
625
+ return null;
626
+ let ref = e;
627
+ let field = null;
628
+ if (e.kind === "recordGet" || e.kind === "fieldGet") {
629
+ field = e;
630
+ ref = e.obj;
631
+ }
632
+ if (ref.kind !== "varRef")
633
+ return null;
634
+ const param = ref.localId === first.localId ? 0 : ref.localId === second.localId ? 1 : null;
635
+ if (param === null)
636
+ return null;
637
+ if (read === undefined)
638
+ read = field;
639
+ else if (!sameKeyRead(read, field))
640
+ return null;
641
+ return param;
642
+ };
643
+ // `x < y` or `x > y` over both parameters, as the first one's relation.
644
+ const relation = (e) => {
645
+ if (e.kind !== "bin" || (e.op !== "<" && e.op !== ">"))
646
+ return null;
647
+ const left = operand(e.left), right = operand(e.right);
648
+ if (left === null || right === null || left === right)
649
+ return null;
650
+ return (e.op === "<") === (left === 0) ? "lt" : "gt";
651
+ };
652
+ const sign = (e) => e.kind === "numLit" && (e.value === 1 || e.value === -1 || e.value === 0) ? e.value : null;
653
+ const value = ret.value;
654
+ if (value.kind === "bin" && value.op === "-") {
655
+ const left = operand(value.left), right = operand(value.right);
656
+ if (left === null || right === null || left === right)
657
+ return null;
658
+ return { order: left === 0 ? 1 : -1, read: read ?? null };
659
+ }
660
+ if (value.kind === "ternary" && value.else_.kind === "ternary") {
661
+ const outer = relation(value.cond), inner = relation(value.else_.cond);
662
+ const outerSign = sign(value.then), innerSign = sign(value.else_.then);
663
+ if (outer === null ||
664
+ inner === null ||
665
+ outer === inner ||
666
+ outerSign === null ||
667
+ outerSign === 0 ||
668
+ innerSign !== -outerSign ||
669
+ sign(value.else_.else_) !== 0)
670
+ return null;
671
+ // Ascending answers negative when the first parameter is less.
672
+ return { order: (outer === "lt") === outerSign < 0 ? 1 : -1, read: read ?? null };
673
+ }
674
+ return null;
675
+ }
676
+ /** The key order of a comparator closure: a zero-capture closure (not a
677
+ * signature adapter) over a lifted function recognizeKeyComparator accepts. */
678
+ export function closureKeyOrder(liftedFns, closure) {
679
+ if (closure.kind !== "closure" || closure.captures.length > 0 || closure.adapts)
680
+ return null;
681
+ const fn = liftedFns.find((lifted) => lifted.name === closure.fnName);
682
+ return fn ? recognizeKeyComparator(fn) : null;
683
+ }
684
+ function sameKeyRead(left, right) {
685
+ if (left === null || right === null)
686
+ return left === right;
687
+ if (left.kind === "recordGet" && right.kind === "recordGet")
688
+ return left.shapeId === right.shapeId && left.field === right.field;
689
+ if (left.kind === "fieldGet" && right.kind === "fieldGet")
690
+ return left.className === right.className && left.field === right.field;
691
+ return false;
692
+ }
693
+ /** The key reader of a recognized field comparator: `(x) => x.k`, the same
694
+ * field read as the comparator's. */
695
+ export function buildSortKeyFn(name, elem, read, loc) {
696
+ const b = new SortIr(loc);
697
+ const x = b.local("x", elem);
698
+ return {
699
+ name,
700
+ params: [{ localId: x.localId, name: "x", type: elem }],
701
+ returnType: F64,
702
+ locals: b.locals,
703
+ body: [{ kind: "return", value: { ...read, obj: x, loc }, loc }],
704
+ loc,
705
+ };
706
+ }
707
+ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc, native = false, keyed = null) {
257
708
  const b = new SortIr(loc);
258
709
  const arrT = arrayOf(elem), fnT = funcOf([elem, elem].slice(0, arity), F64);
259
710
  const a = b.local("a", arrT), f = b.local("f", fnT);
711
+ const keyT = funcOf([elem], F64);
712
+ const key = keyed?.key ? b.local("key", keyT) : null;
713
+ // A recognized comparator lets the runtime order by keys; it still
714
+ // receives the comparator for inputs whose keys it does not order.
715
+ const keyArgs = keyed ? [b.num(keyed.order), ...(key ? [key] : [])] : [];
260
716
  const src = b.local("src", arrT);
261
- const n = b.local("n"), valueCount = b.local("valueCount"), undefinedCount = b.local("undefinedCount");
717
+ const n = b.local("n"), valueCount = b.local("valueCount"), undefinedCount = b.local("undefinedCount"), undefinedValues = b.local("undefinedValues");
262
718
  const index = b.local("index"), state = b.local("state");
263
719
  const isUndefined = (value) => {
264
720
  if (elem.kind === "union" && undefinedTag !== null) {
@@ -274,20 +730,47 @@ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc
274
730
  }
275
731
  return null;
276
732
  };
277
- const greater = (left, right) => {
278
- const compare = {
279
- kind: "bin",
280
- op: ">",
281
- left: { kind: "callValue", callee: f, args: [left, right].slice(0, arity), type: F64, loc },
282
- right: b.num(0),
283
- type: BOOL,
733
+ // A NaN result compares as 0, which `< 0` gives.
734
+ const less = (left, right) => ({
735
+ kind: "bin",
736
+ op: "<",
737
+ left: { kind: "callValue", callee: f, args: [left, right].slice(0, arity), type: F64, loc },
738
+ right: b.num(0),
739
+ type: BOOL,
740
+ loc,
741
+ });
742
+ const keepValue = () => [
743
+ b.branch(b.lt(valueCount, index), [b.set(src, valueCount, b.at(src, index))]),
744
+ b.step(valueCount),
745
+ ];
746
+ const compactValue = () => {
747
+ const undefinedValue = isUndefined(b.at(src, index));
748
+ return undefinedValue === null
749
+ ? { kind: "block", body: keepValue(), loc }
750
+ : b.branch(undefinedValue, [b.step(undefinedValues)], keepValue());
751
+ };
752
+ // The union's undefined value, for the elements that held one.
753
+ const undefinedValue = () => elem.kind === "union" && undefinedTag !== null
754
+ ? {
755
+ kind: "unionWrap",
756
+ unionId: elem.unionId,
757
+ tag: undefinedTag,
758
+ value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc },
759
+ type: elem,
284
760
  loc,
285
- };
286
- const leftUndefined = isUndefined(left), rightUndefined = isUndefined(right);
287
- return leftUndefined !== null && rightUndefined !== null
288
- ? b.choose(leftUndefined, b.not(rightUndefined), b.choose(rightUndefined, { kind: "boolLit", value: false, type: BOOL, loc }, compare))
289
- : compare;
761
+ }
762
+ : null;
763
+ const unionTail = () => {
764
+ const value = undefinedValue();
765
+ return value === null
766
+ ? []
767
+ : [
768
+ b.loop(index, valueCount, b.add(valueCount, undefinedValues), [
769
+ b.set(result, index, value),
770
+ ]),
771
+ ];
290
772
  };
773
+ const tailStart = () => b.add(valueCount, undefinedValues);
291
774
  const result = copyFirst ? src : a;
292
775
  // Dense arrays sort in the runtime without the compacting snapshot below:
293
776
  // `sort` orders the receiver's values outside it and writes them back
@@ -296,7 +779,7 @@ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc
296
779
  kind: "arrIntrinsic",
297
780
  method: "sortDense",
298
781
  receiver,
299
- args: [f, { kind: "boolLit", value: copyFirst, type: BOOL, loc }],
782
+ args: [f, { kind: "boolLit", value: copyFirst, type: BOOL, loc }, ...keyArgs],
300
783
  type: BOOL,
301
784
  loc,
302
785
  }, [{ kind: "return", value: receiver, loc }]);
@@ -307,14 +790,14 @@ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc
307
790
  ...(native && copyFirst ? [dense(src)] : []),
308
791
  b.bind(valueCount, b.num(0)),
309
792
  b.bind(undefinedCount, b.num(0)),
310
- // Compact the owned snapshot before callbacks. Dense values stay in
311
- // place; only values following holes or storage-level undefined move.
793
+ b.bind(undefinedValues, b.num(0)),
794
+ // Compact the owned snapshot before callbacks, as V8 does: holes are
795
+ // dropped, undefined values (storage-level, or a union's undefined arm)
796
+ // are counted, and the comparator only sees the other values. Dense
797
+ // values stay in place; only values following the others move.
312
798
  b.loop(index, b.num(0), n, [
313
799
  b.bind(state, { kind: "arrayState", arr: src, index, type: F64, loc }),
314
- b.branch(b.eq(state, b.num(1)), [
315
- b.branch(b.lt(valueCount, index), [b.set(src, valueCount, b.at(src, index))]),
316
- b.step(valueCount),
317
- ], [b.branch(b.eq(state, b.num(2)), [b.step(undefinedCount)])]),
800
+ b.branch(b.eq(state, b.num(1)), [compactValue()], [b.branch(b.eq(state, b.num(2)), [b.step(undefinedCount)])]),
318
801
  ]),
319
802
  // Sort only the compacted prefix. The tail is overwritten with undefined
320
803
  // for toSorted, or released with this private snapshot for sort.
@@ -328,24 +811,25 @@ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc
328
811
  kind: "arrIntrinsic",
329
812
  method: "sortValues",
330
813
  receiver: src,
331
- args: [valueCount, f],
814
+ args: [valueCount, f, ...keyArgs],
332
815
  type: VOID,
333
816
  loc,
334
817
  },
335
818
  loc,
336
819
  },
337
820
  ]
338
- : stableSort(b, src, valueCount, greater)),
821
+ : timSort(b, src, valueCount, less)),
339
822
  ...(copyFirst
340
823
  ? []
341
824
  : [b.loop(index, b.num(0), valueCount, [b.set(a, index, b.at(src, index))])]),
342
- b.loop(index, valueCount, copyFirst ? n : b.add(valueCount, undefinedCount), [
825
+ ...unionTail(),
826
+ b.loop(index, tailStart(), copyFirst ? n : b.add(tailStart(), undefinedCount), [
343
827
  { kind: "arraySetUndefined", arr: result, index, loc },
344
828
  ]),
345
829
  ...(copyFirst
346
830
  ? []
347
831
  : [
348
- b.loop(index, b.add(valueCount, undefinedCount), n, [
832
+ b.loop(index, b.add(tailStart(), undefinedCount), n, [
349
833
  { kind: "arrayDelete", arr: a, index, loc },
350
834
  ]),
351
835
  ]),
@@ -356,6 +840,7 @@ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc
356
840
  params: [
357
841
  { localId: a.localId, name: "a", type: arrT },
358
842
  { localId: f.localId, name: "f", type: fnT },
843
+ ...(key ? [{ localId: key.localId, name: "key", type: keyT }] : []),
359
844
  ],
360
845
  returnType: arrT,
361
846
  locals: b.locals,
@@ -363,62 +848,44 @@ export function buildArraySortFn(name, elem, arity, copyFirst, undefinedTag, loc
363
848
  loc,
364
849
  };
365
850
  }
366
- /** A byte's complete value domain is small enough for stable default ordering
367
- * without comparisons. Counts use numbers so large inputs cannot wrap. */
368
- function countBytes(b, a, src, n) {
369
- const counts = b.local("counts", arrayOf(F64));
370
- const value = b.local("value"), index = b.local("index"), end = b.local("end");
371
- const zero = b.num(0), one = b.num(1);
372
- return [
373
- b.bind(src, b.allocate(BYTES_U8, n)),
374
- b.bind(counts, b.allocate(counts.type, b.num(256))),
375
- b.loop(value, zero, b.num(256), [b.set(counts, value, zero)]),
376
- b.loop(index, zero, n, [
377
- b.bind(value, b.at(a, index)),
378
- b.set(counts, value, b.add(b.at(counts, value), one)),
379
- ]),
380
- b.bind(index, zero),
381
- b.loop(value, zero, b.num(256), [
382
- b.bind(end, b.add(index, b.at(counts, value))),
383
- b.while(b.lt(index, end), [b.set(src, index, value), b.step(index)]),
384
- ]),
385
- ];
386
- }
387
- export function buildBytesSortFn(name, arity, hasComparator, loc) {
851
+ /** Typed-array `sort` and `toSorted`. `toSorted` orders a private copy;
852
+ * `sort` orders the receiver and returns it. Without a comparator, and for a
853
+ * recognized numeric comparator's `order`, the runtime sorts the elements by
854
+ * value (sortNumeric). Other comparators, and a recognized one the runtime
855
+ * refuses (a NaN or -0 element), take the runtime comparator sort
856
+ * (sortCompare). */
857
+ export function buildBytesSortFn(name, type, arity, hasComparator, copyFirst, order, loc) {
388
858
  const b = new SortIr(loc);
389
- const a = b.local("a", BYTES_U8), src = b.local("src", BYTES_U8), n = b.local("n");
859
+ const a = b.local("a", type), src = b.local("src", type);
390
860
  const fnT = funcOf([F64, F64].slice(0, arity), F64);
391
861
  const f = hasComparator ? b.local("f", fnT) : null;
392
- const body = [b.bind(n, b.length(a))];
393
- if (f !== null) {
394
- body.push(b.bind(src, {
395
- kind: "bytesIntrinsic",
396
- method: "slice",
397
- receiver: a,
398
- args: [],
399
- type: BYTES_U8,
400
- loc,
401
- }));
402
- body.push(...stableSort(b, src, n, (left, right) => ({
403
- kind: "bin",
404
- op: ">",
405
- left: { kind: "callValue", callee: f, args: [left, right].slice(0, arity), type: F64, loc },
406
- right: b.num(0),
407
- type: BOOL,
408
- loc,
409
- })));
410
- }
411
- else {
412
- body.push(...countBytes(b, a, src, n));
413
- }
414
- body.push({ kind: "return", value: src, loc });
862
+ const target = copyFirst ? src : a;
863
+ const intrinsic = (method, arg) => ({
864
+ kind: "bytesIntrinsic",
865
+ method,
866
+ receiver: target,
867
+ args: [arg],
868
+ type: method === "sortNumeric" ? BOOL : VOID,
869
+ loc,
870
+ });
871
+ const body = copyFirst
872
+ ? [b.bind(src, { kind: "bytesIntrinsic", method: "slice", receiver: a, args: [], type, loc })]
873
+ : [];
874
+ const compare = f === null ? [] : [{ kind: "exprStmt", expr: intrinsic("sortCompare", f), loc }];
875
+ if (f === null)
876
+ body.push({ kind: "exprStmt", expr: intrinsic("sortNumeric", b.num(0)), loc });
877
+ else if (order === null)
878
+ body.push(...compare);
879
+ else
880
+ body.push(b.branch(b.not(intrinsic("sortNumeric", b.num(order))), compare));
881
+ body.push({ kind: "return", value: target, loc });
415
882
  return {
416
883
  name,
417
884
  params: [
418
- { localId: a.localId, name: "a", type: BYTES_U8 },
885
+ { localId: a.localId, name: "a", type },
419
886
  ...(f === null ? [] : [{ localId: f.localId, name: "f", type: fnT }]),
420
887
  ],
421
- returnType: BYTES_U8,
888
+ returnType: type,
422
889
  locals: b.locals,
423
890
  body: distinctNodes(body),
424
891
  loc,