@scriptc/compiler 0.1.1 → 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 (209) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +45 -17
  2. package/ambient/scriptc.d.ts +2 -1
  3. package/dist/backend/build-cache.js.map +1 -1
  4. package/dist/backend/c/async.js +24 -2
  5. package/dist/backend/c/async.js.map +1 -1
  6. package/dist/backend/c/c-emitter.d.ts +22 -10
  7. package/dist/backend/c/c-emitter.js +60 -15
  8. package/dist/backend/c/c-emitter.js.map +1 -1
  9. package/dist/backend/c/exprs.js +220 -10
  10. package/dist/backend/c/exprs.js.map +1 -1
  11. package/dist/backend/c/island.js.map +1 -1
  12. package/dist/backend/c/may-throw.js.map +1 -1
  13. package/dist/backend/c/stmts.d.ts +3 -5
  14. package/dist/backend/c/stmts.js +58 -17
  15. package/dist/backend/c/stmts.js.map +1 -1
  16. package/dist/backend/c/types.js.map +1 -1
  17. package/dist/backend/c/walkers.js +31 -5
  18. package/dist/backend/c/walkers.js.map +1 -1
  19. package/dist/backend/external-c.js.map +1 -1
  20. package/dist/backend/linker.js.map +1 -1
  21. package/dist/backend/llvm/blocks.js.map +1 -1
  22. package/dist/backend/llvm/dyn.js +56 -3
  23. package/dist/backend/llvm/dyn.js.map +1 -1
  24. package/dist/backend/llvm/emitter.js +98 -19
  25. package/dist/backend/llvm/emitter.js.map +1 -1
  26. package/dist/backend/llvm/expr-async.js +85 -3
  27. package/dist/backend/llvm/expr-async.js.map +1 -1
  28. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  29. package/dist/backend/llvm/expr-calls.js.map +1 -1
  30. package/dist/backend/llvm/expr-containers.js.map +1 -1
  31. package/dist/backend/llvm/expr-context.d.ts +1 -0
  32. package/dist/backend/llvm/expr-control.js.map +1 -1
  33. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  34. package/dist/backend/llvm/expr-dynamic.js +6 -3
  35. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  36. package/dist/backend/llvm/expr-island.js.map +1 -1
  37. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  38. package/dist/backend/llvm/expr-records.js.map +1 -1
  39. package/dist/backend/llvm/expr-stream-bridges.js +220 -9
  40. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  41. package/dist/backend/llvm/lib-dispatch.js +2 -0
  42. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  43. package/dist/backend/llvm/lib-shared.js +18 -0
  44. package/dist/backend/llvm/lib-shared.js.map +1 -1
  45. package/dist/backend/llvm/lib-stream.js +6 -3
  46. package/dist/backend/llvm/lib-stream.js.map +1 -1
  47. package/dist/backend/llvm/split.js.map +1 -1
  48. package/dist/backend/llvm/unsupported.js.map +1 -1
  49. package/dist/backend/llvm/walkers.js.map +1 -1
  50. package/dist/backend/native-codegen.js.map +1 -1
  51. package/dist/backend/native-codegen.test.js +2 -0
  52. package/dist/backend/native-codegen.test.js.map +1 -1
  53. package/dist/backend/native-toolchain.js.map +1 -1
  54. package/dist/backend/native-toolchain.test.js.map +1 -1
  55. package/dist/backend/runtime-pack.js.map +1 -1
  56. package/dist/backend/targets.js.map +1 -1
  57. package/dist/backend/vendor-archives.js.map +1 -1
  58. package/dist/compat/fetch-profile.js +4 -2
  59. package/dist/compat/fetch-profile.js.map +1 -1
  60. package/dist/coverage/report.js.map +1 -1
  61. package/dist/coverage/surface-manifest.js +12 -0
  62. package/dist/coverage/surface-manifest.js.map +1 -1
  63. package/dist/diagnostics/diagnostic.d.ts +6 -5
  64. package/dist/diagnostics/diagnostic.js +7 -6
  65. package/dist/diagnostics/diagnostic.js.map +1 -1
  66. package/dist/diagnostics/render.js.map +1 -1
  67. package/dist/ffi/ffi-manifest.js.map +1 -1
  68. package/dist/frontend/cjs-lexer.js.map +1 -1
  69. package/dist/frontend/dts-paths.js.map +1 -1
  70. package/dist/frontend/input-tracker.d.ts +10 -0
  71. package/dist/frontend/input-tracker.js +26 -3
  72. package/dist/frontend/input-tracker.js.map +1 -1
  73. package/dist/frontend/input-tracker.test.js +8 -1
  74. package/dist/frontend/input-tracker.test.js.map +1 -1
  75. package/dist/frontend/lib-contract.js.map +1 -1
  76. package/dist/frontend/lowering/array-values.d.ts +4 -0
  77. package/dist/frontend/lowering/array-values.js +18 -2
  78. package/dist/frontend/lowering/array-values.js.map +1 -1
  79. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  80. package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
  81. package/dist/frontend/lowering/containers/bytes.js +1021 -0
  82. package/dist/frontend/lowering/containers/bytes.js.map +1 -0
  83. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
  84. package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
  85. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
  86. package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
  87. package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
  88. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
  89. package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
  90. package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
  91. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
  92. package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
  93. package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
  94. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
  95. package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
  96. package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
  97. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
  98. package/dist/frontend/lowering/lib-boundary.js +7 -2
  99. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  100. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  101. package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
  102. package/dist/frontend/lowering/lower-async-iteration.js +657 -0
  103. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
  104. package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
  105. package/dist/frontend/lowering/lower-builtins.js +219 -48
  106. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  107. package/dist/frontend/lowering/lower-calls.d.ts +13 -4
  108. package/dist/frontend/lowering/lower-calls.js +407 -64
  109. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  110. package/dist/frontend/lowering/lower-classes.d.ts +7 -13
  111. package/dist/frontend/lowering/lower-classes.js +128 -35
  112. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  113. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  114. package/dist/frontend/lowering/lower-containers.d.ts +1 -47
  115. package/dist/frontend/lowering/lower-containers.js +135 -1467
  116. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  117. package/dist/frontend/lowering/lower-event-emitter.js +51 -5
  118. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  119. package/dist/frontend/lowering/lower-exprs.d.ts +0 -78
  120. package/dist/frontend/lowering/lower-exprs.js +402 -2351
  121. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  122. package/dist/frontend/lowering/lower-generators.d.ts +18 -3
  123. package/dist/frontend/lowering/lower-generators.js +145 -9
  124. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  125. package/dist/frontend/lowering/lower-inspect.js +3 -3
  126. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  127. package/dist/frontend/lowering/lower-island.d.ts +6 -0
  128. package/dist/frontend/lowering/lower-island.js +37 -5
  129. package/dist/frontend/lowering/lower-island.js.map +1 -1
  130. package/dist/frontend/lowering/lower-modules.js +52 -15
  131. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  132. package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
  133. package/dist/frontend/lowering/lower-node-module.js +302 -0
  134. package/dist/frontend/lowering/lower-node-module.js.map +1 -0
  135. package/dist/frontend/lowering/lower-server.js +1 -1
  136. package/dist/frontend/lowering/lower-server.js.map +1 -1
  137. package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
  138. package/dist/frontend/lowering/lower-stmts.js +519 -253
  139. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  140. package/dist/frontend/lowering/lower-stream.js +4 -4
  141. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  142. package/dist/frontend/lowering/lowerer.d.ts +37 -34
  143. package/dist/frontend/lowering/lowerer.js +143 -57
  144. package/dist/frontend/lowering/lowerer.js.map +1 -1
  145. package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
  146. package/dist/frontend/lowering/optional-arguments.js +57 -0
  147. package/dist/frontend/lowering/optional-arguments.js.map +1 -0
  148. package/dist/frontend/npm-static-declarations.d.ts +35 -0
  149. package/dist/frontend/npm-static-declarations.js +506 -0
  150. package/dist/frontend/npm-static-declarations.js.map +1 -0
  151. package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
  152. package/dist/frontend/npm-static-declarations.test.js +122 -0
  153. package/dist/frontend/npm-static-declarations.test.js.map +1 -0
  154. package/dist/frontend/npm-static.d.ts +2 -0
  155. package/dist/frontend/npm-static.js +26 -10
  156. package/dist/frontend/npm-static.js.map +1 -1
  157. package/dist/frontend/npm.d.ts +60 -0
  158. package/dist/frontend/npm.js +38 -4
  159. package/dist/frontend/npm.js.map +1 -1
  160. package/dist/frontend/npm.test.d.ts +1 -0
  161. package/dist/frontend/npm.test.js +50 -0
  162. package/dist/frontend/npm.test.js.map +1 -0
  163. package/dist/frontend/program.d.ts +3 -2
  164. package/dist/frontend/program.js +495 -68
  165. package/dist/frontend/program.js.map +1 -1
  166. package/dist/frontend/resolve.d.ts +10 -2
  167. package/dist/frontend/resolve.js +90 -14
  168. package/dist/frontend/resolve.js.map +1 -1
  169. package/dist/frontend/resolve.test.js +4 -1
  170. package/dist/frontend/resolve.test.js.map +1 -1
  171. package/dist/frontend/runtime-resolve.d.ts +22 -0
  172. package/dist/frontend/runtime-resolve.js +101 -0
  173. package/dist/frontend/runtime-resolve.js.map +1 -0
  174. package/dist/frontend/runtime-resolve.test.d.ts +1 -0
  175. package/dist/frontend/runtime-resolve.test.js +18 -0
  176. package/dist/frontend/runtime-resolve.test.js.map +1 -0
  177. package/dist/frontend/ts7/adapter.js +12 -13
  178. package/dist/frontend/ts7/adapter.js.map +1 -1
  179. package/dist/frontend/ts7/ast.js.map +1 -1
  180. package/dist/frontend/ts7/census-check.js +3 -3
  181. package/dist/frontend/ts7/census-check.js.map +1 -1
  182. package/dist/frontend/ts7/checker.d.ts +3 -0
  183. package/dist/frontend/ts7/checker.js +12 -3
  184. package/dist/frontend/ts7/checker.js.map +1 -1
  185. package/dist/frontend/ts7/enums.js.map +1 -1
  186. package/dist/frontend/ts7/program-adapter.js +42 -3
  187. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  188. package/dist/frontend/type-mapper.js +120 -7
  189. package/dist/frontend/type-mapper.js.map +1 -1
  190. package/dist/index.js +5 -5
  191. package/dist/index.js.map +1 -1
  192. package/dist/ir/analysis.js.map +1 -1
  193. package/dist/ir/ir.d.ts +60 -30
  194. package/dist/ir/ir.js +57 -6
  195. package/dist/ir/ir.js.map +1 -1
  196. package/dist/ir/validate.js +44 -59
  197. package/dist/ir/validate.js.map +1 -1
  198. package/dist/library/cache-primitives.js.map +1 -1
  199. package/dist/library/cache-reset.test.js.map +1 -1
  200. package/dist/library/compiler-self-identity.js.map +1 -1
  201. package/dist/library/int-infer.js.map +1 -1
  202. package/dist/library/int-infer.test.js.map +1 -1
  203. package/dist/library/library-profile.js.map +1 -1
  204. package/dist/library/sidecar-validate.js.map +1 -1
  205. package/dist/library/sidecar.js.map +1 -1
  206. package/dist/startup-cache.js.map +1 -1
  207. package/dist/wasi-paths.js.map +1 -1
  208. package/package.json +18 -18
  209. package/surface-manifest.json +60 -4
