@scriptc/compiler 0.0.36 → 0.1.1

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 (113) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +7 -5
  2. package/ambient/scriptc-overrides.d.ts +0 -7
  3. package/ambient/scriptc.d.ts +1 -1
  4. package/dist/backend/c/exprs.js +69 -45
  5. package/dist/backend/c/exprs.js.map +1 -1
  6. package/dist/backend/c/may-throw.js +3 -0
  7. package/dist/backend/c/may-throw.js.map +1 -1
  8. package/dist/backend/c/stmts.js +18 -0
  9. package/dist/backend/c/stmts.js.map +1 -1
  10. package/dist/backend/c/walkers.js +5 -7
  11. package/dist/backend/c/walkers.js.map +1 -1
  12. package/dist/backend/external-c.d.ts +33 -0
  13. package/dist/backend/external-c.js +51 -0
  14. package/dist/backend/external-c.js.map +1 -0
  15. package/dist/backend/link-plan.d.ts +37 -0
  16. package/dist/backend/link-plan.js +26 -0
  17. package/dist/backend/link-plan.js.map +1 -0
  18. package/dist/backend/linker.d.ts +22 -0
  19. package/dist/backend/linker.js +236 -0
  20. package/dist/backend/linker.js.map +1 -0
  21. package/dist/backend/llvm/dyn.js +7 -0
  22. package/dist/backend/llvm/dyn.js.map +1 -1
  23. package/dist/backend/llvm/emitter.js +34 -7
  24. package/dist/backend/llvm/emitter.js.map +1 -1
  25. package/dist/backend/llvm/expr-containers.js +68 -54
  26. package/dist/backend/llvm/expr-containers.js.map +1 -1
  27. package/dist/backend/llvm/expr-context.d.ts +1 -1
  28. package/dist/backend/llvm/expr-dispatch.js +2 -0
  29. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  30. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  31. package/dist/backend/llvm/expr-primitives.js +20 -0
  32. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  33. package/dist/backend/llvm/expr-stream-bridges.js +25 -1
  34. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  35. package/dist/backend/llvm/walkers.js +31 -4
  36. package/dist/backend/llvm/walkers.js.map +1 -1
  37. package/dist/backend/native-codegen.d.ts +8 -1
  38. package/dist/backend/native-codegen.js +39 -25
  39. package/dist/backend/native-codegen.js.map +1 -1
  40. package/dist/backend/native-codegen.test.js +42 -4
  41. package/dist/backend/native-codegen.test.js.map +1 -1
  42. package/dist/backend/native-link-info.d.ts +1 -1
  43. package/dist/backend/native-link-info.js +42 -18
  44. package/dist/backend/native-link-info.js.map +1 -1
  45. package/dist/backend/native-toolchain.test.js +5 -1
  46. package/dist/backend/native-toolchain.test.js.map +1 -1
  47. package/dist/backend/runtime-pack-targets.test.d.ts +1 -0
  48. package/dist/backend/runtime-pack-targets.test.js +54 -0
  49. package/dist/backend/runtime-pack-targets.test.js.map +1 -0
  50. package/dist/backend/runtime-pack.d.ts +5 -30
  51. package/dist/backend/runtime-pack.js +46 -141
  52. package/dist/backend/runtime-pack.js.map +1 -1
  53. package/dist/backend/runtime-pack.test.js +49 -14
  54. package/dist/backend/runtime-pack.test.js.map +1 -1
  55. package/dist/backend/targets.d.ts +63 -17
  56. package/dist/backend/targets.js +251 -35
  57. package/dist/backend/targets.js.map +1 -1
  58. package/dist/backend/targets.test.js +27 -5
  59. package/dist/backend/targets.test.js.map +1 -1
  60. package/dist/coverage/surface-manifest.js +10 -1
  61. package/dist/coverage/surface-manifest.js.map +1 -1
  62. package/dist/frontend/lowering/array-values.d.ts +8 -0
  63. package/dist/frontend/lowering/array-values.js +60 -0
  64. package/dist/frontend/lowering/array-values.js.map +1 -0
  65. package/dist/frontend/lowering/lower-array-sort.d.ts +22 -0
  66. package/dist/frontend/lowering/lower-array-sort.js +619 -0
  67. package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
  68. package/dist/frontend/lowering/lower-builtins.js +164 -4
  69. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  70. package/dist/frontend/lowering/lower-calls.d.ts +3 -4
  71. package/dist/frontend/lowering/lower-calls.js +260 -27
  72. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  73. package/dist/frontend/lowering/lower-containers.js +728 -655
  74. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  75. package/dist/frontend/lowering/lower-exprs.d.ts +4 -0
  76. package/dist/frontend/lowering/lower-exprs.js +769 -101
  77. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  78. package/dist/frontend/lowering/lower-inspect.js +47 -33
  79. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  80. package/dist/frontend/lowering/lower-island.d.ts +5 -4
  81. package/dist/frontend/lowering/lower-island.js +10 -5
  82. package/dist/frontend/lowering/lower-island.js.map +1 -1
  83. package/dist/frontend/lowering/lower-server.js +10 -0
  84. package/dist/frontend/lowering/lower-server.js.map +1 -1
  85. package/dist/frontend/lowering/lower-stmts.js +302 -71
  86. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  87. package/dist/frontend/lowering/lowerer.d.ts +74 -2
  88. package/dist/frontend/lowering/lowerer.js +1087 -10
  89. package/dist/frontend/lowering/lowerer.js.map +1 -1
  90. package/dist/frontend/lowering/surfaces.d.ts +10 -2
  91. package/dist/frontend/lowering/surfaces.js +15 -3
  92. package/dist/frontend/lowering/surfaces.js.map +1 -1
  93. package/dist/index.d.ts +3 -3
  94. package/dist/index.js +45 -23
  95. package/dist/index.js.map +1 -1
  96. package/dist/ir/ir.d.ts +65 -11
  97. package/dist/ir/ir.js +25 -25
  98. package/dist/ir/ir.js.map +1 -1
  99. package/dist/ir/serialize.d.ts +1 -1
  100. package/dist/ir/serialize.js +1 -1
  101. package/dist/ir/validate.js +84 -37
  102. package/dist/ir/validate.js.map +1 -1
  103. package/dist/library/fence-eval.js +3 -1
  104. package/dist/library/fence-eval.js.map +1 -1
  105. package/dist/library/int-infer.js +12 -1
  106. package/dist/library/int-infer.js.map +1 -1
  107. package/dist/library/int-infer.test.js +4 -4
  108. package/dist/library/library-cache.test.js +5 -5
  109. package/dist/startup-cache.d.ts +9 -1
  110. package/dist/startup-cache.js +16 -1
  111. package/dist/startup-cache.js.map +1 -1
  112. package/package.json +17 -4
  113. package/surface-manifest.json +5 -5
