@scriptc/compiler 0.2.9 → 0.2.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.
Files changed (147) hide show
  1. package/dist/backend/cycle-analysis.d.ts +56 -0
  2. package/dist/backend/cycle-analysis.js +175 -14
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/cycle-analysis.test.js +94 -1
  5. package/dist/backend/cycle-analysis.test.js.map +1 -1
  6. package/dist/backend/cycle-mutability.d.ts +2 -6
  7. package/dist/backend/cycle-mutability.js +3 -12
  8. package/dist/backend/cycle-mutability.js.map +1 -1
  9. package/dist/backend/immutability.d.ts +57 -0
  10. package/dist/backend/immutability.js +178 -0
  11. package/dist/backend/immutability.js.map +1 -0
  12. package/dist/backend/immutability.test.d.ts +1 -0
  13. package/dist/backend/immutability.test.js +131 -0
  14. package/dist/backend/immutability.test.js.map +1 -0
  15. package/dist/backend/llvm/borrowed-inputs.d.ts +9 -2
  16. package/dist/backend/llvm/borrowed-inputs.js +31 -3
  17. package/dist/backend/llvm/borrowed-inputs.js.map +1 -1
  18. package/dist/backend/llvm/classes.d.ts +28 -0
  19. package/dist/backend/llvm/classes.js +45 -5
  20. package/dist/backend/llvm/classes.js.map +1 -1
  21. package/dist/backend/llvm/classes.test.js +129 -1
  22. package/dist/backend/llvm/classes.test.js.map +1 -1
  23. package/dist/backend/llvm/common.d.ts +13 -0
  24. package/dist/backend/llvm/common.js +13 -0
  25. package/dist/backend/llvm/common.js.map +1 -1
  26. package/dist/backend/llvm/dense-array-access.js +5 -4
  27. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  28. package/dist/backend/llvm/dense-array-access.test.js +9 -1
  29. package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
  30. package/dist/backend/llvm/dyn.d.ts +2 -0
  31. package/dist/backend/llvm/dyn.js +3 -3
  32. package/dist/backend/llvm/dyn.js.map +1 -1
  33. package/dist/backend/llvm/emitter.d.ts +64 -2
  34. package/dist/backend/llvm/emitter.js +390 -45
  35. package/dist/backend/llvm/emitter.js.map +1 -1
  36. package/dist/backend/llvm/emitter.test.js +18 -0
  37. package/dist/backend/llvm/emitter.test.js.map +1 -1
  38. package/dist/backend/llvm/expr-calls.js +14 -6
  39. package/dist/backend/llvm/expr-calls.js.map +1 -1
  40. package/dist/backend/llvm/expr-containers.js +30 -7
  41. package/dist/backend/llvm/expr-containers.js.map +1 -1
  42. package/dist/backend/llvm/expr-primitives.js +30 -3
  43. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  44. package/dist/backend/llvm/expr-primitives.test.js +53 -0
  45. package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
  46. package/dist/backend/llvm/expr-stream-bridges.js +4 -4
  47. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  48. package/dist/backend/llvm/local-array-reads.js +3 -3
  49. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  50. package/dist/backend/llvm/loop-array-borrows.d.ts +5 -2
  51. package/dist/backend/llvm/loop-array-borrows.js +27 -8
  52. package/dist/backend/llvm/loop-array-borrows.js.map +1 -1
  53. package/dist/backend/llvm/map-number-lookup.d.ts +7 -0
  54. package/dist/backend/llvm/map-number-lookup.js +18 -1
  55. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  56. package/dist/backend/llvm/map-read-lifetimes.d.ts +5 -0
  57. package/dist/backend/llvm/map-read-lifetimes.js +14 -4
  58. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  59. package/dist/backend/llvm/map-read-lifetimes.test.js +5 -0
  60. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  61. package/dist/backend/llvm/reference-writes.d.ts +124 -0
  62. package/dist/backend/llvm/reference-writes.js +1090 -0
  63. package/dist/backend/llvm/reference-writes.js.map +1 -0
  64. package/dist/backend/llvm/shapes.d.ts +8 -5
  65. package/dist/backend/llvm/shapes.js +36 -11
  66. package/dist/backend/llvm/shapes.js.map +1 -1
  67. package/dist/backend/llvm/string-lifetimes.test.js +39 -10
  68. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  69. package/dist/backend/llvm/string-reads.d.ts +3 -0
  70. package/dist/backend/llvm/string-reads.js +31 -0
  71. package/dist/backend/llvm/string-reads.js.map +1 -1
  72. package/dist/backend/llvm/switch-dispatch.d.ts +2 -2
  73. package/dist/backend/llvm/switch-dispatch.js +35 -22
  74. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  75. package/dist/backend/llvm/switch-dispatch.test.js +28 -10
  76. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
  77. package/dist/backend/llvm/walk-borrows.d.ts +8 -1
  78. package/dist/backend/llvm/walk-borrows.js +15 -4
  79. package/dist/backend/llvm/walk-borrows.js.map +1 -1
  80. package/dist/backend/may-throw.d.ts +36 -2
  81. package/dist/backend/may-throw.js +308 -12
  82. package/dist/backend/may-throw.js.map +1 -1
  83. package/dist/backend/may-throw.test.js +146 -1
  84. package/dist/backend/may-throw.test.js.map +1 -1
  85. package/dist/backend/publication.d.ts +5 -0
  86. package/dist/backend/publication.js +10 -0
  87. package/dist/backend/publication.js.map +1 -1
  88. package/dist/backend/runtime-abi.d.ts +2 -2
  89. package/dist/backend/runtime-abi.js +2 -2
  90. package/dist/backend/runtime-pack-targets.test.js +1 -1
  91. package/dist/backend/runtime-pack.test.js +1 -1
  92. package/dist/contracts/check.d.ts +8 -0
  93. package/dist/contracts/check.js +1577 -0
  94. package/dist/contracts/check.js.map +1 -0
  95. package/dist/executable/prepare.js +9 -0
  96. package/dist/executable/prepare.js.map +1 -1
  97. package/dist/frontend/contract-types.d.ts +50 -0
  98. package/dist/frontend/contract-types.js +232 -0
  99. package/dist/frontend/contract-types.js.map +1 -0
  100. package/dist/frontend/lowering/coercions/unions.d.ts +12 -0
  101. package/dist/frontend/lowering/coercions/unions.js +63 -0
  102. package/dist/frontend/lowering/coercions/unions.js.map +1 -1
  103. package/dist/frontend/lowering/expressions/optional-chains.js +4 -1
  104. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  105. package/dist/frontend/lowering/lower-calls.js +9 -2
  106. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  107. package/dist/frontend/lowering/lower-exprs.js +83 -1
  108. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  109. package/dist/frontend/lowering/lowerer.d.ts +9 -0
  110. package/dist/frontend/lowering/lowerer.js +47 -0
  111. package/dist/frontend/lowering/lowerer.js.map +1 -1
  112. package/dist/frontend/lowering/narrowing-stability.d.ts +100 -0
  113. package/dist/frontend/lowering/narrowing-stability.js +1174 -0
  114. package/dist/frontend/lowering/narrowing-stability.js.map +1 -0
  115. package/dist/frontend/lowering/narrowing-stability.test.d.ts +1 -0
  116. package/dist/frontend/lowering/narrowing-stability.test.js +150 -0
  117. package/dist/frontend/lowering/narrowing-stability.test.js.map +1 -0
  118. package/dist/frontend/program.js +1 -1
  119. package/dist/frontend/type-mapper.js +43 -0
  120. package/dist/frontend/type-mapper.js.map +1 -1
  121. package/dist/ir/int32-slots.d.ts +26 -0
  122. package/dist/ir/int32-slots.js +147 -47
  123. package/dist/ir/int32-slots.js.map +1 -1
  124. package/dist/ir/integer-loops.js +3 -0
  125. package/dist/ir/integer-loops.js.map +1 -1
  126. package/dist/ir/integer-loops.test.js +26 -1
  127. package/dist/ir/integer-loops.test.js.map +1 -1
  128. package/dist/ir/integer-ranges.d.ts +20 -0
  129. package/dist/ir/integer-ranges.js +178 -21
  130. package/dist/ir/integer-ranges.js.map +1 -1
  131. package/dist/ir/integer-ranges.test.js +148 -3
  132. package/dist/ir/integer-ranges.test.js.map +1 -1
  133. package/dist/ir/ir.d.ts +32 -0
  134. package/dist/ir/ir.js.map +1 -1
  135. package/dist/ir/serialize.d.ts +5 -1
  136. package/dist/ir/serialize.js +8 -0
  137. package/dist/ir/serialize.js.map +1 -1
  138. package/dist/ir/unshare.d.ts +14 -0
  139. package/dist/ir/unshare.js +60 -0
  140. package/dist/ir/unshare.js.map +1 -0
  141. package/dist/ir/unshare.test.d.ts +1 -0
  142. package/dist/ir/unshare.test.js +115 -0
  143. package/dist/ir/unshare.test.js.map +1 -0
  144. package/dist/library/prepare.js +9 -0
  145. package/dist/library/prepare.js.map +1 -1
  146. package/package.json +20 -20
  147. package/surface-manifest.json +1 -1