@@ -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";
@@ -20,6 +20,23 @@ function streamTypedRefCommitAdapter(emitter, t, snapshot, defs) {
20
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
21
  return `&${commit}`;
22
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(`}`, ``);
38
+ return `&${commit}`;
39
+ }
23
40
  if (t.kind !== "record")
24
41
  return "NULL";
25
42
  const shape = emitter.recordsById.get(t.shapeId);
@@ -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
  }
@@ -2390,7 +2488,10 @@ function emitDynamicExpr(emitter, e) {
2390
2488
  : "scr_dyn_new_null()");
2391
2489
  }
2392
2490
  const v = emitter.emitExpr(e.value);
2393
- 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) {
2394
2495
  if (v.type.kind === "union") {
2395
2496
  const adapter = liveDynUnionRefAdapter(emitter, v.type);
2396
2497
  return emitter.newTemp(e.type, `${adapter}(${v.name})`);
@@ -3072,6 +3173,8 @@ function emitAsyncExpr(emitter, e) {
3072
3173
  throw new InternalCompilerError("emitter bug: yieldExpr with no operand (frontend fills undefined)");
3073
3174
  const v = emitter.emitExpr(e.value);
3074
3175
  const yt = e.value.type;
3176
+ if (e.awaited)
3177
+ emitter.line(`scr_async_gen_hop_done();`);
3075
3178
  if (yt.kind === "f64" || yt.kind === "date") {
3076
3179
  emitter.line(`scr_gen_yield_f64(${v.name});${emitter.srcComment(e.loc)}`);
3077
3180
  }
@@ -3105,8 +3208,9 @@ function emitAsyncExpr(emitter, e) {
3105
3208
  const genT = e.gen.type;
3106
3209
  if (genT.kind !== "generator")
3107
3210
  throw new InternalCompilerError("emitter bug: genResume on a non-generator");
3108
- if (e.type.kind !== "record")
3109
- 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");
3110
3214
  const g = emitter.emitExpr(e.gen); // borrowed for the calls below
3111
3215
  const sendArg = (store) => {
3112
3216
  const a = emitter.emitExpr(e.arg);
@@ -3114,6 +3218,76 @@ function emitAsyncExpr(emitter, e) {
3114
3218
  emitter.moveTemp(a); // the slot takes ownership
3115
3219
  emitter.line(store(a));
3116
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
+ }
3117
3291
  if (e.mode === "next") {
3118
3292
  if (e.arg === null) {
3119
3293
  // Valueless resume: dyn channels read JS's undefined; unit
@@ -3178,7 +3352,7 @@ function emitAsyncExpr(emitter, e) {
3178
3352
  }
3179
3353
  emitter.line(`scr_gen_resume_throw(${g.name});`);
3180
3354
  }
3181
- const helper = genResultThunkFor(emitter, genT, e.type);
3355
+ const helper = genResultThunkFor(emitter, genT, resultT);
3182
3356
  // The record builds before the check so an unwind (a propagated
3183
3357
  // body exception) releases it as the frame's never-read dummy.
3184
3358
  return emitter.fallibleTemp(e.type, `${helper}(${g.name})`);
@@ -6747,6 +6921,38 @@ function emitProcessLibCall(state) {
6747
6921
  return finish(`scr_process_getuid()`);
6748
6922
  case "process.uptime":
6749
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()`);
6750
6956
  case "process.availableMemory":
6751
6957
  return finish(`scr_available_memory()`);
6752
6958
  case "process.constrainedMemory":
@@ -7492,6 +7698,9 @@ function emitStreamLibCall(state) {
7492
7698
  case "stream.destroyErr":
7493
7699
  emitter.usesTimers = true;
7494
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)})`);
7495
7704
  case "stream.prop": {
7496
7705
  // The property NAME is a compile-time literal; args[1]'s
7497
7706
  // emitted temp is unused (released with the statement's frame).
@@ -7791,6 +8000,7 @@ function emitLibCallExpr(emitter, e) {
7791
8000
  return emitAsyncContextLibCall(state);
7792
8001
  case "process":
7793
8002
  case "stdin":
8003
+ case "module":
7794
8004
  return emitProcessLibCall(state);
7795
8005
  case "error":
7796
8006
  case "regex":