@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.
- package/dist/backend/cc.d.ts +16 -0
- package/dist/backend/cc.js +88 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.js +2 -2
- package/dist/backend/emission/emit-async.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +27 -4
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +2 -2
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +54 -8
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +1 -0
- package/dist/backend/emission/emitter.js +108 -0
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +12 -0
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/llvm/dyn.js +23 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +150 -6
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +5 -0
- package/dist/backend/llvm/walkers.js +65 -5
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +25 -0
- package/dist/diagnostics/diagnostic.js +86 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lib-exports.d.ts +16 -0
- package/dist/frontend/lib-exports.js +35 -0
- package/dist/frontend/lib-exports.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +41 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +2 -2
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +1 -1
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +1 -1
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +7 -0
- package/dist/frontend/lowering/lower-inspect.js +130 -28
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +1 -1
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +4 -2
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +107 -0
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +16 -2
- package/dist/frontend/lowering/lowerer.js +64 -15
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.d.ts +3 -0
- package/dist/frontend/npm-static-rewrite.js +677 -0
- package/dist/frontend/npm-static-rewrite.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +8 -1
- package/dist/frontend/npm-static.js +159 -18
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/program.d.ts +6 -0
- package/dist/frontend/program.js +51 -14
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/types.d.ts +68 -6
- package/dist/frontend/types.js +285 -57
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +22 -0
- package/dist/index.js +253 -17
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +50 -4
- package/dist/ir/nodes.js +179 -13
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +61 -0
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/profile.d.ts +52 -0
- package/dist/library/profile.js +232 -0
- package/dist/library/profile.js.map +1 -0
- package/package.json +2 -2
- 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
|
|
1219
|
-
|
|
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
|