@scriptc/compiler 0.0.4 → 0.0.6

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 (74) hide show
  1. package/dist/backend/cc.d.ts +16 -0
  2. package/dist/backend/cc.js +88 -0
  3. package/dist/backend/cc.js.map +1 -1
  4. package/dist/backend/emission/emit-async.js +2 -2
  5. package/dist/backend/emission/emit-async.js.map +1 -1
  6. package/dist/backend/emission/emit-exprs.js +27 -4
  7. package/dist/backend/emission/emit-exprs.js.map +1 -1
  8. package/dist/backend/emission/emit-shapes.js +2 -2
  9. package/dist/backend/emission/emit-shapes.js.map +1 -1
  10. package/dist/backend/emission/emit-walkers.js +54 -8
  11. package/dist/backend/emission/emit-walkers.js.map +1 -1
  12. package/dist/backend/emission/emitter.d.ts +1 -0
  13. package/dist/backend/emission/emitter.js +108 -0
  14. package/dist/backend/emission/emitter.js.map +1 -1
  15. package/dist/backend/emission/may-throw.js +12 -0
  16. package/dist/backend/emission/may-throw.js.map +1 -1
  17. package/dist/backend/llvm/dyn.js +23 -1
  18. package/dist/backend/llvm/dyn.js.map +1 -1
  19. package/dist/backend/llvm/emitter.js +150 -6
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/walkers.d.ts +5 -0
  22. package/dist/backend/llvm/walkers.js +65 -5
  23. package/dist/backend/llvm/walkers.js.map +1 -1
  24. package/dist/diagnostics/diagnostic.d.ts +25 -0
  25. package/dist/diagnostics/diagnostic.js +86 -0
  26. package/dist/diagnostics/diagnostic.js.map +1 -1
  27. package/dist/frontend/lib-exports.d.ts +16 -0
  28. package/dist/frontend/lib-exports.js +35 -0
  29. package/dist/frontend/lib-exports.js.map +1 -0
  30. package/dist/frontend/lowering/lower-assert.js +41 -1
  31. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  32. package/dist/frontend/lowering/lower-calls.js +2 -2
  33. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  34. package/dist/frontend/lowering/lower-classes.js +1 -1
  35. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  36. package/dist/frontend/lowering/lower-exprs.js +1 -1
  37. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  38. package/dist/frontend/lowering/lower-inspect.d.ts +7 -0
  39. package/dist/frontend/lowering/lower-inspect.js +130 -28
  40. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  41. package/dist/frontend/lowering/lower-island.js +1 -1
  42. package/dist/frontend/lowering/lower-island.js.map +1 -1
  43. package/dist/frontend/lowering/lower-mixins.js +4 -2
  44. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  45. package/dist/frontend/lowering/lower-stmts.js +107 -0
  46. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  47. package/dist/frontend/lowering/lowerer.d.ts +16 -2
  48. package/dist/frontend/lowering/lowerer.js +64 -15
  49. package/dist/frontend/lowering/lowerer.js.map +1 -1
  50. package/dist/frontend/npm-static-rewrite.d.ts +3 -0
  51. package/dist/frontend/npm-static-rewrite.js +677 -0
  52. package/dist/frontend/npm-static-rewrite.js.map +1 -0
  53. package/dist/frontend/npm-static.d.ts +8 -1
  54. package/dist/frontend/npm-static.js +159 -18
  55. package/dist/frontend/npm-static.js.map +1 -1
  56. package/dist/frontend/program.d.ts +6 -0
  57. package/dist/frontend/program.js +51 -14
  58. package/dist/frontend/program.js.map +1 -1
  59. package/dist/frontend/types.d.ts +68 -6
  60. package/dist/frontend/types.js +285 -57
  61. package/dist/frontend/types.js.map +1 -1
  62. package/dist/index.d.ts +22 -0
  63. package/dist/index.js +253 -17
  64. package/dist/index.js.map +1 -1
  65. package/dist/ir/nodes.d.ts +50 -4
  66. package/dist/ir/nodes.js +179 -13
  67. package/dist/ir/nodes.js.map +1 -1
  68. package/dist/ir/validate.js +61 -0
  69. package/dist/ir/validate.js.map +1 -1
  70. package/dist/library/profile.d.ts +52 -0
  71. package/dist/library/profile.js +232 -0
  72. package/dist/library/profile.js.map +1 -0
  73. package/package.json +2 -2
  74. package/surface-manifest.json +1 -1
