@scriptc/compiler 0.0.33 → 0.0.35
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/dist/backend/cc-cache.test.js +1091 -7
- package/dist/backend/cc-cache.test.js.map +1 -1
- package/dist/backend/cc.d.ts +109 -18
- package/dist/backend/cc.js +1057 -289
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +26 -1
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +37 -4
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +11 -2
- package/dist/backend/emission/emitter.js +11 -5
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/library-identity.d.ts +22 -0
- package/dist/backend/library-identity.js +103 -0
- package/dist/backend/library-identity.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +3 -0
- package/dist/backend/llvm/emitter.js +35 -5
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +1 -0
- package/dist/backend/llvm/shapes.js +25 -1
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/split.d.ts +43 -0
- package/dist/backend/llvm/split.js +227 -0
- package/dist/backend/llvm/split.js.map +1 -0
- package/dist/backend/llvm/split.test.d.ts +1 -0
- package/dist/backend/llvm/split.test.js +102 -0
- package/dist/backend/llvm/split.test.js.map +1 -0
- package/dist/backend/mangle.d.ts +1 -0
- package/dist/backend/mangle.js +3 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/object-localize.d.ts +5 -5
- package/dist/backend/object-localize.js +19 -16
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +57 -13
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/executable/early-cache.d.ts +86 -0
- package/dist/executable/early-cache.js +460 -0
- package/dist/executable/early-cache.js.map +1 -0
- package/dist/executable/early-cache.test.d.ts +1 -0
- package/dist/executable/early-cache.test.js +300 -0
- package/dist/executable/early-cache.test.js.map +1 -0
- package/dist/ffi/profile.d.ts +7 -2
- package/dist/ffi/profile.js +1 -0
- package/dist/ffi/profile.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +82 -0
- package/dist/frontend/input-tracker.js +380 -0
- package/dist/frontend/input-tracker.js.map +1 -0
- package/dist/frontend/input-tracker.test.d.ts +1 -0
- package/dist/frontend/input-tracker.test.js +137 -0
- package/dist/frontend/input-tracker.test.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.js +4 -10
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +169 -144
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +3 -0
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +66 -32
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +89 -11
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +45 -26
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +3 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +1 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +49 -4
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +73 -29
- package/dist/frontend/lowering/lowerer.js +588 -116
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +1 -1
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.js +25 -26
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.js +29 -30
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm-static.test.d.ts +1 -0
- package/dist/frontend/npm-static.test.js +15 -0
- package/dist/frontend/npm-static.test.js.map +1 -0
- package/dist/frontend/npm.js +5 -17
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.js +44 -19
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.js +8 -29
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +40 -2
- package/dist/frontend/ts7/checker.js +194 -32
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/program.js +17 -18
- package/dist/frontend/ts7/program.js.map +1 -1
- package/dist/frontend/types.d.ts +33 -0
- package/dist/frontend/types.js +134 -45
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +458 -141
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +27 -4
- package/dist/ir/nodes.js +28 -0
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/validate.js +37 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/early-cache.d.ts +65 -0
- package/dist/library/early-cache.js +361 -0
- package/dist/library/early-cache.js.map +1 -0
- package/dist/library/early-cache.test.d.ts +1 -0
- package/dist/library/early-cache.test.js +528 -0
- package/dist/library/early-cache.test.js.map +1 -0
- package/dist/library/implementation-identity.d.ts +23 -0
- package/dist/library/implementation-identity.js +84 -0
- package/dist/library/implementation-identity.js.map +1 -0
- package/dist/library/int-infer.js +14 -0
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +21 -4
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/semantic-source.d.ts +13 -0
- package/dist/library/semantic-source.js +257 -0
- package/dist/library/semantic-source.js.map +1 -0
- package/dist/library/semantic-source.test.d.ts +1 -0
- package/dist/library/semantic-source.test.js +113 -0
- package/dist/library/semantic-source.test.js.map +1 -0
- package/dist/library/sidecar.d.ts +6 -0
- package/dist/library/sidecar.js +11 -0
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.d.ts +6 -0
- package/dist/startup-cache.js +6 -0
- package/dist/startup-cache.js.map +1 -0
- package/package.json +3 -2
- package/surface-manifest.json +1 -1
|
@@ -625,7 +625,7 @@ export function declaredReturnType(L, decl, blame) {
|
|
|
625
625
|
* instead of the generic supported-types recitation; a no-op for every
|
|
626
626
|
* other unmappable type (the caller's badType reports those). */
|
|
627
627
|
function fenceGenericSignatureResult(L, blame, t) {
|
|
628
|
-
const parts = t.isUnionType() ?
|
|
628
|
+
const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
|
|
629
629
|
if (!parts.some((p) => L.checker.getCallSignatures(p).some((s) => (s.typeParameters?.length ?? 0) > 0))) {
|
|
630
630
|
return;
|
|
631
631
|
}
|
|
@@ -931,6 +931,7 @@ export function internGenericInstance(L, blame, info, params, returnType, makeBi
|
|
|
931
931
|
info.instances.set(key, inst);
|
|
932
932
|
L.instantiationQueue.push({ info, inst });
|
|
933
933
|
}
|
|
934
|
+
L.noteGenericInstanceDemand(inst);
|
|
934
935
|
return inst;
|
|
935
936
|
}
|
|
936
937
|
/** The type parameters of `info` declared with a `keyof` CONSTRAINT
|
|
@@ -1045,8 +1046,8 @@ export function unifySignatureBindings(L, info, rsig, bindings, tsBindings) {
|
|
|
1045
1046
|
// unbound type parameter surfaces as a mapping diagnostic later).
|
|
1046
1047
|
if (declared.isUnionType()) {
|
|
1047
1048
|
const unitFlags = ts.TypeFlags.Undefined | ts.TypeFlags.Null;
|
|
1048
|
-
const dParts =
|
|
1049
|
-
const iParts = inst.isUnionType() ?
|
|
1049
|
+
const dParts = ts.constituentTypes(declared).filter((t) => !(t.flags & unitFlags));
|
|
1050
|
+
const iParts = inst.isUnionType() ? ts.constituentTypes(inst).filter((t) => !(t.flags & unitFlags)) : [inst];
|
|
1050
1051
|
if (dParts.length === 1 && iParts.length === 1)
|
|
1051
1052
|
unify(dParts[0], iParts[0], depth + 1);
|
|
1052
1053
|
return;
|
|
@@ -1442,7 +1443,7 @@ export function lowerGenericFnValue(L, ref, info) {
|
|
|
1442
1443
|
// A `Fn | undefined`-flavored slot: the value can only inhabit the
|
|
1443
1444
|
// one callable arm — judge by it (the requireExactArityValue union
|
|
1444
1445
|
// rule).
|
|
1445
|
-
const callable =
|
|
1446
|
+
const callable = ts.constituentTypes(pinT).map((t) => L.checker.getCallSignatures(t)).filter((s) => s.length === 1);
|
|
1446
1447
|
if (callable.length === 1)
|
|
1447
1448
|
target = callable[0][0];
|
|
1448
1449
|
}
|
|
@@ -1781,6 +1782,16 @@ function internImplicitInstance(L, blame, info, shapes, argTypes) {
|
|
|
1781
1782
|
// the pinned signature over a missing body, which the linker never
|
|
1782
1783
|
// sees because the poison also fenced the call statement.
|
|
1783
1784
|
try {
|
|
1785
|
+
// Implicit-any instances lower EAGERLY at the call site so their
|
|
1786
|
+
// inferred return type is available immediately. They therefore do
|
|
1787
|
+
// not pass through emitReachable's queued generic-instance wave,
|
|
1788
|
+
// which normally batches checker work before lowering a body. Prime
|
|
1789
|
+
// this exact committed instance body here; repeated instantiations of
|
|
1790
|
+
// the same declaration find the facade memos warm.
|
|
1791
|
+
L.checker.prefetchRoots([
|
|
1792
|
+
...info.decl.parameters.flatMap((param) => param.initializer ? [param.initializer] : []),
|
|
1793
|
+
...(info.decl.body ? [info.decl.body] : []),
|
|
1794
|
+
]);
|
|
1784
1795
|
const fn = L.lowerGenericInstance(info, inst);
|
|
1785
1796
|
L.implicitFns.push(fn);
|
|
1786
1797
|
}
|
|
@@ -6409,48 +6420,8 @@ export function recordKeysArrayCall(L, receiver, argIr, shape, loc) {
|
|
|
6409
6420
|
helper = `%obj.keys.${L.arrHofHelpers.size}`;
|
|
6410
6421
|
const ref = { kind: "varRef", localId: "r.0", type: argIr, loc };
|
|
6411
6422
|
const outRef = { kind: "varRef", localId: "out.0", type: resultT, loc };
|
|
6412
|
-
const body = [
|
|
6413
|
-
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
6414
|
-
];
|
|
6415
|
-
const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
|
|
6416
|
-
for (const name of order) {
|
|
6417
|
-
const f = shape.fields.find((x) => x.name === name);
|
|
6418
|
-
const pushStmt = {
|
|
6419
|
-
kind: "exprStmt",
|
|
6420
|
-
expr: {
|
|
6421
|
-
kind: "arrIntrinsic",
|
|
6422
|
-
method: "push",
|
|
6423
|
-
receiver: outRef,
|
|
6424
|
-
args: [{ kind: "strLit", value: f.name, type: STRING, loc }],
|
|
6425
|
-
type: F64,
|
|
6426
|
-
loc,
|
|
6427
|
-
},
|
|
6428
|
-
loc,
|
|
6429
|
-
};
|
|
6430
|
-
// Undefined-armed fields: the push is guarded by a tag test (the
|
|
6431
|
-
// key exists exactly when the arm is not undefined).
|
|
6432
|
-
const utag = f.type.kind === "union" ? L.armTag(f.type.unionId, UNDEFINED_T) : -1;
|
|
6433
|
-
body.push(utag >= 0 && f.type.kind === "union"
|
|
6434
|
-
? {
|
|
6435
|
-
kind: "if",
|
|
6436
|
-
cond: {
|
|
6437
|
-
kind: "unionIsTag",
|
|
6438
|
-
unionId: f.type.unionId,
|
|
6439
|
-
tag: utag,
|
|
6440
|
-
negated: true,
|
|
6441
|
-
value: { kind: "recordGet", obj: ref, shapeId: argIr.shapeId, field: f.name, type: f.type, loc },
|
|
6442
|
-
type: BOOL,
|
|
6443
|
-
loc,
|
|
6444
|
-
},
|
|
6445
|
-
then: [pushStmt],
|
|
6446
|
-
else_: null,
|
|
6447
|
-
loc,
|
|
6448
|
-
}
|
|
6449
|
-
: pushStmt);
|
|
6450
|
-
}
|
|
6451
|
-
body.push({ kind: "return", value: outRef, loc });
|
|
6452
6423
|
L.arrHofHelpers.set(key, helper);
|
|
6453
|
-
|
|
6424
|
+
const fn = {
|
|
6454
6425
|
name: helper,
|
|
6455
6426
|
params: [{ localId: "r.0", name: "r", type: argIr }],
|
|
6456
6427
|
returnType: resultT,
|
|
@@ -6458,9 +6429,56 @@ export function recordKeysArrayCall(L, receiver, argIr, shape, loc) {
|
|
|
6458
6429
|
{ id: "r.0", name: "r", type: argIr, mutable: true },
|
|
6459
6430
|
{ id: "out.0", name: "out", type: resultT, mutable: false },
|
|
6460
6431
|
],
|
|
6461
|
-
body,
|
|
6432
|
+
body: [],
|
|
6462
6433
|
loc,
|
|
6463
|
-
}
|
|
6434
|
+
};
|
|
6435
|
+
const finalize = () => {
|
|
6436
|
+
const current = L.shapes.get(argIr.shapeId) ?? shape;
|
|
6437
|
+
const body = [
|
|
6438
|
+
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
6439
|
+
];
|
|
6440
|
+
const order = current.declaredOrder ?? current.fields.map((f) => f.name);
|
|
6441
|
+
for (const name of order) {
|
|
6442
|
+
const f = current.fields.find((x) => x.name === name);
|
|
6443
|
+
const pushStmt = {
|
|
6444
|
+
kind: "exprStmt",
|
|
6445
|
+
expr: {
|
|
6446
|
+
kind: "arrIntrinsic",
|
|
6447
|
+
method: "push",
|
|
6448
|
+
receiver: outRef,
|
|
6449
|
+
args: [{ kind: "strLit", value: f.name, type: STRING, loc }],
|
|
6450
|
+
type: F64,
|
|
6451
|
+
loc,
|
|
6452
|
+
},
|
|
6453
|
+
loc,
|
|
6454
|
+
};
|
|
6455
|
+
// Undefined-armed fields: the push is guarded by a tag test (the
|
|
6456
|
+
// key exists exactly when Object.keys would list it).
|
|
6457
|
+
const utag = f.type.kind === "union" ? L.armTag(f.type.unionId, UNDEFINED_T) : -1;
|
|
6458
|
+
body.push(utag >= 0 && f.type.kind === "union"
|
|
6459
|
+
? {
|
|
6460
|
+
kind: "if",
|
|
6461
|
+
cond: {
|
|
6462
|
+
kind: "unionIsTag",
|
|
6463
|
+
unionId: f.type.unionId,
|
|
6464
|
+
tag: utag,
|
|
6465
|
+
negated: true,
|
|
6466
|
+
value: { kind: "recordGet", obj: ref, shapeId: argIr.shapeId, field: f.name, type: f.type, loc },
|
|
6467
|
+
type: BOOL,
|
|
6468
|
+
loc,
|
|
6469
|
+
},
|
|
6470
|
+
then: [pushStmt],
|
|
6471
|
+
else_: null,
|
|
6472
|
+
loc,
|
|
6473
|
+
}
|
|
6474
|
+
: pushStmt);
|
|
6475
|
+
}
|
|
6476
|
+
body.push({ kind: "return", value: outRef, loc });
|
|
6477
|
+
fn.body = body;
|
|
6478
|
+
};
|
|
6479
|
+
finalize();
|
|
6480
|
+
L.shapeOrderHelperFinalizers.push(finalize);
|
|
6481
|
+
L.liftedFns.push(fn);
|
|
6464
6482
|
}
|
|
6465
6483
|
return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
|
|
6466
6484
|
}
|
|
@@ -7170,109 +7188,15 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
7170
7188
|
L.badType(call, L.typeOf(call));
|
|
7171
7189
|
valueT = tupleShape.fields.find((f) => f.name === "1").type;
|
|
7172
7190
|
}
|
|
7173
|
-
const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
|
|
7174
7191
|
const key = `obj.${member}:${argIr.shapeId}:${typeKey(resultT)}`;
|
|
7175
7192
|
let helper = L.arrHofHelpers.get(key);
|
|
7176
7193
|
if (!helper) {
|
|
7177
7194
|
helper = `%obj.${member}.${L.arrHofHelpers.size}`;
|
|
7178
7195
|
const recT = argIr;
|
|
7179
7196
|
const ref = { kind: "varRef", localId: "r.0", type: recT, loc };
|
|
7180
|
-
const body = [
|
|
7181
|
-
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
7182
|
-
];
|
|
7183
7197
|
const outRef = { kind: "varRef", localId: "out.0", type: resultT, loc };
|
|
7184
|
-
for (const name of order) {
|
|
7185
|
-
const f = shape.fields.find((x) => x.name === name);
|
|
7186
|
-
const raw = { kind: "recordGet", obj: ref, shapeId: argIr.shapeId, field: f.name, type: f.type, loc };
|
|
7187
|
-
// The pushed element per member; null when the field's value
|
|
7188
|
-
// cannot flow into the result element type.
|
|
7189
|
-
const elemOf = (value, vt) => {
|
|
7190
|
-
if (!valueT)
|
|
7191
|
-
return null;
|
|
7192
|
-
if (typeEquals(vt, valueT))
|
|
7193
|
-
return value;
|
|
7194
|
-
if (valueT.kind === "union" && vt.kind !== "union") {
|
|
7195
|
-
const tag = L.armTag(valueT.unionId, vt);
|
|
7196
|
-
if (tag >= 0) {
|
|
7197
|
-
return { kind: "unionWrap", unionId: valueT.unionId, tag, value, type: valueT, loc };
|
|
7198
|
-
}
|
|
7199
|
-
}
|
|
7200
|
-
return null;
|
|
7201
|
-
};
|
|
7202
|
-
// Undefined-armed fields: the push is guarded by a tag test, and
|
|
7203
|
-
// the pushed value is the narrowed non-undefined arm.
|
|
7204
|
-
let guardUndefTag = null;
|
|
7205
|
-
let value = raw;
|
|
7206
|
-
let vt = f.type;
|
|
7207
|
-
if (f.type.kind === "union") {
|
|
7208
|
-
const undefTag = L.armTag(f.type.unionId, UNDEFINED_T);
|
|
7209
|
-
if (undefTag >= 0) {
|
|
7210
|
-
guardUndefTag = undefTag;
|
|
7211
|
-
const arms = L.unions.get(f.type.unionId)?.arms ?? [];
|
|
7212
|
-
const others = arms.filter((a) => a.kind !== "undefinedT");
|
|
7213
|
-
if (typeEquals(f.type, valueT ?? f.type)) {
|
|
7214
|
-
// The field union IS the result union (single-field shapes):
|
|
7215
|
-
// push the raw box — but then the undefined skip must NOT
|
|
7216
|
-
// narrow. Handled below via vt === valueT.
|
|
7217
|
-
value = raw;
|
|
7218
|
-
vt = f.type;
|
|
7219
|
-
}
|
|
7220
|
-
else if (others.length === 1) {
|
|
7221
|
-
vt = others[0];
|
|
7222
|
-
// A UNIT other arm (`null | undefined` fields — the mixed-
|
|
7223
|
-
// defaults spread idiom; undefined was filtered above, so
|
|
7224
|
-
// the unit is null): units carry no payload, so the guarded
|
|
7225
|
-
// push writes the unit LITERAL — unionNarrow to a unit arm
|
|
7226
|
-
// (and unionWrap of a narrowed unit) is malformed IR; the
|
|
7227
|
-
// literal is the one legal unit spelling.
|
|
7228
|
-
value = isUnitType(vt)
|
|
7229
|
-
? { kind: "unitLit", unit: "null", type: vt, loc }
|
|
7230
|
-
: { kind: "unionNarrow", unionId: f.type.unionId, tag: L.armTag(f.type.unionId, vt), value: raw, type: vt, loc };
|
|
7231
|
-
}
|
|
7232
|
-
else {
|
|
7233
|
-
L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' is a multi-arm union that ` +
|
|
7234
|
-
"cannot re-tag into the result element type — read the fields directly)");
|
|
7235
|
-
}
|
|
7236
|
-
}
|
|
7237
|
-
else if (!typeEquals(f.type, valueT ?? f.type)) {
|
|
7238
|
-
L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' is a union that cannot ` +
|
|
7239
|
-
"re-tag into the result element type — read the fields directly)");
|
|
7240
|
-
}
|
|
7241
|
-
}
|
|
7242
|
-
const coerced = elemOf(value, vt);
|
|
7243
|
-
if (!coerced) {
|
|
7244
|
-
L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' of type '${L.fmt(f.type)}' ` +
|
|
7245
|
-
`cannot flow into the '${L.fmt(valueT)}' result element — read the fields directly)`);
|
|
7246
|
-
}
|
|
7247
|
-
const pushed = member === "values"
|
|
7248
|
-
? coerced
|
|
7249
|
-
: {
|
|
7250
|
-
kind: "recordLit",
|
|
7251
|
-
fields: [
|
|
7252
|
-
{ name: "0", value: { kind: "strLit", value: f.name, type: STRING, loc } },
|
|
7253
|
-
{ name: "1", value: coerced },
|
|
7254
|
-
],
|
|
7255
|
-
type: tupleT,
|
|
7256
|
-
loc,
|
|
7257
|
-
};
|
|
7258
|
-
const pushStmt = {
|
|
7259
|
-
kind: "exprStmt",
|
|
7260
|
-
expr: { kind: "arrIntrinsic", method: "push", receiver: outRef, args: [pushed], type: F64, loc },
|
|
7261
|
-
loc,
|
|
7262
|
-
};
|
|
7263
|
-
body.push(guardUndefTag !== null && f.type.kind === "union"
|
|
7264
|
-
? {
|
|
7265
|
-
kind: "if",
|
|
7266
|
-
cond: { kind: "unionIsTag", unionId: f.type.unionId, tag: guardUndefTag, negated: true, value: raw, type: BOOL, loc },
|
|
7267
|
-
then: [pushStmt],
|
|
7268
|
-
else_: null,
|
|
7269
|
-
loc,
|
|
7270
|
-
}
|
|
7271
|
-
: pushStmt);
|
|
7272
|
-
}
|
|
7273
|
-
body.push({ kind: "return", value: outRef, loc });
|
|
7274
7198
|
L.arrHofHelpers.set(key, helper);
|
|
7275
|
-
|
|
7199
|
+
const fn = {
|
|
7276
7200
|
name: helper,
|
|
7277
7201
|
params: [{ localId: "r.0", name: "r", type: recT }],
|
|
7278
7202
|
returnType: resultT,
|
|
@@ -7280,9 +7204,110 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
7280
7204
|
{ id: "r.0", name: "r", type: recT, mutable: true },
|
|
7281
7205
|
{ id: "out.0", name: "out", type: resultT, mutable: false },
|
|
7282
7206
|
],
|
|
7283
|
-
body,
|
|
7207
|
+
body: [],
|
|
7284
7208
|
loc,
|
|
7285
|
-
}
|
|
7209
|
+
};
|
|
7210
|
+
const finalize = () => {
|
|
7211
|
+
const current = L.shapes.get(argIr.shapeId) ?? shape;
|
|
7212
|
+
const body = [
|
|
7213
|
+
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
7214
|
+
];
|
|
7215
|
+
const order = current.declaredOrder ?? current.fields.map((f) => f.name);
|
|
7216
|
+
for (const name of order) {
|
|
7217
|
+
const f = current.fields.find((x) => x.name === name);
|
|
7218
|
+
const raw = { kind: "recordGet", obj: ref, shapeId: argIr.shapeId, field: f.name, type: f.type, loc };
|
|
7219
|
+
// The pushed element per member; null when the field's value
|
|
7220
|
+
// cannot flow into the result element type.
|
|
7221
|
+
const elemOf = (value, vt) => {
|
|
7222
|
+
if (!valueT)
|
|
7223
|
+
return null;
|
|
7224
|
+
if (typeEquals(vt, valueT))
|
|
7225
|
+
return value;
|
|
7226
|
+
if (valueT.kind === "union" && vt.kind !== "union") {
|
|
7227
|
+
const tag = L.armTag(valueT.unionId, vt);
|
|
7228
|
+
if (tag >= 0) {
|
|
7229
|
+
return { kind: "unionWrap", unionId: valueT.unionId, tag, value, type: valueT, loc };
|
|
7230
|
+
}
|
|
7231
|
+
}
|
|
7232
|
+
return null;
|
|
7233
|
+
};
|
|
7234
|
+
// Undefined-armed fields: the push is guarded by a tag test, and
|
|
7235
|
+
// the pushed value is the narrowed non-undefined arm.
|
|
7236
|
+
let guardUndefTag = null;
|
|
7237
|
+
let value = raw;
|
|
7238
|
+
let vt = f.type;
|
|
7239
|
+
if (f.type.kind === "union") {
|
|
7240
|
+
const undefTag = L.armTag(f.type.unionId, UNDEFINED_T);
|
|
7241
|
+
if (undefTag >= 0) {
|
|
7242
|
+
guardUndefTag = undefTag;
|
|
7243
|
+
const arms = L.unions.get(f.type.unionId)?.arms ?? [];
|
|
7244
|
+
const others = arms.filter((a) => a.kind !== "undefinedT");
|
|
7245
|
+
if (typeEquals(f.type, valueT ?? f.type)) {
|
|
7246
|
+
// The field union IS the result union (single-field shapes):
|
|
7247
|
+
// push the raw box — but then the undefined skip must NOT
|
|
7248
|
+
// narrow. Handled below via vt === valueT.
|
|
7249
|
+
value = raw;
|
|
7250
|
+
vt = f.type;
|
|
7251
|
+
}
|
|
7252
|
+
else if (others.length === 1) {
|
|
7253
|
+
vt = others[0];
|
|
7254
|
+
// A UNIT other arm (`null | undefined` fields — the mixed-
|
|
7255
|
+
// defaults spread idiom; undefined was filtered above, so
|
|
7256
|
+
// the unit is null): units carry no payload, so the guarded
|
|
7257
|
+
// push writes the unit LITERAL — unionNarrow to a unit arm
|
|
7258
|
+
// (and unionWrap of a narrowed unit) is malformed IR; the
|
|
7259
|
+
// literal is the one legal unit spelling.
|
|
7260
|
+
value = isUnitType(vt)
|
|
7261
|
+
? { kind: "unitLit", unit: "null", type: vt, loc }
|
|
7262
|
+
: { kind: "unionNarrow", unionId: f.type.unionId, tag: L.armTag(f.type.unionId, vt), value: raw, type: vt, loc };
|
|
7263
|
+
}
|
|
7264
|
+
else {
|
|
7265
|
+
L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' is a multi-arm union that ` +
|
|
7266
|
+
"cannot re-tag into the result element type — read the fields directly)");
|
|
7267
|
+
}
|
|
7268
|
+
}
|
|
7269
|
+
else if (!typeEquals(f.type, valueT ?? f.type)) {
|
|
7270
|
+
L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' is a union that cannot ` +
|
|
7271
|
+
"re-tag into the result element type — read the fields directly)");
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
const coerced = elemOf(value, vt);
|
|
7275
|
+
if (!coerced) {
|
|
7276
|
+
L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' of type '${L.fmt(f.type)}' ` +
|
|
7277
|
+
`cannot flow into the '${L.fmt(valueT)}' result element — read the fields directly)`);
|
|
7278
|
+
}
|
|
7279
|
+
const pushed = member === "values"
|
|
7280
|
+
? coerced
|
|
7281
|
+
: {
|
|
7282
|
+
kind: "recordLit",
|
|
7283
|
+
fields: [
|
|
7284
|
+
{ name: "0", value: { kind: "strLit", value: f.name, type: STRING, loc } },
|
|
7285
|
+
{ name: "1", value: coerced },
|
|
7286
|
+
],
|
|
7287
|
+
type: tupleT,
|
|
7288
|
+
loc,
|
|
7289
|
+
};
|
|
7290
|
+
const pushStmt = {
|
|
7291
|
+
kind: "exprStmt",
|
|
7292
|
+
expr: { kind: "arrIntrinsic", method: "push", receiver: outRef, args: [pushed], type: F64, loc },
|
|
7293
|
+
loc,
|
|
7294
|
+
};
|
|
7295
|
+
body.push(guardUndefTag !== null && f.type.kind === "union"
|
|
7296
|
+
? {
|
|
7297
|
+
kind: "if",
|
|
7298
|
+
cond: { kind: "unionIsTag", unionId: f.type.unionId, tag: guardUndefTag, negated: true, value: raw, type: BOOL, loc },
|
|
7299
|
+
then: [pushStmt],
|
|
7300
|
+
else_: null,
|
|
7301
|
+
loc,
|
|
7302
|
+
}
|
|
7303
|
+
: pushStmt);
|
|
7304
|
+
}
|
|
7305
|
+
body.push({ kind: "return", value: outRef, loc });
|
|
7306
|
+
fn.body = body;
|
|
7307
|
+
};
|
|
7308
|
+
finalize();
|
|
7309
|
+
L.shapeOrderHelperFinalizers.push(finalize);
|
|
7310
|
+
L.liftedFns.push(fn);
|
|
7286
7311
|
}
|
|
7287
7312
|
return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
|
|
7288
7313
|
}
|