@scriptc/compiler 0.0.21 → 0.0.22
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.
- package/ambient/scriptc-node-fallback.d.ts +78 -34
- package/dist/backend/cc-cache.test.d.ts +1 -0
- package/dist/backend/cc-cache.test.js +2507 -0
- package/dist/backend/cc-cache.test.js.map +1 -0
- package/dist/backend/cc.d.ts +69 -11
- package/dist/backend/cc.js +1937 -222
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +355 -8
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +108 -7
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +16 -0
- package/dist/backend/emission/emitter.js +23 -2
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +305 -8
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +527 -2
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +108 -0
- package/dist/compat/fetch-profile.js +482 -0
- package/dist/compat/fetch-profile.js.map +1 -0
- package/dist/coverage/surface-manifest.js +54 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +21 -8
- package/dist/frontend/lowering/lower-builtins.js +137 -14
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +40 -0
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +4 -3
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +2 -2
- package/dist/frontend/lowering/lower-exprs.js +63 -12
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +102 -7
- package/dist/frontend/lowering/lower-island.js +1702 -26
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +17 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +25 -5
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +39 -0
- package/dist/frontend/lowering/lowerer.js +286 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +12 -0
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.d.ts +16 -0
- package/dist/frontend/program.js +130 -6
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/types.d.ts +14 -7
- package/dist/frontend/types.js +95 -31
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +70 -14
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +32 -16
- package/dist/ir/nodes.js +36 -28
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +61 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.js +7 -1
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +80 -0
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/sidecar-validate.js +5 -0
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +3 -0
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +859 -1
|
@@ -1,9 +1,292 @@
|
|
|
1
|
-
import { arrayOf, BOOL, BYTES_U8, bytesOf, canMarshalFuncIntoIsland, CHILDSTREAM_T, DYN, F64, islandPromisePayloadTag, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, RUNTIME_ERROR_CLASSES, STRING, typeEquals } from "../../ir/nodes.js";
|
|
2
|
-
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, retainCallC, vAdapters } from "./emit-types.js";
|
|
1
|
+
import { arrayOf, BOOL, BYTES_U8, bytesOf, canMarshalFuncIntoIsland, CHILDSTREAM_T, DYN, F64, islandPromisePayloadTag, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, RUNTIME_ERROR_CLASSES, STRING, typeEquals, typeKey } from "../../ir/nodes.js";
|
|
2
|
+
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 "./emit-types.js";
|
|
3
3
|
import { mangleClassNew, mangleClassRetain, mangleClassStruct, mangleField, mangleFnClosure, mangleFunction, mangleGlobal, mangleLocal, mangleRecordNew, mangleRecordStruct, mangleVtStruct } from "../mangle.js";
|
|
4
4
|
import { OVERFLOW_MEMBER } from "./emit-shapes.js";
|
|
5
5
|
import { dynDestrCheckHelper, dynIterNHelper, dynKeyGetHelper } from "./emit-walkers.js";
|
|
6
6
|
import { genResultThunkFor } from "./emit-async.js";
|
|
7
|
+
function streamTypedRefCommitAdapter(E, t, snapshot, defs) {
|
|
8
|
+
if (t.kind === "bytes") {
|
|
9
|
+
const commit = `${snapshot}_commit`;
|
|
10
|
+
E.walkerProtos.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d); /* commit live stream element ${typeKey(t)} */`);
|
|
11
|
+
defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ScrBytes *sc_target = (ScrBytes *)sc_p;`, ` ScrBytes *sc_next = ${E.dynCheckHelper(t)}(sc_d, NULL);`, ` if (!sc_next) return;`, ` scr_bytes_copy_contents(sc_target, sc_next);`, ` scr_bytes_release(sc_next);`, `}`, ``);
|
|
12
|
+
return `&${commit}`;
|
|
13
|
+
}
|
|
14
|
+
if (t.kind === "array") {
|
|
15
|
+
const commit = `${snapshot}_commit`;
|
|
16
|
+
E.walkerProtos.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d); /* commit live stream element ${typeKey(t)} */`);
|
|
17
|
+
defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ScrArr *sc_target = (ScrArr *)sc_p;`, ` ScrArr *sc_next = ${E.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);`, `}`, ``);
|
|
18
|
+
return `&${commit}`;
|
|
19
|
+
}
|
|
20
|
+
if (t.kind !== "record")
|
|
21
|
+
return "NULL";
|
|
22
|
+
const shape = E.recordsById.get(t.shapeId);
|
|
23
|
+
if (!shape) {
|
|
24
|
+
throw new Error(`emitter bug: stream typed-ref commit of unknown shape ${t.shapeId}`);
|
|
25
|
+
}
|
|
26
|
+
const commit = `${snapshot}_commit`;
|
|
27
|
+
E.walkerProtos.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d); /* commit live stream element ${typeKey(t)} */`);
|
|
28
|
+
defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ${cDecl(t, "sc_target")} = (${cType(t).trim()})sc_p;`, ` ${cDecl(t, "sc_next")} = ${E.dynCheckHelper(t)}(sc_d, NULL);`, ` if (!sc_next) return;`);
|
|
29
|
+
for (const field of shape.fields) {
|
|
30
|
+
const member = mangleField(field.name);
|
|
31
|
+
defs.push(` {`, ` ${cDecl(field.type, "sc_old")} = sc_target->${member};`, ` sc_target->${member} = sc_next->${member};`, ` sc_next->${member} = sc_old;`, ` }`);
|
|
32
|
+
}
|
|
33
|
+
if (shape.indexValue) {
|
|
34
|
+
defs.push(` {`, ` ScrMap *sc_old = sc_target->${OVERFLOW_MEMBER};`, ` sc_target->${OVERFLOW_MEMBER} = sc_next->${OVERFLOW_MEMBER};`, ` sc_next->${OVERFLOW_MEMBER} = sc_old;`, ` }`);
|
|
35
|
+
}
|
|
36
|
+
defs.push(` ${releaseCallC(t, "sc_next")};`, `}`, ``);
|
|
37
|
+
return `&${commit}`;
|
|
38
|
+
}
|
|
39
|
+
function streamTypedRefEligible(t) {
|
|
40
|
+
return t.kind === "record" || t.kind === "array" || t.kind === "bytes";
|
|
41
|
+
}
|
|
42
|
+
/** Build the live dyn view of one typed stream value. Mutable reference
|
|
43
|
+
* children are capsules of their own, so a write through `v.child.x` or
|
|
44
|
+
* `v.items[0]` commits directly to that child's static source instead of
|
|
45
|
+
* disappearing into the parent's detached snapshot. */
|
|
46
|
+
function streamTypedRefAdapter(E, t, ctx, preferredSnapshot) {
|
|
47
|
+
const key = typeKey(t);
|
|
48
|
+
const existing = ctx.adapters.get(key);
|
|
49
|
+
if (existing)
|
|
50
|
+
return existing;
|
|
51
|
+
const snapshot = preferredSnapshot ??
|
|
52
|
+
`${ctx.prefix}_nested_${ctx.adapters.size}`;
|
|
53
|
+
const adapter = { snapshot, commit: "NULL" };
|
|
54
|
+
/* Register before walking children: recursive record/array types refer
|
|
55
|
+
* back to this prototype without recursively generating helpers. */
|
|
56
|
+
ctx.adapters.set(key, adapter);
|
|
57
|
+
E.walkerProtos.push(`static ScrDyn *${snapshot}(void *sc_p); /* materialize live stream value ${key} */`);
|
|
58
|
+
adapter.commit = streamTypedRefCommitAdapter(E, t, snapshot, ctx.defs);
|
|
59
|
+
const box = (child, expr) => {
|
|
60
|
+
if (!streamTypedRefEligible(child)) {
|
|
61
|
+
return `${E.toDynHelper(child)}(${expr})`;
|
|
62
|
+
}
|
|
63
|
+
const nested = streamTypedRefAdapter(E, child, ctx);
|
|
64
|
+
const rc = vAdapters(child);
|
|
65
|
+
const childKey = typeKey(child);
|
|
66
|
+
const keyLit = cStringLiteral(Buffer.from(childKey, "utf8"));
|
|
67
|
+
return `scr_dyn_new_typed_ref(${expr}, &${rc.retain}, &${rc.release}, ${keyLit}, ${Buffer.byteLength(childKey, "utf8")}, &${nested.snapshot}, ${nested.commit})`;
|
|
68
|
+
};
|
|
69
|
+
const lines = [
|
|
70
|
+
`static ScrDyn *${snapshot}(void *sc_p) { /* materialize live stream value ${key} */`,
|
|
71
|
+
` ${cDecl(t, "v")} = (${cType(t).trim()})sc_p;`,
|
|
72
|
+
];
|
|
73
|
+
if (t.kind === "record") {
|
|
74
|
+
const shape = E.recordsById.get(t.shapeId);
|
|
75
|
+
if (!shape) {
|
|
76
|
+
throw new Error(`emitter bug: stream typed-ref materialize of unknown shape ${t.shapeId}`);
|
|
77
|
+
}
|
|
78
|
+
const ordinary = shape.indexValue || shape.fields.some((field) => field.name === "handleEvent" && field.type.kind === "func");
|
|
79
|
+
if (ordinary) {
|
|
80
|
+
lines.push(` return ${E.toDynHelper(t)}(v);`, `}`, ``);
|
|
81
|
+
ctx.defs.push(...lines);
|
|
82
|
+
return adapter;
|
|
83
|
+
}
|
|
84
|
+
if (shape.tuple) {
|
|
85
|
+
lines.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
86
|
+
const fields = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
87
|
+
for (const field of fields) {
|
|
88
|
+
lines.push(` scr_dyn_arr_push(d, ${box(field.type, `v->${mangleField(field.name)}`)});`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
lines.push(` ScrDyn *d = scr_dyn_new_obj();`);
|
|
93
|
+
const byName = new Map(shape.fields.map((field) => [field.name, field]));
|
|
94
|
+
const order = shape.declaredOrder ?? shape.fields.map((field) => field.name);
|
|
95
|
+
const inOrder = new Set(order);
|
|
96
|
+
const fields = [
|
|
97
|
+
...order.map((name) => byName.get(name)).filter((field) => field !== undefined),
|
|
98
|
+
...shape.fields.filter((field) => !inOrder.has(field.name)),
|
|
99
|
+
];
|
|
100
|
+
for (const field of fields) {
|
|
101
|
+
const keyLit = cStringLiteral(Buffer.from(field.name, "utf8"));
|
|
102
|
+
lines.push(` scr_dyn_obj_set(d, ${keyLit}, ${Buffer.byteLength(field.name, "utf8")}, ${box(field.type, `v->${mangleField(field.name)}`)});`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
lines.push(` return d;`);
|
|
106
|
+
}
|
|
107
|
+
else if (t.kind === "array") {
|
|
108
|
+
const elem = t.elem;
|
|
109
|
+
lines.push(` ScrDyn *d = scr_dyn_new_arr();`, ` for (size_t sc_i = 0; sc_i < v->len; sc_i++) {`);
|
|
110
|
+
if (elem.kind === "f64") {
|
|
111
|
+
lines.push(` scr_dyn_arr_push(d, ${box(elem, "scr_arr_get_f64(v, (double)sc_i)")});`);
|
|
112
|
+
}
|
|
113
|
+
else if (elem.kind === "bool") {
|
|
114
|
+
lines.push(` scr_dyn_arr_push(d, ${box(elem, "scr_arr_get_bool(v, (double)sc_i)")});`);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
lines.push(` ${cDecl(elem, "sc_value")} = (${cType(elem).trim()})scr_arr_get_ref(v, (double)sc_i);`, ` scr_dyn_arr_push(d, ${box(elem, "sc_value")});`, ` ${releaseCallC(elem, "sc_value")};`);
|
|
118
|
+
}
|
|
119
|
+
lines.push(` }`, ` return d;`);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
lines.push(` return ${E.toDynHelper(t)}(v);`);
|
|
123
|
+
}
|
|
124
|
+
lines.push(`}`, ``);
|
|
125
|
+
ctx.defs.push(...lines);
|
|
126
|
+
return adapter;
|
|
127
|
+
}
|
|
128
|
+
/** One per-type capsule adapter for Web API arguments whose JavaScript
|
|
129
|
+
* contract preserves the exact input reference. */
|
|
130
|
+
function liveDynRefAdapter(E, t) {
|
|
131
|
+
const key = typeKey(t);
|
|
132
|
+
const existing = E.liveDynRefAdapters.get(key);
|
|
133
|
+
if (existing)
|
|
134
|
+
return existing;
|
|
135
|
+
if (!streamTypedRefEligible(t)) {
|
|
136
|
+
throw new Error(`emitter bug: live dyn ref of ${key}`);
|
|
137
|
+
}
|
|
138
|
+
const prefix = `sc_ldr_${E.liveDynRefAdapters.size}`;
|
|
139
|
+
const defs = [];
|
|
140
|
+
const adapter = streamTypedRefAdapter(E, t, { prefix, defs, adapters: new Map() }, `${prefix}_materialize`);
|
|
141
|
+
E.liveDynRefAdapters.set(key, adapter);
|
|
142
|
+
E.walkerDefs.push(...defs);
|
|
143
|
+
return adapter;
|
|
144
|
+
}
|
|
145
|
+
/** A union itself is only the tagged box; the identity Web APIs expose is
|
|
146
|
+
* the selected mutable arm. Dispatch on the tag and point the typed capsule
|
|
147
|
+
* directly at that arm's payload. Non-mutable arms keep ordinary dynFrom
|
|
148
|
+
* semantics. */
|
|
149
|
+
function liveDynUnionRefAdapter(E, t) {
|
|
150
|
+
const key = typeKey(t);
|
|
151
|
+
const existing = E.liveDynUnionRefAdapters.get(key);
|
|
152
|
+
if (existing)
|
|
153
|
+
return existing;
|
|
154
|
+
const union = E.unionsById.get(t.unionId);
|
|
155
|
+
if (!union) {
|
|
156
|
+
throw new Error(`emitter bug: live dyn ref of unknown union ${t.unionId}`);
|
|
157
|
+
}
|
|
158
|
+
const mutableArms = union.arms
|
|
159
|
+
.map((arm, tag) => ({ arm, tag }))
|
|
160
|
+
.filter(({ arm }) => streamTypedRefEligible(arm));
|
|
161
|
+
if (mutableArms.length === 0) {
|
|
162
|
+
throw new Error(`emitter bug: live dyn ref of immutable union ${key}`);
|
|
163
|
+
}
|
|
164
|
+
const sym = `sc_ldu_${E.liveDynUnionRefAdapters.size}`;
|
|
165
|
+
E.liveDynUnionRefAdapters.set(key, sym);
|
|
166
|
+
const sig = `static ScrDyn *${sym}(ScrUnion *sc_u)`;
|
|
167
|
+
E.walkerProtos.push(`${sig}; /* materialize live union value ${key} */`);
|
|
168
|
+
const defs = [];
|
|
169
|
+
const adapters = new Map();
|
|
170
|
+
for (const { arm, tag } of mutableArms) {
|
|
171
|
+
const prefix = `${sym}_${tag}`;
|
|
172
|
+
adapters.set(tag, streamTypedRefAdapter(E, arm, { prefix, defs, adapters: new Map() }, `${prefix}_materialize`));
|
|
173
|
+
}
|
|
174
|
+
defs.push(`${sig} {`, ` switch (sc_u->tag) {`);
|
|
175
|
+
for (const { arm, tag } of mutableArms) {
|
|
176
|
+
const adapter = adapters.get(tag);
|
|
177
|
+
const rc = vAdapters(arm);
|
|
178
|
+
const armKey = typeKey(arm);
|
|
179
|
+
const keyLit = cStringLiteral(Buffer.from(armKey, "utf8"));
|
|
180
|
+
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
|
+
}
|
|
182
|
+
defs.push(` default:`, ` return ${E.toDynHelper(t)}(sc_u);`, ` }`, `}`, ``);
|
|
183
|
+
E.walkerDefs.push(...defs);
|
|
184
|
+
return sym;
|
|
185
|
+
}
|
|
186
|
+
function streamFromArrayAdapter(E, t) {
|
|
187
|
+
const elem = t.elem;
|
|
188
|
+
const key = typeKey(elem);
|
|
189
|
+
const existing = E.streamFromArrayAdapters.get(key);
|
|
190
|
+
if (existing)
|
|
191
|
+
return existing;
|
|
192
|
+
const sym = `sc_sfa_${E.streamFromArrayAdapters.size}`;
|
|
193
|
+
E.streamFromArrayAdapters.set(key, sym);
|
|
194
|
+
const sig = `static ScrDyn *${sym}(ScrArr *sc_a, double sc_i)`;
|
|
195
|
+
E.walkerProtos.push(`${sig}; /* ReadableStream.from array<${key}> */`);
|
|
196
|
+
const unionDef = elem.kind === "union"
|
|
197
|
+
? E.unionsById.get(elem.unionId)
|
|
198
|
+
: undefined;
|
|
199
|
+
if (elem.kind === "union" && !unionDef) {
|
|
200
|
+
throw new Error(`emitter bug: streamFrom of unknown union ${elem.unionId}`);
|
|
201
|
+
}
|
|
202
|
+
const unionRefArms = unionDef?.arms
|
|
203
|
+
.map((arm, tag) => ({ arm, tag }))
|
|
204
|
+
.filter(({ arm }) => isRefCounted(arm) && arm.kind !== "dyn" && arm.kind !== "string") ?? [];
|
|
205
|
+
const typedRef = isRefCounted(elem) &&
|
|
206
|
+
elem.kind !== "dyn" &&
|
|
207
|
+
elem.kind !== "string" &&
|
|
208
|
+
elem.kind !== "union";
|
|
209
|
+
const snapshot = `${sym}_materialize`;
|
|
210
|
+
const d = [];
|
|
211
|
+
let commit = "NULL";
|
|
212
|
+
if (typedRef) {
|
|
213
|
+
if (streamTypedRefEligible(elem)) {
|
|
214
|
+
const adapter = streamTypedRefAdapter(E, elem, { prefix: snapshot, defs: d, adapters: new Map() }, snapshot);
|
|
215
|
+
commit = adapter.commit;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
const snapshotSig = `static ScrDyn *${snapshot}(void *sc_p)`;
|
|
219
|
+
E.walkerProtos.push(`${snapshotSig}; /* materialize stream element ${key} */`);
|
|
220
|
+
d.push(`${snapshotSig} {`, ` return ${E.toDynHelper(elem)}((${cType(elem).trim()})sc_p);`, `}`, ``);
|
|
221
|
+
commit = streamTypedRefCommitAdapter(E, elem, snapshot, d);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const unionCommits = new Map();
|
|
225
|
+
for (const { arm, tag } of unionRefArms) {
|
|
226
|
+
const armKey = typeKey(arm);
|
|
227
|
+
const armSnapshot = `${snapshot}_${tag}`;
|
|
228
|
+
const snapshotSig = `static ScrDyn *${armSnapshot}(void *sc_p)`;
|
|
229
|
+
E.walkerProtos.push(`${snapshotSig}; /* materialize stream union arm ${armKey} */`);
|
|
230
|
+
d.push(`${snapshotSig} {`, ` return ${E.toDynHelper(arm)}((${cType(arm).trim()})sc_p);`, `}`, ``);
|
|
231
|
+
unionCommits.set(tag, streamTypedRefCommitAdapter(E, arm, armSnapshot, d));
|
|
232
|
+
}
|
|
233
|
+
d.push(`${sig} { /* ReadableStream.from array<${key}> */`);
|
|
234
|
+
if (elem.kind === "f64") {
|
|
235
|
+
d.push(` return ${E.toDynHelper(elem)}(scr_arr_get_f64(sc_a, sc_i));`);
|
|
236
|
+
}
|
|
237
|
+
else if (elem.kind === "bool") {
|
|
238
|
+
d.push(` return ${E.toDynHelper(elem)}(scr_arr_get_bool(sc_a, sc_i));`);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
d.push(` ${cDecl(elem, "sc_v")} = (${cType(elem).trim()})scr_arr_get_ref(sc_a, sc_i);`);
|
|
242
|
+
if (elem.kind === "union") {
|
|
243
|
+
d.push(` ScrDyn *sc_d;`, ` switch (sc_v->tag) {`);
|
|
244
|
+
for (const { arm, tag } of unionRefArms) {
|
|
245
|
+
const armKey = typeKey(arm);
|
|
246
|
+
const rc = vAdapters(arm);
|
|
247
|
+
const keyLit = cStringLiteral(Buffer.from(armKey, "utf8"));
|
|
248
|
+
d.push(` case ${tag}:`, ` sc_d = scr_dyn_new_typed_ref(scr_union_peek(sc_v), &${rc.retain}, &${rc.release}, ${keyLit}, ${Buffer.byteLength(armKey, "utf8")}, &${snapshot}_${tag}, ${unionCommits.get(tag) ?? "NULL"});`, ` break;`);
|
|
249
|
+
}
|
|
250
|
+
d.push(` default:`, ` sc_d = ${E.toDynHelper(elem)}(sc_v);`, ` break;`, ` }`);
|
|
251
|
+
}
|
|
252
|
+
else if (typedRef) {
|
|
253
|
+
const rc = vAdapters(elem);
|
|
254
|
+
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
255
|
+
const keyLen = Buffer.byteLength(key, "utf8");
|
|
256
|
+
d.push(` ScrDyn *sc_d = scr_dyn_new_typed_ref(sc_v, &${rc.retain}, &${rc.release}, ${keyLit}, ${keyLen}, &${snapshot}, ${commit});`);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
d.push(` ScrDyn *sc_d = ${E.toDynHelper(elem)}(sc_v);`);
|
|
260
|
+
}
|
|
261
|
+
d.push(` ${releaseCallC(elem, "sc_v")};`, ` return sc_d;`);
|
|
262
|
+
}
|
|
263
|
+
d.push(`}`, ``);
|
|
264
|
+
E.walkerDefs.push(...d);
|
|
265
|
+
return sym;
|
|
266
|
+
}
|
|
267
|
+
function dynPromiseAdapter(E, inner) {
|
|
268
|
+
if (!isRefCounted(inner) || inner.kind === "dyn") {
|
|
269
|
+
throw new Error(`dynamic promise adapter requires a concrete reference type, got ${typeKey(inner)}`);
|
|
270
|
+
}
|
|
271
|
+
const key = typeKey(inner);
|
|
272
|
+
const existing = E.dynPromiseAdapters.get(key);
|
|
273
|
+
if (existing)
|
|
274
|
+
return existing;
|
|
275
|
+
const sym = `sc_dpa_${E.dynPromiseAdapters.size}`;
|
|
276
|
+
E.dynPromiseAdapters.set(key, sym);
|
|
277
|
+
const sig = `static void ${sym}(ScrPromise *sc_dst, ScrPromise *sc_src)`;
|
|
278
|
+
E.walkerProtos.push(`${sig}; /* checked-dynamic promise exit ${key} */`);
|
|
279
|
+
let fulfill;
|
|
280
|
+
if (inner.kind === "string") {
|
|
281
|
+
fulfill = `scr_promise_fulfill_str(sc_dst, sc_v);`;
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
const rc = vAdapters(inner);
|
|
285
|
+
fulfill = `scr_promise_fulfill_ref(sc_dst, sc_v, &${rc.retain}, &${rc.release}, ${E.traceArgC(inner)});`;
|
|
286
|
+
}
|
|
287
|
+
E.walkerDefs.push(`${sig} { /* checked-dynamic promise exit ${key} */`, ` ScrDyn *sc_d = (ScrDyn *)scr_promise_payload_ref(sc_src);`, ` ${cDecl(inner, "sc_v")} = ${E.dynCheckHelper(inner)}(sc_d, NULL);`, ` scr_dyn_release(sc_d);`, ` if (scr_exc_pending()) {`, ` scr_promise_reject_pending(sc_dst);`, ` return;`, ` }`, ` ${fulfill}`, `}`, ``);
|
|
288
|
+
return sym;
|
|
289
|
+
}
|
|
7
290
|
export function emitExpr(E, e) {
|
|
8
291
|
switch (e.kind) {
|
|
9
292
|
case "numLit":
|
|
@@ -1692,6 +1975,17 @@ export function emitExpr(E, e) {
|
|
|
1692
1975
|
: "scr_dyn_new_null()");
|
|
1693
1976
|
}
|
|
1694
1977
|
const v = E.emitExpr(e.value);
|
|
1978
|
+
if (e.liveRef) {
|
|
1979
|
+
if (v.type.kind === "union") {
|
|
1980
|
+
const adapter = liveDynUnionRefAdapter(E, v.type);
|
|
1981
|
+
return E.newTemp(e.type, `${adapter}(${v.name})`);
|
|
1982
|
+
}
|
|
1983
|
+
const adapter = liveDynRefAdapter(E, v.type);
|
|
1984
|
+
const rc = vAdapters(v.type);
|
|
1985
|
+
const key = typeKey(v.type);
|
|
1986
|
+
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1987
|
+
return E.newTemp(e.type, `scr_dyn_new_typed_ref(${v.name}, &${rc.retain}, &${rc.release}, ${keyLit}, ${Buffer.byteLength(key, "utf8")}, &${adapter.snapshot}, ${adapter.commit})`);
|
|
1988
|
+
}
|
|
1695
1989
|
if (v.type.kind === "func") {
|
|
1696
1990
|
// A closure boxes as the checked-dynamic tree's function kind: retained closure +
|
|
1697
1991
|
// the per-signature call thunk + the interned signature key. The
|
|
@@ -2039,12 +2333,9 @@ export function emitExpr(E, e) {
|
|
|
2039
2333
|
// engine's own typeof.
|
|
2040
2334
|
`(${d.name}->kind == SCR_DYN_OBJ || ${d.name}->kind == SCR_DYN_ARR || ${d.name}->kind == SCR_DYN_BYTES || ${d.name}->kind == SCR_DYN_HANDLE || ${d.name}->kind == SCR_DYN_PROMISE || ${d.name}->kind == SCR_DYN_NULL || scr_dyn_isl_typeof_is(${d.name}, "object"))`
|
|
2041
2335
|
: e.test === "truthy"
|
|
2042
|
-
? // ToBoolean
|
|
2043
|
-
//
|
|
2044
|
-
|
|
2045
|
-
// JSVAL through the runtime's routed arm (the bigint 0n
|
|
2046
|
-
// edge); the remaining kinds (undefined, null) always false.
|
|
2047
|
-
`(${d.name}->kind == SCR_DYN_BOOL ? ${d.name}->v.b : ${d.name}->kind == SCR_DYN_NUM ? (${d.name}->v.num == ${d.name}->v.num && ${d.name}->v.num != 0) : ${d.name}->kind == SCR_DYN_STR ? ${d.name}->v.str->len != 0 : ${d.name}->kind == SCR_DYN_JSVAL ? scr_dyn_truthy(${d.name}) : (${d.name}->kind == SCR_DYN_OBJ || ${d.name}->kind == SCR_DYN_ARR || ${d.name}->kind == SCR_DYN_BYTES || ${d.name}->kind == SCR_DYN_FUNC || ${d.name}->kind == SCR_DYN_HANDLE || ${d.name}->kind == SCR_DYN_PROMISE))`
|
|
2336
|
+
? // Runtime ToBoolean includes typed-reference capsules and
|
|
2337
|
+
// keeps this backend in lockstep with LLVM.
|
|
2338
|
+
`scr_dyn_truthy(${d.name})`
|
|
2048
2339
|
: e.test === "error"
|
|
2049
2340
|
? // `u instanceof Error`: the checked-dynamic tree's error encoding — an
|
|
2050
2341
|
// object carrying the reserved "%error" marker key
|
|
@@ -2294,6 +2585,58 @@ export function emitExpr(E, e) {
|
|
|
2294
2585
|
};
|
|
2295
2586
|
const fn = e.fn;
|
|
2296
2587
|
switch (fn) {
|
|
2588
|
+
case "fetch.start":
|
|
2589
|
+
E.usesTimers = true;
|
|
2590
|
+
return finish(`scr_fetch_static(${arg(0)}, ${arg(1)})`);
|
|
2591
|
+
case "fetch.responseJson":
|
|
2592
|
+
return finish(`scr_fetch_response_json(${arg(0)})`);
|
|
2593
|
+
case "fetch.responseText":
|
|
2594
|
+
case "fetch.responseBytes": {
|
|
2595
|
+
if (e.type.kind !== "promise") {
|
|
2596
|
+
throw new Error(`emitter bug: ${fn} result`);
|
|
2597
|
+
}
|
|
2598
|
+
const runtimeFn = fn === "fetch.responseText"
|
|
2599
|
+
? "scr_fetch_response_text"
|
|
2600
|
+
: "scr_fetch_response_bytes";
|
|
2601
|
+
const source = E.newTemp({ kind: "promise", inner: DYN }, `${runtimeFn}(${arg(0)})`);
|
|
2602
|
+
const result = E.newTemp(e.type, `scr_promise_new()`);
|
|
2603
|
+
const adapter = dynPromiseAdapter(E, e.type.inner);
|
|
2604
|
+
E.line(`scr_promise_race_add(${result.name}, ${source.name}, &${adapter});${E.srcComment(e.loc)}`);
|
|
2605
|
+
return result;
|
|
2606
|
+
}
|
|
2607
|
+
case "fetch.abortTimeout":
|
|
2608
|
+
E.usesTimers = true;
|
|
2609
|
+
return finish(`scr_fetch_abort_timeout(${arg(0)})`);
|
|
2610
|
+
case "fetch.abortNow":
|
|
2611
|
+
return finish(`scr_fetch_abort_now(${arg(0)})`);
|
|
2612
|
+
case "fetch.abortAny":
|
|
2613
|
+
return finish(`scr_fetch_abort_any(${arg(0)})`);
|
|
2614
|
+
case "fetch.streamNew":
|
|
2615
|
+
E.usesTimers = true;
|
|
2616
|
+
return finish(`scr_fetch_stream_new(${arg(0)})`);
|
|
2617
|
+
case "fetch.streamFrom":
|
|
2618
|
+
E.usesTimers = true;
|
|
2619
|
+
if (e.args[0].type.kind === "array") {
|
|
2620
|
+
const adapter = streamFromArrayAdapter(E, e.args[0].type);
|
|
2621
|
+
return finish(`scr_fetch_stream_from_array(${arg(0)}, &${adapter})`);
|
|
2622
|
+
}
|
|
2623
|
+
if (e.args[0].type.kind === "bytes") {
|
|
2624
|
+
return finish(`scr_fetch_stream_from_bytes(${arg(0)})`);
|
|
2625
|
+
}
|
|
2626
|
+
if (e.args[0].type.kind === "string") {
|
|
2627
|
+
return finish(`scr_fetch_stream_from_string(${arg(0)})`);
|
|
2628
|
+
}
|
|
2629
|
+
return finish(`scr_fetch_stream_from(${arg(0)})`);
|
|
2630
|
+
case "fetch.readerRead": {
|
|
2631
|
+
if (e.type.kind !== "promise" || e.type.inner.kind !== "record") {
|
|
2632
|
+
throw new Error("emitter bug: fetch.readerRead result");
|
|
2633
|
+
}
|
|
2634
|
+
const source = E.newTemp({ kind: "promise", inner: DYN }, `scr_fetch_reader_read(${arg(0)})`);
|
|
2635
|
+
const result = E.newTemp(e.type, `scr_promise_new()`);
|
|
2636
|
+
const adapter = dynPromiseAdapter(E, e.type.inner);
|
|
2637
|
+
E.line(`scr_promise_race_add(${result.name}, ${source.name}, &${adapter});${E.srcComment(e.loc)}`);
|
|
2638
|
+
return result;
|
|
2639
|
+
}
|
|
2297
2640
|
case "island.eval":
|
|
2298
2641
|
// --dynamic builds only (the frontend fences the intrinsic, so
|
|
2299
2642
|
// scr_island_eval is always linked when this emits). Borrows
|
|
@@ -6421,6 +6764,10 @@ export function emitExpr(E, e) {
|
|
|
6421
6764
|
const pack = argPack(args.slice(1).map((x) => x.name));
|
|
6422
6765
|
return finishFallible(`scr_jsval_call_method(${a(0)}, ${nameSym()}, ${args.length - 1}, ${pack})`);
|
|
6423
6766
|
}
|
|
6767
|
+
case "callFnThis": {
|
|
6768
|
+
const pack = argPack(args.slice(2).map((x) => x.name));
|
|
6769
|
+
return finishFallible(`scr_jsval_call_this(${a(0)}, ${a(1)}, ${args.length - 2}, ${pack})`);
|
|
6770
|
+
}
|
|
6424
6771
|
case "callFn": {
|
|
6425
6772
|
const pack = argPack(args.slice(1).map((x) => x.name));
|
|
6426
6773
|
return finishFallible(`scr_jsval_call(${a(0)}, ${args.length - 1}, ${pack})`);
|