@scriptc/compiler 0.0.7 → 0.0.8

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 (68) hide show
  1. package/dist/backend/emission/emit-exprs.js +47 -1
  2. package/dist/backend/emission/emit-exprs.js.map +1 -1
  3. package/dist/backend/emission/emit-island.js +9 -1
  4. package/dist/backend/emission/emit-island.js.map +1 -1
  5. package/dist/backend/emission/emit-stmts.js +3 -1
  6. package/dist/backend/emission/emit-stmts.js.map +1 -1
  7. package/dist/backend/emission/emit-walkers.js +22 -8
  8. package/dist/backend/emission/emit-walkers.js.map +1 -1
  9. package/dist/backend/emission/emitter.js +5 -1
  10. package/dist/backend/emission/emitter.js.map +1 -1
  11. package/dist/backend/emission/may-throw.js +4 -3
  12. package/dist/backend/emission/may-throw.js.map +1 -1
  13. package/dist/backend/llvm/emitter.js +94 -7
  14. package/dist/backend/llvm/emitter.js.map +1 -1
  15. package/dist/diagnostics/diagnostic.d.ts +43 -1
  16. package/dist/diagnostics/diagnostic.js +103 -5
  17. package/dist/diagnostics/diagnostic.js.map +1 -1
  18. package/dist/frontend/lib-contract.d.ts +24 -6
  19. package/dist/frontend/lib-contract.js +125 -44
  20. package/dist/frontend/lib-contract.js.map +1 -1
  21. package/dist/frontend/lowering/lower-builtins.js +16 -1
  22. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  23. package/dist/frontend/lowering/lower-calls.d.ts +47 -7
  24. package/dist/frontend/lowering/lower-calls.js +560 -36
  25. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  26. package/dist/frontend/lowering/lower-classes.d.ts +14 -1
  27. package/dist/frontend/lowering/lower-classes.js +85 -15
  28. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  29. package/dist/frontend/lowering/lower-containers.js +43 -1
  30. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  31. package/dist/frontend/lowering/lower-emitter.js +1 -1
  32. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  33. package/dist/frontend/lowering/lower-exprs.d.ts +26 -3
  34. package/dist/frontend/lowering/lower-exprs.js +455 -40
  35. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  36. package/dist/frontend/lowering/lower-island.d.ts +7 -0
  37. package/dist/frontend/lowering/lower-island.js +71 -10
  38. package/dist/frontend/lowering/lower-island.js.map +1 -1
  39. package/dist/frontend/lowering/lower-mixins.d.ts +1 -1
  40. package/dist/frontend/lowering/lower-mixins.js +1 -1
  41. package/dist/frontend/lowering/lower-modules.js +95 -4
  42. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  43. package/dist/frontend/lowering/lower-stmts.js +421 -43
  44. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  45. package/dist/frontend/lowering/lowerer.d.ts +19 -3
  46. package/dist/frontend/lowering/lowerer.js +188 -11
  47. package/dist/frontend/lowering/lowerer.js.map +1 -1
  48. package/dist/frontend/types.d.ts +28 -1
  49. package/dist/frontend/types.js +300 -8
  50. package/dist/frontend/types.js.map +1 -1
  51. package/dist/index.d.ts +2 -1
  52. package/dist/index.js +37 -7
  53. package/dist/index.js.map +1 -1
  54. package/dist/ir/nodes.d.ts +28 -2
  55. package/dist/ir/nodes.js +35 -3
  56. package/dist/ir/nodes.js.map +1 -1
  57. package/dist/ir/validate.js +35 -6
  58. package/dist/ir/validate.js.map +1 -1
  59. package/dist/library/profile.d.ts +17 -3
  60. package/dist/library/profile.js +38 -9
  61. package/dist/library/profile.js.map +1 -1
  62. package/dist/library/sidecar.js +162 -43
  63. package/dist/library/sidecar.js.map +1 -1
  64. package/dist/library/trap-teaching.d.ts +11 -0
  65. package/dist/library/trap-teaching.js +49 -0
  66. package/dist/library/trap-teaching.js.map +1 -0
  67. package/package.json +2 -2
  68. package/surface-manifest.json +37 -2