@@ -19,6 +19,7 @@ import { constituentTypes } from "../ts7/checker.js";
19
19
  import { dirname } from "node:path";
20
20
  import * as posix from "node:path/posix";
21
21
  import { checkedClassAssertion, checkedClassUnionAssertion } from "./class-assertions.js";
22
+ import { checkedArmExtraction } from "./coercions/unions.js";
22
23
  import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
23
24
  import { lowerUnionFieldRead, lowerUnionFieldWrite } from "./expressions/union-fields.js";
24
25
  import { captureContextArguments } from "./function-context.js";
@@ -825,6 +826,13 @@ function lowerExprInner(lowerer, expr) {
825
826
  // tests, so only side-effect-free reads compose — and when every arm
826
827
  // agrees the whole expression folds to that one string (dropping only
827
828
  // the pure read, the trust-the-checker bet lowerUnitComparison makes).
829
+ // An effectful producer (a getter) evaluates once into a hidden local.
830
+ const prelude = [];
831
+ if (operand.type.kind === "union" && !isSafeToRepeat(operand)) {
832
+ const local = lowerer.declareHiddenLocal("%typeofOperand", operand.type);
833
+ prelude.push({ kind: "varDecl", localId: local.id, init: operand, loc });
834
+ operand = varRef(local.id, operand.type, loc);
835
+ }
828
836
  if (operand.type.kind === "union" && isSafeToRepeat(operand)) {
829
837
  const def = lowerer.unions.get(operand.type.unionId);
830
838
  const answers = def?.arms.map(typeofAnswer);
@@ -875,7 +883,9 @@ function lowerExprInner(lowerer, expr) {
875
883
  loc,
876
884
  };
877
885
  }
878
- return result;
886
+ return prelude.length > 0
887
+ ? { kind: "seqExpr", stmts: prelude, result, type: STRING, loc }
888
+ : result;
879
889
  }
