@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.
- package/dist/backend/emission/emit-exprs.js +47 -1
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +9 -1
- package/dist/backend/emission/emit-island.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +3 -1
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +22 -8
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.js +12 -1
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +4 -3
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/llvm/emitter.js +105 -9
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +49 -1
- package/dist/diagnostics/diagnostic.js +119 -5
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lib-contract.d.ts +114 -0
- package/dist/frontend/lib-contract.js +372 -0
- package/dist/frontend/lib-contract.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.js +16 -1
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +47 -7
- package/dist/frontend/lowering/lower-calls.js +560 -36
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +14 -1
- package/dist/frontend/lowering/lower-classes.js +85 -15
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +43 -1
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.js +1 -1
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +26 -3
- package/dist/frontend/lowering/lower-exprs.js +474 -44
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -0
- package/dist/frontend/lowering/lower-island.js +71 -10
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-modules.js +95 -4
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +430 -44
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +19 -3
- package/dist/frontend/lowering/lowerer.js +188 -11
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/types.d.ts +28 -1
- package/dist/frontend/types.js +300 -8
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.js +96 -7
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +48 -2
- package/dist/ir/nodes.js +103 -3
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +35 -6
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/profile.d.ts +53 -3
- package/dist/library/profile.js +143 -12
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.d.ts +4 -0
- package/dist/library/sidecar-validate.js +506 -0
- package/dist/library/sidecar-validate.js.map +1 -0
- package/dist/library/sidecar.d.ts +191 -0
- package/dist/library/sidecar.js +687 -0
- package/dist/library/sidecar.js.map +1 -0
- package/dist/library/trap-teaching.d.ts +11 -0
- package/dist/library/trap-teaching.js +49 -0
- package/dist/library/trap-teaching.js.map +1 -0
- package/dist/library/wyhash.d.ts +12 -0
- package/dist/library/wyhash.js +116 -0
- package/dist/library/wyhash.js.map +1 -0
- package/package.json +2 -2
- 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": "
|
|
430
|
-
"net.setAutoSelTimeout": "
|
|
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
|
-
|
|
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 ${
|
|
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
|