@scriptc/compiler 0.0.7 → 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 (68) 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 +5 -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 +94 -7
  14. package/dist/backend/llvm/emitter.js.map +1 -1
  15. package/dist/diagnostics/diagnostic.d.ts +43 -1
  16. package/dist/diagnostics/diagnostic.js +103 -5
  17. package/dist/diagnostics/diagnostic.js.map +1 -1
  18. package/dist/frontend/lib-contract.d.ts +24 -6
  19. package/dist/frontend/lib-contract.js +125 -44
  20. package/dist/frontend/lib-contract.js.map +1 -1
  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 +455 -40
  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 +421 -43
  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 +2 -1
  52. package/dist/index.js +37 -7
  53. package/dist/index.js.map +1 -1
  54. package/dist/ir/nodes.d.ts +28 -2
  55. package/dist/ir/nodes.js +35 -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 +17 -3
  60. package/dist/library/profile.js +38 -9
  61. package/dist/library/profile.js.map +1 -1
  62. package/dist/library/sidecar.js +162 -43
  63. package/dist/library/sidecar.js.map +1 -1
  64. package/dist/library/trap-teaching.d.ts +11 -0
  65. package/dist/library/trap-teaching.js +49 -0
  66. package/dist/library/trap-teaching.js.map +1 -0
  67. package/package.json +2 -2
  68. package/surface-manifest.json +37 -2
@@ -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)`);
@@ -1286,6 +1288,14 @@ class LlEmitter {
1286
1288
  const params = [];
1287
1289
  const body = [` call void @scr_library_entry(i1 zeroext ${autoReset ? "true" : "false"})`];
1288
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
+ }
1289
1299
  e.params.forEach((cls, i) => {
1290
1300
  switch (cls) {
1291
1301
  case "f64":
@@ -1319,7 +1329,7 @@ class LlEmitter {
1319
1329
  break;
1320
1330
  case "bytes":
1321
1331
  params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
1322
- 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})`);
1323
1333
  args.push(`ptr %c${i}`);
1324
1334
  break;
1325
1335
  }
@@ -2558,9 +2568,13 @@ class LlEmitter {
2558
2568
  if (isRefCounted(v.type))
2559
2569
  this.moveTemp(v);
2560
2570
  const shape = this.recordShape(s.shapeId);
2561
- 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;
2562
2576
  if (!iv)
2563
- 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}`);
2564
2578
  const vAcc = iv.kind === "f64" ? "f64" : iv.kind === "bool" ? "bool" : "ref";
2565
2579
  if (s.overflowOnly === true) {
2566
2580
  // A LITERAL key naming no declared field: a plain overflow
@@ -2571,7 +2585,7 @@ class LlEmitter {
2571
2585
  }
2572
2586
  const join = B.newLabel("rks.j");
2573
2587
  this.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
2574
- if (iv.kind === "dyn") {
2588
+ if (iv.kind === "dyn" && shape.indexValue) {
2575
2589
  // A dyn-valued shape (the C recordKeySetHelper's dyn arm,
2576
2590
  // inline): declared keys VALIDATE the dyn value against the
2577
2591
  // field's type first (dynCheck — a mismatched write throws the
@@ -2656,6 +2670,19 @@ class LlEmitter {
2656
2670
  B.br(join);
2657
2671
  B.startBlock(ln);
2658
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
+ }
2659
2686
  const ovf = this.recordOvfPtr(obj.name, s.shapeId);
2660
2687
  this.mapSet(ovf, "str", vAcc, key.name, v.name);
2661
2688
  B.br(join);
@@ -4051,6 +4078,31 @@ class LlEmitter {
4051
4078
  // TAG against its unit arms as the test. Pass-through shape: the
4052
4079
  // result IS the left box. Narrowed shape: the single non-unit
4053
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
+ }
4054
4106
  if (e.left.type.kind !== "union")
4055
4107
  throw new Error("llvm emitter bug: nullish left is not a union");
4056
4108
  const def = this.unionsById.get(e.left.type.unionId);
@@ -5797,8 +5849,12 @@ class LlEmitter {
5797
5849
  ? this.islandAdapter(fn.params.length, fn.ret.kind)
5798
5850
  : this.islandTypedAdapter(fn);
5799
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;
5800
5856
  const t = B.tmp();
5801
- 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})`);
5802
5858
  return this.own({ name: t, type: e.type });
5803
5859
  }
5804
5860
  default: {
@@ -5997,6 +6053,30 @@ class LlEmitter {
5997
6053
  B.line(`${t} = call ptr @scr_jsval_obj_lit(i32 ${args.length / 2}, ptr ${pack})`);
5998
6054
  return this.own({ name: t, type: e.type });
5999
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
+ }
6000
6080
  case "arrLit": {
6001
6081
  const pack = argPack(args.map((x) => x.name));
6002
6082
  this.declare(`declare ptr @scr_jsval_arr_lit(i32, ptr)`);
@@ -6306,7 +6386,7 @@ class LlEmitter {
6306
6386
  d.push(` %fnp = getelementptr inbounds %ScrClosure, ptr %c, i64 0, i32 1`, ` %fn = load ptr, ptr %fnp`);
6307
6387
  if (ret.async) {
6308
6388
  // The closure returns a +1 ScrPromise; from_promise takes ownership.
6309
- 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];
6310
6390
  this.declare(`declare ptr @scr_jsval_from_promise(ptr, i32)`);
6311
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`);
6312
6392
  }
@@ -6331,6 +6411,13 @@ class LlEmitter {
6331
6411
  this.declare(`declare void @scr_str_release(ptr)`);
6332
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`);
6333
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;
6334
6421
  case "json": {
6335
6422
  // A JSON-safe composite return: the jsMarshal path — the type-
6336
6423
  // directed serializer, then the engine's JSON parser (deep