@scriptc/compiler 0.0.9 → 0.0.10
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 +136 -12
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +29 -2
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +83 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +151 -9
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +21 -7
- package/dist/diagnostics/diagnostic.js +35 -16
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.js +8 -0
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +11 -1
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +13 -0
- package/dist/frontend/lowering/lower-builtins.js +146 -1
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +41 -0
- package/dist/frontend/lowering/lower-calls.js +524 -10
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +17 -0
- package/dist/frontend/lowering/lower-containers.js +193 -10
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +92 -17
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +179 -10
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +33 -2
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +25 -11
- package/dist/frontend/lowering/lower-namespaces.js +50 -15
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +211 -4
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -5
- package/dist/frontend/lowering/lower-stmts.js +216 -7
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +65 -4
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +36 -1
- package/dist/frontend/lowering/lowerer.js +106 -3
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/types.d.ts +13 -0
- package/dist/frontend/types.js +84 -7
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.js +20 -8
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +99 -5
- package/dist/ir/nodes.js +44 -3
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +53 -3
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.d.ts +77 -0
- package/dist/library/fence-eval.js +385 -0
- package/dist/library/fence-eval.js.map +1 -0
- package/dist/library/profile.d.ts +11 -1
- package/dist/library/profile.js +102 -18
- package/dist/library/profile.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +1 -1
|
@@ -197,6 +197,11 @@ const LIB_FN_SYMS = {
|
|
|
197
197
|
"bytes.compareChk": "scr_bytes_compare_chk",
|
|
198
198
|
"buffer.newStringFail": "scr_buffer_new_string_fail",
|
|
199
199
|
"fs.toUnixTimestamp": "scr_fs_to_unix_timestamp",
|
|
200
|
+
"fs.existsChk": "scr_fs_exists_async",
|
|
201
|
+
"fs.mkdtempSyncChk": "scr_fs_mkdtemp_sync_chk",
|
|
202
|
+
"net.connectAttempt": "scr_net_connect_attempt",
|
|
203
|
+
"fs.lchmodSyncChk": "scr_fs_lchmod_sync_chk",
|
|
204
|
+
"fsp.lchmodChk": "scr_fsp_lchmod_chk",
|
|
200
205
|
"fs.readFileSyncBuf": "scr_fs_read_file_bytes",
|
|
201
206
|
"fs.readFileSyncBytes": "scr_fs_read_file_bytes",
|
|
202
207
|
"fs.writeFileSyncBytes": "scr_fs_write_file_bytes",
|
|
@@ -342,9 +347,10 @@ const LIB_FN_SYMS = {
|
|
|
342
347
|
// ambient-this read never throw. The fs dyn read is the sync-fs story.
|
|
343
348
|
"json.parse": "scr_json_parse",
|
|
344
349
|
"dyn.keySet": "scr_dyn_key_set",
|
|
350
|
+
"dyn.iterPack": "scr_dyn_iter_pack",
|
|
345
351
|
"dyn.defineProps": "scr_dyn_define_props",
|
|
346
352
|
"dyn.typeof": "scr_dyn_typeof",
|
|
347
|
-
"dyn.toString": "
|
|
353
|
+
"dyn.toString": "scr_dyn_to_string_method",
|
|
348
354
|
"dyn.this": "scr_dyn_this_get",
|
|
349
355
|
"insp.dyn": "scr_insp_dyn",
|
|
350
356
|
"insp.dynS": "scr_insp_dyn_s",
|
|
@@ -559,6 +565,14 @@ const LIB_FN_SYMS = {
|
|
|
559
565
|
"dyn.objKeys": "scr_dyn_obj_keys",
|
|
560
566
|
"dyn.hasOwn": "scr_dyn_has_own",
|
|
561
567
|
"dyn.assign": "scr_dyn_assign",
|
|
568
|
+
// variadic Object.assign: the source pack (push never throws; the
|
|
569
|
+
// spread flatten throws V8's spread-call TypeErrors) and the final
|
|
570
|
+
// left-to-right copy (ToObject TypeError on a nullish target).
|
|
571
|
+
"dyn.packPush": "scr_dyn_pack_push",
|
|
572
|
+
"dyn.packPushSpread": "scr_dyn_pack_push_spread",
|
|
573
|
+
"dyn.packPushSpreadIter": "scr_dyn_pack_push_spread_iter",
|
|
574
|
+
"dyn.assignAll": "scr_dyn_assign_all",
|
|
575
|
+
"dyn.objCreateNullProto": "scr_dyn_new_obj_null_proto",
|
|
562
576
|
"dyn.objValues": "scr_dyn_obj_values",
|
|
563
577
|
"dyn.objEntries": "scr_dyn_obj_entries",
|
|
564
578
|
"dyn.structuredClone": "scr_structured_clone",
|
|
@@ -603,7 +617,8 @@ const USES_TIMERS_LIB_FNS = new Set([
|
|
|
603
617
|
"stream.finished", "stream.finishedDyn", "stream.pipeline", "stream.pipelineDyn",
|
|
604
618
|
"sp.finished", "sp.pipeline",
|
|
605
619
|
"net.listen", "net.listenCb", "net.listenOpts", "net.listenOptsCb",
|
|
606
|
-
"net.connect", "net.connectCb", "net.connectLookup",
|
|
620
|
+
"net.connect", "net.connectCb", "net.connectLookup", "net.connectAttempt",
|
|
621
|
+
"fs.existsChk",
|
|
607
622
|
"http.createServer", "http.createServerEmpty",
|
|
608
623
|
"http.request", "http.requestCb", "http.requestUrl", "http.requestUrlCb",
|
|
609
624
|
"http.requestConn", "http.requestConnCb",
|
|
@@ -4178,6 +4193,33 @@ class LlEmitter {
|
|
|
4178
4193
|
B.line(`${t} = load ptr, ptr ${slot}`);
|
|
4179
4194
|
return this.own({ name: t, type: e.type });
|
|
4180
4195
|
}
|
|
4196
|
+
if (e.left.type.kind === "dyn") {
|
|
4197
|
+
// The checked-dynamic form: the runtime kind decides (UNDEF/
|
|
4198
|
+
// NULL take the default; a wrapped island value asks the
|
|
4199
|
+
// engine); the right runs lazily in its branch (already dyn).
|
|
4200
|
+
const l = this.emitExpr(e.left);
|
|
4201
|
+
this.moveTemp(l);
|
|
4202
|
+
this.declare(`declare zeroext i1 @scr_dyn_is_nullish(ptr)`);
|
|
4203
|
+
const slot = B.slot();
|
|
4204
|
+
B.entryAllocas.push(`${slot} = alloca ptr`);
|
|
4205
|
+
const isN = B.tmp();
|
|
4206
|
+
B.line(`${isN} = call zeroext i1 @scr_dyn_is_nullish(ptr ${l.name})`);
|
|
4207
|
+
const lu = B.newLabel("nuld.u");
|
|
4208
|
+
const lv = B.newLabel("nuld.v");
|
|
4209
|
+
const lj = B.newLabel("nuld.j");
|
|
4210
|
+
B.condBr(isN, lu, lv);
|
|
4211
|
+
B.startBlock(lu);
|
|
4212
|
+
this.releaseValue(l.name, e.left.type);
|
|
4213
|
+
this.emitBranchInto(slot, e.right);
|
|
4214
|
+
B.br(lj);
|
|
4215
|
+
B.startBlock(lv);
|
|
4216
|
+
B.line(`store ptr ${l.name}, ptr ${slot}`);
|
|
4217
|
+
B.br(lj);
|
|
4218
|
+
B.startBlock(lj);
|
|
4219
|
+
const t = B.tmp();
|
|
4220
|
+
B.line(`${t} = load ptr, ptr ${slot}`);
|
|
4221
|
+
return this.own({ name: t, type: e.type });
|
|
4222
|
+
}
|
|
4181
4223
|
if (e.left.type.kind !== "union")
|
|
4182
4224
|
throw new Error("llvm emitter bug: nullish left is not a union");
|
|
4183
4225
|
const def = this.unionsById.get(e.left.type.unionId);
|
|
@@ -5500,6 +5542,16 @@ class LlEmitter {
|
|
|
5500
5542
|
B.line(`${t} = call ptr @${conv}(${valTy} ${v.name})`);
|
|
5501
5543
|
return this.own({ name: t, type: e.type });
|
|
5502
5544
|
}
|
|
5545
|
+
case "dynFromJsval": {
|
|
5546
|
+
// Island value → DOM: the by-reference wrap (scr_dyn_from_jsval
|
|
5547
|
+
// retains the cell in; engine scalars normalize to native DOM
|
|
5548
|
+
// kinds at wrap time). Operand borrowed, result +1, never throws.
|
|
5549
|
+
const v = this.emitExpr(e.value);
|
|
5550
|
+
this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
|
|
5551
|
+
const t = B.tmp();
|
|
5552
|
+
B.line(`${t} = call ptr @scr_dyn_from_jsval(ptr ${v.name})`);
|
|
5553
|
+
return this.own({ name: t, type: e.type });
|
|
5554
|
+
}
|
|
5503
5555
|
case "caughtToDyn": {
|
|
5504
5556
|
// A catch binding flowing into an `unknown` slot: the snapshot's
|
|
5505
5557
|
// runtime kind converts through the interned helper (+1 fresh
|
|
@@ -5681,7 +5733,8 @@ class LlEmitter {
|
|
|
5681
5733
|
B.startBlock(lNotObj);
|
|
5682
5734
|
const isArr = B.tmp();
|
|
5683
5735
|
B.line(`${isArr} = icmp eq i32 ${kd}, ${DK.ARR}`);
|
|
5684
|
-
B.
|
|
5736
|
+
const lNotArr = B.newLabel("dhk.na");
|
|
5737
|
+
B.condBr(isArr, lArr, lNotArr);
|
|
5685
5738
|
B.startBlock(lArr);
|
|
5686
5739
|
if (e.key === "length") {
|
|
5687
5740
|
B.line(`store i1 true, ptr ${slot}`);
|
|
@@ -5696,9 +5749,20 @@ class LlEmitter {
|
|
|
5696
5749
|
B.line(`store i1 ${inR}, ptr ${slot}`);
|
|
5697
5750
|
}
|
|
5698
5751
|
B.br(lj);
|
|
5752
|
+
// An ISLAND-held receiver fences loudly (Node asks the real
|
|
5753
|
+
// engine object — `false` would be a silent wrong answer); the
|
|
5754
|
+
// helper answers false for every other kind, so this arm is a
|
|
5755
|
+
// plain unconditional call.
|
|
5756
|
+
B.startBlock(lNotArr);
|
|
5757
|
+
this.declare(`declare zeroext i1 @scr_dyn_isl_fence(ptr, ptr)`);
|
|
5758
|
+
const fenced = B.tmp();
|
|
5759
|
+
B.line(`${fenced} = call zeroext i1 @scr_dyn_isl_fence(ptr ${d.name}, ptr ${this.cstr("'in'")})`);
|
|
5760
|
+
B.line(`store i1 ${fenced}, ptr ${slot}`);
|
|
5761
|
+
B.br(lj);
|
|
5699
5762
|
B.startBlock(lj);
|
|
5700
5763
|
const raw = B.tmp();
|
|
5701
5764
|
B.line(`${raw} = load i1, ptr ${slot}`);
|
|
5765
|
+
this.emitPendingCheck();
|
|
5702
5766
|
if (!e.negated)
|
|
5703
5767
|
return { name: raw, type: e.type };
|
|
5704
5768
|
const neg = B.tmp();
|
|
@@ -5778,13 +5842,18 @@ class LlEmitter {
|
|
|
5778
5842
|
}
|
|
5779
5843
|
else if (e.test === "error") {
|
|
5780
5844
|
// `u instanceof Error`: the DOM's error encoding — an object
|
|
5781
|
-
// carrying the reserved "%error" marker key
|
|
5845
|
+
// carrying the reserved "%error" marker key — or a real engine
|
|
5846
|
+
// Error held by reference (the isl helper answers false for
|
|
5847
|
+
// every non-JSVAL kind, so the call is unconditional).
|
|
5782
5848
|
const kd = this.dynKind(d.name);
|
|
5783
5849
|
const isObj = B.tmp();
|
|
5784
5850
|
B.line(`${isObj} = icmp eq i32 ${kd}, ${DK.OBJ}`);
|
|
5785
5851
|
const slot = B.slot();
|
|
5786
5852
|
B.entryAllocas.push(`${slot} = alloca i1`);
|
|
5787
|
-
|
|
5853
|
+
this.declare(`declare zeroext i1 @scr_dyn_isl_is_error(ptr)`);
|
|
5854
|
+
const isl = B.tmp();
|
|
5855
|
+
B.line(`${isl} = call zeroext i1 @scr_dyn_isl_is_error(ptr ${d.name})`);
|
|
5856
|
+
B.line(`store i1 ${isl}, ptr ${slot}`);
|
|
5788
5857
|
const lObj = B.newLabel("dts.o");
|
|
5789
5858
|
const lj = B.newLabel("dts.j");
|
|
5790
5859
|
B.condBr(isObj, lObj, lj);
|
|
@@ -5818,13 +5887,33 @@ class LlEmitter {
|
|
|
5818
5887
|
}
|
|
5819
5888
|
return acc;
|
|
5820
5889
|
};
|
|
5890
|
+
// ISLAND-held nodes route the tests that depend on the engine's
|
|
5891
|
+
// answer through the scr_dyn_isl_* helpers (false on every
|
|
5892
|
+
// other kind — the calls stay unconditional and branch-free).
|
|
5893
|
+
const orIsl = (acc, helper, arg) => {
|
|
5894
|
+
this.declare(`declare zeroext i1 @${helper}(ptr${arg !== undefined ? ", ptr" : ""})`);
|
|
5895
|
+
const c = B.tmp();
|
|
5896
|
+
B.line(`${c} = call zeroext i1 @${helper}(ptr ${d.name}${arg !== undefined ? `, ptr ${arg}` : ""})`);
|
|
5897
|
+
const o = B.tmp();
|
|
5898
|
+
B.line(`${o} = or i1 ${acc}, ${c}`);
|
|
5899
|
+
return o;
|
|
5900
|
+
};
|
|
5821
5901
|
if (e.test === "nullish") {
|
|
5822
5902
|
test = oneOf([DK.UNDEF, DK.NULL]);
|
|
5823
5903
|
}
|
|
5824
5904
|
else if (e.test === "object") {
|
|
5825
5905
|
// `typeof v === "object"`: objects, arrays, bytes, native
|
|
5826
|
-
// handles, promises, AND null
|
|
5827
|
-
|
|
5906
|
+
// handles, promises, AND null — engine-held objects by the
|
|
5907
|
+
// engine's own typeof.
|
|
5908
|
+
test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
|
|
5909
|
+
}
|
|
5910
|
+
else if (e.test === "array") {
|
|
5911
|
+
// Array.isArray: the DOM's array kind, or the engine's own
|
|
5912
|
+
// answer for an engine-held value.
|
|
5913
|
+
test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
|
|
5914
|
+
}
|
|
5915
|
+
else if (e.test === "function") {
|
|
5916
|
+
test = orIsl(oneOf([DK.FUNC]), "scr_dyn_isl_typeof_is", this.cstr("function"));
|
|
5828
5917
|
}
|
|
5829
5918
|
else {
|
|
5830
5919
|
const kindOf = {
|
|
@@ -5834,8 +5923,6 @@ class LlEmitter {
|
|
|
5834
5923
|
undefined: DK.UNDEF,
|
|
5835
5924
|
null: DK.NULL,
|
|
5836
5925
|
bytes: DK.BYTES,
|
|
5837
|
-
array: DK.ARR,
|
|
5838
|
-
function: DK.FUNC,
|
|
5839
5926
|
};
|
|
5840
5927
|
test = oneOf([kindOf[e.test]]);
|
|
5841
5928
|
}
|
|
@@ -5947,6 +6034,13 @@ class LlEmitter {
|
|
|
5947
6034
|
return simple("scr_jsval_from_bool", "i1", false);
|
|
5948
6035
|
case "string":
|
|
5949
6036
|
return simple("scr_jsval_from_str", "ptr", false);
|
|
6037
|
+
case "dyn":
|
|
6038
|
+
// A CHECKED-DYNAMIC (DOM) value entering the island: deep copy,
|
|
6039
|
+
// data kinds only — boxed functions/handles/promises throw the
|
|
6040
|
+
// catchable TypeError in the runtime, and a wrapped island value
|
|
6041
|
+
// unwraps to the SAME engine value (the identity round trip).
|
|
6042
|
+
// The C emitter's rule, mirrored.
|
|
6043
|
+
return simple("scr_jsval_from_dyn", "ptr", true);
|
|
5950
6044
|
case "bytes":
|
|
5951
6045
|
// A typed array crossing IN: a COPY (the boundary's copy stance).
|
|
5952
6046
|
return simple("scr_jsval_from_bytes", "ptr", true);
|
|
@@ -8666,6 +8760,54 @@ class LlEmitter {
|
|
|
8666
8760
|
this.emitPendingCheck();
|
|
8667
8761
|
return out;
|
|
8668
8762
|
}
|
|
8763
|
+
if (e.fn === "error.propTypeThrow") {
|
|
8764
|
+
// The property flavor of argTypeThrow — same always-throw shape.
|
|
8765
|
+
const an = this.emitExpr(e.args[0]);
|
|
8766
|
+
const ex = this.emitExpr(e.args[1]);
|
|
8767
|
+
const got = this.emitExpr(e.args[2]);
|
|
8768
|
+
this.declare(`declare void @scr_throw_prop_type(ptr, ptr, ptr)`);
|
|
8769
|
+
B.line(`call void @scr_throw_prop_type(ptr ${an.name}, ptr ${ex.name}, ptr ${got.name})`);
|
|
8770
|
+
const ty = this.llType(e.type);
|
|
8771
|
+
if (ty === "void") {
|
|
8772
|
+
this.emitPendingCheck();
|
|
8773
|
+
return { name: "", type: e.type };
|
|
8774
|
+
}
|
|
8775
|
+
const dummy = ty === "double" ? f64Lit(0) : ty === "i1" ? "false" : "null";
|
|
8776
|
+
const out = this.own({ name: dummy, type: e.type });
|
|
8777
|
+
this.emitPendingCheck();
|
|
8778
|
+
return out;
|
|
8779
|
+
}
|
|
8780
|
+
{
|
|
8781
|
+
// The fs validation-ladder Chk forms that ALWAYS throw (a
|
|
8782
|
+
// validation error or the trailing compiler-rendered fence): every
|
|
8783
|
+
// argument is a ptr (dyns + the fence string), and the typed dummy
|
|
8784
|
+
// is abandoned by the pending check's unwind.
|
|
8785
|
+
const FS_CHK_THROW_SYMS = {
|
|
8786
|
+
"fs.mkdtempChk": "scr_fs_mkdtemp_chk",
|
|
8787
|
+
"fs.readFileChk": "scr_fs_read_file_chk",
|
|
8788
|
+
"fs.opendirChk": "scr_fs_opendir_chk",
|
|
8789
|
+
"fs.watchFileChk": "scr_fs_watch_file_chk",
|
|
8790
|
+
"fs.lchmodChk": "scr_fs_lchmod_chk",
|
|
8791
|
+
"fs.readChk": "scr_fs_read_chk",
|
|
8792
|
+
"fs.streamOptsChk": "scr_fs_stream_opts_chk",
|
|
8793
|
+
"net.connectOptsChk": "scr_net_connect_opts_chk",
|
|
8794
|
+
};
|
|
8795
|
+
const sym = FS_CHK_THROW_SYMS[e.fn];
|
|
8796
|
+
if (sym !== undefined) {
|
|
8797
|
+
const args = e.args.map((a) => this.emitExpr(a));
|
|
8798
|
+
this.declare(`declare void @${sym}(${args.map(() => "ptr").join(", ")})`);
|
|
8799
|
+
B.line(`call void @${sym}(${args.map((a) => `ptr ${a.name}`).join(", ")})`);
|
|
8800
|
+
const ty = this.llType(e.type);
|
|
8801
|
+
if (ty === "void") {
|
|
8802
|
+
this.emitPendingCheck();
|
|
8803
|
+
return { name: "", type: e.type };
|
|
8804
|
+
}
|
|
8805
|
+
const dummy = ty === "double" ? f64Lit(0) : ty === "i1" ? "false" : "null";
|
|
8806
|
+
const out = this.own({ name: dummy, type: e.type });
|
|
8807
|
+
this.emitPendingCheck();
|
|
8808
|
+
return out;
|
|
8809
|
+
}
|
|
8810
|
+
}
|
|
8669
8811
|
if (e.fn === "error.nodeThrow") {
|
|
8670
8812
|
// The compiler-resolved Node-parity throw (always throws — the
|
|
8671
8813
|
// typed dummy is abandoned by the pending check's unwind).
|