@scriptc/compiler 0.0.6 → 0.0.8

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 (75) hide show
  1. package/dist/backend/emission/emit-exprs.js +47 -1
  2. package/dist/backend/emission/emit-exprs.js.map +1 -1
  3. package/dist/backend/emission/emit-island.js +9 -1
  4. package/dist/backend/emission/emit-island.js.map +1 -1
  5. package/dist/backend/emission/emit-stmts.js +3 -1
  6. package/dist/backend/emission/emit-stmts.js.map +1 -1
  7. package/dist/backend/emission/emit-walkers.js +22 -8
  8. package/dist/backend/emission/emit-walkers.js.map +1 -1
  9. package/dist/backend/emission/emitter.js +12 -1
  10. package/dist/backend/emission/emitter.js.map +1 -1
  11. package/dist/backend/emission/may-throw.js +4 -3
  12. package/dist/backend/emission/may-throw.js.map +1 -1
  13. package/dist/backend/llvm/emitter.js +105 -9
  14. package/dist/backend/llvm/emitter.js.map +1 -1
  15. package/dist/diagnostics/diagnostic.d.ts +49 -1
  16. package/dist/diagnostics/diagnostic.js +119 -5
  17. package/dist/diagnostics/diagnostic.js.map +1 -1
  18. package/dist/frontend/lib-contract.d.ts +114 -0
  19. package/dist/frontend/lib-contract.js +372 -0
  20. package/dist/frontend/lib-contract.js.map +1 -0
  21. package/dist/frontend/lowering/lower-builtins.js +16 -1
  22. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  23. package/dist/frontend/lowering/lower-calls.d.ts +47 -7
  24. package/dist/frontend/lowering/lower-calls.js +560 -36
  25. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  26. package/dist/frontend/lowering/lower-classes.d.ts +14 -1
  27. package/dist/frontend/lowering/lower-classes.js +85 -15
  28. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  29. package/dist/frontend/lowering/lower-containers.js +43 -1
  30. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  31. package/dist/frontend/lowering/lower-emitter.js +1 -1
  32. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  33. package/dist/frontend/lowering/lower-exprs.d.ts +26 -3
  34. package/dist/frontend/lowering/lower-exprs.js +474 -44
  35. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  36. package/dist/frontend/lowering/lower-island.d.ts +7 -0
  37. package/dist/frontend/lowering/lower-island.js +71 -10
  38. package/dist/frontend/lowering/lower-island.js.map +1 -1
  39. package/dist/frontend/lowering/lower-mixins.d.ts +1 -1
  40. package/dist/frontend/lowering/lower-mixins.js +1 -1
  41. package/dist/frontend/lowering/lower-modules.js +95 -4
  42. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  43. package/dist/frontend/lowering/lower-stmts.js +430 -44
  44. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  45. package/dist/frontend/lowering/lowerer.d.ts +19 -3
  46. package/dist/frontend/lowering/lowerer.js +188 -11
  47. package/dist/frontend/lowering/lowerer.js.map +1 -1
  48. package/dist/frontend/types.d.ts +28 -1
  49. package/dist/frontend/types.js +300 -8
  50. package/dist/frontend/types.js.map +1 -1
  51. package/dist/index.d.ts +11 -2
  52. package/dist/index.js +96 -7
  53. package/dist/index.js.map +1 -1
  54. package/dist/ir/nodes.d.ts +48 -2
  55. package/dist/ir/nodes.js +103 -3
  56. package/dist/ir/nodes.js.map +1 -1
  57. package/dist/ir/validate.js +35 -6
  58. package/dist/ir/validate.js.map +1 -1
  59. package/dist/library/profile.d.ts +53 -3
  60. package/dist/library/profile.js +143 -12
  61. package/dist/library/profile.js.map +1 -1
  62. package/dist/library/sidecar-validate.d.ts +4 -0
  63. package/dist/library/sidecar-validate.js +506 -0
  64. package/dist/library/sidecar-validate.js.map +1 -0
  65. package/dist/library/sidecar.d.ts +191 -0
  66. package/dist/library/sidecar.js +687 -0
  67. package/dist/library/sidecar.js.map +1 -0
  68. package/dist/library/trap-teaching.d.ts +11 -0
  69. package/dist/library/trap-teaching.js +49 -0
  70. package/dist/library/trap-teaching.js.map +1 -0
  71. package/dist/library/wyhash.d.ts +12 -0
  72. package/dist/library/wyhash.js +116 -0
  73. package/dist/library/wyhash.js.map +1 -0
  74. package/package.json +2 -2
  75. package/surface-manifest.json +37 -2