@@ -921,15 +921,17 @@ declare module "module" {
921
921
  export * from "node:module";
922
922
  }
923
923
  /* import.meta: module-loader metadata with no value representation —
924
- * every read fences (SC1090) EXCEPT as createRequire's base, where it
925
- * only NAMES the containing file (import.meta.url, import.meta.filename,
926
- * and __filename all mean "this file" there). Declared so the pattern
927
- * typechecks under the fallback surface; @types/node's own augmentation
928
- * stands in when adopted. */
924
+ * direct file-backed fields lower to constants, while the object and
925
+ * remaining members fence (SC1090) EXCEPT as createRequire's base, where it
926
+ * only NAMES the containing file. Declared so unsupported forms reach their
927
+ * named lowering fences; @types/node's own augmentation stands in when
928
+ * adopted. */
929
929
  interface ImportMeta {
930
930
  url: string;
931
931
  filename: string;
932
932
  dirname: string;
933
+ main: boolean;
934
+ resolve(specifier: string, parent?: string | URL): string;
933
935
  }
934
936
 
935
937
  /* The synchronous node:fs surface — utf8-only, no options objects, no
@@ -13,13 +13,6 @@
13
13
  * primitives every world needs (comptime, setTimeout, __island_eval) live
14
14
  * in scriptc.d.ts, which ships to BOTH programs. */
