@scriptc/compiler 0.1.6 → 0.1.7

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 (116) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +0 -1
  2. package/ambient/scriptc.d.ts +13 -5
  3. package/dist/backend/c/c-emitter.d.ts +5 -0
  4. package/dist/backend/c/c-emitter.js +15 -0
  5. package/dist/backend/c/c-emitter.js.map +1 -1
  6. package/dist/backend/c/exprs.js +45 -1
  7. package/dist/backend/c/exprs.js.map +1 -1
  8. package/dist/backend/c/stmts.js +25 -1
  9. package/dist/backend/c/stmts.js.map +1 -1
  10. package/dist/backend/c/walkers.js +2 -3
  11. package/dist/backend/c/walkers.js.map +1 -1
  12. package/dist/backend/debug-symbols.d.ts +8 -0
  13. package/dist/backend/debug-symbols.js +52 -0
  14. package/dist/backend/debug-symbols.js.map +1 -0
  15. package/dist/backend/link-plan.d.ts +1 -0
  16. package/dist/backend/link-plan.js +2 -0
  17. package/dist/backend/link-plan.js.map +1 -1
  18. package/dist/backend/linker.js +8 -0
  19. package/dist/backend/linker.js.map +1 -1
  20. package/dist/backend/llvm/blocks.d.ts +2 -0
  21. package/dist/backend/llvm/blocks.js +18 -2
  22. package/dist/backend/llvm/blocks.js.map +1 -1
  23. package/dist/backend/llvm/debug-info.d.ts +32 -0
  24. package/dist/backend/llvm/debug-info.js +203 -0
  25. package/dist/backend/llvm/debug-info.js.map +1 -0
  26. package/dist/backend/llvm/dyn.js +4 -10
  27. package/dist/backend/llvm/dyn.js.map +1 -1
  28. package/dist/backend/llvm/emitter.d.ts +2 -0
  29. package/dist/backend/llvm/emitter.js +49 -4
  30. package/dist/backend/llvm/emitter.js.map +1 -1
  31. package/dist/backend/llvm/expr-dynamic.js +10 -0
  32. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  33. package/dist/backend/llvm/lib-filesystem.js +29 -0
  34. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  35. package/dist/backend/llvm/lib-shared.js +8 -0
  36. package/dist/backend/llvm/lib-shared.js.map +1 -1
  37. package/dist/backend/llvm/split.js +4 -1
  38. package/dist/backend/llvm/split.js.map +1 -1
  39. package/dist/backend/llvm/split.test.js +26 -1
  40. package/dist/backend/llvm/split.test.js.map +1 -1
  41. package/dist/backend/native-toolchain.js +58 -8
  42. package/dist/backend/native-toolchain.js.map +1 -1
  43. package/dist/backend/native-toolchain.test.js +10 -0
  44. package/dist/backend/native-toolchain.test.js.map +1 -1
  45. package/dist/backend/source-locations.d.ts +12 -0
  46. package/dist/backend/source-locations.js +32 -0
  47. package/dist/backend/source-locations.js.map +1 -0
  48. package/dist/backend/source-locations.test.d.ts +1 -0
  49. package/dist/backend/source-locations.test.js +16 -0
  50. package/dist/backend/source-locations.test.js.map +1 -0
  51. package/dist/diagnostics/diagnostic.d.ts +4 -0
  52. package/dist/diagnostics/diagnostic.js +12 -0
  53. package/dist/diagnostics/diagnostic.js.map +1 -1
  54. package/dist/executable/executable-cache.js +28 -4
  55. package/dist/executable/executable-cache.js.map +1 -1
  56. package/dist/executable/executable-cache.test.js +23 -0
  57. package/dist/executable/executable-cache.test.js.map +1 -1
  58. package/dist/frontend/arguments-usage.d.ts +6 -0
  59. package/dist/frontend/arguments-usage.js +40 -0
  60. package/dist/frontend/arguments-usage.js.map +1 -0
  61. package/dist/frontend/binding-source.d.ts +4 -0
  62. package/dist/frontend/binding-source.js +18 -0
  63. package/dist/frontend/binding-source.js.map +1 -0
  64. package/dist/frontend/lowering/expressions/object-literals.js +13 -8
  65. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  66. package/dist/frontend/lowering/expressions/optional-chains.d.ts +5 -6
  67. package/dist/frontend/lowering/expressions/optional-chains.js +7 -6
  68. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  69. package/dist/frontend/lowering/lower-builtins.js +15 -4
  70. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  71. package/dist/frontend/lowering/lower-calls.d.ts +2 -9
  72. package/dist/frontend/lowering/lower-calls.js +140 -30
  73. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  74. package/dist/frontend/lowering/lower-exprs.js +116 -16
  75. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  76. package/dist/frontend/lowering/lower-island.d.ts +1 -1
  77. package/dist/frontend/lowering/lower-island.js +1 -1
  78. package/dist/frontend/lowering/lower-modules.js +19 -8
  79. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  80. package/dist/frontend/lowering/lower-stmts.js +4 -37
  81. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  82. package/dist/frontend/lowering/lowerer.js +14 -3
  83. package/dist/frontend/lowering/lowerer.js.map +1 -1
  84. package/dist/frontend/lowering/surfaces.d.ts +1 -1
  85. package/dist/frontend/lowering/surfaces.js +37 -6
  86. package/dist/frontend/lowering/surfaces.js.map +1 -1
  87. package/dist/frontend/program.d.ts +5 -0
  88. package/dist/frontend/program.js +216 -32
  89. package/dist/frontend/program.js.map +1 -1
  90. package/dist/frontend/program.test.d.ts +1 -0
  91. package/dist/frontend/program.test.js +117 -0
  92. package/dist/frontend/program.test.js.map +1 -0
  93. package/dist/frontend/type-mapper.d.ts +4 -2
  94. package/dist/frontend/type-mapper.js +249 -186
  95. package/dist/frontend/type-mapper.js.map +1 -1
  96. package/dist/frontend/type-mapper.test.d.ts +1 -0
  97. package/dist/frontend/type-mapper.test.js +86 -0
  98. package/dist/frontend/type-mapper.test.js.map +1 -0
  99. package/dist/index.d.ts +2 -1
  100. package/dist/index.js +7 -2
  101. package/dist/index.js.map +1 -1
  102. package/dist/ir/analysis.js +4 -2
  103. package/dist/ir/analysis.js.map +1 -1
  104. package/dist/ir/ir.d.ts +18 -12
  105. package/dist/ir/ir.js +3 -1
  106. package/dist/ir/ir.js.map +1 -1
  107. package/dist/ir/validate.js +14 -5
  108. package/dist/ir/validate.js.map +1 -1
  109. package/dist/library/compiler-self-identity.d.ts +1 -1
  110. package/dist/library/compiler-self-identity.js +31 -15
  111. package/dist/library/compiler-self-identity.js.map +1 -1
  112. package/dist/library/compiler-self-identity.test.d.ts +1 -0
  113. package/dist/library/compiler-self-identity.test.js +93 -0
  114. package/dist/library/compiler-self-identity.test.js.map +1 -0
  115. package/package.json +17 -17
  116. package/surface-manifest.json +120 -1