880
890
  }
881
891
  if (operand.type.kind === "dyn") {
@@ -3149,6 +3159,11 @@ export function maybeNarrow(lowerer, expr, node) {
3149
3159
  if (narrowed?.kind === "object" &&
3150
3160
  narrowed.className !== expr.type.className &&
3151
3161
  lowerer.isSubclassOf(narrowed.className, expr.type.className)) {
3162
+ if (lowerer.narrowing.untrusted(node, narrowed)) {
3163
+ const checked = checkedClassAssertion(lowerer, expr, narrowed, expr.loc);
3164
+ if (checked)
3165
+ return checked;
3166
+ }
3152
3167
  return { kind: "downcast", value: expr, type: narrowed, loc: expr.loc };
3153
3168
  }
3154
3169
  return expr;
@@ -3191,6 +3206,9 @@ export function maybeNarrow(lowerer, expr, node) {
3191
3206
  const arrayTags = lowerer.arrayValueTags(expr.type.unionId);
3192
3207
  if (arrayTags.length === 1) {
3193
3208
  const arm = def.arms[arrayTags[0]];
3209
+ const checked = checkedStaleArm(lowerer, node, expr, arrayTags[0], arm);
3210
+ if (checked)
3211
+ return checked;
3194
3212
  return {
3195
3213
  kind: "unionNarrow",
3196
3214
  unionId: expr.type.unionId,
@@ -3224,6 +3242,9 @@ export function maybeNarrow(lowerer, expr, node) {
3224
3242
  const values = literalValues(lowerer.checker.getTypeOfSymbol(property));
3225
3243
  const arm = values && literalUnionArm(def, values, (id) => lowerer.shapes.get(id));
3226
3244
  if (arm) {
3245
+ const checked = checkedStaleArm(lowerer, node, expr, lowerer.armTag(expr.type.unionId, arm), arm);
3246
+ if (checked)
3247
+ return checked;
3227
3248
  return {
3228
3249
  kind: "unionNarrow",
3229
3250
  unionId: expr.type.unionId,
@@ -3249,6 +3270,10 @@ export function maybeNarrow(lowerer, expr, node) {
3249
3270
  arm.kind !== "object" ||
3250
3271
  !lowerer.isSubclassOf(narrowed.className, arm.className)) &&
3251
3272
  lowerer.isSubclassOf(narrowed.className, valueType.className)) {
3273
+ const checked = checkedStaleArm(lowerer, node, expr, valueTag, valueType, narrowed);
3274
+ if (checked) {
3275
+ return checkedClassAssertion(lowerer, checked, narrowed, expr.loc) ?? checked;
3276
+ }
3252
3277
  return {
3253
3278
  kind: "downcast",
3254
3279
  value: {
@@ -3265,6 +3290,9 @@ export function maybeNarrow(lowerer, expr, node) {
3265
3290
  }
3266
3291
  return expr;
3267
3292
  }
3293
+ const checked = checkedStaleArm(lowerer, node, expr, tag, narrowed);
3294
+ if (checked)
3295
+ return checked;
3268
3296
  return {
3269
3297
  kind: "unionNarrow",
3270
3298
  unionId: expr.type.unionId,
@@ -3274,6 +3302,60 @@ export function maybeNarrow(lowerer, expr, node) {
3274
3302
  loc: expr.loc,
3275
3303
  };
3276
3304
  }
3305
+ /** The checked form of maybeNarrow's arm extraction for a narrowing the
3306
+ * checker may hold past code that replaced the value (a call clearing the
3307
+ * property; see NarrowingStability). Every other arm throws the TypeError
3308
+ * Node raises for the operation consuming the read (`Cannot read
3309
+ * properties of undefined (reading 'x')`, `o.f is not a function`), or the
3310
+ * stranded-value TypeError where Node would carry the value on. Null when
3311
+ * the narrowing is provably current. `narrowed` is the checker's type when
3312
+ * it refines the arm (a subclass view). */
3313
+ function checkedStaleArm(lowerer, node, value, tag, arm, narrowed = arm) {
3314
+ if (value.type.kind !== "union" || tag < 0)
3315
+ return null;
3316
+ if (!lowerer.narrowing.untrusted(node, narrowed))
3317
+ return null;
3318
+ const inPlace = checkedArmExtraction(lowerer, value, tag, arm, (found) => staleReadMessage(node, found));
3319
+ if (inPlace)
3320
+ return inPlace;
3321
+ const helper = lowerer.narrowedArmHelper(value.type.unionId, arm, value.loc);
3322
+ return helper ? lowerer.checkedNarrowCall(helper, value, arm, value.loc) : null;
3323
+ }
3324
+ /** Node's TypeError for the operation consuming `node` when it holds a
3325
+ * value of type `found`, or null where Node would not throw. */
3326
+ function staleReadMessage(node, found) {
3327
+ let child = node;
3328
+ let parent = node.parent;
3329
+ while (ts.isParenthesizedExpression(parent)) {
3330
+ child = parent;
3331
+ parent = parent.parent;
3332
+ }
3333
+ if (ts.isCallExpression(parent) && parent.expression === child && !parent.questionDotToken) {
3334
+ return found.kind === "func" ? null : `${node.getText()} is not a function`;
3335
+ }
3336
+ const unit = found.kind === "undefinedT" ? "undefined" : found.kind === "nullT" ? "null" : null;
3337
+ if (unit === null)
3338
+ return null;
3339
+ if (!(ts.isPropertyAccessExpression(parent) || ts.isElementAccessExpression(parent)) ||
3340
+ parent.expression !== child ||
3341
+ parent.questionDotToken)
3342
+ return null;
3343
+ let key = null;
3344
+ if (ts.isPropertyAccessExpression(parent))
3345
+ key = parent.name.text;
3346
+ else if (ts.isStringLiteral(parent.argumentExpression))
3347
+ key = parent.argumentExpression.text;
3348
+ else if (ts.isNumericLiteral(parent.argumentExpression))
3349
+ key = String(Number(parent.argumentExpression.text));
3350
+ if (key === null)
3351
+ return null;
3352
+ const store = parent.parent;
3353
+ return ts.isBinaryExpression(store) &&
3354
+ store.left === parent &&
3355
+ store.operatorToken.kind === ts.SyntaxKind.EqualsToken
3356
+ ? `Cannot set properties of ${unit} (setting '${key}')`
3357
+ : `Cannot read properties of ${unit} (reading '${key}')`;
3358
+ }
3277
3359
  /** A runtime-optional slot can be assigned while a truthy guard is in
3278
3360
  * force. TypeScript then types a direct member receiver as the plain arm,
3279
3361
  * even though an OOB-safe assignment may have restored undefined. Check