15
15
 
16
- /* `pop(): T`, not the lib's `T | undefined`: popping an empty array traps
17
- * at runtime — a documented divergence (SEMANTICS.md) this override keeps
18
- * typecheckable. Check `.length` first, as real code must. */
19
- interface Array<T> {
20
- pop(): T;
21
- }
22
-
23
16
  /* `at(): string`, not the lib's `string | undefined`: undefined is
24
17
  * unrepresentable, so an out-of-range at() THROWS a catchable TypeError at
25
18
  * the validated island exit instead of returning undefined (documented
@@ -15,7 +15,7 @@
15
15
  * This file ships to EVERY program scriptc builds — the lowering program
16
16
  * and preflight's project-world second-chance program alike (a project
17
17
  * using comptime must typecheck in both). The divergence/precision
18
- * overrides (JSON.parse(): unknown, pop(): T, the Promise executor shape,
18
+ * overrides (JSON.parse(): unknown, the Promise executor shape,
19
19
  * ...) live in scriptc-overrides.d.ts, which joins the LOWERING program only.
20
20
  *
21
21
  * console, process, and the "node:fs" module live in scriptc-node-fallback.d.ts,
@@ -17,7 +17,7 @@ function streamTypedRefCommitAdapter(emitter, t, snapshot, defs) {
17
17
  if (t.kind === "array") {
18
18
  const commit = `${snapshot}_commit`;
19
19
  emitter.walkerProtos.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d); /* commit live stream element ${typeKey(t)} */`);
20
- defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ScrArr *sc_target = (ScrArr *)sc_p;`, ` ScrArr *sc_next = ${emitter.dynCheckHelper(t)}(sc_d, NULL);`, ` if (!sc_next) return;`, ` size_t sc_target_len = sc_target->len;`, ` size_t sc_target_cap = sc_target->cap;`, ` uint64_t *sc_target_data = sc_target->data;`, ` 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);`, `}`, ``);
20
+ defs.push(`static void ${commit}(void *sc_p, const ScrDyn *sc_d) {`, ` ScrArr *sc_target = (ScrArr *)sc_p;`, ` ScrArr *sc_next = ${emitter.dynCheckHelper(t)}(sc_d, NULL);`, ` if (!sc_next) return;`, ` size_t sc_target_len = sc_target->len;`, ` size_t sc_target_cap = sc_target->cap;`, ` uint64_t *sc_target_data = sc_target->data;`, ` uint8_t *sc_target_present = sc_target->present;`, ` ScrArrSparseSlot *sc_target_sparse = sc_target->sparse;`, ` size_t sc_target_sparse_len = sc_target->sparse_len;`, ` size_t sc_target_sparse_cap = sc_target->sparse_cap;`, ` ScrArrProp *sc_target_props = sc_target->props;`, ` size_t sc_target_prop_len = sc_target->prop_len;`, ` size_t sc_target_prop_cap = sc_target->prop_cap;`, ` sc_target->len = sc_next->len;`, ` sc_target->cap = sc_next->cap;`, ` sc_target->data = sc_next->data;`, ` sc_target->present = sc_next->present;`, ` sc_target->sparse = sc_next->sparse;`, ` sc_target->sparse_len = sc_next->sparse_len;`, ` sc_target->sparse_cap = sc_next->sparse_cap;`, ` sc_target->props = sc_next->props;`, ` sc_target->prop_len = sc_next->prop_len;`, ` sc_target->prop_cap = sc_next->prop_cap;`, ` sc_next->len = sc_target_len;`, ` sc_next->cap = sc_target_cap;`, ` sc_next->data = sc_target_data;`, ` sc_next->present = sc_target_present;`, ` sc_next->sparse = sc_target_sparse;`, ` sc_next->sparse_len = sc_target_sparse_len;`, ` sc_next->sparse_cap = sc_target_sparse_cap;`, ` sc_next->props = sc_target_props;`, ` sc_next->prop_len = sc_target_prop_len;`, ` sc_next->prop_cap = sc_target_prop_cap;`, ` scr_arr_release(sc_next);`, `}`, ``);
21
21
  return `&${commit}`;
