@scriptc/compiler 0.0.36 → 0.1.2

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 (256) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +52 -22
  2. package/ambient/scriptc-overrides.d.ts +0 -7
  3. package/ambient/scriptc.d.ts +3 -2
  4. package/dist/backend/build-cache.js.map +1 -1
  5. package/dist/backend/c/async.js +24 -2
  6. package/dist/backend/c/async.js.map +1 -1
  7. package/dist/backend/c/c-emitter.d.ts +22 -10
  8. package/dist/backend/c/c-emitter.js +60 -15
  9. package/dist/backend/c/c-emitter.js.map +1 -1
  10. package/dist/backend/c/exprs.js +289 -55
  11. package/dist/backend/c/exprs.js.map +1 -1
  12. package/dist/backend/c/island.js.map +1 -1
  13. package/dist/backend/c/may-throw.js +3 -0
  14. package/dist/backend/c/may-throw.js.map +1 -1
  15. package/dist/backend/c/stmts.d.ts +3 -5
  16. package/dist/backend/c/stmts.js +76 -17
  17. package/dist/backend/c/stmts.js.map +1 -1
  18. package/dist/backend/c/types.js.map +1 -1
  19. package/dist/backend/c/walkers.js +36 -12
  20. package/dist/backend/c/walkers.js.map +1 -1
  21. package/dist/backend/external-c.d.ts +33 -0
  22. package/dist/backend/external-c.js +51 -0
  23. package/dist/backend/external-c.js.map +1 -0
  24. package/dist/backend/link-plan.d.ts +37 -0
  25. package/dist/backend/link-plan.js +26 -0
  26. package/dist/backend/link-plan.js.map +1 -0
  27. package/dist/backend/linker.d.ts +22 -0
  28. package/dist/backend/linker.js +236 -0
  29. package/dist/backend/linker.js.map +1 -0
  30. package/dist/backend/llvm/blocks.js.map +1 -1
  31. package/dist/backend/llvm/dyn.js +63 -3
  32. package/dist/backend/llvm/dyn.js.map +1 -1
  33. package/dist/backend/llvm/emitter.js +132 -26
  34. package/dist/backend/llvm/emitter.js.map +1 -1
  35. package/dist/backend/llvm/expr-async.js +85 -3
  36. package/dist/backend/llvm/expr-async.js.map +1 -1
  37. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  38. package/dist/backend/llvm/expr-calls.js.map +1 -1
  39. package/dist/backend/llvm/expr-containers.js +68 -54
  40. package/dist/backend/llvm/expr-containers.js.map +1 -1
  41. package/dist/backend/llvm/expr-context.d.ts +2 -1
  42. package/dist/backend/llvm/expr-control.js.map +1 -1
  43. package/dist/backend/llvm/expr-dispatch.js +2 -0
  44. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  45. package/dist/backend/llvm/expr-dynamic.js +6 -3
  46. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  47. package/dist/backend/llvm/expr-island.js.map +1 -1
  48. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  49. package/dist/backend/llvm/expr-primitives.js +20 -0
  50. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  51. package/dist/backend/llvm/expr-records.js.map +1 -1
  52. package/dist/backend/llvm/expr-stream-bridges.js +245 -10
  53. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  54. package/dist/backend/llvm/lib-dispatch.js +2 -0
  55. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  56. package/dist/backend/llvm/lib-shared.js +18 -0
  57. package/dist/backend/llvm/lib-shared.js.map +1 -1
  58. package/dist/backend/llvm/lib-stream.js +6 -3
  59. package/dist/backend/llvm/lib-stream.js.map +1 -1
  60. package/dist/backend/llvm/split.js.map +1 -1
  61. package/dist/backend/llvm/unsupported.js.map +1 -1
  62. package/dist/backend/llvm/walkers.js +31 -4
  63. package/dist/backend/llvm/walkers.js.map +1 -1
  64. package/dist/backend/native-codegen.d.ts +8 -1
  65. package/dist/backend/native-codegen.js +39 -25
  66. package/dist/backend/native-codegen.js.map +1 -1
  67. package/dist/backend/native-codegen.test.js +44 -4
  68. package/dist/backend/native-codegen.test.js.map +1 -1
  69. package/dist/backend/native-link-info.d.ts +1 -1
  70. package/dist/backend/native-link-info.js +42 -18
  71. package/dist/backend/native-link-info.js.map +1 -1
  72. package/dist/backend/native-toolchain.js.map +1 -1
  73. package/dist/backend/native-toolchain.test.js +5 -1
  74. package/dist/backend/native-toolchain.test.js.map +1 -1
  75. package/dist/backend/runtime-pack-targets.test.d.ts +1 -0
  76. package/dist/backend/runtime-pack-targets.test.js +54 -0
  77. package/dist/backend/runtime-pack-targets.test.js.map +1 -0
  78. package/dist/backend/runtime-pack.d.ts +5 -30
  79. package/dist/backend/runtime-pack.js +46 -141
  80. package/dist/backend/runtime-pack.js.map +1 -1
  81. package/dist/backend/runtime-pack.test.js +49 -14
  82. package/dist/backend/runtime-pack.test.js.map +1 -1
  83. package/dist/backend/targets.d.ts +63 -17
  84. package/dist/backend/targets.js +251 -35
  85. package/dist/backend/targets.js.map +1 -1
  86. package/dist/backend/targets.test.js +27 -5
  87. package/dist/backend/targets.test.js.map +1 -1
  88. package/dist/backend/vendor-archives.js.map +1 -1
  89. package/dist/compat/fetch-profile.js +4 -2
  90. package/dist/compat/fetch-profile.js.map +1 -1
  91. package/dist/coverage/report.js.map +1 -1
  92. package/dist/coverage/surface-manifest.js +22 -1
  93. package/dist/coverage/surface-manifest.js.map +1 -1
  94. package/dist/diagnostics/diagnostic.d.ts +6 -5
  95. package/dist/diagnostics/diagnostic.js +7 -6
  96. package/dist/diagnostics/diagnostic.js.map +1 -1
  97. package/dist/diagnostics/render.js.map +1 -1
  98. package/dist/ffi/ffi-manifest.js.map +1 -1
  99. package/dist/frontend/cjs-lexer.js.map +1 -1
  100. package/dist/frontend/dts-paths.js.map +1 -1
  101. package/dist/frontend/input-tracker.d.ts +10 -0
  102. package/dist/frontend/input-tracker.js +26 -3
  103. package/dist/frontend/input-tracker.js.map +1 -1
  104. package/dist/frontend/input-tracker.test.js +8 -1
  105. package/dist/frontend/input-tracker.test.js.map +1 -1
  106. package/dist/frontend/lib-contract.js.map +1 -1
  107. package/dist/frontend/lowering/array-values.d.ts +12 -0
  108. package/dist/frontend/lowering/array-values.js +76 -0
  109. package/dist/frontend/lowering/array-values.js.map +1 -0
  110. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  111. package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
  112. package/dist/frontend/lowering/containers/bytes.js +1021 -0
  113. package/dist/frontend/lowering/containers/bytes.js.map +1 -0
  114. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
  115. package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
  116. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
  117. package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
  118. package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
  119. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
  120. package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
  121. package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
  122. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
  123. package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
  124. package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
  125. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
  126. package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
  127. package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
  128. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
  129. package/dist/frontend/lowering/lib-boundary.js +7 -2
  130. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  131. package/dist/frontend/lowering/lower-array-sort.d.ts +22 -0
  132. package/dist/frontend/lowering/lower-array-sort.js +619 -0
  133. package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
  134. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  135. package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
  136. package/dist/frontend/lowering/lower-async-iteration.js +657 -0
  137. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
  138. package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
  139. package/dist/frontend/lowering/lower-builtins.js +379 -48
  140. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  141. package/dist/frontend/lowering/lower-calls.d.ts +16 -8
  142. package/dist/frontend/lowering/lower-calls.js +667 -91
  143. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  144. package/dist/frontend/lowering/lower-classes.d.ts +7 -13
  145. package/dist/frontend/lowering/lower-classes.js +128 -35
  146. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  147. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  148. package/dist/frontend/lowering/lower-containers.d.ts +1 -47
  149. package/dist/frontend/lowering/lower-containers.js +779 -2038
  150. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  151. package/dist/frontend/lowering/lower-event-emitter.js +51 -5
  152. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  153. package/dist/frontend/lowering/lower-exprs.d.ts +4 -78
  154. package/dist/frontend/lowering/lower-exprs.js +1128 -2409
  155. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  156. package/dist/frontend/lowering/lower-generators.d.ts +18 -3
  157. package/dist/frontend/lowering/lower-generators.js +145 -9
  158. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  159. package/dist/frontend/lowering/lower-inspect.js +50 -36
  160. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  161. package/dist/frontend/lowering/lower-island.d.ts +11 -4
  162. package/dist/frontend/lowering/lower-island.js +47 -10
  163. package/dist/frontend/lowering/lower-island.js.map +1 -1
  164. package/dist/frontend/lowering/lower-modules.js +52 -15
  165. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  166. package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
  167. package/dist/frontend/lowering/lower-node-module.js +302 -0
  168. package/dist/frontend/lowering/lower-node-module.js.map +1 -0
  169. package/dist/frontend/lowering/lower-server.js +11 -1
  170. package/dist/frontend/lowering/lower-server.js.map +1 -1
  171. package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
  172. package/dist/frontend/lowering/lower-stmts.js +811 -314
  173. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  174. package/dist/frontend/lowering/lower-stream.js +4 -4
  175. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  176. package/dist/frontend/lowering/lowerer.d.ts +109 -34
  177. package/dist/frontend/lowering/lowerer.js +1225 -62
  178. package/dist/frontend/lowering/lowerer.js.map +1 -1
  179. package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
  180. package/dist/frontend/lowering/optional-arguments.js +57 -0
  181. package/dist/frontend/lowering/optional-arguments.js.map +1 -0
  182. package/dist/frontend/lowering/surfaces.d.ts +10 -2
  183. package/dist/frontend/lowering/surfaces.js +15 -3
  184. package/dist/frontend/lowering/surfaces.js.map +1 -1
  185. package/dist/frontend/npm-static-declarations.d.ts +35 -0
  186. package/dist/frontend/npm-static-declarations.js +506 -0
  187. package/dist/frontend/npm-static-declarations.js.map +1 -0
  188. package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
  189. package/dist/frontend/npm-static-declarations.test.js +122 -0
  190. package/dist/frontend/npm-static-declarations.test.js.map +1 -0
  191. package/dist/frontend/npm-static.d.ts +2 -0
  192. package/dist/frontend/npm-static.js +26 -10
  193. package/dist/frontend/npm-static.js.map +1 -1
  194. package/dist/frontend/npm.d.ts +60 -0
  195. package/dist/frontend/npm.js +38 -4
  196. package/dist/frontend/npm.js.map +1 -1
  197. package/dist/frontend/npm.test.d.ts +1 -0
  198. package/dist/frontend/npm.test.js +50 -0
  199. package/dist/frontend/npm.test.js.map +1 -0
  200. package/dist/frontend/program.d.ts +3 -2
  201. package/dist/frontend/program.js +495 -68
  202. package/dist/frontend/program.js.map +1 -1
  203. package/dist/frontend/resolve.d.ts +10 -2
  204. package/dist/frontend/resolve.js +90 -14
  205. package/dist/frontend/resolve.js.map +1 -1
  206. package/dist/frontend/resolve.test.js +4 -1
  207. package/dist/frontend/resolve.test.js.map +1 -1
  208. package/dist/frontend/runtime-resolve.d.ts +22 -0
  209. package/dist/frontend/runtime-resolve.js +101 -0
  210. package/dist/frontend/runtime-resolve.js.map +1 -0
  211. package/dist/frontend/runtime-resolve.test.d.ts +1 -0
  212. package/dist/frontend/runtime-resolve.test.js +18 -0
  213. package/dist/frontend/runtime-resolve.test.js.map +1 -0
  214. package/dist/frontend/ts7/adapter.js +12 -13
  215. package/dist/frontend/ts7/adapter.js.map +1 -1
  216. package/dist/frontend/ts7/ast.js.map +1 -1
  217. package/dist/frontend/ts7/census-check.js +3 -3
  218. package/dist/frontend/ts7/census-check.js.map +1 -1
  219. package/dist/frontend/ts7/checker.d.ts +3 -0
  220. package/dist/frontend/ts7/checker.js +12 -3
  221. package/dist/frontend/ts7/checker.js.map +1 -1
  222. package/dist/frontend/ts7/enums.js.map +1 -1
  223. package/dist/frontend/ts7/program-adapter.js +42 -3
  224. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  225. package/dist/frontend/type-mapper.js +120 -7
  226. package/dist/frontend/type-mapper.js.map +1 -1
  227. package/dist/index.d.ts +3 -3
  228. package/dist/index.js +50 -28
  229. package/dist/index.js.map +1 -1
  230. package/dist/ir/analysis.js.map +1 -1
  231. package/dist/ir/ir.d.ts +125 -41
  232. package/dist/ir/ir.js +82 -31
  233. package/dist/ir/ir.js.map +1 -1
  234. package/dist/ir/serialize.d.ts +1 -1
  235. package/dist/ir/serialize.js +1 -1
  236. package/dist/ir/validate.js +127 -95
  237. package/dist/ir/validate.js.map +1 -1
  238. package/dist/library/cache-primitives.js.map +1 -1
  239. package/dist/library/cache-reset.test.js.map +1 -1
  240. package/dist/library/compiler-self-identity.js.map +1 -1
  241. package/dist/library/fence-eval.js +3 -1
  242. package/dist/library/fence-eval.js.map +1 -1
  243. package/dist/library/int-infer.js +12 -1
  244. package/dist/library/int-infer.js.map +1 -1
  245. package/dist/library/int-infer.test.js +4 -4
  246. package/dist/library/int-infer.test.js.map +1 -1
  247. package/dist/library/library-cache.test.js +5 -5
  248. package/dist/library/library-profile.js.map +1 -1
  249. package/dist/library/sidecar-validate.js.map +1 -1
  250. package/dist/library/sidecar.js.map +1 -1
  251. package/dist/startup-cache.d.ts +9 -1
  252. package/dist/startup-cache.js +16 -1
  253. package/dist/startup-cache.js.map +1 -1
  254. package/dist/wasi-paths.js.map +1 -1
  255. package/package.json +18 -5
  256. package/surface-manifest.json +64 -8
