@scriptc/compiler 0.3.3 → 0.3.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 (352) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +844 -36
  2. package/dist/backend/cycle-mutability.d.ts +5 -0
  3. package/dist/backend/cycle-mutability.js +62 -3
  4. package/dist/backend/cycle-mutability.js.map +1 -1
  5. package/dist/backend/executable-features.js +1 -0
  6. package/dist/backend/executable-features.js.map +1 -1
  7. package/dist/backend/library-pack.js +1 -0
  8. package/dist/backend/library-pack.js.map +1 -1
  9. package/dist/backend/llvm/array-search.js +1 -1
  10. package/dist/backend/llvm/array-search.js.map +1 -1
  11. package/dist/backend/llvm/call-lifetimes.d.ts +11 -1
  12. package/dist/backend/llvm/call-lifetimes.js +30 -3
  13. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  14. package/dist/backend/llvm/call-lifetimes.test.js +31 -1
  15. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  16. package/dist/backend/llvm/common.d.ts +5 -0
  17. package/dist/backend/llvm/common.js +7 -0
  18. package/dist/backend/llvm/common.js.map +1 -1
  19. package/dist/backend/llvm/constant-callbacks.d.ts +2 -21
  20. package/dist/backend/llvm/constant-callbacks.js +36 -219
  21. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  22. package/dist/backend/llvm/constant-callbacks.test.js +22 -0
  23. package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
  24. package/dist/backend/llvm/dense-array-access.d.ts +9 -0
  25. package/dist/backend/llvm/dense-array-access.js +29 -3
  26. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  27. package/dist/backend/llvm/dyn.d.ts +46 -1
  28. package/dist/backend/llvm/dyn.js +218 -33
  29. package/dist/backend/llvm/dyn.js.map +1 -1
  30. package/dist/backend/llvm/emitter.d.ts +87 -1
  31. package/dist/backend/llvm/emitter.js +568 -61
  32. package/dist/backend/llvm/emitter.js.map +1 -1
  33. package/dist/backend/llvm/expr-async.js +17 -7
  34. package/dist/backend/llvm/expr-async.js.map +1 -1
  35. package/dist/backend/llvm/expr-bytes.d.ts +9 -0
  36. package/dist/backend/llvm/expr-bytes.js +159 -64
  37. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  38. package/dist/backend/llvm/expr-callbacks.d.ts +11 -0
  39. package/dist/backend/llvm/expr-callbacks.js +53 -0
  40. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  41. package/dist/backend/llvm/expr-calls.d.ts +3 -1
  42. package/dist/backend/llvm/expr-calls.js +137 -3
  43. package/dist/backend/llvm/expr-calls.js.map +1 -1
  44. package/dist/backend/llvm/expr-containers.js +63 -29
  45. package/dist/backend/llvm/expr-containers.js.map +1 -1
  46. package/dist/backend/llvm/expr-primitives.js +9 -1
  47. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  48. package/dist/backend/llvm/expr-stream-bridges.js +4 -0
  49. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  50. package/dist/backend/llvm/integer-clones.d.ts +103 -0
  51. package/dist/backend/llvm/integer-clones.js +1336 -0
  52. package/dist/backend/llvm/integer-clones.js.map +1 -0
  53. package/dist/backend/llvm/integer-clones.test.d.ts +1 -0
  54. package/dist/backend/llvm/integer-clones.test.js +219 -0
  55. package/dist/backend/llvm/integer-clones.test.js.map +1 -0
  56. package/dist/backend/llvm/intern-tables.test.d.ts +1 -0
  57. package/dist/backend/llvm/intern-tables.test.js +77 -0
  58. package/dist/backend/llvm/intern-tables.test.js.map +1 -0
  59. package/dist/backend/llvm/lib-datagram.js +24 -0
  60. package/dist/backend/llvm/lib-datagram.js.map +1 -1
  61. package/dist/backend/llvm/lib-dispatch.js +96 -1
  62. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  63. package/dist/backend/llvm/lib-filesystem.js +51 -0
  64. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  65. package/dist/backend/llvm/lib-network.js +16 -0
  66. package/dist/backend/llvm/lib-network.js.map +1 -1
  67. package/dist/backend/llvm/lib-process.js +24 -0
  68. package/dist/backend/llvm/lib-process.js.map +1 -1
  69. package/dist/backend/llvm/lib-shared.d.ts +5 -0
  70. package/dist/backend/llvm/lib-shared.js +114 -3
  71. package/dist/backend/llvm/lib-shared.js.map +1 -1
  72. package/dist/backend/llvm/lib-stream.js +87 -0
  73. package/dist/backend/llvm/lib-stream.js.map +1 -1
  74. package/dist/backend/llvm/lib-test.js +9 -0
  75. package/dist/backend/llvm/lib-test.js.map +1 -1
  76. package/dist/backend/llvm/lib-tls.js +6 -0
  77. package/dist/backend/llvm/lib-tls.js.map +1 -1
  78. package/dist/backend/llvm/local-array-reads.js +1 -1
  79. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  80. package/dist/backend/llvm/map-entry-fusion.d.ts +28 -0
  81. package/dist/backend/llvm/map-entry-fusion.js +233 -0
  82. package/dist/backend/llvm/map-entry-fusion.js.map +1 -0
  83. package/dist/backend/llvm/map-entry-fusion.test.d.ts +1 -0
  84. package/dist/backend/llvm/map-entry-fusion.test.js +183 -0
  85. package/dist/backend/llvm/map-entry-fusion.test.js.map +1 -0
  86. package/dist/backend/llvm/map-number-lookup.d.ts +6 -0
  87. package/dist/backend/llvm/map-number-lookup.js +23 -1
  88. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  89. package/dist/backend/llvm/map-number-lookup.test.js +60 -5
  90. package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
  91. package/dist/backend/llvm/map-read-lifetimes.d.ts +11 -0
  92. package/dist/backend/llvm/map-read-lifetimes.js +92 -1
  93. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  94. package/dist/backend/llvm/map-read-lifetimes.test.js +131 -3
  95. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  96. package/dist/backend/llvm/publish.d.ts +21 -0
  97. package/dist/backend/llvm/publish.js +101 -11
  98. package/dist/backend/llvm/publish.js.map +1 -1
  99. package/dist/backend/llvm/publish.test.d.ts +1 -0
  100. package/dist/backend/llvm/publish.test.js +94 -0
  101. package/dist/backend/llvm/publish.test.js.map +1 -0
  102. package/dist/backend/llvm/record-results.js +76 -2
  103. package/dist/backend/llvm/record-results.js.map +1 -1
  104. package/dist/backend/llvm/record-sources.d.ts +7 -0
  105. package/dist/backend/llvm/record-sources.js +14 -0
  106. package/dist/backend/llvm/record-sources.js.map +1 -0
  107. package/dist/backend/llvm/reference-writes.js +5 -2
  108. package/dist/backend/llvm/reference-writes.js.map +1 -1
  109. package/dist/backend/llvm/regions.d.ts +4 -1
  110. package/dist/backend/llvm/regions.js +12 -3
  111. package/dist/backend/llvm/regions.js.map +1 -1
  112. package/dist/backend/llvm/shapes.d.ts +9 -3
  113. package/dist/backend/llvm/shapes.js +18 -14
  114. package/dist/backend/llvm/shapes.js.map +1 -1
  115. package/dist/backend/llvm/shapes.test.js +5 -3
  116. package/dist/backend/llvm/shapes.test.js.map +1 -1
  117. package/dist/backend/llvm/string-lifetimes.test.js +75 -1
  118. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  119. package/dist/backend/llvm/string-reads.js +2 -2
  120. package/dist/backend/llvm/string-reads.js.map +1 -1
  121. package/dist/backend/llvm/string-slices.js +2 -2
  122. package/dist/backend/llvm/string-slices.js.map +1 -1
  123. package/dist/backend/llvm/walkers.d.ts +17 -0
  124. package/dist/backend/llvm/walkers.js +123 -0
  125. package/dist/backend/llvm/walkers.js.map +1 -1
  126. package/dist/backend/may-throw.js +4 -0
  127. package/dist/backend/may-throw.js.map +1 -1
  128. package/dist/backend/native/contracts.d.ts +5 -1
  129. package/dist/backend/native/executable.js +16 -6
  130. package/dist/backend/native/executable.js.map +1 -1
  131. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  132. package/dist/backend/native/runtime-inputs.js +1 -0
  133. package/dist/backend/native/runtime-inputs.js.map +1 -1
  134. package/dist/backend/native-codegen-core.d.ts +4 -4
  135. package/dist/backend/native-codegen-core.js +4 -6
  136. package/dist/backend/native-codegen-core.js.map +1 -1
  137. package/dist/backend/native-codegen.test.js +7 -8
  138. package/dist/backend/native-codegen.test.js.map +1 -1
  139. package/dist/backend/native-link-info-core.d.ts +3 -0
  140. package/dist/backend/native-link-info-core.js.map +1 -1
  141. package/dist/backend/publication.js +3 -1
  142. package/dist/backend/publication.js.map +1 -1
  143. package/dist/backend/runtime-abi.d.ts +2 -2
  144. package/dist/backend/runtime-abi.js +2 -2
  145. package/dist/backend/runtime-pack-targets.test.js +2 -1
  146. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  147. package/dist/backend/runtime-pack.test.js +2 -1
  148. package/dist/backend/runtime-pack.test.js.map +1 -1
  149. package/dist/backend/target-diagnostics.js +7 -0
  150. package/dist/backend/target-diagnostics.js.map +1 -1
  151. package/dist/backend/warm-cache.js +1 -0
  152. package/dist/backend/warm-cache.js.map +1 -1
  153. package/dist/executable/executable-cache.d.ts +1 -0
  154. package/dist/executable/executable-cache.js +1 -0
  155. package/dist/executable/executable-cache.js.map +1 -1
  156. package/dist/executable/executable-cache.test.js +1 -0
  157. package/dist/executable/executable-cache.test.js.map +1 -1
  158. package/dist/frontend/experimental-import.d.ts +5 -1
  159. package/dist/frontend/experimental-import.js +28 -3
  160. package/dist/frontend/experimental-import.js.map +1 -1
  161. package/dist/frontend/lowering/assert-instances.d.ts +38 -0
  162. package/dist/frontend/lowering/assert-instances.js +269 -0
  163. package/dist/frontend/lowering/assert-instances.js.map +1 -0
  164. package/dist/frontend/lowering/builtin-calls.js +3 -0
  165. package/dist/frontend/lowering/builtin-calls.js.map +1 -1
  166. package/dist/frontend/lowering/builtins/callable-aliases.js +54 -8
  167. package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
  168. package/dist/frontend/lowering/builtins/child-process-async.d.ts +8 -6
  169. package/dist/frontend/lowering/builtins/child-process-async.js +45 -29
  170. package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
  171. package/dist/frontend/lowering/builtins/compression.d.ts +18 -0
  172. package/dist/frontend/lowering/builtins/compression.js +175 -2
  173. package/dist/frontend/lowering/builtins/compression.js.map +1 -1
  174. package/dist/frontend/lowering/builtins/constants.js +7 -2
  175. package/dist/frontend/lowering/builtins/constants.js.map +1 -1
  176. package/dist/frontend/lowering/builtins/crypto.d.ts +6 -0
  177. package/dist/frontend/lowering/builtins/crypto.js +111 -1
  178. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  179. package/dist/frontend/lowering/builtins/errors.js +23 -0
  180. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  181. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +2 -0
  182. package/dist/frontend/lowering/builtins/filesystem-calls.js +5 -0
  183. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  184. package/dist/frontend/lowering/builtins/filesystem.js +60 -0
  185. package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
  186. package/dist/frontend/lowering/builtins/fs-streams.d.ts +26 -0
  187. package/dist/frontend/lowering/builtins/fs-streams.js +131 -0
  188. package/dist/frontend/lowering/builtins/fs-streams.js.map +1 -0
  189. package/dist/frontend/lowering/builtins/module-calls.js +5 -1
  190. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  191. package/dist/frontend/lowering/builtins/timers.d.ts +3 -0
  192. package/dist/frontend/lowering/builtins/timers.js +109 -23
  193. package/dist/frontend/lowering/builtins/timers.js.map +1 -1
  194. package/dist/frontend/lowering/call-signatures.js +6 -0
  195. package/dist/frontend/lowering/call-signatures.js.map +1 -1
  196. package/dist/frontend/lowering/class-dynamic-dispatch.js +216 -20
  197. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  198. package/dist/frontend/lowering/containers/bytes.js +33 -12
  199. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  200. package/dist/frontend/lowering/devirtualize.js +20 -7
  201. package/dist/frontend/lowering/devirtualize.js.map +1 -1
  202. package/dist/frontend/lowering/intern-tables.d.ts +13 -0
  203. package/dist/frontend/lowering/intern-tables.js +536 -0
  204. package/dist/frontend/lowering/intern-tables.js.map +1 -0
  205. package/dist/frontend/lowering/lower-assert.js +700 -61
  206. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  207. package/dist/frontend/lowering/lower-async-iteration.js +11 -2
  208. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  209. package/dist/frontend/lowering/lower-calls.js +75 -6
  210. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  211. package/dist/frontend/lowering/lower-classes.d.ts +3 -0
  212. package/dist/frontend/lowering/lower-classes.js +43 -0
  213. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  214. package/dist/frontend/lowering/lower-dgram.js +132 -67
  215. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  216. package/dist/frontend/lowering/lower-event-emitter.d.ts +9 -1
  217. package/dist/frontend/lowering/lower-event-emitter.js +78 -0
  218. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  219. package/dist/frontend/lowering/lower-exprs.d.ts +4 -0
  220. package/dist/frontend/lowering/lower-exprs.js +144 -58
  221. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  222. package/dist/frontend/lowering/lower-inspect.d.ts +6 -0
  223. package/dist/frontend/lowering/lower-inspect.js +138 -39
  224. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  225. package/dist/frontend/lowering/lower-mock.d.ts +11 -0
  226. package/dist/frontend/lowering/lower-mock.js +504 -0
  227. package/dist/frontend/lowering/lower-mock.js.map +1 -0
  228. package/dist/frontend/lowering/lower-modules.js +7 -0
  229. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  230. package/dist/frontend/lowering/lower-server.d.ts +4 -0
  231. package/dist/frontend/lowering/lower-server.js +448 -30
  232. package/dist/frontend/lowering/lower-server.js.map +1 -1
  233. package/dist/frontend/lowering/lower-stmts.js +35 -8
  234. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  235. package/dist/frontend/lowering/lower-stream.d.ts +10 -6
  236. package/dist/frontend/lowering/lower-stream.js +794 -27
  237. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  238. package/dist/frontend/lowering/lower-test.js +86 -8
  239. package/dist/frontend/lowering/lower-test.js.map +1 -1
  240. package/dist/frontend/lowering/lowerer.d.ts +25 -1
  241. package/dist/frontend/lowering/lowerer.js +74 -9
  242. package/dist/frontend/lowering/lowerer.js.map +1 -1
  243. package/dist/frontend/lowering/pairs-snapshot.d.ts +6 -0
  244. package/dist/frontend/lowering/pairs-snapshot.js +49 -0
  245. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  246. package/dist/frontend/lowering/record-sources.d.ts +15 -0
  247. package/dist/frontend/lowering/record-sources.js +46 -0
  248. package/dist/frontend/lowering/record-sources.js.map +1 -0
  249. package/dist/frontend/lowering/surfaces.d.ts +4 -0
  250. package/dist/frontend/lowering/surfaces.js +94 -16
  251. package/dist/frontend/lowering/surfaces.js.map +1 -1
  252. package/dist/frontend/lowering/zlib-constants.d.ts +1 -0
  253. package/dist/frontend/lowering/zlib-constants.js +181 -0
  254. package/dist/frontend/lowering/zlib-constants.js.map +1 -0
  255. package/dist/frontend/mock-shapes.d.ts +10 -0
  256. package/dist/frontend/mock-shapes.js +76 -0
  257. package/dist/frontend/mock-shapes.js.map +1 -0
  258. package/dist/frontend/pipeline.js +5 -3
  259. package/dist/frontend/pipeline.js.map +1 -1
  260. package/dist/frontend/program.js +6 -1
  261. package/dist/frontend/program.js.map +1 -1
  262. package/dist/frontend/resolve.d.ts +4 -0
  263. package/dist/frontend/resolve.js +14 -0
  264. package/dist/frontend/resolve.js.map +1 -1
  265. package/dist/frontend/tsc-codes.js +1 -0
  266. package/dist/frontend/tsc-codes.js.map +1 -1
  267. package/dist/frontend/type-mapper.d.ts +8 -0
  268. package/dist/frontend/type-mapper.js +155 -9
  269. package/dist/frontend/type-mapper.js.map +1 -1
  270. package/dist/index.js +2 -1
  271. package/dist/index.js.map +1 -1
  272. package/dist/ir/analysis.d.ts +10 -0
  273. package/dist/ir/analysis.js +35 -0
  274. package/dist/ir/analysis.js.map +1 -1
  275. package/dist/ir/analysis.test.js +69 -1
  276. package/dist/ir/analysis.test.js.map +1 -1
  277. package/dist/ir/builtin-effects.js +72 -0
  278. package/dist/ir/builtin-effects.js.map +1 -1
  279. package/dist/ir/builtin-signatures.d.ts +1 -1
  280. package/dist/ir/builtin-signatures.js +238 -15
  281. package/dist/ir/builtin-signatures.js.map +1 -1
  282. package/dist/ir/capture-values.d.ts +107 -0
  283. package/dist/ir/capture-values.js +850 -0
  284. package/dist/ir/capture-values.js.map +1 -0
  285. package/dist/ir/capture-values.test.d.ts +1 -0
  286. package/dist/ir/capture-values.test.js +268 -0
  287. package/dist/ir/capture-values.test.js.map +1 -0
  288. package/dist/ir/field-values.d.ts +16 -0
  289. package/dist/ir/field-values.js +128 -0
  290. package/dist/ir/field-values.js.map +1 -0
  291. package/dist/ir/field-values.test.d.ts +1 -0
  292. package/dist/ir/field-values.test.js +160 -0
  293. package/dist/ir/field-values.test.js.map +1 -0
  294. package/dist/ir/final-fields.d.ts +4 -1
  295. package/dist/ir/final-fields.js +11 -3
  296. package/dist/ir/final-fields.js.map +1 -1
  297. package/dist/ir/function-references.test.js +1 -1
  298. package/dist/ir/function-references.test.js.map +1 -1
  299. package/dist/ir/init-only-globals.d.ts +16 -0
  300. package/dist/ir/init-only-globals.js +121 -0
  301. package/dist/ir/init-only-globals.js.map +1 -0
  302. package/dist/ir/init-only-globals.test.d.ts +1 -0
  303. package/dist/ir/init-only-globals.test.js +115 -0
  304. package/dist/ir/init-only-globals.test.js.map +1 -0
  305. package/dist/ir/initializer-bindings.d.ts +18 -1
  306. package/dist/ir/initializer-bindings.js +91 -1
  307. package/dist/ir/initializer-bindings.js.map +1 -1
  308. package/dist/ir/initializer-bindings.test.js +57 -2
  309. package/dist/ir/initializer-bindings.test.js.map +1 -1
  310. package/dist/ir/int32-slots.d.ts +22 -0
  311. package/dist/ir/int32-slots.js +376 -13
  312. package/dist/ir/int32-slots.js.map +1 -1
  313. package/dist/ir/int32-slots.test.js +91 -8
  314. package/dist/ir/int32-slots.test.js.map +1 -1
  315. package/dist/ir/integer-loop-facts.d.ts +19 -1
  316. package/dist/ir/integer-loop-facts.js +155 -7
  317. package/dist/ir/integer-loop-facts.js.map +1 -1
  318. package/dist/ir/integer-ranges.d.ts +8 -5
  319. package/dist/ir/integer-ranges.js +147 -55
  320. package/dist/ir/integer-ranges.js.map +1 -1
  321. package/dist/ir/integer-ranges.test.js +225 -7
  322. package/dist/ir/integer-ranges.test.js.map +1 -1
  323. package/dist/ir/ir.d.ts +29 -2
  324. package/dist/ir/ir.js +17 -0
  325. package/dist/ir/ir.js.map +1 -1
  326. package/dist/ir/property-bags.d.ts +14 -0
  327. package/dist/ir/property-bags.js +121 -0
  328. package/dist/ir/property-bags.js.map +1 -0
  329. package/dist/ir/receiver-readers.d.ts +21 -0
  330. package/dist/ir/receiver-readers.js +217 -0
  331. package/dist/ir/receiver-readers.js.map +1 -0
  332. package/dist/ir/runtime-features.d.ts +1 -0
  333. package/dist/ir/runtime-features.js +34 -2
  334. package/dist/ir/runtime-features.js.map +1 -1
  335. package/dist/ir/validate.js +221 -5
  336. package/dist/ir/validate.js.map +1 -1
  337. package/dist/ir/validate.test.js +21 -0
  338. package/dist/ir/validate.test.js.map +1 -1
  339. package/dist/library/int-infer.js +3 -0
  340. package/dist/library/int-infer.js.map +1 -1
  341. package/dist/library/ir-policy.js +1 -0
  342. package/dist/library/ir-policy.js.map +1 -1
  343. package/dist/native/cli.js +1 -0
  344. package/dist/native/cli.js.map +1 -1
  345. package/dist/native/compiler.js +1 -3
  346. package/dist/native/compiler.js.map +1 -1
  347. package/dist/native/prepare.js +1 -0
  348. package/dist/native/prepare.js.map +1 -1
  349. package/dist/native/sanitizer.test.js +1 -0
  350. package/dist/native/sanitizer.test.js.map +1 -1
  351. package/package.json +20 -20
  352. package/surface-manifest.json +896 -49