22
22
  }
23
23
  if (t.kind !== "record")
@@ -1284,12 +1284,7 @@ function emitContainerExpr(emitter, e) {
1284
1284
  e.elems.forEach((el, i) => {
1285
1285
  const v = emitter.emitExpr(el);
1286
1286
  if (spreadSet.has(i)) {
1287
- const n = `sc_i${emitter.tempCounter++}`;
1288
- emitter.line(`for (size_t ${n} = 0, ${n}_len = (size_t)scr_arr_len(${v.name}); ${n} < ${n}_len; ${n}++) {`);
1289
- emitter.indent++;
1290
- emitter.line(`scr_arr_push_${acc}(${arr.name}, scr_arr_get_${acc}(${v.name}, (double)${n}));`);
1291
- emitter.indent--;
1292
- emitter.line(`}`);
1287
+ emitter.line(`scr_arr_push_spread(${arr.name}, ${v.name});`);
1293
1288
  return;
1294
1289
  }
1295
1290
  if (acc === "ref")
@@ -1335,6 +1330,20 @@ function emitContainerExpr(emitter, e) {
1335
1330
  const acc = elemAccess(e.arr.type.elem);
1336
1331
  return emitter.newTemp(e.type, `scr_arr_get_${acc}(${arr.name}, ${idx.name})`);
1337
1332
  }
1333
+ case "arrayHas": {
1334
+ const arr = emitter.emitExpr(e.arr);
1335
+ const idx = emitter.emitExpr(e.index);
1336
+ if (e.arr.type.kind !== "array")
1337
+ throw new InternalCompilerError("emitter bug: arrayHas on non-array");
1338
+ return emitter.newTemp(e.type, `scr_arr_has(${arr.name}, ${idx.name})`);
1339
+ }
1340
+ case "arrayState": {
1341
+ const arr = emitter.emitExpr(e.arr);
1342
+ const idx = emitter.emitExpr(e.index);
1343
+ if (e.arr.type.kind !== "array")
1344
+ throw new InternalCompilerError("emitter bug: arrayState on non-array");
1345
+ return emitter.newTemp(e.type, `scr_arr_state(${arr.name}, ${idx.name})`);
1346
+ }
1338
1347
  case "arrIntrinsic": {
1339
1348
  const r = emitter.emitExpr(e.receiver);
1340
1349
  if (e.receiver.type.kind !== "array")
@@ -1344,6 +1353,10 @@ function emitContainerExpr(emitter, e) {
1344
1353
  switch (method) {
1345
1354
  case "length":
1346
1355
  return emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1356
+ case "nextPresent": {
1357
+ const start = emitter.emitExpr(e.args[0]);
1358
+ return emitter.newTemp(e.type, `scr_arr_next_present(${r.name}, ${start.name})`);
1359
+ }
1347
1360
  case "push": {
1348
1361
  // Variadic like JS: every argument evaluates first (left to
1349
1362
  // right — an argument reading the array sees the pre-push
@@ -1363,18 +1376,15 @@ function emitContainerExpr(emitter, e) {
1363
1376
  : emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1364
1377
  }
1365
1378
  case "pushSpread": {
1366
- // `a.push(...src)`: append src's elements in order. The source
1367
- // is BORROWED; the count snapshots before the loop so
1368
- // `a.push(...a)` duplicates exactly like JS. _get_ref's +1
1369
- // moves into _push_ref — RC-balanced. Result: the new length.
1379
+ // `a.push(...src)`: append src's indexed state in order while
1380
+ // preserving holes; the runtime snapshots self-spread and
1381
+ // retains copied refs. Result: the new length.
1370
1382
  const src = emitter.emitExpr(e.args[0]);
1371
- const n = `sc_i${emitter.tempCounter++}`;
1372
- emitter.line(`for (size_t ${n} = 0, ${n}_len = (size_t)scr_arr_len(${src.name}); ${n} < ${n}_len; ${n}++) {`);
1373
- emitter.indent++;
1374
- emitter.line(`scr_arr_push_${acc}(${r.name}, scr_arr_get_${acc}(${src.name}, (double)${n}));`);
1375
- emitter.indent--;
1376
- emitter.line(`}`);
1377
- return emitter.newTemp(e.type, `scr_arr_len(${r.name})`);
1383
+ return emitter.newTemp(e.type, `scr_arr_push_spread(${r.name}, ${src.name})`);
1384
+ }
1385
+ case "concatSpread": {
1386
+ const src = emitter.emitExpr(e.args[0]);
1387
+ return emitter.newTemp(e.type, `scr_arr_concat_copy(${r.name}, ${src.name})`);
1378
1388
  }
1379
1389
  case "unshift": {
1380
1390
  // Like push, every argument evaluates before mutation. Apply
@@ -1396,9 +1406,39 @@ function emitContainerExpr(emitter, e) {
1396
1406
  return emitter.newTemp(e.type, `scr_arr_unshift_spread(${r.name}, ${src.name})`);
1397
1407
  }
1398
1408
  case "pop":
1399
- // Ownership of a refcounted element moves OUT of the array to
1400
- // this temp (+1 to us, the runtime does not release it).
1401
- return emitter.newTemp(e.type, `scr_arr_pop_${acc}(${r.name})`);
1409
+ case "shift": {
1410
+ // Move the slot once, preserving undefined and holes as values
1411
+ // while still applying the method's length/index mutation.
1412
+ if (e.type.kind !== "union")
1413
+ throw new InternalCompilerError("emitter bug: array removal result is not a union");
1414
+ const elemT = e.receiver.type.elem;
1415
+ const def = emitter.unionsById.get(e.type.unionId);
1416
+ const tag = def ? def.arms.findIndex((arm) => typeEquals(arm, elemT)) : -1;
1417
+ const undefTag = undefinedArmTag(e.type, emitter.unionsById);
1418
+ const sameUnion = elemT.kind === "union" && typeEquals(elemT, e.type);
1419
+ if ((!sameUnion && tag < 0) || undefTag < 0)
1420
+ throw new InternalCompilerError("emitter bug: array removal union lacks its arms");
1421
+ const state = `sc_remove_state${emitter.tempCounter++}`;
1422
+ const slot = `sc_remove_slot${emitter.tempCounter++}`;
1423
+ emitter.line(`uint64_t ${slot} = 0;`);
1424
+ emitter.line(`uint8_t ${state} = scr_arr_${method}_state(${r.name}, &${slot});`);
1425
+ let present;
1426
+ if (elemT.kind === "f64") {
1427
+ const number = `sc_remove_number${emitter.tempCounter++}`;
1428
+ emitter.line(`double ${number}; memcpy(&${number}, &${slot}, sizeof ${number});`);
1429
+ present = `scr_union_new_f64(${tag}, ${number})`;
1430
+ }
1431
+ else if (elemT.kind === "bool") {
1432
+ present = `scr_union_new_bool(${tag}, ${slot} != 0)`;
1433
+ }
1434
+ else {
1435
+ const ref = `sc_remove_ref${emitter.tempCounter++}`;
1436
+ emitter.line(`void *${ref}; memcpy(&${ref}, &${slot}, sizeof ${ref});`);
1437
+ const rc = vAdapters(elemT);
1438
+ present = sameUnion ? `(ScrUnion *)${ref}` : `scr_union_new_ref(${tag}, ${ref}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(elemT)})`;
1439
+ }
1440
+ return emitter.newTemp(e.type, `${state} == SCR_ARR_VALUE ? ${present} : ${emitter.unitInstanceRef(e.type.unionId, undefTag)}`);
1441
+ }
1402
1442
  case "indexOf": {
1403
1443
  // The needle is BORROWED (released with this statement's frame);
1404
1444
  // the ref variant dispatches on the array's element kind
@@ -1448,6 +1488,12 @@ function emitContainerExpr(emitter, e) {
1448
1488
  emitter.emitPendingCheck();
1449
1489
  return out;
1450
1490
  }
1491
+ case "withUndefined": {
1492
+ const index = emitter.emitExpr(e.args[0]);
1493
+ const out = emitter.newTemp(e.type, `scr_arr_with_undefined(${r.name}, ${index.name})`);
1494
+ emitter.emitPendingCheck();
1495
+ return out;
1496
+ }
1451
1497
  case "splice": {
1452
1498
  // The removal splice: the removed elements come back as a
1453
1499
  // fresh +1 array, their ownership MOVED out of the receiver
@@ -1457,30 +1503,6 @@ function emitContainerExpr(emitter, e) {
1457
1503
  const cnt = e.args[1] ? emitter.emitExpr(e.args[1]).name : "INFINITY";
1458
1504
  return emitter.newTemp(e.type, `scr_arr_splice(${r.name}, ${start.name}, ${cnt})`);
1459
1505
  }
1460
- case "shift": {
1461
- // JS shift: undefined on an empty array, else the first
1462
- // element out (ref ownership moves into the union box) with
1463
- // the tail sliding down. Union construction is type-directed
1464
- // here, the envGet convention.
1465
- if (e.type.kind !== "union")
1466
- throw new InternalCompilerError("emitter bug: shift result is not a union");
1467
- const elemT = e.receiver.type.elem;
1468
- const def = emitter.unionsById.get(e.type.unionId);
1469
- const tag = def ? def.arms.findIndex((a) => typeEquals(a, elemT)) : -1;
1470
- const undefTag = undefinedArmTag(e.type, emitter.unionsById);
1471
- if (tag < 0 || undefTag < 0)
1472
- throw new InternalCompilerError("emitter bug: shift union lacks its arms");
1473
- const absent = emitter.unitInstanceRef(e.type.unionId, undefTag);
1474
- const present = elemT.kind === "f64"
1475
- ? `scr_union_new_f64(${tag}, scr_arr_shift_f64(${r.name}))`
1476
- : elemT.kind === "bool"
1477
- ? `scr_union_new_bool(${tag}, scr_arr_shift_bool(${r.name}))`
1478
- : (() => {
1479
- const rc = vAdapters(elemT);
1480
- return `scr_union_new_ref(${tag}, scr_arr_shift_ref(${r.name}), &${rc.retain}, &${rc.release}, ${emitter.traceArgC(elemT)})`;
1481
- })();
1482
- return emitter.newTemp(e.type, `scr_arr_len(${r.name}) ? ${present} : ${absent}`);
1483
- }
1484
1506
  default: {
1485
1507
  const _exhaustive = method;
1486
1508
  void _exhaustive;
@@ -7832,6 +7854,8 @@ export function emitExpr(emitter, e) {
7832
7854
  case "arrayLit":
7833
7855
  case "arrayNewLen":
7834
7856
  case "arrayGet":
7857
+ case "arrayHas":
7858
+ case "arrayState":
7835
7859
  case "arrIntrinsic":
7836
7860
  case "bytesNew":
7837
7861
  case "bytesIntrinsic":