@@ -6,7 +6,7 @@ import { buildClassGraph, classFieldIndex, classStructSym, emitClassObjDefs, emi
6
6
  import { DK, LlDyn } from "./dyn.js";
7
7
  import { LlvmUnsupportedError } from "./unsupported.js";
8
8
  import { LlWalkers } from "./walkers.js";
9
- import { arrNewCall, boxAccess, boxNewCall, computeTraced, elemAccess, emitRecordShapes, FN_ATTRS, llFieldType, mapKeyAccess, mapKeyKindNum, mapValKindNum, releaseSym, retainSym, traceArg, vAdapters, } from "./shapes.js";
9
+ import { arrNewCall, boxAccess, boxNewCall, computeTraced, elemAccess, emitRecordShapes, FN_ATTRS, llFieldType, mapKeyAccess, mapKeyKindNum, mapValKindNum, releaseSym, retainSym, traceAdapter, traceArg, vAdapters, } from "./shapes.js";
10
10
  export { LlvmUnsupportedError } from "./unsupported.js";
11
11
  export function emitLlvmModule(mod) {
12
12
  return new LlEmitter(mod).emit();
@@ -159,6 +159,8 @@ const LIB_FN_SYMS = {
159
159
  "assert.eqDyn": "scr_assert_eq_dyn",
160
160
  "assert.deepResult": "scr_assert_deep_result",
161
161
  "assert.sameValue": "scr_assert_same_value_f64",
162
+ "assert.deqEnter": "scr_assert_deq_enter",
163
+ "assert.deqLeave": "scr_assert_deq_leave",
162
164
  "assert.match": "scr_assert_match",
163
165
  "assert.throwsNone": "scr_assert_throws_none",
164
166
  "assert.throwsMismatch": "scr_assert_throws_mismatch",
@@ -229,6 +231,13 @@ const LIB_FN_SYMS = {
229
231
  "insp.key": "scr_insp_key",
230
232
  "insp.moreItems": "scr_insp_more_items",
231
233
  "insp.end": "scr_insp_end",
234
+ // Circular references over cycle-capable composites (Node's
235
+ // seen/circular machinery — none of these throw; refWrap borrows its
236
+ // string and answers +1).
237
+ "insp.circCheck": "scr_insp_circ_check",
238
+ "insp.seenPush": "scr_insp_seen_push",
239
+ "insp.refWrap": "scr_insp_ref_wrap",
240
+ "insp.circular": "scr_insp_circular",
232
241
  // WHATWG URL + URLSearchParams (scr_url.c / scr_url_params.c):
233
242
  // constructions +1; url.new, the fileURLToPath pair, the win32
234
243
  // pathToFileURL flavor, and sp.fromPairs throw catchably (may-throw).
@@ -1001,6 +1010,28 @@ class LlEmitter {
1001
1010
  this.declare(`declare void @scr_loop_run()`);
1002
1011
  this.declare(`declare zeroext i1 @scr_report_unhandled_rejections()`);
1003
1012
  }
1013
+ // LIBRARY mode: the runtime entry points the generated library
1014
+ // symbols delegate to — declared before the extern block flushes.
1015
+ if (this.mod.lib !== undefined) {
1016
+ this.declare(`declare void @scr_library_entry(i1 zeroext)`);
1017
+ this.declare(`declare void @scr_library_reset()`);
1018
+ this.declare(`declare void @scr_library_check_exc()`);
1019
+ this.declare(`declare void @scr_library_set_sink(ptr, ptr)`);
1020
+ this.declare(`declare void @scr_library_arena_reset()`);
1021
+ this.declare(`declare void @scr_library_collect()`);
1022
+ if (this.mod.lib.exports.some((e) => e.params.includes("string"))) {
1023
+ this.declare(`declare ptr @scr_library_str_in(ptr, i64)`);
1024
+ }
1025
+ if (this.mod.lib.exports.some((e) => e.params.includes("bytes"))) {
1026
+ this.declare(`declare ptr @scr_library_bytes_in(ptr, i64)`);
1027
+ }
1028
+ if (this.mod.lib.exports.some((e) => e.returns === "string")) {
1029
+ this.declare(`declare void @scr_library_str_out(ptr, ptr, ptr)`);
1030
+ }
1031
+ if (this.mod.lib.exports.some((e) => e.returns === "bytes")) {
1032
+ this.declare(`declare void @scr_library_bytes_out(ptr, ptr, ptr)`);
1033
+ }
1034
+ }
1004
1035
  // Helpers assemble BEFORE the declaration table flushes (they add
1005
1036
  // write/abort declarations).
1006
1037
  const helpers = this.helperDefs();
@@ -1045,7 +1076,7 @@ class LlEmitter {
1045
1076
  // slot } — TDZ reads peek the payload slot (offset 40) directly.
1046
1077
  `%ScrBox = type { i64, i32, ptr, ptr, ptr, i64 }`,
1047
1078
  // The stack buffer of the emitted JSON serializers { data, len, cap }.
1048
- `%ScrJsonBuf = type { ptr, i64, i64 }`,
1079
+ `%ScrJsonBuf = type { ptr, i64, i64, ptr, i64, i64 }`,
1049
1080
  // The dynCheck error-path spine { parent, key, index } — the emitted
1050
1081
  // builders stack-allocate one per recursion level (dyn.ts).
1051
1082
  `%ScrDynPath = type { ptr, ptr, i64 }`,
@@ -1151,13 +1182,20 @@ class LlEmitter {
1151
1182
  out.push(`declare void @scr_error_set_traced()`, ``);
1152
1183
  stamps.push(` call void @scr_error_set_traced()`);
1153
1184
  }
1154
- if (entryMayThrow || runsLoop) {
1185
+ if ((entryMayThrow || runsLoop) && this.mod.lib === undefined) {
1155
1186
  // Declared inline: the extern block already flushed (LLVM is
1156
1187
  // order-free — the scr_error_set_traced precedent). Only the
1157
1188
  // printer emits here (nothing else declares it); scr_exc_pending
1158
1189
  // and the loop entry points rode the Set before the flush.
1159
1190
  out.push(`declare void @scr_exc_print_uncaught()`, ``);
1160
1191
  }
1192
+ if (this.mod.lib !== undefined) {
1193
+ // LIBRARY mode: no @main — the profile-declared external
1194
+ // symbols instead, from the same IR facts the C emission consumes.
1195
+ out.push(...this.emitLibDefs(globals, globalReleaseLines, stamps));
1196
+ out.push(`attributes #0 = { sanitize_address }`, ``);
1197
+ return out.join("\n");
1198
+ }
1161
1199
  out.push(`define i32 @main(i32 %argc, ptr %argv) ${FN_ATTRS} {`, `entry:`, ` call void @scr_init()`, ...stamps,
1162
1200
  // Event-surface programs (signal/exit listeners) fill the loop's
1163
1201
  // nullable event hooks before %main — scr_events.c links only when
@@ -1208,16 +1246,116 @@ class LlEmitter {
1208
1246
  `attributes #0 = { sanitize_address }`, ``);
1209
1247
  return out.join("\n");
1210
1248
  }
1249
+ /** LIBRARY mode: the profile-declared external definitions — the
1250
+ * export-map wrappers plus init / sink-registration / reset / collect.
1251
+ * Plain `define` (not `define internal`) — the exact linkage distinction
1252
+ * that separates the executable lane's @main from everything else. The
1253
+ * bodies delegate every runtime half to scr_library.c, mirroring the C
1254
+ * emission line for line, so the two lanes are identical by
1255
+ * construction. */
1256
+ emitLibDefs(globals, globalReleaseLines, stamps) {
1257
+ const lib = this.mod.lib;
1258
+ const autoReset = lib.resultResetSymbol === null;
1259
+ const out = [``, `; ── library-mode entries (profile: ${lib.profileName}) ──`, ``];
1260
+ // The init entry: full deterministic reset-and-reevaluate. Program
1261
+ // globals release and zero first (run-once guards included), then the
1262
+ // runtime session reset, the error-vt interval stamps verbatim from
1263
+ // the executable main, %main itself, and the escaped-exception check.
1264
+ const zeroStores = globals.map((g) => {
1265
+ const ty = this.llType(g.type);
1266
+ const zero = ty === "double" ? f64Lit(0) : ty === "ptr" ? "null" : "false";
1267
+ return ` store ${ty} ${zero}, ptr @${mangleGlobal(g.id)} ; ${g.name}`;
1268
+ });
1269
+ 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`, `}`, ``);
1270
+ if (lib.resultResetSymbol !== null) {
1271
+ 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
+ }
1273
+ if (lib.collectSymbol !== null) {
1274
+ out.push(`define void @${lib.collectSymbol}() ${FN_ATTRS} {`, `entry:`, ` call void @scr_library_entry(i1 zeroext false)`, ` call void @scr_library_collect() ; arena reset + a full cycle collection`, ` ret void`, `}`, ``);
1275
+ }
1276
+ for (const e of lib.exports) {
1277
+ const params = [];
1278
+ const body = [` call void @scr_library_entry(i1 zeroext ${autoReset ? "true" : "false"})`];
1279
+ const args = [];
1280
+ e.params.forEach((cls, i) => {
1281
+ switch (cls) {
1282
+ case "f64":
1283
+ params.push(`double %a${i}`);
1284
+ args.push(`double %a${i}`);
1285
+ break;
1286
+ case "bool":
1287
+ params.push(`i8 %a${i}`);
1288
+ body.push(` %c${i} = icmp ne i8 %a${i}, 0`);
1289
+ args.push(`i1 %c${i}`);
1290
+ break;
1291
+ case "u8":
1292
+ params.push(`i8 %a${i}`);
1293
+ body.push(` %c${i} = uitofp i8 %a${i} to double`);
1294
+ args.push(`double %c${i}`);
1295
+ break;
1296
+ case "u32":
1297
+ params.push(`i32 %a${i}`);
1298
+ body.push(` %c${i} = uitofp i32 %a${i} to double`);
1299
+ args.push(`double %c${i}`);
1300
+ break;
1301
+ case "i32":
1302
+ params.push(`i32 %a${i}`);
1303
+ body.push(` %c${i} = sitofp i32 %a${i} to double`);
1304
+ args.push(`double %c${i}`);
1305
+ break;
1306
+ case "string":
1307
+ params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
1308
+ body.push(` %c${i} = call ptr @scr_library_str_in(ptr %a${i}_ptr, i64 %a${i}_len)`);
1309
+ args.push(`ptr %c${i}`);
1310
+ break;
1311
+ case "bytes":
1312
+ 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)`);
1314
+ args.push(`ptr %c${i}`);
1315
+ break;
1316
+ }
1317
+ });
1318
+ if (e.returns === "string" || e.returns === "bytes") {
1319
+ params.push(`ptr %out`, `ptr %out_len`);
1320
+ }
1321
+ const target = `@${mangleFunction(e.fnName)}`;
1322
+ const callArgs = args.join(", ");
1323
+ let retType = "void";
1324
+ switch (e.returns) {
1325
+ case "void":
1326
+ body.push(` call void ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` ret void`);
1327
+ break;
1328
+ case "f64":
1329
+ retType = "double";
1330
+ body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` ret double %r`);
1331
+ break;
1332
+ case "bool":
1333
+ retType = "i8";
1334
+ body.push(` %r = call i1 ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = zext i1 %r to i8`, ` ret i8 %z`);
1335
+ break;
1336
+ case "string":
1337
+ body.push(` %r = call ptr ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` call void @scr_library_str_out(ptr %r, ptr %out, ptr %out_len)`, ` ret void`);
1338
+ break;
1339
+ case "bytes":
1340
+ body.push(` %r = call ptr ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` call void @scr_library_bytes_out(ptr %r, ptr %out, ptr %out_len)`, ` ret void`);
1341
+ break;
1342
+ }
1343
+ out.push(`define ${retType} @${e.symbol}(${params.join(", ")}) ${FN_ATTRS} { ; library export ${e.fnName}`, `entry:`, ...body, `}`, ``);
1344
+ }
1345
+ return out;
1346
+ }
1211
1347
  /** The shared abort helpers (emitted only when referenced): the OOM
1212
1348
  * abort of untraced shape allocation and the invalid-union-tag abort —
1213
1349
  * both print the C emitter's exact message on fd 2 and abort. */
1214
1350
  helperDefs() {
1215
1351
  const defs = [];
1216
1352
  const msgHelper = (fnName, msgSym, msg) => {
1353
+ // The message routes through the runtime's trap funnel: executable
1354
+ // builds expand to the historical bytes-on-stderr + abort; library
1355
+ // builds route to the registered panic sink (scr_runtime.h).
1217
1356
  const bytes = Buffer.byteLength(msg, "utf8");
1218
- this.declare(`declare i64 @write(i32, ptr, i64)`);
1219
- this.declare(`declare void @abort()`);
1220
- defs.push(`@${msgSym} = internal constant [${bytes} x i8] c"${llStrBytes(msg).slice(0, -3)}"`, `define internal void @${fnName}() ${FN_ATTRS} {`, `entry:`, ` %w = call i64 @write(i32 2, ptr @${msgSym}, i64 ${bytes})`, ` call void @abort()`, ` unreachable`, `}`, ``);
1357
+ this.declare(`declare void @scr_trap(ptr)`);
1358
+ defs.push(`@${msgSym} = internal constant [${bytes + 1} x i8] c"${llStrBytes(msg)}"`, `define internal void @${fnName}() ${FN_ATTRS} {`, `entry:`, ` call void @scr_trap(ptr @${msgSym})`, ` unreachable`, `}`, ``);
1221
1359
  };
1222
1360
  if (this.needsOom)
1223
1361
  msgHelper("sc_oom", "sc_oom_msg", "scriptc: out of memory\n");
@@ -4582,6 +4720,12 @@ class LlEmitter {
4582
4720
  const t = B.tmp();
4583
4721
  B.line(`${t} = call ptr @scr_jb_finish(ptr ${buf})`);
4584
4722
  compact = this.own({ name: t, type: e.type });
4723
+ // A cycle-capable root can throw the circular-structure
4724
+ // TypeError mid-walk: finish still runs (frees the buffer, the
4725
+ // partial string joins the frame and releases on unwind), then
4726
+ // the pending check unwinds — the C emitter's contract exactly.
4727
+ if (traceAdapter(this, e.value.type) !== null)
4728
+ this.emitPendingCheck();
4585
4729
  }
4586
4730
  // A pretty-print form (`stringify(v, null, 2)`): the frontend
4587
4731
  // resolved the space to a compile-time indent string (Node's