@@ -1,8 +1,10 @@
1
1
  import * as ts from "../ts7/adapter.js";
2
+ import { bodyReadsArguments } from "../arguments-usage.js";
2
3
  import type { Lowerer } from "./lowerer.js";
3
4
  import { IrExpr, IrFunction, IrStmt, IrType, SrcLoc } from "../../ir/ir.js";
4
5
  import type { ScrDiagnostic } from "../../diagnostics/diagnostic.js";
5
6
  import { type ClassInfo } from "./lower-classes.js";
7
+ export { bodyReadsArguments };
6
8
  /** How a parameter participates in CALL-SITE COMPLETION (the frontend
7
9
  * completes every call to the one full signature, so the IR and backends
8
10
  * stay count-exact — see docs/ir.md). `required` params must be passed;
@@ -423,15 +425,6 @@ export declare function lambdaSignature(lowerer: Lowerer, node: ts.ArrowFunction
423
425
  kind: "func";
424
426
  };
425
427
  };
426
- /** Does this function's OWN body read `arguments`? Nested plain functions
427
- * and methods have their own `arguments` (the walk skips them); arrows
428
- * see the enclosing one (the walk descends). Exported for the lowerer's
429
- * dynFallbackType: tsgo does not synthesize the `arguments` rest
430
- * parameter into inferred signatures (5.9.3 did — its param-count
431
- * mismatch was the detector), so the 7 world asks the BODY directly. */
432
- export declare function bodyReadsArguments(fn: {
433
- body?: ts.Node | undefined;
434
- }): boolean;
435
428
  /** Lifts an arrow function / function expression / nested declaration /
436
429
  * object-literal shorthand method to a module-level function and yields
437
430
  * the `closure` expression creating it. */
