@scriptc/compiler 0.0.33 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/backend/cc-cache.test.js +122 -0
  2. package/dist/backend/cc-cache.test.js.map +1 -1
  3. package/dist/backend/cc.d.ts +19 -0
  4. package/dist/backend/cc.js +111 -20
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/emission/emit-exprs.js +26 -1
  7. package/dist/backend/emission/emit-exprs.js.map +1 -1
  8. package/dist/backend/emission/emit-shapes.js +37 -4
  9. package/dist/backend/emission/emit-shapes.js.map +1 -1
  10. package/dist/backend/emission/emitter.d.ts +11 -2
  11. package/dist/backend/emission/emitter.js +11 -5
  12. package/dist/backend/emission/emitter.js.map +1 -1
  13. package/dist/backend/library-identity.d.ts +22 -0
  14. package/dist/backend/library-identity.js +103 -0
  15. package/dist/backend/library-identity.js.map +1 -0
  16. package/dist/backend/llvm/emitter.d.ts +3 -0
  17. package/dist/backend/llvm/emitter.js +35 -5
  18. package/dist/backend/llvm/emitter.js.map +1 -1
  19. package/dist/backend/llvm/shapes.d.ts +1 -0
  20. package/dist/backend/llvm/shapes.js +25 -1
  21. package/dist/backend/llvm/shapes.js.map +1 -1
  22. package/dist/backend/mangle.d.ts +1 -0
  23. package/dist/backend/mangle.js +3 -0
  24. package/dist/backend/mangle.js.map +1 -1
  25. package/dist/backend/object-localize.d.ts +5 -5
  26. package/dist/backend/object-localize.js +19 -16
  27. package/dist/backend/object-localize.js.map +1 -1
  28. package/dist/backend/object-localize.test.js +37 -13
  29. package/dist/backend/object-localize.test.js.map +1 -1
  30. package/dist/frontend/input-tracker.d.ts +82 -0
  31. package/dist/frontend/input-tracker.js +380 -0
  32. package/dist/frontend/input-tracker.js.map +1 -0
  33. package/dist/frontend/input-tracker.test.d.ts +1 -0
  34. package/dist/frontend/input-tracker.test.js +137 -0
  35. package/dist/frontend/input-tracker.test.js.map +1 -0
  36. package/dist/frontend/lowering/lower-builtins.js +2 -8
  37. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  38. package/dist/frontend/lowering/lower-calls.js +155 -140
  39. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  40. package/dist/frontend/lowering/lower-classes.js +3 -0
  41. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  42. package/dist/frontend/lowering/lower-containers.js +48 -9
  43. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  44. package/dist/frontend/lowering/lower-exprs.js +67 -1
  45. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  46. package/dist/frontend/lowering/lower-inspect.js +45 -26
  47. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  48. package/dist/frontend/lowering/lower-modules.js +1 -1
  49. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  50. package/dist/frontend/lowering/lower-stmts.js +48 -3
  51. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  52. package/dist/frontend/lowering/lowerer.d.ts +67 -29
  53. package/dist/frontend/lowering/lowerer.js +410 -87
  54. package/dist/frontend/lowering/lowerer.js.map +1 -1
  55. package/dist/frontend/npm-static-rewrite.js +25 -26
  56. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  57. package/dist/frontend/npm-static.js +29 -30
  58. package/dist/frontend/npm-static.js.map +1 -1
  59. package/dist/frontend/npm-static.test.d.ts +1 -0
  60. package/dist/frontend/npm-static.test.js +15 -0
  61. package/dist/frontend/npm-static.test.js.map +1 -0
  62. package/dist/frontend/npm.js +5 -17
  63. package/dist/frontend/npm.js.map +1 -1
  64. package/dist/frontend/program.js +2 -6
  65. package/dist/frontend/program.js.map +1 -1
  66. package/dist/frontend/resolve.js +8 -29
  67. package/dist/frontend/resolve.js.map +1 -1
  68. package/dist/frontend/ts7/program.js +17 -18
  69. package/dist/frontend/ts7/program.js.map +1 -1
  70. package/dist/frontend/types.d.ts +33 -0
  71. package/dist/frontend/types.js +114 -3
  72. package/dist/frontend/types.js.map +1 -1
  73. package/dist/index.d.ts +1 -1
  74. package/dist/index.js +241 -42
  75. package/dist/index.js.map +1 -1
  76. package/dist/ir/nodes.d.ts +21 -4
  77. package/dist/ir/nodes.js.map +1 -1
  78. package/dist/ir/serialize.d.ts +1 -1
  79. package/dist/ir/serialize.js +1 -1
  80. package/dist/ir/validate.js +31 -1
  81. package/dist/ir/validate.js.map +1 -1
  82. package/dist/library/early-cache.d.ts +65 -0
  83. package/dist/library/early-cache.js +380 -0
  84. package/dist/library/early-cache.js.map +1 -0
  85. package/dist/library/early-cache.test.d.ts +1 -0
  86. package/dist/library/early-cache.test.js +528 -0
  87. package/dist/library/early-cache.test.js.map +1 -0
  88. package/dist/library/int-infer.js +14 -0
  89. package/dist/library/int-infer.js.map +1 -1
  90. package/dist/library/int-infer.test.js +21 -4
  91. package/dist/library/int-infer.test.js.map +1 -1
  92. package/dist/library/semantic-source.d.ts +13 -0
  93. package/dist/library/semantic-source.js +257 -0
  94. package/dist/library/semantic-source.js.map +1 -0
  95. package/dist/library/semantic-source.test.d.ts +1 -0
  96. package/dist/library/semantic-source.test.js +113 -0
  97. package/dist/library/semantic-source.test.js.map +1 -0
  98. package/dist/library/sidecar.d.ts +6 -0
  99. package/dist/library/sidecar.js +11 -0
  100. package/dist/library/sidecar.js.map +1 -1
  101. package/package.json +2 -2
  102. package/surface-manifest.json +1 -1