@@ -568,6 +568,19 @@ export declare function genericOverrideBelow(L: Lowerer, info: ClassInfo, name:
568
568
  * new D()` receiver is exactly D, not its annotation. Distinct from
569
569
  * exactClassOfReceiver, which answers for CLASS-VALUE receivers. */
570
570
  export declare function exactInstanceClassOf(L: Lowerer, expr: ts.Expression): ClassInfo | null;
571
+ /** `const r: Repo = new MemRepo()` where EVERY member of the annotation's
572
+ * checker type is a generic-callable method (`interface Repo { get<T>(id:
573
+ * string): T }`): the record shape maps EMPTY — generic members are
574
+ * excluded (no closure slot can hold a generic function) — so the
575
+ * copy-reshape width coercion would DROP the exact class the method
576
+ * calls monomorphize against, and in JS the binding IS the instance (no
577
+ * copy exists). The binding keeps the initializer's class
578
+ * representation instead: generic-method calls resolve like class-typed
579
+ * receivers (exactInstanceClassOf reads the same const+new discipline),
580
+ * and uses that want the empty record width-coerce at the use site.
581
+ * Const + direct `new` only — a reassignable binding or a produced
582
+ * value keeps today's record story and its fences. */
583
+ export declare function genericIfaceBindingKeepsClass(L: Lowerer, decl: ts.VariableDeclaration, declaredType: IrType): boolean;
571
584
  /** `recv.m<T>(args)` — a GENERIC method call, dispatched STATICALLY: the
572
585
  * checker's resolved signature (type arguments substituted, inferred or
573
586
  * explicit) keys one instantiation of the nearest declarer's body, and
@@ -579,7 +592,7 @@ export declare function exactInstanceClassOf(L: Lowerer, expr: ts.Expression): C
579
592
  export declare function lowerClassGenericMethodCall(L: Lowerer, call: ts.CallExpression, access: ts.PropertyAccessExpression, recvInfo: ClassInfo, found: {
580
593
  declarer: ClassInfo;
581
594
  info: GenericFnInfo;
582
- }): IrExpr;
595
+ }, recvIr?: IrExpr): IrExpr;
583
596
  /** Wraps a derived-class expression in an upcast when the target base
584
597
  * class differs (a no-op reinterpret at runtime; keeps IR types exact). */
585
598
  export declare function upcastTo(L: Lowerer, expr: IrExpr, className: string): IrExpr;
@@ -2802,13 +2802,28 @@ export function lowerStaticMethodCall(L, call, access) {
2802
2802
  return null;
2803
2803
  return staticCallOn(L, call, access, info, throughValue);
2804
2804
  }
2805
+ /** True when a class-VALUE receiver can only hold `info`'s own class
2806
+ * object at runtime: the receiver provably IS the class
2807
+ * (exactClassOfReceiver — the name, or a const bound to the class
2808
+ * expression / class name), or `info` is a LEAF class, so no strict
2809
+ * descendant exists to flow into the slot (the static-write path's
2810
+ * rule — a rebindable decorated name rides this arm, since replacement
2811
+ * decorators fence any class with subclasses before minting the
2812
+ * rebindable global). Exactly then a #private static access through
2813
+ * the value always carries the declaring class's brand — Node's
2814
+ * TypeError cannot arise. */
2815
+ function classValueIsExactlyOwn(L, recv, info) {
2816
+ return exactClassOfReceiver(L, recv) === info || info.subclasses.length === 0;
2817
+ }
2805
2818
  function staticCallOn(L, call, access, info, throughValue) {
2806
2819
  const loc = locOf(call);
2807
- // #private statics: through-a-VALUE receivers fence (a classval slot
2808
- // can hold a descendant at runtime and only the declaring class
2809
- // object carries the brand in JS), and the direct spelling resolves
2810
- // only on the declaring class itself — `D.#s` is Node's TypeError.
2811
- if (access.name.text.startsWith("#") && throughValue) {
2820
+ // #private statics: through-a-VALUE receiver the call devirtualizes
2821
+ // exactly when the value can only BE the declaring class
2822
+ // (classValueIsExactlyOwn — a slot that could hold a descendant at
2823
+ // runtime fences, since only the declaring class object carries the
2824
+ // brand in JS), and the direct spelling resolves only on the
2825
+ // declaring class itself — `D.#s` is Node's TypeError.
2826
+ if (access.name.text.startsWith("#") && throughValue && !classValueIsExactlyOwn(L, access.expression, info)) {
2812
2827
  L.unsupported("SC1090", call, `calling the private static '${access.name.text}' through a class value (JS brands the declaring class object alone — call it through the class's own name)`);
2813
2828
  }
2814
2829
  const found = findStaticOn(L, info, access.name.text);
@@ -2897,13 +2912,21 @@ export function lowerClassValueProperty(L, expr) {
2897
2912
  if (!found) {
2898
2913
  L.unsupported("SC1090", expr, `the static member '${member}' of class '${info.def.name.replace(/^%|^%m\d+\./, "")}' (static accessors and initializer-less static fields have no lowering, and Function members like .call/.bind/.prototype have no value form)`);
2899
2914
  }
2900
- // #private statics never read through class VALUES: the slot can hold
2901
- // a descendant at runtime and JS brands the declaring class object
2902
- // alone (Node's TypeError on any other receiver). The direct
2903
- // class-name spelling resolved in lowerStaticFieldRead, so a private
2904
- // reaching here is a classval-typed binding.
2915
+ // #private statics read through a class VALUE exactly when the value
2916
+ // can only BE the declaring class (classValueIsExactlyOwn — a const
2917
+ // bound to the class expression / class name, or a leaf class): a
2918
+ // slot that could hold a descendant at runtime fences, since JS
2919
+ // brands the declaring class object alone (Node's TypeError on any
2920
+ // other receiver). The direct class-name spelling resolved in
2921
+ // lowerStaticFieldRead, so a private reaching here is a
2922
+ // classval-typed binding.
2905
2923
  if (member.startsWith("#")) {
2906
- L.unsupported("SC1090", expr, `reading the private static '${member}' through a class value (JS brands the declaring class object alone — spell the declaring class's name)`);
2924
+ if (!classValueIsExactlyOwn(L, expr.expression, info)) {
2925
+ L.unsupported("SC1090", expr, `reading the private static '${member}' through a class value (JS brands the declaring class object alone — spell the declaring class's name)`);
2926
+ }
2927
+ if (found.declarer !== info) {
2928
+ L.unsupported("SC1090", expr, `reading the private static '${member}' through the subclass '${info.def.name.replace(/^%|^%m\d+\./, "")}' (JS brands the declaring class object alone — Node throws a TypeError here; spell the declaring class's name)`);
2929
+ }
2907
2930
  }
2908
2931
  if (staticShadowBelow(L, info, member)) {
2909
2932
  L.unsupported("SC1090", expr, `reading the static member '${member}' through a class value (a subclass of '${info.def.name.replace(/^%|^%m\d+\./, "")}' redeclares it, so the runtime class decides which declaration answers)`);
@@ -3012,6 +3035,39 @@ export function exactInstanceClassOf(L, expr) {
3012
3035
  init = init.expression;
3013
3036
  return classOfNew(init);
3014
3037
  }
3038
+ /** `const r: Repo = new MemRepo()` where EVERY member of the annotation's
3039
+ * checker type is a generic-callable method (`interface Repo { get<T>(id:
3040
+ * string): T }`): the record shape maps EMPTY — generic members are
3041
+ * excluded (no closure slot can hold a generic function) — so the
3042
+ * copy-reshape width coercion would DROP the exact class the method
3043
+ * calls monomorphize against, and in JS the binding IS the instance (no
3044
+ * copy exists). The binding keeps the initializer's class
3045
+ * representation instead: generic-method calls resolve like class-typed
3046
+ * receivers (exactInstanceClassOf reads the same const+new discipline),
3047
+ * and uses that want the empty record width-coerce at the use site.
3048
+ * Const + direct `new` only — a reassignable binding or a produced
3049
+ * value keeps today's record story and its fences. */
3050
+ export function genericIfaceBindingKeepsClass(L, decl, declaredType) {
3051
+ if (declaredType.kind !== "record")
3052
+ return false;
3053
+ if (!ts.isIdentifier(decl.name) || decl.initializer === undefined || decl.type === undefined)
3054
+ return false;
3055
+ if ((ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) === 0)
3056
+ return false;
3057
+ let init = decl.initializer;
3058
+ while (ts.isParenthesizedExpression(init))
3059
+ init = init.expression;
3060
+ if (!ts.isNewExpression(init))
3061
+ return false;
3062
+ const shape = L.shapes.get(declaredType.shapeId);
3063
+ if (!shape || shape.fields.length > 0 || shape.indexValue !== undefined || shape.tuple === true)
3064
+ return false;
3065
+ const annT = L.typeOf(decl.name);
3066
+ const props = L.checker.getPropertiesOfType(annT);
3067
+ if (props.length === 0)
3068
+ return false;
3069
+ return props.every((p) => isGenericCallableMemberType(L.checker.getTypeOfSymbol(p), L.checker));
3070
+ }
3015
3071
  /** `recv.m<T>(args)` — a GENERIC method call, dispatched STATICALLY: the
3016
3072
  * checker's resolved signature (type arguments substituted, inferred or
3017
3073
  * explicit) keys one instantiation of the nearest declarer's body, and
@@ -3020,7 +3076,7 @@ export function exactInstanceClassOf(L, expr) {
3020
3076
  * runtime class could OVERRIDE the method (genericOverrideBelow) must be
3021
3077
  * statically exact (exactInstanceClassOf) — the override set then
3022
3078
  * resolves at compile time — or fences by name. */
3023
- export function lowerClassGenericMethodCall(L, call, access, recvInfo, found) {
3079
+ export function lowerClassGenericMethodCall(L, call, access, recvInfo, found, recvIr) {
3024
3080
  const name = access.name.text;
3025
3081
  let { declarer, info } = found;
3026
3082
  if (genericOverrideBelow(L, recvInfo, name)) {
@@ -3038,7 +3094,7 @@ export function lowerClassGenericMethodCall(L, call, access, recvInfo, found) {
3038
3094
  const instance = info.implicitParams
3039
3095
  ? implicitCallInstance(L, call, info)
3040
3096
  : genericCallInstance(L, call, info);
3041
- const receiver = L.lowerExpr(access.expression);
3097
+ const receiver = recvIr ?? L.lowerExpr(access.expression);
3042
3098
  const loc = locOf(call);
3043
3099
  // The declarer sits at/above the receiver's static class on the plain
3044
3100
  // path; the EXACT path can land below it (a base-typed const provably
@@ -4426,8 +4482,8 @@ export function lowerNew(L, expr) {
4426
4482
  // construct-and-set loop, pairs in array order, duplicates
4427
4483
  // overwrite). Other seeds — another Map, general iterables — keep
4428
4484
  // the fence: never silently an empty map. Unsupported key/value
4429
- // types get their half named specifically instead of the generic
4430
- // SC2001 (which fires for Map-typed slots elsewhere).
4485
+ // types get their half named specifically instead of the component
4486
+ // fence (SC2009, which names Map slots at value positions elsewhere).
4431
4487
  // `new Array<T>()` and the ELEMENTS forms (`new Array('hi', 'bye')`,
4432
4488
  // any argument list that is not one lone number) ARE array literals
4433
4489
  // — the spec's ArrayCreate + element writes. The one-NUMBER form
@@ -4514,6 +4570,20 @@ export function lowerNew(L, expr) {
4514
4570
  return { kind: "mapNew", seed, type: mapped, loc };
4515
4571
  }
4516
4572
  const targs = L.checker.getTypeArguments(tsType);
4573
+ // JAVASCRIPT `new Map()` whose arguments never resolved past
4574
+ // Map<any, any> (no annotation, no contextual type, no seed): the
4575
+ // WeakMap stance below — the VALUE lowers as an opaque DOM object
4576
+ // (identity and truthiness are real), and every reached METHOD use
4577
+ // meets its own per-site fence at runtime. The formatter's
4578
+ // config-cache shape: module init constructs the caches
4579
+ // unconditionally; the format path never touches them. TypeScript
4580
+ // keeps the compile fence.
4581
+ if (isJsSourceFile(expr.getSourceFile()) &&
4582
+ (expr.arguments?.length ?? 0) === 0 &&
4583
+ targs.length > 0 &&
4584
+ targs.every((t) => (t.flags & ts.TypeFlags.Any) !== 0)) {
4585
+ return { kind: "dynObjLit", type: DYN, loc };
4586
+ }
4517
4587
  const keyIr = targs[0] ? L.mapTypeOf(targs[0]) : null;
4518
4588
  if (targs[0] && (!keyIr || !isSupportedMapKey(keyIr))) {
4519
4589
  L.unsupported("SC1090", expr, `Map keys of type '${L.checker.typeToString(targs[0])}' ` +