@@ -4,6 +4,7 @@ import { InternalCompilerError } from "../../errors.js";
4
4
  * function/lambda lowering and signature collection, and monomorphizing
5
5
  * generic instantiation (bounded by MAX_GENERIC_INSTANCES). */
6
6
  import * as ts from "../ts7/adapter.js";
7
+ import { bodyReadsArguments } from "../arguments-usage.js";
7
8
  import { lowerGenMethodCall } from "./lower-generators.js";
8
9
  import { BIGINT_T, BOOL, CAUGHT, DYN, F64, JSVAL, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
9
10
  import { isJsSourceFile, isNodeEsmFile, locOf } from "../program.js";
@@ -33,6 +34,7 @@ import { countedFor, varRef } from "../../ir/build.js";
33
34
  import { rejectStaticThis } from "./static-this.js";
34
35
  import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
35
36
  import { defaultAfterUndefined, lowerOptionalArgument, lowerStaticallyUndefinedArgument, positionNumber } from "./optional-arguments.js";
37
+ export { bodyReadsArguments };
36
38
  /** The one func-type projection of completed parameter shapes. Typed rest
37
39
  * parameters keep their packed array as the trailing native ABI slot and
38
40
  * mark the value variadic so indirect call sites run completeArgs before
@@ -6349,31 +6351,6 @@ export function lambdaSignature(lowerer, node) {
6349
6351
  funcType.rest = true;
6350
6352
  return { shapes, funcType };
6351
6353
  }
6352
- /** Does this function's OWN body read `arguments`? Nested plain functions
6353
- * and methods have their own `arguments` (the walk skips them); arrows
6354
- * see the enclosing one (the walk descends). Exported for the lowerer's
6355
- * dynFallbackType: tsgo does not synthesize the `arguments` rest
6356
- * parameter into inferred signatures (5.9.3 did — its param-count
6357
- * mismatch was the detector), so the 7 world asks the BODY directly. */
6358
- export function bodyReadsArguments(fn) {
6359
- let found = false;
6360
- if (fn.body === undefined)
6361
- return false;
6362
- // Iterative walk (walkPreorder): function bodies can hold pathologically
6363
- // deep expression chains that a recursive visit would die on.
6364
- ts.walkPreorder(fn.body, (n) => {
6365
- if (ts.isIdentifier(n) && n.text === "arguments" && !(ts.isPropertyAccessExpression(n.parent) && n.parent.name === n)) {
6366
- found = true;
6367
- return "stop";
6368
- }
6369
- if ((ts.isFunctionExpression(n) || ts.isFunctionDeclaration(n) || ts.isMethodDeclaration(n)) &&
6370
- n !== fn) {
6371
- return "skip"; // own `arguments` scope
6372
- }
6373
- return undefined;
6374
- });
6375
- return found;
6376
- }
6377
6354
  /** Lifts an arrow function / function expression / nested declaration /
6378
6355
  * object-literal shorthand method to a module-level function and yields
6379
6356
  * the `closure` expression creating it. */
@@ -6569,9 +6546,8 @@ export function lowerLambda(lowerer, node) {
6569
6546
  * becomes the catch binding, and a handler VALUE would need a
6570
6547
  * caught-typed closure parameter, which cannot exist. finally takes
6571
6548
  * any () => void closure (its callback sees no arguments). then takes
6572
- * exactly one FULFILLMENT handler (any closure value of the settled
6573
- * value's type — the two-argument onRejected form stays fenced toward
6574
- * .catch); a promise-returning handler flattens through the async
6549
+ * a fulfillment handler and optionally a rejection handler; a
6550
+ * promise-returning handler flattens through the async
6575
6551
  * return path, a receiver rejection passes through untouched (the
6576
6552
  * wrapper's await re-throws it), and a handler throw rejects the
6577
6553
  * result — the spec's onFulfilled rules by construction. Null for
@@ -6670,9 +6646,9 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
6670
6646
  };
6671
6647
  const passthrough = call.arguments.length === 0 ||
6672
6648
  (call.arguments.length === 1 && isAbsentHandler(call.arguments[0]));
6673
- if (call.arguments.length !== 1 && !passthrough) {
6649
+ if (call.arguments.length !== 1 && !passthrough && !(member === "then" && call.arguments.length === 2)) {
6674
6650
  lowerer.noLowering(`${member} with ${call.arguments.length} arguments`, call, member === "then"
6675
- ? "the supported form takes exactly one fulfillment handler — chain .catch(...) for the rejection half"
6651
+ ? "the supported form takes a fulfillment handler and an optional rejection handler"
6676
6652
  : `the supported form takes exactly one ${member === "catch" ? "inline handler" : "callback"}`);
6677
6653
  }
6678
6654
  // The receiver evaluates FIRST, in the enclosing function, like JS.
@@ -6744,6 +6720,140 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
6744
6720
  }
6745
6721
  }
6746
6722
  if (member === "then") {
6723
+ if (call.arguments.length === 2) {
6724
+ const fulfilledNode = call.arguments[0];
6725
+ const rejectedNode = call.arguments[1];
6726
+ const fulfilledAbsent = isAbsentHandler(fulfilledNode);
6727
+ const rejectedAbsent = isAbsentHandler(rejectedNode);
6728
+ const resultT = lowerer.mapTypeOf(lowerer.typeOf(call));
6729
+ if (resultT?.kind !== "promise") {
6730
+ lowerer.noLowering("then with these handlers", call, "the result must be a representable promise");
6731
+ }
6732
+ const R = resultT.inner;
6733
+ if (!fulfilledAbsent && inner.kind === "jsval")
6734
+ markJsvalHandlerParams(lowerer, fulfilledNode);
6735
+ if (!fulfilledAbsent && inner.kind === "moduleNs")
6736
+ markModuleNsHandlerParams(lowerer, fulfilledNode, inner);
6737
+ const boxHandler = (node, allowDirect) => {
6738
+ const value = lowerer.lowerExpr(node);
6739
+ if (allowDirect && value.type.kind === "func" && value.type.params.length <= 1 &&
6740
+ (value.type.params.length === 0 || (inner.kind !== "void" && typeEquals(value.type.params[0], inner)))) {
6741
+ return { value, direct: true, returnsPromise: value.type.ret.kind === "promise" };
6742
+ }
6743
+ if (value.type.kind === "dyn")
6744
+ return { value, direct: false, returnsPromise: false };
6745
+ if (value.type.kind === "func" && value.type.params.length <= 1 &&
6746
+ canBoxFuncIntoDyn(value.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
6747
+ return { value: { kind: "dynFrom", value, type: DYN, loc }, direct: false, returnsPromise: value.type.ret.kind === "promise" };
6748
+ }
6749
+ lowerer.unsupported("SC1090", node, "then handlers that cannot be called with one value");
6750
+ };
6751
+ // Evaluate both callback expressions before the wrapper runs, in source order.
6752
+ const fulfilled = fulfilledAbsent ? null : boxHandler(fulfilledNode, true);
6753
+ const rejected = rejectedAbsent ? null : boxHandler(rejectedNode, false);
6754
+ const fnName = `%fn${lowerer.lambdaCounter++}_then2`;
6755
+ const paramTypes = [promT, ...(fulfilled ? [fulfilled.value.type] : []), ...(rejected ? [DYN] : [])];
6756
+ const funcType = { kind: "func", params: paramTypes, ret: resultT };
6757
+ const fnCtx = newFnCtx(true, null, funcType, R);
6758
+ fnCtx.isAsync = true;
6759
+ lowerer.fnStack.push(fnCtx);
6760
+ try {
6761
+ const pLocal = lowerer.declareHiddenLocal("p", promT);
6762
+ const fLocal = fulfilled ? lowerer.declareHiddenLocal("f", fulfilled.value.type) : null;
6763
+ const rLocal = rejected ? lowerer.declareHiddenLocal("r", DYN) : null;
6764
+ const eLocal = lowerer.declareHiddenLocal("e", CAUGHT);
6765
+ const vLocal = inner.kind === "void" ? null : lowerer.declareHiddenLocal("v", inner);
6766
+ const awaitE = {
6767
+ kind: "awaitExpr",
6768
+ value: { kind: "varRef", localId: pLocal.id, type: promT, loc },
6769
+ type: inner,
6770
+ loc,
6771
+ };
6772
+ const tryBody = vLocal
6773
+ ? [{ kind: "varDecl", localId: vLocal.id, init: awaitE, loc }]
6774
+ : [{ kind: "exprStmt", expr: awaitE, loc }];
6775
+ const resultOf = (value, returnsPromise = false) => {
6776
+ const settled = value.type.kind === "promise"
6777
+ ? { kind: "awaitExpr", value, type: value.type.inner, loc }
6778
+ : returnsPromise
6779
+ ? { kind: "libCall", fn: "async.awaitDyn", args: [value], type: DYN, loc }
6780
+ : value;
6781
+ return R.kind === "void"
6782
+ ? [{ kind: "exprStmt", expr: settled, loc }, { kind: "return", value: null, loc }]
6783
+ : [{ kind: "return", value: lowerer.coerceInto(call, settled, R), loc }];
6784
+ };
6785
+ const rejectedCall = rLocal ? {
6786
+ kind: "dynCall",
6787
+ callee: { kind: "varRef", localId: rLocal.id, type: DYN, loc },
6788
+ calleeName: jsFuncNameOf(rejectedNode) ?? "onRejected",
6789
+ args: [{ kind: "caughtToDyn", value: { kind: "varRef", localId: eLocal.id, type: CAUGHT, loc }, type: DYN, loc }],
6790
+ type: DYN,
6791
+ loc,
6792
+ } : null;
6793
+ const catchBody = rejectedCall
6794
+ ? resultOf(rejectedCall, rejected?.returnsPromise)
6795
+ : [{ kind: "rethrow", localId: eLocal.id, loc }];
6796
+ const body = [{ kind: "tryCatch", tryBody, catchBody, catchLocalId: eLocal.id, finallyBody: null, loc }];
6797
+ // The fulfillment callback sits after the catch so a throw from it
6798
+ // rejects the result instead of reaching onRejected.
6799
+ if (fLocal) {
6800
+ const settled = vLocal
6801
+ ? { kind: "varRef", localId: vLocal.id, type: inner, loc }
6802
+ : dynUndefinedExpr(loc);
6803
+ if (fulfilled.direct && fLocal.type.kind === "func") {
6804
+ body.push(...resultOf({
6805
+ kind: "callValue",
6806
+ callee: { kind: "varRef", localId: fLocal.id, type: fLocal.type, loc },
6807
+ args: fLocal.type.params.length === 0 ? [] : [settled],
6808
+ type: fLocal.type.ret,
6809
+ loc,
6810
+ }));
6811
+ }
6812
+ else {
6813
+ const arg = settled.type.kind === "dyn" ? settled
6814
+ : canConvertToDyn(settled.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))
6815
+ ? { kind: "dynFrom", value: settled, type: DYN, loc }
6816
+ : lowerer.unsupported("SC1090", fulfilledNode, "then fulfillment values that cannot cross the checked-dynamic boundary");
6817
+ body.push(...resultOf({
6818
+ kind: "dynCall",
6819
+ callee: { kind: "varRef", localId: fLocal.id, type: DYN, loc },
6820
+ calleeName: jsFuncNameOf(fulfilledNode) ?? "onFulfilled",
6821
+ args: [arg], type: DYN, loc,
6822
+ }, fulfilled?.returnsPromise));
6823
+ }
6824
+ }
6825
+ else if (vLocal) {
6826
+ body.push(...resultOf({ kind: "varRef", localId: vLocal.id, type: inner, loc }));
6827
+ }
6828
+ else if (R.kind === "void") {
6829
+ body.push({ kind: "return", value: null, loc });
6830
+ }
6831
+ else {
6832
+ body.push({ kind: "return", value: lowerer.coerceInto(call, dynUndefinedExpr(loc), R), loc });
6833
+ }
6834
+ const ctx = lowerer.ctx;
6835
+ const lifted = {
6836
+ name: fnName,
6837
+ params: [
6838
+ { localId: pLocal.id, name: pLocal.name, type: promT },
6839
+ ...(fLocal ? [{ localId: fLocal.id, name: fLocal.name, type: fLocal.type }] : []),
6840
+ ...(rLocal ? [{ localId: rLocal.id, name: rLocal.name, type: DYN }] : []),
6841
+ ],
6842
+ returnType: R,
6843
+ locals: ctx.locals,
6844
+ captures: ctx.captures,
6845
+ body,
6846
+ loc,
6847
+ async: true,
6848
+ };
6849
+ lowerer.liftedFns.push(lifted);
6850
+ const closure = { kind: "closure", fnName, captures: ctx.captureSources, type: funcType, loc };
6851
+ return { kind: "callValue", callee: closure, args: [receiver, ...(fulfilled ? [fulfilled.value] : []), ...(rejected ? [rejected.value] : [])], type: resultT, loc };
6852
+ }
6853
+ finally {
6854
+ lowerer.fnStack.pop();
6855
+ }
6856
+ }
6747
6857
  // The settled value is an island HANDLE: an inline handler's
6748
6858
  // unannotated parameter binds it as jsval, whatever the checker's
6749
6859
  // contextual type spelled (a module-namespace type has no mapping —