@@ -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
@@ -6409,48 +6410,8 @@ export function recordKeysArrayCall(L, receiver, argIr, shape, loc) {
6409
6410
  helper = `%obj.keys.${L.arrHofHelpers.size}`;
6410
6411
  const ref = { kind: "varRef", localId: "r.0", type: argIr, loc };
6411
6412
  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
6413
  L.arrHofHelpers.set(key, helper);
6453
- L.liftedFns.push({
6414
+ const fn = {
6454
6415
  name: helper,
6455
6416
  params: [{ localId: "r.0", name: "r", type: argIr }],
6456
6417
  returnType: resultT,
@@ -6458,9 +6419,56 @@ export function recordKeysArrayCall(L, receiver, argIr, shape, loc) {
6458
6419
  { id: "r.0", name: "r", type: argIr, mutable: true },
6459
6420
  { id: "out.0", name: "out", type: resultT, mutable: false },
6460
6421
  ],
6461
- body,
6422
+ body: [],
6462
6423
  loc,
6463
- });
6424
+ };
6425
+ const finalize = () => {
6426
+ const current = L.shapes.get(argIr.shapeId) ?? shape;
6427
+ const body = [
6428
+ { kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
6429
+ ];
6430
+ const order = current.declaredOrder ?? current.fields.map((f) => f.name);
6431
+ for (const name of order) {
6432
+ const f = current.fields.find((x) => x.name === name);
6433
+ const pushStmt = {
6434
+ kind: "exprStmt",
6435
+ expr: {
6436
+ kind: "arrIntrinsic",
6437
+ method: "push",
6438
+ receiver: outRef,
6439
+ args: [{ kind: "strLit", value: f.name, type: STRING, loc }],
6440
+ type: F64,
6441
+ loc,
6442
+ },
6443
+ loc,
6444
+ };
6445
+ // Undefined-armed fields: the push is guarded by a tag test (the
6446
+ // key exists exactly when Object.keys would list it).
6447
+ const utag = f.type.kind === "union" ? L.armTag(f.type.unionId, UNDEFINED_T) : -1;
6448
+ body.push(utag >= 0 && f.type.kind === "union"
6449
+ ? {
6450
+ kind: "if",
6451
+ cond: {
6452
+ kind: "unionIsTag",
6453
+ unionId: f.type.unionId,
6454
+ tag: utag,
6455
+ negated: true,
6456
+ value: { kind: "recordGet", obj: ref, shapeId: argIr.shapeId, field: f.name, type: f.type, loc },
6457
+ type: BOOL,
6458
+ loc,
6459
+ },
6460
+ then: [pushStmt],
6461
+ else_: null,
6462
+ loc,
6463
+ }
6464
+ : pushStmt);
6465
+ }
6466
+ body.push({ kind: "return", value: outRef, loc });
6467
+ fn.body = body;
6468
+ };
6469
+ finalize();
6470
+ L.shapeOrderHelperFinalizers.push(finalize);
6471
+ L.liftedFns.push(fn);
6464
6472
  }
6465
6473
  return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
6466
6474
  }
