@scriptc/compiler 0.0.23 → 0.0.25
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/ambient/scriptc-node-fallback.d.ts +100 -11
- package/dist/backend/cc.d.ts +13 -0
- package/dist/backend/cc.js +11 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.d.ts +4 -0
- package/dist/backend/emission/emit-async.js +31 -1
- package/dist/backend/emission/emit-async.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +147 -14
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -0
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +24 -5
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-types.js +10 -0
- package/dist/backend/emission/emit-types.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +10 -2
- package/dist/backend/emission/emitter.js +49 -30
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.js +284 -25
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +9 -1
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/mangle.d.ts +3 -0
- package/dist/backend/mangle.js +5 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +14 -9
- package/dist/frontend/lowering/lower-builtins.js +737 -62
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +2 -1
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +2 -1
- package/dist/frontend/lowering/lower-containers.js +99 -32
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +53 -2
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +59 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +5 -0
- package/dist/frontend/lowering/lower-server.js +1 -1
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +6 -2
- package/dist/frontend/lowering/lower-stmts.js +45 -10
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +2 -2
- package/dist/frontend/lowering/lowerer.js +11 -6
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +65 -13
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/types.d.ts +3 -0
- package/dist/frontend/types.js +78 -0
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +23 -0
- package/dist/ir/integer-loops.js +82 -0
- package/dist/ir/integer-loops.js.map +1 -0
- package/dist/ir/nodes.d.ts +84 -21
- package/dist/ir/nodes.js +84 -1
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +92 -18
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.js +4 -3
- package/dist/library/fence-eval.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +50 -2
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as ts from "../ts7/adapter.js";
|
|
2
2
|
import type { Lowerer } from "./lowerer.js";
|
|
3
3
|
import { IrExpr, IrFunction, IrRecordShape, IrStmt, IrType, SrcLoc } from "../../ir/nodes.js";
|
|
4
|
-
/** Ambient array method calls. `push`/`pop`/`
|
|
4
|
+
/** Ambient array method calls. `push`/`unshift`/`pop`/`reverse`/
|
|
5
|
+
* `indexOf`/`includes`/`join`
|
|
5
6
|
* lower to arrIntrinsic; the HOF family — `map`/`filter`/`forEach`/
|
|
6
7
|
* `find`/`some`/`every`/`flatMap`/`reduce`/`reduceRight` — desugars to a
|
|
7
8
|
* direct call of a synthetic loop function (see lowerArrayHofCall and
|
|
@@ -70,11 +70,29 @@ function defaultAfterUndefined(value, defaultValue) {
|
|
|
70
70
|
}
|
|
71
71
|
function lowerOptionalDefaultArg(L, node, expected, defaultValue) {
|
|
72
72
|
const undefinedArg = lowerStaticallyUndefinedArg(L, node);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
if (undefinedArg)
|
|
74
|
+
return defaultAfterUndefined(undefinedArg, defaultValue);
|
|
75
|
+
const value = L.lowerExpr(node);
|
|
76
|
+
if (value.type.kind === "union") {
|
|
77
|
+
const def = L.unions.get(value.type.unionId);
|
|
78
|
+
if (def?.arms.length === 2 &&
|
|
79
|
+
def.arms.some((arm) => arm.kind === "undefinedT") &&
|
|
80
|
+
def.arms.some((arm) => typeEquals(arm, expected))) {
|
|
81
|
+
// A runtime optional argument uses its API default only on the
|
|
82
|
+
// undefined arm. The exact two-arm gate deliberately excludes null:
|
|
83
|
+
// optional parameters do not admit it, and an asserted null must keep
|
|
84
|
+
// the ordinary checked-narrow failure instead of defaulting.
|
|
85
|
+
return { kind: "nullish", left: value, right: defaultValue, type: expected, loc: value.loc };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return L.coerceInto(node, value, expected);
|
|
76
89
|
}
|
|
77
|
-
|
|
90
|
+
function lowerSplitLimitArg(L, node, loc) {
|
|
91
|
+
const defaultValue = { kind: "numLit", value: 4294967295, type: F64, loc };
|
|
92
|
+
return node ? lowerOptionalDefaultArg(L, node, F64, defaultValue) : defaultValue;
|
|
93
|
+
}
|
|
94
|
+
/** Ambient array method calls. `push`/`unshift`/`pop`/`reverse`/
|
|
95
|
+
* `indexOf`/`includes`/`join`
|
|
78
96
|
* lower to arrIntrinsic; the HOF family — `map`/`filter`/`forEach`/
|
|
79
97
|
* `find`/`some`/`every`/`flatMap`/`reduce`/`reduceRight` — desugars to a
|
|
80
98
|
* direct call of a synthetic loop function (see lowerArrayHofCall and
|
|
@@ -184,6 +202,19 @@ export function lowerArrayMethodCall(L, call, access) {
|
|
|
184
202
|
loc,
|
|
185
203
|
};
|
|
186
204
|
}
|
|
205
|
+
if (name === "reverse") {
|
|
206
|
+
if (call.arguments.length !== 0) {
|
|
207
|
+
L.noLowering(`.reverse with ${call.arguments.length} arguments`, call);
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
kind: "arrIntrinsic",
|
|
211
|
+
method: "reverse",
|
|
212
|
+
receiver: L.lowerExpr(access.expression),
|
|
213
|
+
args: [],
|
|
214
|
+
type: receiverIr,
|
|
215
|
+
loc,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
187
218
|
if (name === "with") {
|
|
188
219
|
if (call.arguments.length !== 2 || call.arguments.some(ts.isSpreadElement)) {
|
|
189
220
|
L.noLowering(`.with with ${call.arguments.length} arguments`, call);
|
|
@@ -238,11 +269,11 @@ export function lowerArrayMethodCall(L, call, access) {
|
|
|
238
269
|
// indexOf/includes take a fromIndex, join's separator is optional, the
|
|
239
270
|
// predicate/mapping HOFs take a thisArg. Each unlowered form is fenced
|
|
240
271
|
// per site (SC2020), never silently truncated to the supported
|
|
241
|
-
// arguments. push
|
|
272
|
+
// arguments. push/unshift lower every declared form (variadic, 0 args
|
|
242
273
|
// included — Node returns the unchanged length); reduce/reduceRight
|
|
243
274
|
// lower both declared forms (with and without an initial value).
|
|
244
275
|
const arity = {
|
|
245
|
-
push: [0, Number.MAX_SAFE_INTEGER], pop: [0, 0], indexOf: [1, 1], includes: [1, 1], join: [1, 1],
|
|
276
|
+
push: [0, Number.MAX_SAFE_INTEGER], unshift: [0, Number.MAX_SAFE_INTEGER], pop: [0, 0], indexOf: [1, 1], includes: [1, 1], join: [1, 1],
|
|
246
277
|
concat: [0, Number.MAX_SAFE_INTEGER],
|
|
247
278
|
slice: [0, 2], shift: [0, 0], splice: [1, 2], at: [1, 1],
|
|
248
279
|
map: [1, 1], filter: [1, 1], forEach: [1, 1], find: [1, 1], findIndex: [1, 1], some: [1, 1],
|
|
@@ -262,36 +293,43 @@ export function lowerArrayMethodCall(L, call, access) {
|
|
|
262
293
|
: undefined;
|
|
263
294
|
L.noLowering(`.${name} with ${call.arguments.length} argument${call.arguments.length === 1 ? "" : "s"}`, call, hint);
|
|
264
295
|
}
|
|
265
|
-
if (name === "push" || name === "pop") {
|
|
296
|
+
if (name === "push" || name === "unshift" || name === "pop") {
|
|
266
297
|
const receiver = L.lowerExpr(access.expression);
|
|
267
|
-
// `a.push(...src)`:
|
|
268
|
-
// snapshotted first, so
|
|
269
|
-
// return the new length.
|
|
298
|
+
// `a.push(...src)` / `a.unshift(...src)`: copy src's elements in
|
|
299
|
+
// order (count snapshotted first, so the self-spread forms duplicate
|
|
300
|
+
// like JS) and return the new length.
|
|
270
301
|
const spreadArg = call.arguments.length === 1 && ts.isSpreadElement(call.arguments[0])
|
|
271
302
|
? call.arguments[0]
|
|
272
303
|
: null;
|
|
273
|
-
if (name === "push" && spreadArg && ts.isSpreadElement(spreadArg)) {
|
|
304
|
+
if ((name === "push" || name === "unshift") && spreadArg && ts.isSpreadElement(spreadArg)) {
|
|
274
305
|
let src = L.lowerExpr(spreadArg.expression);
|
|
275
|
-
// `a.push(...someSet)`: a same-element Set drains first
|
|
306
|
+
// `a.push(...someSet)` / `a.unshift(...someSet)`: a same-element Set drains first
|
|
276
307
|
// (setIntrinsic toArray — insertion order), then appends.
|
|
277
308
|
if (src.type.kind === "set" && typeEquals(src.type.elem, elem)) {
|
|
278
309
|
src = { kind: "setIntrinsic", method: "toArray", receiver: src, args: [], type: arrayOf(src.type.elem), loc };
|
|
279
310
|
}
|
|
280
311
|
if (!typeEquals(src.type, receiverIr)) {
|
|
281
|
-
L.unsupported("SC1090", spreadArg,
|
|
312
|
+
L.unsupported("SC1090", spreadArg, `${name === "push" ? "pushing" : "unshifting"} a spread of '${L.fmt(src.type)}' onto a '${L.fmt(receiverIr)}' array (only a same-element-type array spreads)`);
|
|
282
313
|
}
|
|
283
|
-
return {
|
|
314
|
+
return {
|
|
315
|
+
kind: "arrIntrinsic",
|
|
316
|
+
method: name === "push" ? "pushSpread" : "unshiftSpread",
|
|
317
|
+
receiver,
|
|
318
|
+
args: [src],
|
|
319
|
+
type: F64,
|
|
320
|
+
loc,
|
|
321
|
+
};
|
|
284
322
|
}
|
|
285
|
-
//
|
|
323
|
+
// Inserted values flow into the element slot like an assignment would:
|
|
286
324
|
// union-element arrays wrap plain arm values (coerceInto is inert
|
|
287
325
|
// when the types already agree).
|
|
288
|
-
const args = call.arguments.map((a) => name === "push" ? L.lowerExprExpecting(a, elem) : L.lowerExpr(a));
|
|
326
|
+
const args = call.arguments.map((a) => name === "push" || name === "unshift" ? L.lowerExprExpecting(a, elem) : L.lowerExpr(a));
|
|
289
327
|
return {
|
|
290
328
|
kind: "arrIntrinsic",
|
|
291
329
|
method: name,
|
|
292
330
|
receiver,
|
|
293
331
|
args,
|
|
294
|
-
type: name === "push" ? F64 : elem,
|
|
332
|
+
type: name === "push" || name === "unshift" ? F64 : elem,
|
|
295
333
|
loc,
|
|
296
334
|
};
|
|
297
335
|
}
|
|
@@ -539,7 +577,7 @@ export function lowerArrayHofCall(L, call, access, method, elem) {
|
|
|
539
577
|
if (method === "map" &&
|
|
540
578
|
(fnRet.kind === "map" || fnRet.kind === "set" || fnRet.kind === "url" ||
|
|
541
579
|
fnRet.kind === "searchParams" || fnRet.kind === "generator" || fnRet.kind === "caught" ||
|
|
542
|
-
fnRet.kind === "stats" || fnRet.kind === "spawnRes" || fnRet.kind === "netSocket" ||
|
|
580
|
+
fnRet.kind === "stats" || fnRet.kind === "fileHandle" || fnRet.kind === "spawnRes" || fnRet.kind === "netSocket" ||
|
|
543
581
|
fnRet.kind === "dgramSocket" || fnRet.kind === "testCtx" || fnRet.kind === "httpReq" ||
|
|
544
582
|
fnRet.kind === "httpRes" || fnRet.kind === "httpClientReq" || fnRet.kind === "secureCtx" ||
|
|
545
583
|
fnRet.kind === "fsWatcher" || fnRet.kind === "childStream" || fnRet.kind === "procStream" ||
|
|
@@ -4618,14 +4656,13 @@ export function lowerRegexMethodCall(L, call, access, dynReceiver) {
|
|
|
4618
4656
|
const arg0 = call.arguments[0];
|
|
4619
4657
|
if (!arg0 || L.mapTypeOf(L.typeOf(arg0))?.kind !== "regex")
|
|
4620
4658
|
return null;
|
|
4621
|
-
// The lib declares forms beyond the lowered slice: split's limit
|
|
4622
|
-
// parameter and function replacement values both typecheck now —
|
|
4623
|
-
// fenced with the regex-surface code (its hint lists what works).
|
|
4624
|
-
if (name === "split" && call.arguments.length !== 1) {
|
|
4625
|
-
L.unsupported("SC1120", call, "'.split()' with a limit argument");
|
|
4626
|
-
}
|
|
4627
4659
|
const receiver = lowerReceiver();
|
|
4628
|
-
|
|
4660
|
+
// Split's omitted or undefined limit is 2^32-1. Complete it here so
|
|
4661
|
+
// both IR backends and the runtime have one required (regex, limit)
|
|
4662
|
+
// shape; an optional-number value selects the default at runtime.
|
|
4663
|
+
const args = name === "split"
|
|
4664
|
+
? [L.lowerExpr(arg0), lowerSplitLimitArg(L, call.arguments[1], loc)]
|
|
4665
|
+
: call.arguments.map((a) => L.lowerExpr(a));
|
|
4629
4666
|
if (name !== "split" && args[1]?.type.kind !== "string") {
|
|
4630
4667
|
L.unsupported("SC1120", call.arguments[1] ?? call, "function replacement values (replacements must be string templates)");
|
|
4631
4668
|
}
|
|
@@ -4677,7 +4714,9 @@ export function lowerStringMethodCall(L, call, access, dynReceiver) {
|
|
|
4677
4714
|
L.noLowering(`.${access.name.text} with ${call.arguments.length} argument${call.arguments.length === 1 ? "" : "s"} on strings`, call);
|
|
4678
4715
|
}
|
|
4679
4716
|
const receiver = dynReceiver ? dynReceiver() : L.lowerExpr(access.expression);
|
|
4680
|
-
const args =
|
|
4717
|
+
const args = entry.method === "split"
|
|
4718
|
+
? [L.lowerExpr(call.arguments[0]), lowerSplitLimitArg(L, call.arguments[1], locOf(call))]
|
|
4719
|
+
: call.arguments.map((a) => L.lowerExpr(a));
|
|
4681
4720
|
// split's separator must BE a string here (a regex argument was
|
|
4682
4721
|
// claimed by lowerRegexMethodCall before this path) — the lib's
|
|
4683
4722
|
// `string | RegExp` union has no lowering as a VALUE.
|
|
@@ -5041,10 +5080,38 @@ export function lowerBytesMethodCall(L, call, access) {
|
|
|
5041
5080
|
}
|
|
5042
5081
|
if (nArgs > 3)
|
|
5043
5082
|
L.noLowering(`.toString with ${nArgs} arguments on Buffers`, call);
|
|
5044
|
-
const encNode = call.arguments[0];
|
|
5045
|
-
const encName = encNode ? bufEncoding(L, "Buffer.toString", encNode) : "utf8";
|
|
5046
5083
|
const receiver = L.lowerExpr(access.expression);
|
|
5047
|
-
const
|
|
5084
|
+
const encNode = call.arguments[0];
|
|
5085
|
+
let method = "toString";
|
|
5086
|
+
let enc = { kind: "strLit", value: "utf8", type: STRING, loc };
|
|
5087
|
+
if (encNode) {
|
|
5088
|
+
const encType = L.typeOf(encNode);
|
|
5089
|
+
const encName = encType.isStringLiteralType()
|
|
5090
|
+
? knownBufEncoding(encType.value)
|
|
5091
|
+
: undefined;
|
|
5092
|
+
if (encName !== undefined) {
|
|
5093
|
+
// Keep literals on the canonical, non-throwing fast path.
|
|
5094
|
+
enc = { kind: "strLit", value: encName, type: STRING, loc };
|
|
5095
|
+
}
|
|
5096
|
+
else {
|
|
5097
|
+
const undefinedArg = lowerStaticallyUndefinedArg(L, encNode);
|
|
5098
|
+
if (undefinedArg) {
|
|
5099
|
+
// An explicit undefined is the omitted-encoding default. Keep
|
|
5100
|
+
// the canonical, non-throwing path while preserving effects
|
|
5101
|
+
// from equivalent spellings such as `void sideEffect()`.
|
|
5102
|
+
enc = defaultAfterUndefined(undefinedArg, enc);
|
|
5103
|
+
}
|
|
5104
|
+
else {
|
|
5105
|
+
// A BufferEncoding-typed variable selects its decoder at
|
|
5106
|
+
// runtime. Optional variables default their undefined arm to
|
|
5107
|
+
// utf8; the checked intrinsic canonicalizes every present
|
|
5108
|
+
// alias/case and raises Node's ERR_UNKNOWN_ENCODING when a cast
|
|
5109
|
+
// lets a bad value through.
|
|
5110
|
+
enc = lowerOptionalDefaultArg(L, encNode, STRING, enc);
|
|
5111
|
+
method = "toStringVar";
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5048
5115
|
// The range form toString(enc, start[, end]) decodes the clamped
|
|
5049
5116
|
// [start, end) byte window (Node's slice-then-decode). An omitted
|
|
5050
5117
|
// end stays omitted (2 intrinsic args) — the emitter supplies the
|
|
@@ -5054,11 +5121,11 @@ export function lowerBytesMethodCall(L, call, access) {
|
|
|
5054
5121
|
const start = L.lowerExprExpecting(call.arguments[1], F64);
|
|
5055
5122
|
if (nArgs === 3) {
|
|
5056
5123
|
const end = L.lowerExprExpecting(call.arguments[2], F64);
|
|
5057
|
-
return { kind: "bytesIntrinsic", method
|
|
5124
|
+
return { kind: "bytesIntrinsic", method, receiver, args: [enc, start, end], type: STRING, loc };
|
|
5058
5125
|
}
|
|
5059
|
-
return { kind: "bytesIntrinsic", method
|
|
5126
|
+
return { kind: "bytesIntrinsic", method, receiver, args: [enc, start], type: STRING, loc };
|
|
5060
5127
|
}
|
|
5061
|
-
return { kind: "bytesIntrinsic", method
|
|
5128
|
+
return { kind: "bytesIntrinsic", method, receiver, args: [enc], type: STRING, loc };
|
|
5062
5129
|
}
|
|
5063
5130
|
// The Buffer-declared comparison/search/mutation surface. All of
|
|
5064
5131
|
// these resolve against the Buffer interface (the checker keeps most
|