@@ -1,5 +1,5 @@
1
1
  import { InternalCompilerError } from "../../errors.js";
2
- import { arrayOf, BOOL, BYTES_U8, bytesOf, canMarshalFuncIntoIsland, CHILDSTREAM_T, DYN, F64, islandPromisePayloadTag, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, RUNTIME_ERROR_CLASSES, STRING, typeEquals, typeKey } from "../../ir/ir.js";
2
+ import { arrayOf, BOOL, BYTES_U8, bytesOf, canMarshalFuncIntoIsland, CHILDSTREAM_T, DYN, F64, islandPromisePayloadTag, isClassOwnEnumerableFieldName, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, RUNTIME_ERROR_CLASSES, STRING, typeEquals, typeKey } from "../../ir/ir.js";
3
3
  import { boxAccess, BYTES_NUM_KIND_C, BYTES_NUM_VAR_C, bytesElemKindC, cDecl, cFnPtrCast, cNumberLiteral, cStringLiteral, cType, DV_GET_KIND_C, DV_SET_KIND_C, elemAccess, mapKeyAccess, mapKeyKindC, mapValKindC, releaseCallC, retainCallC, vAdapters } from "./types.js";
4
4
  import { mangleClassNew, mangleClassRetain, mangleClassStruct, mangleField, mangleFnClosure, mangleFunction, mangleGlobal, mangleLocal, mangleRecordClone, mangleRecordNew, mangleRecordStruct, mangleVtStruct } from "../mangle.js";