@@ -7170,109 +7178,15 @@ function lowerObjectStaticCall(L, call, access) {
7170
7178
  L.badType(call, L.typeOf(call));
7171
7179
  valueT = tupleShape.fields.find((f) => f.name === "1").type;
7172
7180
  }
7173
- const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
7174
7181
  const key = `obj.${member}:${argIr.shapeId}:${typeKey(resultT)}`;
7175
7182
  let helper = L.arrHofHelpers.get(key);
7176
7183
  if (!helper) {
7177
7184
  helper = `%obj.${member}.${L.arrHofHelpers.size}`;
7178
7185
  const recT = argIr;
7179
7186
  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
7187
  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
7188
  L.arrHofHelpers.set(key, helper);
7275
- L.liftedFns.push({
7189
+ const fn = {
7276
7190
  name: helper,
7277
7191
  params: [{ localId: "r.0", name: "r", type: recT }],
7278
7192
  returnType: resultT,
@@ -7280,9 +7194,110 @@ function lowerObjectStaticCall(L, call, access) {
7280
7194
  { id: "r.0", name: "r", type: recT, mutable: true },
7281
7195
  { id: "out.0", name: "out", type: resultT, mutable: false },
7282
7196
  ],
7283
- body,
7197
+ body: [],
7284
7198
  loc,
7285
- });
7199
+ };
7200
+ const finalize = () => {
7201
+ const current = L.shapes.get(argIr.shapeId) ?? shape;
7202
+ const body = [
7203
+ { kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
7204
+ ];
7205
+ const order = current.declaredOrder ?? current.fields.map((f) => f.name);
7206
+ for (const name of order) {
7207
+ const f = current.fields.find((x) => x.name === name);
7208
+ const raw = { kind: "recordGet", obj: ref, shapeId: argIr.shapeId, field: f.name, type: f.type, loc };
7209
+ // The pushed element per member; null when the field's value
7210
+ // cannot flow into the result element type.
7211
+ const elemOf = (value, vt) => {
7212
+ if (!valueT)
7213
+ return null;
7214
+ if (typeEquals(vt, valueT))
7215
+ return value;
7216
+ if (valueT.kind === "union" && vt.kind !== "union") {
7217
+ const tag = L.armTag(valueT.unionId, vt);
7218
+ if (tag >= 0) {
7219
+ return { kind: "unionWrap", unionId: valueT.unionId, tag, value, type: valueT, loc };
7220
+ }
7221
+ }
7222
+ return null;
7223
+ };
7224
+ // Undefined-armed fields: the push is guarded by a tag test, and
7225
+ // the pushed value is the narrowed non-undefined arm.
7226
+ let guardUndefTag = null;
7227
+ let value = raw;
7228
+ let vt = f.type;
7229
+ if (f.type.kind === "union") {
7230
+ const undefTag = L.armTag(f.type.unionId, UNDEFINED_T);
7231
+ if (undefTag >= 0) {
7232
+ guardUndefTag = undefTag;
7233
+ const arms = L.unions.get(f.type.unionId)?.arms ?? [];
7234
+ const others = arms.filter((a) => a.kind !== "undefinedT");
7235
+ if (typeEquals(f.type, valueT ?? f.type)) {
7236
+ // The field union IS the result union (single-field shapes):
7237
+ // push the raw box — but then the undefined skip must NOT
7238
+ // narrow. Handled below via vt === valueT.
7239
+ value = raw;
7240
+ vt = f.type;
7241
+ }
7242
+ else if (others.length === 1) {
7243
+ vt = others[0];
7244
+ // A UNIT other arm (`null | undefined` fields — the mixed-
7245
+ // defaults spread idiom; undefined was filtered above, so
7246
+ // the unit is null): units carry no payload, so the guarded
7247
+ // push writes the unit LITERAL — unionNarrow to a unit arm
7248
+ // (and unionWrap of a narrowed unit) is malformed IR; the
7249
+ // literal is the one legal unit spelling.
7250
+ value = isUnitType(vt)
7251
+ ? { kind: "unitLit", unit: "null", type: vt, loc }
7252
+ : { kind: "unionNarrow", unionId: f.type.unionId, tag: L.armTag(f.type.unionId, vt), value: raw, type: vt, loc };
7253
+ }
7254
+ else {
7255
+ L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' is a multi-arm union that ` +
7256
+ "cannot re-tag into the result element type — read the fields directly)");
7257
+ }
7258
+ }
7259
+ else if (!typeEquals(f.type, valueT ?? f.type)) {
7260
+ L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' is a union that cannot ` +
7261
+ "re-tag into the result element type — read the fields directly)");
7262
+ }
7263
+ }
7264
+ const coerced = elemOf(value, vt);
7265
+ if (!coerced) {
7266
+ L.unsupported("SC1090", call, `Object.${member} over '${L.fmt(argIr)}' (field '${f.name}' of type '${L.fmt(f.type)}' ` +
7267
+ `cannot flow into the '${L.fmt(valueT)}' result element — read the fields directly)`);
7268
+ }
7269
+ const pushed = member === "values"
7270
+ ? coerced
7271
+ : {
7272
+ kind: "recordLit",
7273
+ fields: [
7274
+ { name: "0", value: { kind: "strLit", value: f.name, type: STRING, loc } },
7275
+ { name: "1", value: coerced },
7276
+ ],
7277
+ type: tupleT,
7278
+ loc,
7279
+ };
7280
+ const pushStmt = {
7281
+ kind: "exprStmt",
7282
+ expr: { kind: "arrIntrinsic", method: "push", receiver: outRef, args: [pushed], type: F64, loc },
7283
+ loc,
7284
+ };
7285
+ body.push(guardUndefTag !== null && f.type.kind === "union"
7286
+ ? {
7287
+ kind: "if",
7288
+ cond: { kind: "unionIsTag", unionId: f.type.unionId, tag: guardUndefTag, negated: true, value: raw, type: BOOL, loc },
7289
+ then: [pushStmt],
7290
+ else_: null,
7291
+ loc,
7292
+ }
7293
+ : pushStmt);
7294
+ }
7295
+ body.push({ kind: "return", value: outRef, loc });
7296
+ fn.body = body;
7297
+ };
7298
+ finalize();
7299
+ L.shapeOrderHelperFinalizers.push(finalize);
7300
+ L.liftedFns.push(fn);
7286
7301
  }
7287
7302
  return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
7288
7303
  }