@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.
Files changed (65) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +100 -11
  2. package/dist/backend/cc.d.ts +13 -0
  3. package/dist/backend/cc.js +11 -0
  4. package/dist/backend/cc.js.map +1 -1
  5. package/dist/backend/emission/emit-async.d.ts +4 -0
  6. package/dist/backend/emission/emit-async.js +31 -1
  7. package/dist/backend/emission/emit-async.js.map +1 -1
  8. package/dist/backend/emission/emit-exprs.js +147 -14
  9. package/dist/backend/emission/emit-exprs.js.map +1 -1
  10. package/dist/backend/emission/emit-shapes.js +1 -0
  11. package/dist/backend/emission/emit-shapes.js.map +1 -1
  12. package/dist/backend/emission/emit-stmts.js +24 -5
  13. package/dist/backend/emission/emit-stmts.js.map +1 -1
  14. package/dist/backend/emission/emit-types.js +10 -0
  15. package/dist/backend/emission/emit-types.js.map +1 -1
  16. package/dist/backend/emission/emitter.d.ts +10 -2
  17. package/dist/backend/emission/emitter.js +49 -30
  18. package/dist/backend/emission/emitter.js.map +1 -1
  19. package/dist/backend/llvm/emitter.js +284 -25
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/shapes.js +9 -1
  22. package/dist/backend/llvm/shapes.js.map +1 -1
  23. package/dist/backend/mangle.d.ts +3 -0
  24. package/dist/backend/mangle.js +5 -0
  25. package/dist/backend/mangle.js.map +1 -1
  26. package/dist/frontend/lowering/lower-builtins.d.ts +14 -9
  27. package/dist/frontend/lowering/lower-builtins.js +737 -62
  28. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  29. package/dist/frontend/lowering/lower-calls.js +2 -1
  30. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  31. package/dist/frontend/lowering/lower-containers.d.ts +2 -1
  32. package/dist/frontend/lowering/lower-containers.js +99 -32
  33. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  34. package/dist/frontend/lowering/lower-exprs.js +53 -2
  35. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  36. package/dist/frontend/lowering/lower-inspect.js +59 -1
  37. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  38. package/dist/frontend/lowering/lower-server.d.ts +5 -0
  39. package/dist/frontend/lowering/lower-server.js +1 -1
  40. package/dist/frontend/lowering/lower-server.js.map +1 -1
  41. package/dist/frontend/lowering/lower-stmts.d.ts +6 -2
  42. package/dist/frontend/lowering/lower-stmts.js +45 -10
  43. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  44. package/dist/frontend/lowering/lowerer.d.ts +2 -2
  45. package/dist/frontend/lowering/lowerer.js +11 -6
  46. package/dist/frontend/lowering/lowerer.js.map +1 -1
  47. package/dist/frontend/lowering/surfaces.js +65 -13
  48. package/dist/frontend/lowering/surfaces.js.map +1 -1
  49. package/dist/frontend/types.d.ts +3 -0
  50. package/dist/frontend/types.js +78 -0
  51. package/dist/frontend/types.js.map +1 -1
  52. package/dist/index.js +8 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/ir/integer-loops.d.ts +23 -0
  55. package/dist/ir/integer-loops.js +82 -0
  56. package/dist/ir/integer-loops.js.map +1 -0
  57. package/dist/ir/nodes.d.ts +84 -21
  58. package/dist/ir/nodes.js +84 -1
  59. package/dist/ir/nodes.js.map +1 -1
  60. package/dist/ir/validate.js +92 -18
  61. package/dist/ir/validate.js.map +1 -1
  62. package/dist/library/fence-eval.js +4 -3
  63. package/dist/library/fence-eval.js.map +1 -1
  64. package/package.json +2 -2
  65. 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`/`indexOf`/`includes`/`join`
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
- return undefinedArg
74
- ? defaultAfterUndefined(undefinedArg, defaultValue)
75
- : L.lowerExprExpecting(node, expected);
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
- /** Ambient array method calls. `push`/`pop`/`indexOf`/`includes`/`join`
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 lowers every declared form (variadic, 0 args
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)`: append src's elements in order (count
268
- // snapshotted first, so `a.push(...a)` duplicates like JS) and
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, `pushing a spread of '${L.fmt(src.type)}' onto a '${L.fmt(receiverIr)}' array (only a same-element-type array spreads)`);
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 { kind: "arrIntrinsic", method: "pushSpread", receiver, args: [src], type: F64, loc };
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
- // Pushed values flow into the element slot like an assignment would:
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
- const args = call.arguments.map((a) => L.lowerExpr(a));
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 = call.arguments.map((a) => L.lowerExpr(a));
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 enc = { kind: "strLit", value: encName, type: STRING, loc };
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: "toString", receiver, args: [enc, start, end], type: STRING, loc };
5124
+ return { kind: "bytesIntrinsic", method, receiver, args: [enc, start, end], type: STRING, loc };
5058
5125
  }
5059
- return { kind: "bytesIntrinsic", method: "toString", receiver, args: [enc, start], type: STRING, loc };
5126
+ return { kind: "bytesIntrinsic", method, receiver, args: [enc, start], type: STRING, loc };
5060
5127
  }
5061
- return { kind: "bytesIntrinsic", method: "toString", receiver, args: [enc], type: STRING, loc };
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