5
5
  import { OVERFLOW_MEMBER } from "./shapes.js";
@@ -17,7 +17,24 @@ function streamTypedRefCommitAdapter(emitter, t, snapshot, defs) {
17
17
  if (t.kind === "array") {
18
18
  const commit = `${snapshot}_commit`;
19
19
  emitter.walkerProtos.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d); /* commit live stream element ${typeKey(t)} */`);
20
- defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ScrArr *sc_target = (ScrArr *)sc_p;`, ` ScrArr *sc_next = ${emitter.dynCheckHelper(t)}(sc_d, NULL);`, ` if (!sc_next) return;`, ` size_t sc_target_len = sc_target->len;`, ` size_t sc_target_cap = sc_target->cap;`, ` uint64_t *sc_target_data = sc_target->data;`, ` sc_target->len = sc_next->len;`, ` sc_target->cap = sc_next->cap;`, ` sc_target->data = sc_next->data;`, ` sc_next->len = sc_target_len;`, ` sc_next->cap = sc_target_cap;`, ` sc_next->data = sc_target_data;`, ` scr_arr_release(sc_next);`, `}`, ``);
20
+ defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ScrArr *sc_target = (ScrArr *)sc_p;`, ` ScrArr *sc_next = ${emitter.dynCheckHelper(t)}(sc_d, NULL);`, ` if (!sc_next) return;`, ` size_t sc_target_len = sc_target->len;`, ` size_t sc_target_cap = sc_target->cap;`, ` uint64_t *sc_target_data = sc_target->data;`, ` uint8_t *sc_target_present = sc_target->present;`, ` ScrArrSparseSlot *sc_target_sparse = sc_target->sparse;`, ` size_t sc_target_sparse_len = sc_target->sparse_len;`, ` size_t sc_target_sparse_cap = sc_target->sparse_cap;`, ` ScrArrProp *sc_target_props = sc_target->props;`, ` size_t sc_target_prop_len = sc_target->prop_len;`, ` size_t sc_target_prop_cap = sc_target->prop_cap;`, ` sc_target->len = sc_next->len;`, ` sc_target->cap = sc_next->cap;`, ` sc_target->data = sc_next->data;`, ` sc_target->present = sc_next->present;`, ` sc_target->sparse = sc_next->sparse;`, ` sc_target->sparse_len = sc_next->sparse_len;`, ` sc_target->sparse_cap = sc_next->sparse_cap;`, ` sc_target->props = sc_next->props;`, ` sc_target->prop_len = sc_next->prop_len;`, ` sc_target->prop_cap = sc_next->prop_cap;`, ` sc_next->len = sc_target_len;`, ` sc_next->cap = sc_target_cap;`, ` sc_next->data = sc_target_data;`, ` sc_next->present = sc_target_present;`, ` sc_next->sparse = sc_target_sparse;`, ` sc_next->sparse_len = sc_target_sparse_len;`, ` sc_next->sparse_cap = sc_target_sparse_cap;`, ` sc_next->props = sc_target_props;`, ` sc_next->prop_len = sc_target_prop_len;`, ` sc_next->prop_cap = sc_target_prop_cap;`, ` scr_arr_release(sc_next);`, `}`, ``);
21
+ return `&${commit}`;
22
+ }
23
+ if (isDynTypedRefType(t)) {
24
+ const meta = emitter.classMeta.get(t.className);
25
+ if (!meta) {
26
+ throw new InternalCompilerError(`emitter bug: typed-ref commit of unknown class ${t.className}`);
27
+ }
28
+ const commit = `${snapshot}_commit`;
29
+ emitter.walkerProtos.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d); /* commit unknown class ${typeKey(t)} */`);
30
+ defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ${cDecl(t, "sc_target")} = (${cType(t).trim()})sc_p;`);
31
+ for (const field of meta.def.fields.filter((f) => isClassOwnEnumerableFieldName(f.name))) {
32
+ const member = mangleField(field.name);
33
+ const keyLit = cStringLiteral(Buffer.from(field.name, "utf8"));
34
+ const keyLen = Buffer.byteLength(field.name, "utf8");
35
+ defs.push(` {`, ` const ScrDyn *sc_member = scr_dyn_obj_get(sc_d, ${keyLit}, ${keyLen});`, ` ${cDecl(field.type, "sc_next")} = ${emitter.dynCheckHelper(field.type)}(sc_member ? sc_member : scr_dyn_undefined(), NULL);`, ` if (scr_exc_pending()) return;`, ` ${cDecl(field.type, "sc_old")} = sc_target->${member};`, ` sc_target->${member} = sc_next;`, ...(isRefCounted(field.type) ? [` ${releaseCallC(field.type, "sc_old")};`] : [" (void)sc_old;"]), ` }`);
36
+ }
37
+ defs.push(`}`, ``);
21
38
  return `&${commit}`;
22
39
  }
23
40
  if (t.kind !== "record")
@@ -39,6 +56,51 @@ function streamTypedRefCommitAdapter(emitter, t, snapshot, defs) {
39
56
  defs.push(` ${releaseCallC(t, "sc_next")};`, `}`, ``);
40
57
  return `&${commit}`;
41
58
  }
59
+ /** Boxes a union selected at runtime, preserving mutable/class arm identity
60
+ * while converting scalar and unit arms normally. It shares the enclosing
61
+ * adapter context so recursive class fields reuse the prototype already
62
+ * registered by streamTypedRefAdapter instead of recursing forever. */
63
+ function nestedTypedRefUnionAdapter(emitter, t, ctx) {
64
+ const key = typeKey(t);
65
+ const unions = (ctx.unions ??= new Map());
66
+ const existing = unions.get(key);
67
+ if (existing)
68
+ return existing;
69
+ const def = emitter.unionsById.get(t.unionId);
70
+ if (!def)
71
+ throw new InternalCompilerError(`emitter bug: typed-ref union ${t.unionId} is undeclared`);
72
+ const sym = `${ctx.prefix}_union_${unions.size}`;
73
+ unions.set(key, sym);
74
+ emitter.walkerProtos.push(`static ScrDyn *${sym}(ScrUnion *sc_u); /* typed-ref union ${key} */`);
75
+ const lines = [`static ScrDyn *${sym}(ScrUnion *sc_u) {`, ` switch (sc_u->tag) {`];
76
+ def.arms.forEach((arm, tag) => {
77
+ if (streamTypedRefEligible(arm) || isDynTypedRefType(arm)) {
78
+ const adapter = streamTypedRefAdapter(emitter, arm, ctx);
79
+ const rc = vAdapters(arm);
80
+ const armKey = typeKey(arm);
81
+ const keyLit = cStringLiteral(Buffer.from(armKey, "utf8"));
82
+ lines.push(` case ${tag}: return scr_dyn_new_typed_ref(scr_union_peek(sc_u), &${rc.retain}, &${rc.release}, ${keyLit}, ${Buffer.byteLength(armKey, "utf8")}, &${adapter.snapshot}, ${adapter.commit});`);
83
+ }
84
+ else if (arm.kind === "undefinedT") {
85
+ lines.push(` case ${tag}: return scr_dyn_retain(scr_dyn_undefined());`);
86
+ }
87
+ else if (arm.kind === "nullT") {
88
+ lines.push(` case ${tag}: return scr_dyn_new_null();`);
89
+ }
90
+ else if (arm.kind === "f64") {
91
+ lines.push(` case ${tag}: return scr_dyn_new_num(scr_union_get_f64(sc_u));`);
92
+ }
93
+ else if (arm.kind === "bool") {
94
+ lines.push(` case ${tag}: return scr_dyn_new_bool(scr_union_get_bool(sc_u));`);
95
+ }
96
+ else {
97
+ lines.push(` case ${tag}: return ${emitter.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(sc_u));`);
98
+ }
99
+ });
100
+ lines.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
101
+ ctx.defs.push(...lines);
102
+ return sym;
103
+ }
42
104
  /** Build the live dyn view of one typed stream value. Mutable reference
43
105
  * children are capsules of their own, so a write through `v.child.x` or
44
106
  * `v.items[0]` commits directly to that child's static source instead of
@@ -57,7 +119,11 @@ function streamTypedRefAdapter(emitter, t, ctx, preferredSnapshot) {
57
119
  emitter.walkerProtos.push(`static ScrDyn *${snapshot}(void *sc_p); /* materialize live stream value ${key} */`);
58
120
  adapter.commit = streamTypedRefCommitAdapter(emitter, t, snapshot, ctx.defs);
59
121
  const box = (child, expr) => {
60
- if (!streamTypedRefEligible(child)) {
122
+ if (child.kind === "union" &&
123
+ (emitter.unionsById.get(child.unionId)?.arms.some((arm) => streamTypedRefEligible(arm) || isDynTypedRefType(arm)) ?? false)) {
124
+ return `${nestedTypedRefUnionAdapter(emitter, child, ctx)}(${expr})`;
125
+ }
126
+ if (!streamTypedRefEligible(child) && !isDynTypedRefType(child)) {
61
127
  return `${emitter.toDynHelper(child)}(${expr})`;
62
128
  }
63
129
  const nested = streamTypedRefAdapter(emitter, child, ctx);
@@ -70,7 +136,19 @@ function streamTypedRefAdapter(emitter, t, ctx, preferredSnapshot) {
70
136
  `static ScrDyn *${snapshot}(void *sc_p) { /* materialize live stream value ${key} */`,
71
137
  ` ${cDecl(t, "v")} = (${cType(t).trim()})sc_p;`,
72
138
  ];
73
- if (t.kind === "record") {
139
+ if (isDynTypedRefType(t)) {
140
+ const meta = emitter.classMeta.get(t.className);
141
+ if (!meta) {
142
+ throw new InternalCompilerError(`emitter bug: typed-ref materialize of unknown class ${t.className}`);
143
+ }
144
+ lines.push(` ScrDyn *d = scr_dyn_new_obj();`);
145
+ for (const field of meta.def.fields.filter((f) => isClassOwnEnumerableFieldName(f.name))) {
146
+ const keyLit = cStringLiteral(Buffer.from(field.name, "utf8"));
147
+ lines.push(` scr_dyn_obj_set(d, ${keyLit}, ${Buffer.byteLength(field.name, "utf8")}, ${box(field.type, `v->${mangleField(field.name)}`)});`);
148
+ }
149
+ lines.push(` return d;`);
150
+ }
151
+ else if (t.kind === "record") {
74
152
  const shape = emitter.recordsById.get(t.shapeId);
75
153
  if (!shape) {
76
154
  throw new InternalCompilerError(`emitter bug: stream typed-ref materialize of unknown shape ${t.shapeId}`);
@@ -132,7 +210,7 @@ function liveDynRefAdapter(emitter, t) {
132
210
  const existing = emitter.liveDynRefAdapters.get(key);
133
211
  if (existing)
134
212
  return existing;
135
- if (!streamTypedRefEligible(t)) {
213
+ if (!streamTypedRefEligible(t) && !isDynTypedRefType(t)) {
136
214
  throw new InternalCompilerError(`emitter bug: live dyn ref of ${key}`);
137
215
  }
138
216
  const prefix = `sc_ldr_${emitter.liveDynRefAdapters.size}`;
@@ -157,7 +235,7 @@ function liveDynUnionRefAdapter(emitter, t) {
157
235
  }
158
236
  const mutableArms = union.arms
159
237
  .map((arm, tag) => ({ arm, tag }))
160
- .filter(({ arm }) => streamTypedRefEligible(arm));
238
+ .filter(({ arm }) => streamTypedRefEligible(arm) || isDynTypedRefType(arm));
161
239
  if (mutableArms.length === 0) {
162
240
  throw new InternalCompilerError(`emitter bug: live dyn ref of immutable union ${key}`);
163
241
  }
@@ -179,7 +257,27 @@ function liveDynUnionRefAdapter(emitter, t) {
179
257
  const keyLit = cStringLiteral(Buffer.from(armKey, "utf8"));
180
258
  defs.push(` case ${tag}:`, ` return scr_dyn_new_typed_ref(scr_union_peek(sc_u), &${rc.retain}, &${rc.release}, ${keyLit}, ${Buffer.byteLength(armKey, "utf8")}, &${adapter.snapshot}, ${adapter.commit});`);
181
259
  }
182
- defs.push(` default:`, ` return ${emitter.toDynHelper(t)}(sc_u);`, ` }`, `}`, ``);
260
+ const mutableTags = new Set(mutableArms.map(({ tag }) => tag));
261
+ union.arms.forEach((arm, tag) => {
262
+ if (mutableTags.has(tag))
263
+ return;
264
+ if (arm.kind === "undefinedT") {
265
+ defs.push(` case ${tag}: return scr_dyn_retain(scr_dyn_undefined());`);
266
+ }
267
+ else if (arm.kind === "nullT") {
268
+ defs.push(` case ${tag}: return scr_dyn_new_null();`);
269
+ }
270
+ else if (arm.kind === "f64") {
271
+ defs.push(` case ${tag}: return scr_dyn_new_num(scr_union_get_f64(sc_u));`);
272
+ }
273
+ else if (arm.kind === "bool") {
274
+ defs.push(` case ${tag}: return scr_dyn_new_bool(scr_union_get_bool(sc_u));`);
275
+ }
276
+ else {
277
+ defs.push(` case ${tag}: return ${emitter.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(sc_u));`);
278
+ }
279
+ });
280
+ defs.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
183
281
  emitter.walkerDefs.push(...defs);
184
282
  return sym;
185
283
  }
@@ -1284,12 +1382,7 @@ function emitContainerExpr(emitter, e) {
1284
1382
  e.elems.forEach((el, i) => {
1285
1383
  const v = emitter.emitExpr(el);
1286
1384
  if (spreadSet.has(i)) {
1287
- const n = `sc_i${emitter.tempCounter++}`;
1288
- emitter.line(`for (size_t ${n} = 0, ${n}_len = (size_t)scr_arr_len(${v.name}); ${n} < ${n}_len; ${n}++) {`);
1289
- emitter.indent++;
1290
- emitter.line(`scr_arr_push_${acc}(${arr.name}, scr_arr_get_${acc}(${v.name}, (double)${n}));`);
1291
- emitter.indent--;
1292
- emitter.line(`}`);
1385
+ emitter.line(`scr_arr_push_spread(${arr.name}, ${v.name});`);
1293
1386
  return;
1294
1387
  }
1295
1388
  if (acc === "ref")
@@ -1335,6 +1428,20 @@ function emitContainerExpr(emitter, e) {
1335
1428
  const acc = elemAccess(e.arr.type.elem);
1336
1429
  return emitter.newTemp(e.type, `scr_arr_get_${acc}(${arr.name}, ${idx.name})`);
1337
1430
  }
1431
+ case "arrayHas": {
1432
+ const arr = emitter.emitExpr(e.arr);
1433
+ const idx = emitter.emitExpr(e.index);
1434
+ if (e.arr.type.kind !== "array")
1435
+ throw new InternalCompilerError("emitter bug: arrayHas on non-array");
1436
+ return emitter.newTemp(e.type, `scr_arr_has(${arr.name}, ${idx.name})`);
1437
+ }
1438
+ case "arrayState": {
1439
+ const arr = emitter.emitExpr(e.arr);
1440
+ const idx = emitter.emitExpr(e.index);
1441
+ if (e.arr.type.kind !== "array")
1442
+ throw new InternalCompilerError("emitter bug: arrayState on non-array");
1443
+ return emitter.newTemp(e.type, `scr_arr_state(${arr.name}, ${idx.name})`);
1444
+ }
1338
1445
  case "arrIntrinsic": {
1339
1446
  const r = emitter.emitExpr(e.receiver);
1340
1447
  if (e.receiver.type.kind !== "array")
@@ -1344,6 +1451,10 @@ function emitContainerExpr(emitter, e) {
1344
1451
  switch (method) {
1345
1452
  case "length":
1346
1453
  return emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1454
+ case "nextPresent": {
1455
+ const start = emitter.emitExpr(e.args[0]);
1456
+ return emitter.newTemp(e.type, `scr_arr_next_present(${r.name}, ${start.name})`);
1457
+ }
1347
1458
  case "push": {
1348
1459
  // Variadic like JS: every argument evaluates first (left to
1349
1460
  // right — an argument reading the array sees the pre-push
@@ -1363,18 +1474,15 @@ function emitContainerExpr(emitter, e) {
1363
1474
  : emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1364
1475
  }
1365
1476
  case "pushSpread": {
1366
- // `a.push(...src)`: append src's elements in order. The source
1367
- // is BORROWED; the count snapshots before the loop so
1368
- // `a.push(...a)` duplicates exactly like JS. _get_ref's +1
1369
- // moves into _push_ref — RC-balanced. Result: the new length.
1477
+ // `a.push(...src)`: append src's indexed state in order while
1478
+ // preserving holes; the runtime snapshots self-spread and
1479
+ // retains copied refs. Result: the new length.
1370
1480
  const src = emitter.emitExpr(e.args[0]);
1371
- const n = `sc_i${emitter.tempCounter++}`;
1372
- emitter.line(`for (size_t ${n} = 0, ${n}_len = (size_t)scr_arr_len(${src.name}); ${n} < ${n}_len; ${n}++) {`);
1373
- emitter.indent++;
1374
- emitter.line(`scr_arr_push_${acc}(${r.name}, scr_arr_get_${acc}(${src.name}, (double)${n}));`);
1375
- emitter.indent--;
1376
- emitter.line(`}`);
1377
- return emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1481
+ return emitter.newTemp(e.type, `scr_arr_push_spread(${r.name}, ${src.name})`);
1482
+ }
1483
+ case "concatSpread": {
1484
+ const src = emitter.emitExpr(e.args[0]);
1485
+ return emitter.newTemp(e.type, `scr_arr_concat_copy(${r.name}, ${src.name})`);
1378
1486
  }
1379
1487
  case "unshift": {
1380
1488
  // Like push, every argument evaluates before mutation. Apply
@@ -1396,9 +1504,39 @@ function emitContainerExpr(emitter, e) {
1396
1504
  return emitter.newTemp(e.type, `scr_arr_unshift_spread(${r.name}, ${src.name})`);
1397
1505
  }
1398
1506
  case "pop":
1399
- // Ownership of a refcounted element moves OUT of the array to
1400
- // this temp (+1 to us, the runtime does not release it).
1401
- return emitter.newTemp(e.type, `scr_arr_pop_${acc}(${r.name})`);
1507
+ case "shift": {
1508
+ // Move the slot once, preserving undefined and holes as values
1509
+ // while still applying the method's length/index mutation.
1510
+ if (e.type.kind !== "union")
1511
+ throw new InternalCompilerError("emitter bug: array removal result is not a union");
1512
+ const elemT = e.receiver.type.elem;
1513
+ const def = emitter.unionsById.get(e.type.unionId);
1514
+ const tag = def ? def.arms.findIndex((arm) => typeEquals(arm, elemT)) : -1;
1515
+ const undefTag = undefinedArmTag(e.type, emitter.unionsById);
1516
+ const sameUnion = elemT.kind === "union" && typeEquals(elemT, e.type);
1517
+ if ((!sameUnion && tag < 0) || undefTag < 0)
1518
+ throw new InternalCompilerError("emitter bug: array removal union lacks its arms");
1519
+ const state = `sc_remove_state${emitter.tempCounter++}`;
1520
+ const slot = `sc_remove_slot${emitter.tempCounter++}`;
1521
+ emitter.line(`uint64_t ${slot} = 0;`);
1522
+ emitter.line(`uint8_t ${state} = scr_arr_${method}_state(${r.name}, &${slot});`);
1523
+ let present;
1524
+ if (elemT.kind === "f64") {
1525
+ const number = `sc_remove_number${emitter.tempCounter++}`;
1526
+ emitter.line(`double ${number}; memcpy(&${number}, &${slot}, sizeof ${number});`);
1527
+ present = `scr_union_new_f64(${tag}, ${number})`;
1528
+ }
1529
+ else if (elemT.kind === "bool") {
1530
+ present = `scr_union_new_bool(${tag}, ${slot} != 0)`;
1531
+ }
1532
+ else {
1533
+ const ref = `sc_remove_ref${emitter.tempCounter++}`;
1534
+ emitter.line(`void *${ref}; memcpy(&${ref}, &${slot}, sizeof ${ref});`);
1535
+ const rc = vAdapters(elemT);
1536
+ present = sameUnion ? `(ScrUnion *)${ref}` : `scr_union_new_ref(${tag}, ${ref}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(elemT)})`;
1537
+ }
1538
+ return emitter.newTemp(e.type, `${state} == SCR_ARR_VALUE ? ${present} : ${emitter.unitInstanceRef(e.type.unionId, undefTag)}`);
1539
+ }
1402
1540
  case "indexOf": {
1403
1541
  // The needle is BORROWED (released with this statement's frame);
1404
1542
  // the ref variant dispatches on the array's element kind
@@ -1448,6 +1586,12 @@ function emitContainerExpr(emitter, e) {
1448
1586
  emitter.emitPendingCheck();
1449
1587
  return out;
1450
1588
  }
1589
+ case "withUndefined": {
1590
+ const index = emitter.emitExpr(e.args[0]);
1591
+ const out = emitter.newTemp(e.type, `scr_arr_with_undefined(${r.name}, ${index.name})`);
1592
+ emitter.emitPendingCheck();
1593
+ return out;
1594
+ }
1451
1595
  case "splice": {
1452
1596
  // The removal splice: the removed elements come back as a
1453
1597
  // fresh +1 array, their ownership MOVED out of the receiver
@@ -1457,30 +1601,6 @@ function emitContainerExpr(emitter, e) {
1457
1601
  const cnt = e.args[1] ? emitter.emitExpr(e.args[1]).name : "INFINITY";
1458
1602
  return emitter.newTemp(e.type, `scr_arr_splice(${r.name}, ${start.name}, ${cnt})`);
1459
1603
  }
1460
- case "shift": {
1461
- // JS shift: undefined on an empty array, else the first
1462
- // element out (ref ownership moves into the union box) with
1463
- // the tail sliding down. Union construction is type-directed
1464
- // here, the envGet convention.
1465
- if (e.type.kind !== "union")
1466
- throw new InternalCompilerError("emitter bug: shift result is not a union");
1467
- const elemT = e.receiver.type.elem;
1468
- const def = emitter.unionsById.get(e.type.unionId);
1469
- const tag = def ? def.arms.findIndex((a) => typeEquals(a, elemT)) : -1;
1470
- const undefTag = undefinedArmTag(e.type, emitter.unionsById);
1471
- if (tag < 0 || undefTag < 0)
1472
- throw new InternalCompilerError("emitter bug: shift union lacks its arms");
1473
- const absent = emitter.unitInstanceRef(e.type.unionId, undefTag);
1474
- const present = elemT.kind === "f64"
1475
- ? `scr_union_new_f64(${tag}, scr_arr_shift_f64(${r.name}))`
1476
- : elemT.kind === "bool"
1477
- ? `scr_union_new_bool(${tag}, scr_arr_shift_bool(${r.name}))`
1478
- : (() => {
1479
- const rc = vAdapters(elemT);
1480
- return `scr_union_new_ref(${tag}, scr_arr_shift_ref(${r.name}), &${rc.retain}, &${rc.release}, ${emitter.traceArgC(elemT)})`;
1481
- })();
1482
- return emitter.newTemp(e.type, `scr_arr_len(${r.name}) ? ${present} : ${absent}`);
1483
- }
1484
1604
  default: {
1485
1605
  const _exhaustive = method;
1486
1606
  void _exhaustive;
@@ -2368,7 +2488,10 @@ function emitDynamicExpr(emitter, e) {
2368
2488
  : "scr_dyn_new_null()");
2369
2489
  }
2370
2490
  const v = emitter.emitExpr(e.value);
2371
- if (e.liveRef) {
2491
+ const identityRef = isDynTypedRefType(v.type) ||
2492
+ (v.type.kind === "union" &&
2493
+ (emitter.unionsById.get(v.type.unionId)?.arms.some(isDynTypedRefType) ?? false));
2494
+ if (e.liveRef || identityRef) {
2372
2495
  if (v.type.kind === "union") {
2373
2496
  const adapter = liveDynUnionRefAdapter(emitter, v.type);
2374
2497
  return emitter.newTemp(e.type, `${adapter}(${v.name})`);
@@ -3050,6 +3173,8 @@ function emitAsyncExpr(emitter, e) {
3050
3173
  throw new InternalCompilerError("emitter bug: yieldExpr with no operand (frontend fills undefined)");
3051
3174
  const v = emitter.emitExpr(e.value);
3052
3175
  const yt = e.value.type;
3176
+ if (e.awaited)
3177
+ emitter.line(`scr_async_gen_hop_done();`);
3053
3178
  if (yt.kind === "f64" || yt.kind === "date") {
3054
3179
  emitter.line(`scr_gen_yield_f64(${v.name});${emitter.srcComment(e.loc)}`);
3055
3180
  }
@@ -3083,8 +3208,9 @@ function emitAsyncExpr(emitter, e) {
3083
3208
  const genT = e.gen.type;
3084
3209
  if (genT.kind !== "generator")
3085
3210
  throw new InternalCompilerError("emitter bug: genResume on a non-generator");
3086
- if (e.type.kind !== "record")
3087
- throw new InternalCompilerError("emitter bug: genResume result is not a record");
3211
+ const resultT = genT.async ? (e.type.kind === "promise" ? e.type.inner : null) : e.type;
3212
+ if (resultT?.kind !== "record")
3213
+ throw new InternalCompilerError("emitter bug: genResume result is not an IteratorResult record");
3088
3214
  const g = emitter.emitExpr(e.gen); // borrowed for the calls below
3089
3215
  const sendArg = (store) => {
3090
3216
  const a = emitter.emitExpr(e.arg);
@@ -3092,6 +3218,76 @@ function emitAsyncExpr(emitter, e) {
3092
3218
  emitter.moveTemp(a); // the slot takes ownership
3093
3219
  emitter.line(store(a));
3094
3220
  };
3221
+ if (genT.async) {
3222
+ let call;
3223
+ if (e.mode === "next") {
3224
+ if (e.arg === null) {
3225
+ if (genT.nextT.kind === "dyn") {
3226
+ call = `scr_async_gen_next_ref(${g.name}, scr_dyn_retain(scr_dyn_undefined()), scr_dyn_release_v)`;
3227
+ }
3228
+ else {
3229
+ call = `scr_async_gen_next_none(${g.name})`;
3230
+ }
3231
+ }
3232
+ else {
3233
+ const a = emitter.emitExpr(e.arg);
3234
+ const t = e.arg.type;
3235
+ if (isRefCounted(t))
3236
+ emitter.moveTemp(a);
3237
+ call = t.kind === "f64" || t.kind === "date"
3238
+ ? `scr_async_gen_next_f64(${g.name}, ${a.name})`
3239
+ : t.kind === "bool"
3240
+ ? `scr_async_gen_next_bool(${g.name}, ${a.name})`
3241
+ : `scr_async_gen_next_ref(${g.name}, ${a.name}, ${vAdapters(t).release})`;
3242
+ }
3243
+ }
3244
+ else if (e.mode === "return") {
3245
+ if (e.arg === null) {
3246
+ call = `scr_async_gen_return_none(${g.name})`;
3247
+ }
3248
+ else {
3249
+ const a = emitter.emitExpr(e.arg);
3250
+ const t = e.arg.type;
3251
+ if (isRefCounted(t))
3252
+ emitter.moveTemp(a);
3253
+ call = t.kind === "f64" || t.kind === "date"
3254
+ ? `scr_async_gen_return_f64(${g.name}, ${a.name})`
3255
+ : t.kind === "bool"
3256
+ ? `scr_async_gen_return_bool(${g.name}, ${a.name})`
3257
+ : `scr_async_gen_return_ref(${g.name}, ${a.name}, ${vAdapters(t).release})`;
3258
+ }
3259
+ }
3260
+ else {
3261
+ if (e.arg === null)
3262
+ throw new InternalCompilerError("emitter bug: async genResume throw with no payload");
3263
+ const a = emitter.emitExpr(e.arg);
3264
+ const t = e.arg.type;
3265
+ if (isRefCounted(t))
3266
+ emitter.moveTemp(a);
3267
+ if (t.kind === "date") {
3268
+ throw new InternalCompilerError("emitter bug: Date async-generator throw reached backend");
3269
+ }
3270
+ else if (t.kind === "f64") {
3271
+ emitter.line(`scr_throw_f64(${a.name});${emitter.srcComment(e.loc)}`);
3272
+ }
3273
+ else if (t.kind === "bool") {
3274
+ emitter.line(`scr_throw_bool(${a.name});${emitter.srcComment(e.loc)}`);
3275
+ }
3276
+ else if (t.kind === "string") {
3277
+ emitter.line(`scr_throw_str(${a.name});${emitter.srcComment(e.loc)}`);
3278
+ }
3279
+ else if (t.kind === "object" && emitter.classMeta.get(t.className)?.hierarchy) {
3280
+ const rc = vAdapters(t);
3281
+ emitter.line(`scr_throw_obj(${a.name}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(t)});${emitter.srcComment(e.loc)}`);
3282
+ }
3283
+ else {
3284
+ const rc = vAdapters(t);
3285
+ emitter.line(`scr_throw_ref(${a.name}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(t)});${emitter.srcComment(e.loc)}`);
3286
+ }
3287
+ call = `scr_async_gen_throw(${g.name})`;
3288
+ }
3289
+ return emitter.newTemp(e.type, call);
3290
+ }
3095
3291
  if (e.mode === "next") {
3096
3292
  if (e.arg === null) {
3097
3293
  // Valueless resume: dyn channels read JS's undefined; unit
@@ -3156,7 +3352,7 @@ function emitAsyncExpr(emitter, e) {
3156
3352
  }
3157
3353
  emitter.line(`scr_gen_resume_throw(${g.name});`);
3158
3354
  }
3159
- const helper = genResultThunkFor(emitter, genT, e.type);
3355
+ const helper = genResultThunkFor(emitter, genT, resultT);
3160
3356
  // The record builds before the check so an unwind (a propagated
3161
3357
  // body exception) releases it as the frame's never-read dummy.
3162
3358
  return emitter.fallibleTemp(e.type, `${helper}(${g.name})`);
@@ -6725,6 +6921,38 @@ function emitProcessLibCall(state) {
6725
6921
  return finish(`scr_process_getuid()`);
6726
6922
  case "process.uptime":
6727
6923
  return finish(`scr_process_uptime()`);
6924
+ case "module.registryInit":
6925
+ return finish(`scr_module_registry_init(${arg(0)})`);
6926
+ case "module.define":
6927
+ return finish(`scr_module_define(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)})`);
6928
+ case "module.enter":
6929
+ return finish(`scr_module_enter(${arg(0)})`);
6930
+ case "module.link":
6931
+ return finish(`scr_module_link(${arg(0)}, ${arg(1)})`);
6932
+ case "module.finish":
6933
+ return finish(`scr_module_finish(${arg(0)})`);
6934
+ case "module.fail":
6935
+ return finish(`scr_module_fail(${arg(0)})`);
6936
+ case "module.filename":
6937
+ return finish(`scr_module_filename(${arg(0)})`);
6938
+ case "module.id":
6939
+ return finish(`scr_module_id(${arg(0)})`);
6940
+ case "module.path":
6941
+ return finish(`scr_module_path(${arg(0)})`);
6942
+ case "module.paths":
6943
+ return finish(`scr_module_paths(${arg(0)})`);
6944
+ case "module.children":
6945
+ return finish(`scr_module_children(${arg(0)})`);
6946
+ case "module.parent":
6947
+ return finish(`scr_module_parent(${arg(0)})`);
6948
+ case "module.loaded":
6949
+ return finish(`scr_module_loaded(${arg(0)})`);
6950
+ case "module.cacheGet":
6951
+ return finish(`scr_module_cache_get(${arg(0)})`);
6952
+ case "module.cacheHas":
6953
+ return finish(`scr_module_cache_has(${arg(0)})`);
6954
+ case "module.cacheKeys":
6955
+ return finish(`scr_module_cache_keys()`);
6728
6956
  case "process.availableMemory":
6729
6957
  return finish(`scr_available_memory()`);
6730
6958
  case "process.constrainedMemory":
@@ -7470,6 +7698,9 @@ function emitStreamLibCall(state) {
7470
7698
  case "stream.destroyErr":
7471
7699
  emitter.usesTimers = true;
7472
7700
  return finish(`(${cType(e.type).trim()})scr_stream_destroy((ScrStream *)${arg(0)}, ${arg(1)})`);
7701
+ case "stream.iteratorClose":
7702
+ emitter.usesTimers = true;
7703
+ return finish(`(${cType(e.type).trim()})scr_stream_iterator_close((ScrStream *)${arg(0)})`);
7473
7704
  case "stream.prop": {
7474
7705
  // The property NAME is a compile-time literal; args[1]'s
7475
7706
  // emitted temp is unused (released with the statement's frame).
@@ -7769,6 +8000,7 @@ function emitLibCallExpr(emitter, e) {
7769
8000
  return emitAsyncContextLibCall(state);
7770
8001
  case "process":
7771
8002
  case "stdin":
8003
+ case "module":
7772
8004
  return emitProcessLibCall(state);
7773
8005
  case "error":
7774
8006
  case "regex":
@@ -7832,6 +8064,8 @@ export function emitExpr(emitter, e) {
7832
8064
  case "arrayLit":
7833
8065
  case "arrayNewLen":
7834
8066
  case "arrayGet":
8067
+ case "arrayHas":
8068
+ case "arrayState":
7835
8069
  case "arrIntrinsic":
7836
8070
  case "bytesNew":
7837
8071
  case "bytesIntrinsic":