@@ -1,4 +1,4 @@
1
- import { analyzeIntegerRanges, INT32_RANGE, withinInt32, } from "./integer-ranges.js";
1
+ import { analyzeIntegerRanges, INT32_RANGE, NON_NEGATIVE_INT32_RANGE, withinInt32, } from "./integer-ranges.js";
2
2
  import { exprFunctionReference, moduleFunctionReferences } from "./function-references.js";
3
3
  import { findInitializerBindings, withInitializerBindings } from "./initializer-bindings.js";
4
4
  import { everyExprChild, everyStmtChild, everyStmtList, everyTypeChild } from "./traverse.js";
@@ -40,6 +40,8 @@ export class Int32Slots {
40
40
  familyOf = new Map();
41
41
  paramFacts = new Map();
42
42
  returns = new Set();
43
+ /** Results narrowed below their level (narrowSlotRanges). */
44
+ returnRanges = new Map();
43
45
  /** Captured-binding groups (one shared box) that hold an int32, and the
44
46
  * group of each `function\0local` member. */
45
47
  boxes = new Set();
@@ -58,6 +60,12 @@ export class Int32Slots {
58
60
  /** Drops the analysis attempted on pinned slots. The contract check and
59
61
  * this analysis use the same range proofs, so this stays empty. */
60
62
  pinViolations = [];
63
+ /** Parameter, return and box candidates (`param:`, `ret:`, `box:` keys)
64
+ * still assumed to hold only non-negative int32s. The optimistic fixpoint
65
+ * starts every unpinned candidate here and demotes it to int32 when a
66
+ * write is an int32 that may be negative: `(x * 31 + n) % m` only proves
67
+ * a result when x and n are known not to be negative. */
68
+ nonNegative = new Set();
61
69
  constructor(classes = new Map()) {
62
70
  this.classes = classes;
63
71
  }
@@ -96,10 +104,14 @@ export class Int32Slots {
96
104
  this.boxes.size === 0 &&
97
105
  this.int32Locals.size === 0)
98
106
  return {};
107
+ const level = (key) => this.nonNegative.has(key) ? NON_NEGATIVE_INT32_RANGE : INT32_RANGE;
99
108
  const result = {
100
109
  field: (className, field) => (this.isField(className, field) ? INT32_RANGE : null),
101
- call: (callee) => (this.returns.has(callee) ? INT32_RANGE : null),
102
- boxed: (localId) => (this.hasBox(this.boxGroup(fnName, localId)) ? INT32_RANGE : null),
110
+ call: (callee) => this.returns.has(callee) ? (this.returnRanges.get(callee) ?? level(`ret:${callee}`)) : null,
111
+ boxed: (localId) => {
112
+ const group = this.boxGroup(fnName, localId);
113
+ return group !== null && this.boxes.has(group) ? level(`box:${group}`) : null;
114
+ },
103
115
  };
104
116
  if (this.int32Locals.size > 0)
105
117
  result.locals = (localId) => this.int32Locals.has(`${fnName}\0${localId}`) || this.int32Locals.has(`\0${localId}`)
@@ -107,9 +119,47 @@ export class Int32Slots {
107
119
  : null;
108
120
  const params = this.paramFacts.get(fnName);
109
121
  if (params)
110
- result.params = params;
122
+ result.params =
123
+ this.nonNegative.size === 0
124
+ ? params
125
+ : new Map([...params].map(([id, range]) => {
126
+ const key = `param:${fnName}\0${id}`;
127
+ return [id, this.nonNegative.has(key) ? NON_NEGATIVE_INT32_RANGE : range];
128
+ }));
111
129
  return result;
112
130
  }
131
+ /** Assume an unpinned candidate holds only non-negative int32s. */
132
+ assumeNonNegative(key) {
133
+ if (!this.pinned.has(key))
134
+ this.nonNegative.add(key);
135
+ }
136
+ isNonNegative(key) {
137
+ return this.nonNegative.has(key);
138
+ }
139
+ /** Widen a non-negative candidate to int32; whether it was one. */
140
+ demote(key) {
141
+ return this.nonNegative.delete(key);
142
+ }
143
+ isPinned(key) {
144
+ return this.pinned.has(key);
145
+ }
146
+ /** The range a parameter fact currently asserts, if it has one. */
147
+ paramRange(fnName, localId) {
148
+ return this.facts(fnName).params?.get(localId) ?? null;
149
+ }
150
+ /** The range a result fact currently asserts, if it has one. */
151
+ returnRange(fnName) {
152
+ return this.facts(fnName).call?.(fnName) ?? null;
153
+ }
154
+ /** Replace a parameter fact with a narrower proven range. */
155
+ narrowParam(fnName, localId, range) {
156
+ this.nonNegative.delete(`param:${fnName}\0${localId}`);
157
+ this.addParam(fnName, localId, range);
158
+ }
159
+ /** Replace a result fact with a narrower proven range. */
160
+ narrowReturn(fnName, range) {
161
+ this.returnRanges.set(fnName, range);
162
+ }
113
163
  boxGroup(fnName, localId) {
114
164
  return this.boxGroupOf.get(`${fnName}\0${localId}`) ?? null;
115
165
  }
@@ -137,6 +187,7 @@ export class Int32Slots {
137
187
  dropBox(group) {
138
188
  if (this.refusePinned(`box:${group}`))
139
189
  return false;
190
+ this.nonNegative.delete(`box:${group}`);
140
191
  return this.boxes.delete(group);
141
192
  }
142
193
  hasBox(group) {
@@ -162,6 +213,7 @@ export class Int32Slots {
162
213
  dropParam(fnName, localId) {
163
214
  if (this.refusePinned(`param:${fnName}\0${localId}`))
164
215
  return false;
216
+ this.nonNegative.delete(`param:${fnName}\0${localId}`);
165
217
  const params = this.paramFacts.get(fnName);
166
218
  if (!params?.delete(localId))
167
219
  return false;
@@ -178,6 +230,8 @@ export class Int32Slots {
178
230
  dropReturn(fnName) {
179
231
  if (this.refusePinned(`ret:${fnName}`))
180
232
  return false;
233
+ this.nonNegative.delete(`ret:${fnName}`);
234
+ this.returnRanges.delete(fnName);
181
235
  return this.returns.delete(fnName);
182
236
  }
183
237
  hasReturn(fnName) {
@@ -235,7 +289,13 @@ const DYN_READ_ONLY = new Set([
235
289
  "dyn.arrLen",
236
290
  "dyn.bagGet",
237
291
  "dyn.compare",
292
+ "dyn.forInKeyStrings",
293
+ "dyn.forInKeys",
294
+ "dyn.forInStable",
295
+ "dyn.getOwnPropertyNames",
296
+ "dyn.getPrototype",
238
297
  "dyn.hasKey",
298
+ "dyn.hasOwn",
239
299
  "dyn.in",
240
300
  "dyn.iterator",
241
301
  "dyn.iteratorCanStep",
@@ -245,13 +305,23 @@ const DYN_READ_ONLY = new Set([
245
305
  "dyn.mapSeedEntries",
246
306
  "dyn.mapSeedEntry",
247
307
  "dyn.numberConstructor",
308
+ "dyn.objCreate",
309
+ "dyn.objEntries",
310
+ "dyn.objEntryPairs",
311
+ "dyn.objKeyStrings",
312
+ "dyn.objKeys",
313
+ "dyn.objValues",
314
+ "dyn.objectTag",
315
+ "dyn.ownKeys",
248
316
  "dyn.packPush",
249
317
  "dyn.packPushSpread",
250
318
  "dyn.stringConstructor",
251
319
  "dyn.this",
320
+ "dyn.toString",
252
321
  "dyn.toStringCoerce",
253
322
  "dyn.typedRefIs",
254
323
  "dyn.typedRefKeyIs",
324
+ "dyn.typeof",
255
325
  // error.ctorOptions runs scr_error_init_options, the initializer
256
326
  // error.newOptions also runs: it stamps the receiver's runtime-owned
257
327
  // error prefix and reads `options.cause`.
@@ -259,6 +329,8 @@ const DYN_READ_ONLY = new Set([
259
329
  "error.new",
260
330
  "error.newOptions",
261
331
  "fs.utimesSync",
332
+ "insp.dyn",
333
+ "insp.dynS",
262
334
  "json.stringifyReplacer",
263
335
  "json.stringifyValue",
264
336
  "num.toStringRadix",
@@ -654,8 +726,10 @@ export function analyzeInt32Slots(mod) {
654
726
  },
655
727
  });
656
728
  for (const fn of mod.functions) {
657
- if (fn.returnType.kind === "f64" && !fn.async && !fn.generator)
729
+ if (fn.returnType.kind === "f64" && !fn.async && !fn.generator) {
658
730
  slots.addReturn(fn.name);
731
+ slots.assumeNonNegative(`ret:${fn.name}`);
732
+ }
659
733
  if (fn.async ||
660
734
  fn.generator ||
661
735
  !called.has(fn.name) ||
@@ -663,8 +737,10 @@ export function analyzeInt32Slots(mod) {
663
737
  virtual(fn.name))
664
738
  continue;
665
739
  for (const param of fn.params)
666
- if (param.type.kind === "f64")
740
+ if (param.type.kind === "f64" && !slots.isPinned(paramKey(fn.name, param.localId))) {
667
741
  slots.addParam(fn.name, param.localId);
742
+ slots.assumeNonNegative(paramKey(fn.name, param.localId));
743
+ }
668
744
  }
669
745
  const arityChecked = (fn, args, offset) => {
670
746
  if (fn && fn.params.length !== args + offset)
@@ -784,6 +860,11 @@ export function analyzeInt32Slots(mod) {
784
860
  }
785
861
  boxOrigin.set(`param:${fnName}\0${localId}`, group);
786
862
  slots.addBox(group, members);
863
+ // A box starts from its origin parameter's value: it can only be
864
+ // non-negative while that parameter is.
865
+ if (!origin.params.some((p) => p.localId === localId) ||
866
+ slots.isNonNegative(paramKey(fnName, localId)))
867
+ slots.assumeNonNegative(`box:${group}`);
787
868
  }
788
869
  const dropBox = (group, why) => {
789
870
  if (group === null)
@@ -876,6 +957,9 @@ export function analyzeInt32Slots(mod) {
876
957
  });
877
958
  };
878
959
  const provenByFunction = new Map();
960
+ // Each function's parameter and result writes under its latest analysis:
961
+ // at the fixpoint, the ranges of every write under the final facts.
962
+ const lastWrites = new Map();
879
963
  while (queue.length) {
880
964
  const fn = functions.get(queue.pop());
881
965
  queued.delete(fn.name);
@@ -888,16 +972,35 @@ export function analyzeInt32Slots(mod) {
888
972
  const ranges = hasCandidateWrite(fn)
889
973
  ? analyzeIntegerRanges(numeric(fn), slots.facts(fn.name))
890
974
  : new Map();
975
+ if (ranges.size > 0)
976
+ lastWrites.set(fn.name, slotWrites(fn, ranges, functions));
977
+ else
978
+ lastWrites.delete(fn.name);
891
979
  const proven = [];
892
980
  const int32 = (e) => withinInt32(ranges.get(e));
981
+ // An int32 written into a slot still assumed non-negative: widen the
982
+ // assumption when the value may be negative, and reanalyze its readers.
983
+ const settle = (slot, e) => {
984
+ if (!slots.isNonNegative(slot) || (ranges.get(e)?.min ?? -1) >= 0)
985
+ return;
986
+ slots.demote(slot);
987
+ invalidate(slot);
988
+ const group = boxOrigin.get(slot);
989
+ if (group !== undefined && slots.demote(`box:${group}`))
990
+ invalidate(`box:${group}`);
991
+ };
893
992
  const args = (callee, list, offset) => {
894
993
  if (!callee)
895
994
  return;
896
995
  list.forEach((arg, i) => {
897
996
  const param = callee.params[i + offset];
898
- if (!param || !slots.hasParam(callee.name, param.localId) || int32(arg))
997
+ if (!param || !slots.hasParam(callee.name, param.localId))
899
998
  return;
900
999
  const slot = `param:${callee.name}\0${param.localId}`;
1000
+ if (int32(arg)) {
1001
+ settle(slot, arg);
1002
+ return;
1003
+ }
901
1004
  if (dropParam(callee.name, param.localId, `argument in ${fn.name} is not int32`)) {
902
1005
  invalidate(slot);
903
1006
  // An argument computed where the caller's own parameters were
@@ -913,9 +1016,11 @@ export function analyzeInt32Slots(mod) {
913
1016
  };
914
1017
  const boxWrite = (localId, value) => {
915
1018
  const group = slots.boxGroup(fn.name, localId);
916
- if (!slots.hasBox(group) || int32(value))
1019
+ if (!slots.hasBox(group))
917
1020
  return;
918
- if (dropBox(group, `write in ${fn.name} is not int32`))
1021
+ if (int32(value))
1022
+ settle(`box:${group}`, value);
1023
+ else if (dropBox(group, `write in ${fn.name} is not int32`))
919
1024
  invalidate(`box:${group}`);
920
1025
  };
921
1026
  walkFunction(fn, {
@@ -936,8 +1041,10 @@ export function analyzeInt32Slots(mod) {
936
1041
  }
937
1042
  }
938
1043
  else if (s.kind === "return" && slots.hasReturn(fn.name)) {
939
- if (s.value && int32(s.value))
1044
+ if (s.value && int32(s.value)) {
1045
+ settle(`ret:${fn.name}`, s.value);
940
1046
  return;
1047
+ }
941
1048
  reason(`ret:${fn.name}`, "return is not int32");
942
1049
  slots.dropReturn(fn.name);
943
1050
  invalidate(`ret:${fn.name}`);
@@ -957,7 +1064,8 @@ export function analyzeInt32Slots(mod) {
957
1064
  for (const proven of provenByFunction.values())
958
1065
  for (const value of proven)
959
1066
  slots.provenWrites.add(value);
960
- rangedParameters(slots, functions, retry, numeric, (callee) => readers.get(`ret:${callee}`));
1067
+ const ranged = rangedParameters(slots, functions, retry, numeric, (callee) => readers.get(`ret:${callee}`));
1068
+ narrowSlotRanges(slots, functions, numeric, lastWrites, ranged, (slot) => readers.get(slot));
961
1069
  return slots;
962
1070
  }
963
1071
  /** Bounds a widened parameter range jumps to: the int32 limits, and the
@@ -985,8 +1093,9 @@ const widenMax = (max) => WIDEN_MAX.find((bound) => bound >= max) ?? Infinity;
985
1093
  * every call site is checked under the final ranges. The facts the main
986
1094
  * fixpoint proved are fixed here: these ranges only add precision. */
987
1095
  function rangedParameters(slots, functions, retry, numeric, callersOf) {
1096
+ const changed = new Set();
988
1097
  if (retry.size === 0)
989
- return;
1098
+ return changed;
990
1099
  // Per function: retried parameter → its range so far (absent: no call
991
1100
  // site analyzed yet; null: failed).
992
1101
  const retried = new Map();
@@ -1097,7 +1206,261 @@ function rangedParameters(slots, functions, retry, numeric, callersOf) {
1097
1206
  }
1098
1207
  for (const [fnName, ranges] of retried)
1099
1208
  for (const [id, range] of ranges)
1100
- if (range)
1209
+ if (range) {
1101
1210
  slots.addParam(fnName, id, range);
1211
+ changed.add(fnName);
1212
+ }
1213
+ return changed;
1214
+ }
1215
+ const joinRanges = (a, b) => a && b ? { min: Math.min(a.min, b.min), max: Math.max(a.max, b.max) } : null;
1216
+ const rangeWithin = (inner, outer) => inner !== null && inner.min >= outer.min && inner.max <= outer.max;
1217
+ const sameRange = (a, b) => a.min === b.min && a.max === b.max;
1218
+ /** The values one analysis of a function writes into parameter slots of
1219
+ * its direct callees and into its own result slot (`param:` and `ret:`
1220
+ * keys), joined per slot; null when some write has no proven range. */
1221
+ function slotWrites(fn, ranges, functions) {
1222
+ const writes = new Map();
1223
+ const write = (key, value) => {
1224
+ const range = value ? (ranges.get(value) ?? null) : null;
1225
+ const previous = writes.get(key);
1226
+ writes.set(key, previous === undefined ? range : joinRanges(previous, range));
1227
+ };
1228
+ const args = (callee, list, offset) => {
1229
+ if (!callee)
1230
+ return;
1231
+ list.forEach((arg, i) => {
1232
+ const param = callee.params[i + offset];
1233
+ if (param)
1234
+ write(`param:${callee.name}\0${param.localId}`, arg);
1235
+ });
1236
+ };
1237
+ walkFunction(fn, {
1238
+ stmt: (s) => {
1239
+ if (s.kind === "return")
1240
+ write(`ret:${fn.name}`, s.value);
1241
+ },
1242
+ expr: (e) => {
1243
+ if (e.kind === "call")
1244
+ args(functions.get(e.callee), e.args, 0);
1245
+ else if (e.kind === "new")
1246
+ args(functions.get(`%${e.className}.constructor`), e.args, 1);
1247
+ },
1248
+ });
1249
+ return writes;
1250
+ }
1251
+ /** Rounds after which narrowSlotRanges keeps its last verified ranges. */
1252
+ const NARROW_ROUNDS = 6;
1253
+ /** Narrows parameter and result facts from their proven level (int32 or
1254
+ * non-negative int32, or a call-site range) to the values actually written
1255
+ * into them, and revives results the level could not prove. `(x * 31 + n)
1256
+ * % m` proves its result only under a positive divisor, and keeps i32
1257
+ * arithmetic only when `x` is known to be small; the levels know neither,
1258
+ * the values passed and returned do.
1259
+ *
1260
+ * A descending iteration from the fixpoint's facts: each round assumes a
1261
+ * range for every slot, reanalyzes the functions that read a slot whose
1262
+ * assumption changed, and joins the ranges of every write into each slot.
1263
+ * The assumptions are verified (inductive) when every slot's writes land
1264
+ * inside its assumed range: then, by induction over the execution, every
1265
+ * slot holds only values in its range. A verified round adopts the joined
1266
+ * writes as the next assumptions (each bound moves at most once, so the
1267
+ * iteration ends), and a reanalyzed function whose every return is now an
1268
+ * int32 joins with that range as a result candidate. A slot whose writes
1269
+ * leave its assumption falls back to its last verified range (a revived
1270
+ * result to none). Only verified assumptions are kept, and a reanalyzed
1271
+ * function must still prove every write into a field or box slot (whose
1272
+ * facts do not change here), or the narrowing is abandoned. Pinned
1273
+ * (contract) slots keep their contract range. */
1274
+ function narrowSlotRanges(slots, functions, numeric, lastWrites, changed, readersOf) {
1275
+ // Every parameter and result slot with a fact, and that fact.
1276
+ const proven = new Map();
1277
+ const fixed = new Set();
1278
+ // Results the fixpoint dropped (a return was not an int32 at the level).
1279
+ const revivable = new Set();
1280
+ for (const fn of functions.values()) {
1281
+ const result = slots.hasReturn(fn.name) ? slots.returnRange(fn.name) : null;
1282
+ if (result)
1283
+ proven.set(`ret:${fn.name}`, result);
1284
+ else if (fn.returnType.kind === "f64" && !fn.async && !fn.generator)
1285
+ revivable.add(`ret:${fn.name}`);
1286
+ for (const param of fn.params) {
1287
+ const range = slots.hasParam(fn.name, param.localId)
1288
+ ? slots.paramRange(fn.name, param.localId)
1289
+ : null;
1290
+ if (range)
1291
+ proven.set(`param:${fn.name}\0${param.localId}`, range);
1292
+ }
1293
+ }
1294
+ for (const key of proven.keys())
1295
+ if (slots.isPinned(key))
1296
+ fixed.add(key);
1297
+ if (proven.size === fixed.size)
1298
+ return;
1299
+ // The readers of a slot: a parameter's function, a result's callers.
1300
+ const readersOfKey = (key) => {
1301
+ if (key.startsWith("param:"))
1302
+ return [key.slice(6, key.indexOf("\0"))];
1303
+ const readers = readersOf(key);
1304
+ return readers ? [...readers] : [];
1305
+ };
1306
+ const factsUnder = (fn, assumed) => {
1307
+ const base = slots.facts(fn.name);
1308
+ const params = new Map(base.params ?? []);
1309
+ for (const param of fn.params) {
1310
+ const range = assumed.get(`param:${fn.name}\0${param.localId}`);
1311
+ if (range)
1312
+ params.set(param.localId, range);
1313
+ }
1314
+ const call = base.call;
1315
+ return {
1316
+ ...base,
1317
+ params,
1318
+ call: (callee) => assumed.get(`ret:${callee}`) ?? (call ? call(callee) : null),
1319
+ };
1320
+ };
1321
+ // Reanalyze one function: its slot writes, and whether it still proves
1322
+ // every write into field and box slots.
1323
+ const observe = (fn, assumed) => {
1324
+ const ranges = analyzeIntegerRanges(numeric(fn), factsUnder(fn, assumed));
1325
+ let sound = true;
1326
+ const box = (localId, value) => {
1327
+ const group = slots.boxGroup(fn.name, localId);
1328
+ if (!slots.hasBox(group))
1329
+ return;
1330
+ const range = ranges.get(value) ?? null;
1331
+ const level = slots.isNonNegative(`box:${group}`) ? NON_NEGATIVE_INT32_RANGE : INT32_RANGE;
1332
+ if (!rangeWithin(range, level))
1333
+ sound = false;
1334
+ };
1335
+ walkFunction(fn, {
1336
+ stmt: (s) => {
1337
+ if (s.kind === "assign")
1338
+ box(s.localId, s.value);
1339
+ else if (s.kind === "varDecl" && s.init)
1340
+ box(s.localId, s.init);
1341
+ else if (s.kind === "fieldSet" && slots.isField(s.className, s.field))
1342
+ if (!withinInt32(ranges.get(s.value)))
1343
+ sound = false;
1344
+ },
1345
+ expr: (e) => {
1346
+ if (e.kind === "assignExpr")
1347
+ box(e.localId, e.value);
1348
+ },
1349
+ });
1350
+ return { writes: slotWrites(fn, ranges, functions), sound };
1351
+ };
1352
+ const writesByFunction = new Map(lastWrites);
1353
+ const join = () => {
1354
+ const joined = new Map();
1355
+ for (const writes of writesByFunction.values())
1356
+ for (const [key, range] of writes) {
1357
+ if (!proven.has(key) && !revivable.has(key))
1358
+ continue;
1359
+ const previous = joined.get(key);
1360
+ joined.set(key, previous === undefined ? range : joinRanges(previous, range));
1361
+ }
1362
+ return joined;
1363
+ };
1364
+ // The ranges every function was last analyzed under.
1365
+ let analyzed = new Map(proven);
1366
+ let verified = new Map(proven);
1367
+ // Functions whose recorded writes predate their current facts.
1368
+ const dirty = new Set(changed);
1369
+ // The narrowing operator: a bound moves at most once from its proven
1370
+ // value (a revived result's from int32), so recursion that shifts its
1371
+ // argument (`f(d - 1)`) cannot walk a bound down one step per round.
1372
+ const narrowed = (joined) => {
1373
+ const next = new Map(verified);
1374
+ for (const [key, range] of joined) {
1375
+ const current = verified.get(key);
1376
+ if (!current || fixed.has(key) || !range || !rangeWithin(range, current))
1377
+ continue;
1378
+ const original = proven.get(key) ?? INT32_RANGE;
1379
+ next.set(key, {
1380
+ min: current.min === original.min ? range.min : current.min,
1381
+ max: current.max === original.max ? range.max : current.max,
1382
+ });
1383
+ }
1384
+ return next;
1385
+ };
1386
+ let assumed = dirty.size > 0 ? new Map(proven) : narrowed(join());
1387
+ for (let round = 0; round < NARROW_ROUNDS; round++) {
1388
+ for (const [key, range] of assumed) {
1389
+ const before = analyzed.get(key);
1390
+ if (!before || !sameRange(range, before))
1391
+ for (const name of readersOfKey(key))
1392
+ dirty.add(name);
1393
+ }
1394
+ for (const key of analyzed.keys())
1395
+ if (!assumed.has(key))
1396
+ for (const name of readersOfKey(key))
1397
+ dirty.add(name);
1398
+ const observedNow = new Set();
1399
+ for (const name of dirty) {
1400
+ const fn = functions.get(name);
1401
+ if (!fn)
1402
+ continue;
1403
+ const observed = observe(fn, assumed);
1404
+ if (!observed.sound)
1405
+ return;
1406
+ writesByFunction.set(name, observed.writes);
1407
+ observedNow.add(name);
1408
+ }
1409
+ dirty.clear();
1410
+ analyzed = assumed;
1411
+ const joined = join();
1412
+ let inductive = true;
1413
+ const next = new Map(assumed);
1414
+ for (const [key, range] of assumed) {
1415
+ const written = joined.get(key);
1416
+ if (written === undefined || rangeWithin(written, range))
1417
+ continue;
1418
+ inductive = false;
1419
+ const fallback = verified.get(key);
1420
+ if (fallback)
1421
+ next.set(key, fallback);
1422
+ else
1423
+ next.delete(key);
1424
+ }
1425
+ if (inductive) {
1426
+ verified = assumed;
1427
+ const tighter = narrowed(joined);
1428
+ // Results that reanalysis under the narrowed facts proves now.
1429
+ for (const key of revivable) {
1430
+ const range = joined.get(key);
1431
+ if (!tighter.has(key) && observedNow.has(key.slice(4)) && withinInt32(range))
1432
+ tighter.set(key, range);
1433
+ }
1434
+ if (tighter.size === assumed.size &&
1435
+ [...tighter].every(([key, range]) => sameRange(range, assumed.get(key))))
1436
+ break;
1437
+ assumed = tighter;
1438
+ }
1439
+ else if (next.size !== assumed.size ||
1440
+ [...next].some(([key, range]) => !sameRange(range, assumed.get(key)))) {
1441
+ assumed = next;
1442
+ }
1443
+ else
1444
+ break; // narrowing other slots broke a verified one: keep `verified`
1445
+ }
1446
+ for (const [key, range] of verified) {
1447
+ if (fixed.has(key))
1448
+ continue;
1449
+ const original = proven.get(key);
1450
+ if (original && sameRange(range, original))
1451
+ continue;
1452
+ if (key.startsWith("ret:")) {
1453
+ const fnName = key.slice(4);
1454
+ if (!original) {
1455
+ slots.addReturn(fnName);
1456
+ slots.reasons.delete(key);
1457
+ }
1458
+ slots.narrowReturn(fnName, range);
1459
+ }
1460
+ else {
1461
+ const cut = key.indexOf("\0");
1462
+ slots.narrowParam(key.slice(6, cut), key.slice(cut + 1), range);
1463
+ }
1464
+ }
1102
1465
  }
1103
1466
  //# sourceMappingURL=int32-slots.js.map