@@ -426,8 +426,8 @@ const LIB_FN_SYMS = {
426
426
  "net.sockUnshift": "scr_net_sock_unshift_bytes",
427
427
  "net.sockPipeRes": "scr_http_sock_pipe_res",
428
428
  "net.serverEmitConnection": "scr_net_server_emit_connection",
429
- "net.getAutoSelTimeout": "scr_net_get_auto_sel_timeout",
430
- "net.setAutoSelTimeout": "scr_net_set_auto_sel_timeout",
429
+ "net.getAutoSelTimeout": "scr_net_get_autosel_timeout",
430
+ "net.setAutoSelTimeout": "scr_net_set_autosel_timeout",
431
431
  "http.reqUrl": "scr_http_req_url",
432
432
  "http.reqMethod": "scr_http_req_method",
433
433
  "http.reqSocket": "scr_http_req_socket",
@@ -542,6 +542,8 @@ const LIB_FN_SYMS = {
542
542
  // (option/DataClone/cycle errors), and new RegExp's eager compile
543
543
  // (catchable SyntaxError) — all may-throw generics over the DOM.
544
544
  "dyn.objKeys": "scr_dyn_obj_keys",
545
+ "dyn.hasOwn": "scr_dyn_has_own",
546
+ "dyn.assign": "scr_dyn_assign",
545
547
  "dyn.objValues": "scr_dyn_obj_values",
546
548
  "dyn.objEntries": "scr_dyn_obj_entries",
547
549
  "dyn.structuredClone": "scr_structured_clone",
@@ -1023,7 +1025,7 @@ class LlEmitter {
1023
1025
  this.declare(`declare ptr @scr_library_str_in(ptr, i64)`);
1024
1026
  }
1025
1027
  if (this.mod.lib.exports.some((e) => e.params.includes("bytes"))) {
1026
- this.declare(`declare ptr @scr_library_bytes_in(ptr, i64)`);
1028
+ this.declare(`declare ptr @scr_library_bytes_in(ptr, i64, ptr)`);
1027
1029
  }
1028
1030
  if (this.mod.lib.exports.some((e) => e.returns === "string")) {
1029
1031
  this.declare(`declare void @scr_library_str_out(ptr, ptr, ptr)`);
@@ -1267,6 +1269,15 @@ class LlEmitter {
1267
1269
  return ` store ${ty} ${zero}, ptr @${mangleGlobal(g.id)} ; ${g.name}`;
1268
1270
  });
1269
1271
  out.push(`define void @${lib.initSymbol}() ${FN_ATTRS} {`, `entry:`, ` call void @scr_library_entry(i1 zeroext true) ; init always resets the result arena`, ...globalReleaseLines("ci"), ...zeroStores, ` call void @scr_library_reset()`, ...stamps, ` call void @${mangleFunction(this.mod.entry)}()`, ` call void @scr_library_check_exc()`, ` ret void`, `}`, ``, `define void @${lib.sinkRegisterSymbol}(ptr %fn, ptr %ctx) ${FN_ATTRS} {`, `entry:`, ` call void @scr_library_set_sink(ptr %fn, ptr %ctx)`, ` ret void`, `}`, ``);
1272
+ if (lib.identity !== undefined) {
1273
+ // Profile-declared identity getters (the ask-2 sidecar's boot-time
1274
+ // pairing fence): pure data returns with NO entry prologue — exempt
1275
+ // from the poisoned guard and every runtime touch (ratified), so a
1276
+ // host can read them before init and after a trap. The u64 rides
1277
+ // i64 two's-complement (LLVM integer constants are signed).
1278
+ const buildId = BigInt.asIntN(64, BigInt(`0x${lib.identity.buildId}`)).toString();
1279
+ out.push(`define i64 @${lib.identity.buildIdSymbol}() ${FN_ATTRS} { ; identity getter build_id 0x${lib.identity.buildId}`, `entry:`, ` ret i64 ${buildId}`, `}`, ``, `define i32 @${lib.identity.abiVersionSymbol}() ${FN_ATTRS} { ; identity getter abi_version`, `entry:`, ` ret i32 ${lib.identity.abiVersion}`, `}`, ``);
1280
+ }
1270
1281
  if (lib.resultResetSymbol !== null) {
1271
1282
  out.push(`define void @${lib.resultResetSymbol}() ${FN_ATTRS} {`, `entry:`, ` call void @scr_library_entry(i1 zeroext false)`, ` call void @scr_library_arena_reset()`, ` ret void`, `}`, ``);
1272
1283
  }
@@ -1277,6 +1288,14 @@ class LlEmitter {
1277
1288
  const params = [];
1278
1289
  const body = [` call void @scr_library_entry(i1 zeroext ${autoReset ? "true" : "false"})`];
1279
1290
  const args = [];
1291
+ if (e.inboundBytesTrap !== undefined) {
1292
+ // The bytes-in helper's trap message: the compiler-assembled
1293
+ // structured trap-teaching form (0x01 text 0x1F SC4012 0x1F symbol
1294
+ // [0x1F remediation]) — the same bytes the C emission passes, so
1295
+ // the sink message is emission-invariant by construction.
1296
+ const trapBytes = Buffer.byteLength(e.inboundBytesTrap, "utf8");
1297
+ out.push(`@sc_lib_bytes_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundBytesTrap)}"`, ``);
1298
+ }
1280
1299
  e.params.forEach((cls, i) => {
1281
1300
  switch (cls) {
1282
1301
  case "f64":
@@ -1310,7 +1329,7 @@ class LlEmitter {
1310
1329
  break;
1311
1330
  case "bytes":
1312
1331
  params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
1313
- body.push(` %c${i} = call ptr @scr_library_bytes_in(ptr %a${i}_ptr, i64 %a${i}_len)`);
1332
+ body.push(` %c${i} = call ptr @scr_library_bytes_in(ptr %a${i}_ptr, i64 %a${i}_len, ptr @sc_lib_bytes_trap_${e.symbol})`);
1314
1333
  args.push(`ptr %c${i}`);
1315
1334
  break;
1316
1335
  }
@@ -2549,9 +2568,13 @@ class LlEmitter {
2549
2568
  if (isRefCounted(v.type))
2550
2569
  this.moveTemp(v);
2551
2570
  const shape = this.recordShape(s.shapeId);
2552
- const iv = shape.indexValue;
2571
+ // Signature-free shapes dispatch over their (one-typed) declared
2572
+ // fields and TRAP on a miss (scr_record_key_miss — JS would add
2573
+ // the property, which a monomorphic struct cannot); overflow
2574
+ // shapes keep the map insert tail.
2575
+ const iv = shape.indexValue ?? shape.fields[0]?.type;
2553
2576
  if (!iv)
2554
- throw new Error(`llvm emitter bug: keyed write on non-overflow shape ${s.shapeId}`);
2577
+ throw new Error(`llvm emitter bug: keyed write on field-free non-overflow shape ${s.shapeId}`);
2555
2578
  const vAcc = iv.kind === "f64" ? "f64" : iv.kind === "bool" ? "bool" : "ref";
2556
2579
  if (s.overflowOnly === true) {
2557
2580
  // A LITERAL key naming no declared field: a plain overflow
@@ -2562,7 +2585,7 @@ class LlEmitter {
2562
2585
  }
2563
2586
  const join = B.newLabel("rks.j");
2564
2587
  this.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
2565
- if (iv.kind === "dyn") {
2588
+ if (iv.kind === "dyn" && shape.indexValue) {
2566
2589
  // A dyn-valued shape (the C recordKeySetHelper's dyn arm,
2567
2590
  // inline): declared keys VALIDATE the dyn value against the
2568
2591
  // field's type first (dynCheck — a mismatched write throws the
@@ -2647,6 +2670,19 @@ class LlEmitter {
2647
2670
  B.br(join);
2648
2671
  B.startBlock(ln);
2649
2672
  }
2673
+ if (!shape.indexValue) {
2674
+ // The MISS on a fixed shape: release the moved-in value, throw
2675
+ // the catchable TypeError naming the key (scr_record_key_miss —
2676
+ // JS would add the property, the documented divergence).
2677
+ if (isRefCounted(iv))
2678
+ this.releaseValue(v.name, iv);
2679
+ this.declare(`declare void @scr_record_key_miss(ptr)`);
2680
+ B.line(`call void @scr_record_key_miss(ptr ${key.name})`);
2681
+ B.br(join);
2682
+ B.startBlock(join);
2683
+ this.emitPendingCheck();
2684
+ break;
2685
+ }
2650
2686
  const ovf = this.recordOvfPtr(obj.name, s.shapeId);
2651
2687
  this.mapSet(ovf, "str", vAcc, key.name, v.name);
2652
2688
  B.br(join);
@@ -4042,6 +4078,31 @@ class LlEmitter {
4042
4078
  // TAG against its unit arms as the test. Pass-through shape: the
4043
4079
  // result IS the left box. Narrowed shape: the single non-unit
4044
4080
  // arm's payload extracts (+1 for ref kinds) and the box releases.
4081
+ if (e.left.type.kind === "jsval") {
4082
+ // The island form: engine nullish test, lazy right (jsval).
4083
+ const l = this.emitExpr(e.left);
4084
+ this.moveTemp(l);
4085
+ this.declare(`declare zeroext i1 @scr_jsval_is_nullish(ptr)`);
4086
+ const slot = B.slot();
4087
+ B.entryAllocas.push(`${slot} = alloca ptr`);
4088
+ const isN = B.tmp();
4089
+ B.line(`${isN} = call zeroext i1 @scr_jsval_is_nullish(ptr ${l.name})`);
4090
+ const lu = B.newLabel("nulj.u");
4091
+ const lv = B.newLabel("nulj.v");
4092
+ const lj = B.newLabel("nulj.j");
4093
+ B.condBr(isN, lu, lv);
4094
+ B.startBlock(lu);
4095
+ this.releaseValue(l.name, e.left.type);
4096
+ this.emitBranchInto(slot, e.right);
4097
+ B.br(lj);
4098
+ B.startBlock(lv);
4099
+ B.line(`store ptr ${l.name}, ptr ${slot}`);
4100
+ B.br(lj);
4101
+ B.startBlock(lj);
4102
+ const t = B.tmp();
4103
+ B.line(`${t} = load ptr, ptr ${slot}`);
4104
+ return this.own({ name: t, type: e.type });
4105
+ }
4045
4106
  if (e.left.type.kind !== "union")
4046
4107
  throw new Error("llvm emitter bug: nullish left is not a union");
4047
4108
  const def = this.unionsById.get(e.left.type.unionId);
@@ -5788,8 +5849,12 @@ class LlEmitter {
5788
5849
  ? this.islandAdapter(fn.params.length, fn.ret.kind)
5789
5850
  : this.islandTypedAdapter(fn);
5790
5851
  this.declare(`declare ptr @scr_jsval_from_closure(ptr, i32, ptr)`);
5852
+ // ISLAND-REST closures encode a NEGATIVE arity (the C emitter's
5853
+ // rule): the wrapper hands the trailing slot the engine array of
5854
+ // the surplus arguments.
5855
+ const arity = fn.rest === true && fn.restAbi === "jsval" ? -fn.params.length : fn.params.length;
5791
5856
  const t = B.tmp();
5792
- B.line(`${t} = call ptr @scr_jsval_from_closure(ptr ${v.name}, i32 ${fn.params.length}, ptr @${adapter})`);
5857
+ B.line(`${t} = call ptr @scr_jsval_from_closure(ptr ${v.name}, i32 ${arity}, ptr @${adapter})`);
5793
5858
  return this.own({ name: t, type: e.type });
5794
5859
  }
5795
5860
  default: {
@@ -5988,6 +6053,30 @@ class LlEmitter {
5988
6053
  B.line(`${t} = call ptr @scr_jsval_obj_lit(i32 ${args.length / 2}, ptr ${pack})`);
5989
6054
  return this.own({ name: t, type: e.type });
5990
6055
  }
6056
+ case "tplStrings": {
6057
+ const pack = argPack(args.map((x) => x.name));
6058
+ this.declare(`declare ptr @scr_jsval_tpl_strings(i32, ptr)`);
6059
+ const t = B.tmp();
6060
+ B.line(`${t} = call ptr @scr_jsval_tpl_strings(i32 ${args.length / 2}, ptr ${pack})`);
6061
+ return this.own({ name: t, type: e.type });
6062
+ }
6063
+ case "objSpread": {
6064
+ this.declare(`declare ptr @scr_jsval_obj_spread(ptr, ptr)`);
6065
+ return fallible(() => {
6066
+ const t = B.tmp();
6067
+ B.line(`${t} = call ptr @scr_jsval_obj_spread(ptr ${a(0)}, ptr ${a(1)})`);
6068
+ return t;
6069
+ });
6070
+ }
6071
+ case "defineGetter": {
6072
+ // Getter completion for an island literal (the C emitter's
6073
+ // scr_jsval_define_getter shape): defines key a(1) on obj a(0)
6074
+ // as an engine getter invoking a(2); answers the object (+1).
6075
+ this.declare(`declare ptr @scr_jsval_define_getter(ptr, ptr, ptr)`);
6076
+ const t = B.tmp();
6077
+ B.line(`${t} = call ptr @scr_jsval_define_getter(ptr ${a(0)}, ptr ${a(1)}, ptr ${a(2)})`);
6078
+ return this.own({ name: t, type: e.type });
6079
+ }
5991
6080
  case "arrLit": {
5992
6081
  const pack = argPack(args.map((x) => x.name));
5993
6082
  this.declare(`declare ptr @scr_jsval_arr_lit(i32, ptr)`);
@@ -6297,7 +6386,7 @@ class LlEmitter {
6297
6386
  d.push(` %fnp = getelementptr inbounds %ScrClosure, ptr %c, i64 0, i32 1`, ` %fn = load ptr, ptr %fnp`);
6298
6387
  if (ret.async) {
6299
6388
  // The closure returns a +1 ScrPromise; from_promise takes ownership.
6300
- const tagN = { void: 0, f64: 1, bool: 2, string: 3, jsval: 4, json: 0 }[ret.tag];
6389
+ const tagN = { void: 0, f64: 1, bool: 2, string: 3, jsval: 4, json: 0, dyn: 0 }[ret.tag];
6301
6390
  this.declare(`declare ptr @scr_jsval_from_promise(ptr, i32)`);
6302
6391
  d.push(` %pr = call ptr %fn(${passed.join(", ")})`, ` %prn = icmp eq ptr %pr, null`, ` br i1 %prn, label %pnull, label %pok`, `pnull:`, ` ret ptr null`, `pok:`, ` %pj = call ptr @scr_jsval_from_promise(ptr %pr, i32 ${tagN})`, ` ret ptr %pj`);
6303
6392
  }
@@ -6322,6 +6411,13 @@ class LlEmitter {
6322
6411
  this.declare(`declare void @scr_str_release(ptr)`);
6323
6412
  d.push(` %r = call ptr %fn(${passed.join(", ")})`, ` %rn = icmp eq ptr %r, null`, ` br i1 %rn, label %snull, label %sok`, `snull:`, ` ret ptr null`, `sok:`, ` %j = call ptr @scr_jsval_from_str(ptr %r)`, ` call void @scr_str_release(ptr %r)`, ` ret ptr %j`);
6324
6413
  break;
6414
+ case "dyn":
6415
+ // A checked-dynamic (+1 DOM) result: deep copy into the engine
6416
+ // (the jsMarshal dyn rule); NULL is the throw-path dummy.
6417
+ this.declare(`declare ptr @scr_jsval_from_dyn(ptr)`);
6418
+ this.declare(`declare void @scr_dyn_release(ptr)`);
6419
+ d.push(` %r = call ptr %fn(${passed.join(", ")})`, ` %rn = icmp eq ptr %r, null`, ` br i1 %rn, label %dnull, label %dok`, `dnull:`, ` ret ptr null`, `dok:`, ` %j = call ptr @scr_jsval_from_dyn(ptr %r)`, ` call void @scr_dyn_release(ptr %r)`, ` ret ptr %j`);
6420
+ break;
6325
6421
  case "json": {
6326
6422
  // A JSON-safe composite return: the jsMarshal path — the type-
6327
6423
  // directed serializer, then the engine's JSON parser (deep