@scriptc/compiler 0.0.21 → 0.0.23
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 +117 -37
- 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-async.js +3 -1
- package/dist/backend/emission/emit-async.js.map +1 -1
- package/dist/backend/emission/emit-exprs.d.ts +10 -0
- package/dist/backend/emission/emit-exprs.js +482 -18
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +13 -5
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-types.js +4 -1
- package/dist/backend/emission/emit-types.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 +27 -1
- package/dist/backend/emission/emitter.js +84 -3
- 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 +831 -23
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +3 -2
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +118 -0
- package/dist/compat/fetch-profile.js +531 -0
- package/dist/compat/fetch-profile.js.map +1 -0
- package/dist/coverage/surface-manifest.js +69 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +10 -0
- package/dist/diagnostics/diagnostic.js +27 -1
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +24 -15
- package/dist/frontend/lowering/lower-builtins.js +217 -69
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +41 -0
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +32 -11
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +3 -3
- package/dist/frontend/lowering/lower-exprs.js +87 -15
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +7 -1
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +123 -7
- package/dist/frontend/lowering/lower-island.js +1976 -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 +33 -9
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +40 -0
- package/dist/frontend/lowering/lowerer.js +290 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +55 -12
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.d.ts +20 -4
- package/dist/frontend/program.js +391 -49
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +10 -0
- package/dist/frontend/resolve.js +37 -0
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/ts7/enums.d.ts +9 -0
- package/dist/frontend/ts7/enums.js +8 -6
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/program.js +4 -1
- package/dist/frontend/ts7/program.js.map +1 -1
- package/dist/frontend/types.d.ts +16 -9
- package/dist/frontend/types.js +119 -38
- 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 +55 -26
- package/dist/ir/nodes.js +42 -29
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +106 -9
- 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 +1097 -130
|
@@ -1,9 +1,345 @@
|
|
|
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
|
+
}
|
|
290
|
+
/** True when evaluating an index/value expression cannot overwrite the bytes
|
|
291
|
+
* receiver binding. This deliberately small whitelist enables borrowed
|
|
292
|
+
* receivers in typed-array hot loops while side-effecting/calling shapes
|
|
293
|
+
* retain the full snapshot ownership required by JS evaluation order. */
|
|
294
|
+
export function isStableBytesOperand(e, receiverLocalId) {
|
|
295
|
+
switch (e.kind) {
|
|
296
|
+
case "numLit":
|
|
297
|
+
case "boolLit":
|
|
298
|
+
case "varRef":
|
|
299
|
+
case "incDec":
|
|
300
|
+
return true;
|
|
301
|
+
case "assignExpr":
|
|
302
|
+
// An assignment nested under truthiness/ternary can still produce the
|
|
303
|
+
// numeric index/value while overwriting the bytes-typed receiver.
|
|
304
|
+
return e.localId !== receiverLocalId && isStableBytesOperand(e.value, receiverLocalId);
|
|
305
|
+
case "bin":
|
|
306
|
+
return (isStableBytesOperand(e.left, receiverLocalId) &&
|
|
307
|
+
isStableBytesOperand(e.right, receiverLocalId));
|
|
308
|
+
case "unary":
|
|
309
|
+
case "toBool":
|
|
310
|
+
return isStableBytesOperand(e.operand, receiverLocalId);
|
|
311
|
+
case "logical":
|
|
312
|
+
return (isStableBytesOperand(e.left, receiverLocalId) &&
|
|
313
|
+
isStableBytesOperand(e.right, receiverLocalId));
|
|
314
|
+
case "ternary":
|
|
315
|
+
return (isStableBytesOperand(e.cond, receiverLocalId) &&
|
|
316
|
+
isStableBytesOperand(e.then, receiverLocalId) &&
|
|
317
|
+
isStableBytesOperand(e.else_, receiverLocalId));
|
|
318
|
+
case "bytesIntrinsic":
|
|
319
|
+
return ((e.method === "get" || e.method === "length" || e.method === "byteLength") &&
|
|
320
|
+
e.receiver.kind === "varRef" &&
|
|
321
|
+
e.args.every((arg) => isStableBytesOperand(arg, receiverLocalId)));
|
|
322
|
+
default:
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/** Evaluate a bytes receiver as a borrow when it is a direct, unboxed
|
|
327
|
+
* binding and all later operands are stable. The binding's scope/global
|
|
328
|
+
* owner then keeps the value alive, avoiding retain/release traffic around
|
|
329
|
+
* every indexed access. Any uncertain shape falls back to an owned temp. */
|
|
330
|
+
export function emitBytesReceiver(E, receiver, following) {
|
|
331
|
+
if (receiver.kind === "varRef" &&
|
|
332
|
+
following.every((operand) => isStableBytesOperand(operand, receiver.localId))) {
|
|
333
|
+
const local = E.currentLocals.get(receiver.localId);
|
|
334
|
+
if (local && !local.boxed) {
|
|
335
|
+
return E.newBorrowedTemp(receiver.type, mangleLocal(receiver.localId));
|
|
336
|
+
}
|
|
337
|
+
if (!local && E.globalsById.has(receiver.localId)) {
|
|
338
|
+
return E.newBorrowedTemp(receiver.type, mangleGlobal(receiver.localId));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return E.emitExpr(receiver);
|
|
342
|
+
}
|
|
7
343
|
export function emitExpr(E, e) {
|
|
8
344
|
switch (e.kind) {
|
|
9
345
|
case "numLit":
|
|
@@ -1020,17 +1356,26 @@ export function emitExpr(E, e) {
|
|
|
1020
1356
|
E.emitPendingCheck();
|
|
1021
1357
|
return t;
|
|
1022
1358
|
}
|
|
1023
|
-
const r = E.emitExpr(e.receiver);
|
|
1024
|
-
const args = e.args.map((a) => E.emitExpr(a));
|
|
1025
1359
|
const method = e.method;
|
|
1360
|
+
const directElementAccess = method === "length" || method === "byteLength" || method === "get";
|
|
1361
|
+
const r = directElementAccess
|
|
1362
|
+
? emitBytesReceiver(E, e.receiver, e.args)
|
|
1363
|
+
: E.emitExpr(e.receiver);
|
|
1364
|
+
const args = e.args.map((a) => E.emitExpr(a));
|
|
1026
1365
|
switch (method) {
|
|
1027
1366
|
case "length":
|
|
1028
|
-
return E.newTemp(e.type, `
|
|
1367
|
+
return E.newTemp(e.type, `(double)${r.name}->len`);
|
|
1029
1368
|
case "byteLength":
|
|
1030
|
-
|
|
1369
|
+
if (e.receiver.type.kind !== "bytes") {
|
|
1370
|
+
throw new Error("emitter bug: bytesIntrinsic byteLength on non-bytes");
|
|
1371
|
+
}
|
|
1372
|
+
return E.newTemp(e.type, `(double)(${r.name}->len * ${e.receiver.type.elem === "u8" ? "1" : "4"})`);
|
|
1031
1373
|
case "get":
|
|
1032
1374
|
// Any invalid index traps (the array runtime's discipline).
|
|
1033
|
-
|
|
1375
|
+
if (e.receiver.type.kind !== "bytes") {
|
|
1376
|
+
throw new Error("emitter bug: bytesIntrinsic get on non-bytes");
|
|
1377
|
+
}
|
|
1378
|
+
return E.newTemp(e.type, `${E.bytesElementHelper("get", e.receiver.type.elem)}(${r.name}, ${args[0].name})`);
|
|
1034
1379
|
case "slice":
|
|
1035
1380
|
// Omitted relative indices default like string slice: start 0,
|
|
1036
1381
|
// end +Infinity (math.h is always included). Fresh copy, +1.
|
|
@@ -1692,6 +2037,17 @@ export function emitExpr(E, e) {
|
|
|
1692
2037
|
: "scr_dyn_new_null()");
|
|
1693
2038
|
}
|
|
1694
2039
|
const v = E.emitExpr(e.value);
|
|
2040
|
+
if (e.liveRef) {
|
|
2041
|
+
if (v.type.kind === "union") {
|
|
2042
|
+
const adapter = liveDynUnionRefAdapter(E, v.type);
|
|
2043
|
+
return E.newTemp(e.type, `${adapter}(${v.name})`);
|
|
2044
|
+
}
|
|
2045
|
+
const adapter = liveDynRefAdapter(E, v.type);
|
|
2046
|
+
const rc = vAdapters(v.type);
|
|
2047
|
+
const key = typeKey(v.type);
|
|
2048
|
+
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
2049
|
+
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})`);
|
|
2050
|
+
}
|
|
1695
2051
|
if (v.type.kind === "func") {
|
|
1696
2052
|
// A closure boxes as the checked-dynamic tree's function kind: retained closure +
|
|
1697
2053
|
// the per-signature call thunk + the interned signature key. The
|
|
@@ -2039,12 +2395,9 @@ export function emitExpr(E, e) {
|
|
|
2039
2395
|
// engine's own typeof.
|
|
2040
2396
|
`(${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
2397
|
: 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))`
|
|
2398
|
+
? // Runtime ToBoolean includes typed-reference capsules and
|
|
2399
|
+
// keeps this backend in lockstep with LLVM.
|
|
2400
|
+
`scr_dyn_truthy(${d.name})`
|
|
2048
2401
|
: e.test === "error"
|
|
2049
2402
|
? // `u instanceof Error`: the checked-dynamic tree's error encoding — an
|
|
2050
2403
|
// object carrying the reserved "%error" marker key
|
|
@@ -2212,6 +2565,7 @@ export function emitExpr(E, e) {
|
|
|
2212
2565
|
const t = e.args[0].type;
|
|
2213
2566
|
switch (t.kind) {
|
|
2214
2567
|
case "f64":
|
|
2568
|
+
case "date":
|
|
2215
2569
|
E.line(`scr_promise_fulfill_f64(${p.name}, ${v.name});${E.srcComment(e.loc)}`);
|
|
2216
2570
|
break;
|
|
2217
2571
|
case "bool":
|
|
@@ -2294,6 +2648,62 @@ export function emitExpr(E, e) {
|
|
|
2294
2648
|
};
|
|
2295
2649
|
const fn = e.fn;
|
|
2296
2650
|
switch (fn) {
|
|
2651
|
+
case "fetch.start":
|
|
2652
|
+
E.usesTimers = true;
|
|
2653
|
+
return finish(`scr_fetch_static(${arg(0)}, ${arg(1)})`);
|
|
2654
|
+
case "fetch.responseNew":
|
|
2655
|
+
return finish(`scr_fetch_response_new(${arg(0)}, ${arg(1)})`);
|
|
2656
|
+
case "fetch.responseJson":
|
|
2657
|
+
return finish(`scr_fetch_response_json(${arg(0)})`);
|
|
2658
|
+
case "fetch.responseText":
|
|
2659
|
+
case "fetch.responseBytes": {
|
|
2660
|
+
if (e.type.kind !== "promise") {
|
|
2661
|
+
throw new Error(`emitter bug: ${fn} result`);
|
|
2662
|
+
}
|
|
2663
|
+
const runtimeFn = fn === "fetch.responseText"
|
|
2664
|
+
? "scr_fetch_response_text"
|
|
2665
|
+
: "scr_fetch_response_bytes";
|
|
2666
|
+
const source = E.newTemp({ kind: "promise", inner: DYN }, `${runtimeFn}(${arg(0)})`);
|
|
2667
|
+
const result = E.newTemp(e.type, `scr_promise_new()`);
|
|
2668
|
+
const adapter = dynPromiseAdapter(E, e.type.inner);
|
|
2669
|
+
E.line(`scr_promise_race_add(${result.name}, ${source.name}, &${adapter});${E.srcComment(e.loc)}`);
|
|
2670
|
+
return result;
|
|
2671
|
+
}
|
|
2672
|
+
case "fetch.abortControllerNew":
|
|
2673
|
+
return finish(`scr_fetch_abort_controller_new()`);
|
|
2674
|
+
case "fetch.abortTimeout":
|
|
2675
|
+
E.usesTimers = true;
|
|
2676
|
+
return finish(`scr_fetch_abort_timeout(${arg(0)})`);
|
|
2677
|
+
case "fetch.abortNow":
|
|
2678
|
+
return finish(`scr_fetch_abort_now(${arg(0)})`);
|
|
2679
|
+
case "fetch.abortAny":
|
|
2680
|
+
return finish(`scr_fetch_abort_any(${arg(0)})`);
|
|
2681
|
+
case "fetch.streamNew":
|
|
2682
|
+
E.usesTimers = true;
|
|
2683
|
+
return finish(`scr_fetch_stream_new(${arg(0)})`);
|
|
2684
|
+
case "fetch.streamFrom":
|
|
2685
|
+
E.usesTimers = true;
|
|
2686
|
+
if (e.args[0].type.kind === "array") {
|
|
2687
|
+
const adapter = streamFromArrayAdapter(E, e.args[0].type);
|
|
2688
|
+
return finish(`scr_fetch_stream_from_array(${arg(0)}, &${adapter})`);
|
|
2689
|
+
}
|
|
2690
|
+
if (e.args[0].type.kind === "bytes") {
|
|
2691
|
+
return finish(`scr_fetch_stream_from_bytes(${arg(0)})`);
|
|
2692
|
+
}
|
|
2693
|
+
if (e.args[0].type.kind === "string") {
|
|
2694
|
+
return finish(`scr_fetch_stream_from_string(${arg(0)})`);
|
|
2695
|
+
}
|
|
2696
|
+
return finish(`scr_fetch_stream_from(${arg(0)})`);
|
|
2697
|
+
case "fetch.readerRead": {
|
|
2698
|
+
if (e.type.kind !== "promise" || e.type.inner.kind !== "record") {
|
|
2699
|
+
throw new Error("emitter bug: fetch.readerRead result");
|
|
2700
|
+
}
|
|
2701
|
+
const source = E.newTemp({ kind: "promise", inner: DYN }, `scr_fetch_reader_read(${arg(0)})`);
|
|
2702
|
+
const result = E.newTemp(e.type, `scr_promise_new()`);
|
|
2703
|
+
const adapter = dynPromiseAdapter(E, e.type.inner);
|
|
2704
|
+
E.line(`scr_promise_race_add(${result.name}, ${source.name}, &${adapter});${E.srcComment(e.loc)}`);
|
|
2705
|
+
return result;
|
|
2706
|
+
}
|
|
2297
2707
|
case "island.eval":
|
|
2298
2708
|
// --dynamic builds only (the frontend fences the intrinsic, so
|
|
2299
2709
|
// scr_island_eval is always linked when this emits). Borrows
|
|
@@ -2821,7 +3231,7 @@ export function emitExpr(E, e) {
|
|
|
2821
3231
|
// comes back as f64.
|
|
2822
3232
|
return finish(`scr_fs_open(${arg(0)}, ${arg(1)})`);
|
|
2823
3233
|
case "fs.readSync":
|
|
2824
|
-
return finish(`scr_fs_read_sync(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)})`);
|
|
3234
|
+
return finish(`scr_fs_read_sync(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)})`);
|
|
2825
3235
|
case "fs.closeSync":
|
|
2826
3236
|
return finish(`scr_fs_close(${arg(0)})`);
|
|
2827
3237
|
case "fs.watch":
|
|
@@ -5789,7 +6199,17 @@ export function emitExpr(E, e) {
|
|
|
5789
6199
|
case "date.now":
|
|
5790
6200
|
// Node's integer milliseconds since epoch. Never throws.
|
|
5791
6201
|
return finish(`scr_date_now()`);
|
|
6202
|
+
case "date.newNow":
|
|
6203
|
+
return finish(`scr_date_now()`);
|
|
6204
|
+
case "date.newMs":
|
|
6205
|
+
return finish(`scr_date_new_ms(${arg(0)})`);
|
|
6206
|
+
case "date.newString":
|
|
6207
|
+
return finish(`scr_date_parse_get_time(${arg(0)})`);
|
|
6208
|
+
case "date.getTime":
|
|
6209
|
+
case "date.valueOf":
|
|
6210
|
+
return finish(`${arg(0)}`);
|
|
5792
6211
|
case "date.toISOString":
|
|
6212
|
+
case "date.toISOStringValue":
|
|
5793
6213
|
// +1 string, or Node's "Invalid time value" RangeError
|
|
5794
6214
|
// (may-throw seed set).
|
|
5795
6215
|
return finish(`scr_date_to_iso(${arg(0)})`);
|
|
@@ -5801,6 +6221,39 @@ export function emitExpr(E, e) {
|
|
|
5801
6221
|
// MakeDay/MakeTime/TimeClip over seven completed number
|
|
5802
6222
|
// arguments; NaN outside the time range. Never throws.
|
|
5803
6223
|
return finish(`scr_date_utc(${arg(0)}, ${arg(1)}, ${arg(2)}, ${arg(3)}, ${arg(4)}, ${arg(5)}, ${arg(6)})`);
|
|
6224
|
+
case "date.getFullYear":
|
|
6225
|
+
return finish(`scr_date_get_full_year(${arg(0)}, false)`);
|
|
6226
|
+
case "date.getUTCFullYear":
|
|
6227
|
+
return finish(`scr_date_get_full_year(${arg(0)}, true)`);
|
|
6228
|
+
case "date.getMonth":
|
|
6229
|
+
return finish(`scr_date_get_month(${arg(0)}, false)`);
|
|
6230
|
+
case "date.getUTCMonth":
|
|
6231
|
+
return finish(`scr_date_get_month(${arg(0)}, true)`);
|
|
6232
|
+
case "date.getDate":
|
|
6233
|
+
return finish(`scr_date_get_date(${arg(0)}, false)`);
|
|
6234
|
+
case "date.getUTCDate":
|
|
6235
|
+
return finish(`scr_date_get_date(${arg(0)}, true)`);
|
|
6236
|
+
case "date.getDay":
|
|
6237
|
+
return finish(`scr_date_get_day(${arg(0)}, false)`);
|
|
6238
|
+
case "date.getUTCDay":
|
|
6239
|
+
return finish(`scr_date_get_day(${arg(0)}, true)`);
|
|
6240
|
+
case "date.getHours":
|
|
6241
|
+
return finish(`scr_date_get_hours(${arg(0)}, false)`);
|
|
6242
|
+
case "date.getUTCHours":
|
|
6243
|
+
return finish(`scr_date_get_hours(${arg(0)}, true)`);
|
|
6244
|
+
case "date.getMinutes":
|
|
6245
|
+
return finish(`scr_date_get_minutes(${arg(0)}, false)`);
|
|
6246
|
+
case "date.getUTCMinutes":
|
|
6247
|
+
return finish(`scr_date_get_minutes(${arg(0)}, true)`);
|
|
6248
|
+
case "date.getSeconds":
|
|
6249
|
+
return finish(`scr_date_get_seconds(${arg(0)}, false)`);
|
|
6250
|
+
case "date.getUTCSeconds":
|
|
6251
|
+
return finish(`scr_date_get_seconds(${arg(0)}, true)`);
|
|
6252
|
+
case "date.getMilliseconds":
|
|
6253
|
+
case "date.getUTCMilliseconds":
|
|
6254
|
+
return finish(`scr_date_get_milliseconds(${arg(0)})`);
|
|
6255
|
+
case "date.getTimezoneOffset":
|
|
6256
|
+
return finish(`scr_date_get_timezone_offset(${arg(0)})`);
|
|
5804
6257
|
case "text.decode":
|
|
5805
6258
|
// WHATWG utf-8 decode with the leading BOM stripped
|
|
5806
6259
|
// (scr_bytes.c). Borrowed bytes; +1 string; never throws.
|
|
@@ -5959,7 +6412,7 @@ export function emitExpr(E, e) {
|
|
|
5959
6412
|
throw new Error("emitter bug: yieldExpr with no operand (frontend fills undefined)");
|
|
5960
6413
|
const v = E.emitExpr(e.value);
|
|
5961
6414
|
const yt = e.value.type;
|
|
5962
|
-
if (yt.kind === "f64") {
|
|
6415
|
+
if (yt.kind === "f64" || yt.kind === "date") {
|
|
5963
6416
|
E.line(`scr_gen_yield_f64(${v.name});${E.srcComment(e.loc)}`);
|
|
5964
6417
|
}
|
|
5965
6418
|
else if (yt.kind === "bool") {
|
|
@@ -5976,6 +6429,7 @@ export function emitExpr(E, e) {
|
|
|
5976
6429
|
// fences value-position yields on this channel).
|
|
5977
6430
|
return { name: "", type: e.type };
|
|
5978
6431
|
case "f64":
|
|
6432
|
+
case "date":
|
|
5979
6433
|
return E.newTemp(e.type, `scr_gen_take_in_f64()`);
|
|
5980
6434
|
case "bool":
|
|
5981
6435
|
return E.newTemp(e.type, `scr_gen_take_in_bool()`);
|
|
@@ -6013,7 +6467,7 @@ export function emitExpr(E, e) {
|
|
|
6013
6467
|
}
|
|
6014
6468
|
else {
|
|
6015
6469
|
const nt = e.arg.type;
|
|
6016
|
-
sendArg((a) => nt.kind === "f64" ? `scr_gen_in_f64(${g.name}, ${a.name});${E.srcComment(e.loc)}`
|
|
6470
|
+
sendArg((a) => nt.kind === "f64" || nt.kind === "date" ? `scr_gen_in_f64(${g.name}, ${a.name});${E.srcComment(e.loc)}`
|
|
6017
6471
|
: nt.kind === "bool" ? `scr_gen_in_bool(${g.name}, ${a.name});${E.srcComment(e.loc)}`
|
|
6018
6472
|
: `scr_gen_in_ref(${g.name}, ${a.name}, ${vAdapters(nt).release});${E.srcComment(e.loc)}`);
|
|
6019
6473
|
}
|
|
@@ -6025,7 +6479,7 @@ export function emitExpr(E, e) {
|
|
|
6025
6479
|
}
|
|
6026
6480
|
else {
|
|
6027
6481
|
const rt = e.arg.type;
|
|
6028
|
-
sendArg((a) => rt.kind === "f64" ? `scr_gen_ret_f64(${g.name}, ${a.name});${E.srcComment(e.loc)}`
|
|
6482
|
+
sendArg((a) => rt.kind === "f64" || rt.kind === "date" ? `scr_gen_ret_f64(${g.name}, ${a.name});${E.srcComment(e.loc)}`
|
|
6029
6483
|
: rt.kind === "bool" ? `scr_gen_ret_bool(${g.name}, ${a.name});${E.srcComment(e.loc)}`
|
|
6030
6484
|
: `scr_gen_ret_ref(${g.name}, ${a.name}, ${vAdapters(rt).release});${E.srcComment(e.loc)}`);
|
|
6031
6485
|
}
|
|
@@ -6042,7 +6496,10 @@ export function emitExpr(E, e) {
|
|
|
6042
6496
|
const t = e.arg.type;
|
|
6043
6497
|
if (isRefCounted(t))
|
|
6044
6498
|
E.moveTemp(a); // the cell takes ownership
|
|
6045
|
-
if (t.kind === "
|
|
6499
|
+
if (t.kind === "date") {
|
|
6500
|
+
throw new Error("emitter bug: Date generator throw reached backend");
|
|
6501
|
+
}
|
|
6502
|
+
else if (t.kind === "f64") {
|
|
6046
6503
|
E.line(`scr_throw_f64(${a.name});${E.srcComment(e.loc)}`);
|
|
6047
6504
|
}
|
|
6048
6505
|
else if (t.kind === "bool") {
|
|
@@ -6075,6 +6532,7 @@ export function emitExpr(E, e) {
|
|
|
6075
6532
|
let read;
|
|
6076
6533
|
switch (e.type.kind) {
|
|
6077
6534
|
case "f64":
|
|
6535
|
+
case "date":
|
|
6078
6536
|
read = `scr_await_f64(${pr.name})`;
|
|
6079
6537
|
break;
|
|
6080
6538
|
case "bool":
|
|
@@ -6197,6 +6655,7 @@ export function emitExpr(E, e) {
|
|
|
6197
6655
|
let mk;
|
|
6198
6656
|
switch (inner.kind) {
|
|
6199
6657
|
case "f64":
|
|
6658
|
+
case "date":
|
|
6200
6659
|
mk = `scr_make_resolve(${p.name}, 0)`;
|
|
6201
6660
|
break;
|
|
6202
6661
|
case "bool":
|
|
@@ -6251,6 +6710,7 @@ export function emitExpr(E, e) {
|
|
|
6251
6710
|
let mk;
|
|
6252
6711
|
switch (inner.kind) {
|
|
6253
6712
|
case "f64":
|
|
6713
|
+
case "date":
|
|
6254
6714
|
mk = `scr_make_resolve(${p.name}, 0)`;
|
|
6255
6715
|
break;
|
|
6256
6716
|
case "bool":
|
|
@@ -6421,6 +6881,10 @@ export function emitExpr(E, e) {
|
|
|
6421
6881
|
const pack = argPack(args.slice(1).map((x) => x.name));
|
|
6422
6882
|
return finishFallible(`scr_jsval_call_method(${a(0)}, ${nameSym()}, ${args.length - 1}, ${pack})`);
|
|
6423
6883
|
}
|
|
6884
|
+
case "callFnThis": {
|
|
6885
|
+
const pack = argPack(args.slice(2).map((x) => x.name));
|
|
6886
|
+
return finishFallible(`scr_jsval_call_this(${a(0)}, ${a(1)}, ${args.length - 2}, ${pack})`);
|
|
6887
|
+
}
|
|
6424
6888
|
case "callFn": {
|
|
6425
6889
|
const pack = argPack(args.slice(1).map((x) => x.name));
|
|
6426
6890
|
return finishFallible(`scr_jsval_call(${a(0)}, ${args.length - 1}, ${pack})`);
|