@scriptc/compiler 0.0.9 → 0.0.11

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 (97) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +54 -9
  2. package/dist/backend/emission/emit-exprs.js +170 -14
  3. package/dist/backend/emission/emit-exprs.js.map +1 -1
  4. package/dist/backend/emission/emit-walkers.js +29 -2
  5. package/dist/backend/emission/emit-walkers.js.map +1 -1
  6. package/dist/backend/emission/emitter.js +25 -1
  7. package/dist/backend/emission/emitter.js.map +1 -1
  8. package/dist/backend/llvm/dyn.d.ts +1 -0
  9. package/dist/backend/llvm/dyn.js +83 -1
  10. package/dist/backend/llvm/dyn.js.map +1 -1
  11. package/dist/backend/llvm/emitter.js +210 -13
  12. package/dist/backend/llvm/emitter.js.map +1 -1
  13. package/dist/coverage/surface-manifest.js +16 -2
  14. package/dist/coverage/surface-manifest.js.map +1 -1
  15. package/dist/diagnostics/diagnostic.d.ts +41 -14
  16. package/dist/diagnostics/diagnostic.js +79 -27
  17. package/dist/diagnostics/diagnostic.js.map +1 -1
  18. package/dist/diagnostics/render.js +8 -0
  19. package/dist/diagnostics/render.js.map +1 -1
  20. package/dist/frontend/lowering/lib-boundary.js +11 -1
  21. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  22. package/dist/frontend/lowering/lower-builtins.d.ts +69 -0
  23. package/dist/frontend/lowering/lower-builtins.js +380 -4
  24. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  25. package/dist/frontend/lowering/lower-calls.d.ts +41 -0
  26. package/dist/frontend/lowering/lower-calls.js +559 -11
  27. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  28. package/dist/frontend/lowering/lower-classes.d.ts +7 -0
  29. package/dist/frontend/lowering/lower-classes.js +51 -1
  30. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  31. package/dist/frontend/lowering/lower-containers.d.ts +21 -0
  32. package/dist/frontend/lowering/lower-containers.js +262 -17
  33. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  34. package/dist/frontend/lowering/lower-dgram.js +92 -17
  35. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  36. package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
  37. package/dist/frontend/lowering/lower-emitter.js +436 -29
  38. package/dist/frontend/lowering/lower-emitter.js.map +1 -1
  39. package/dist/frontend/lowering/lower-exprs.d.ts +80 -5
  40. package/dist/frontend/lowering/lower-exprs.js +651 -23
  41. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  42. package/dist/frontend/lowering/lower-modules.d.ts +8 -5
  43. package/dist/frontend/lowering/lower-modules.js +144 -19
  44. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  45. package/dist/frontend/lowering/lower-namespaces.d.ts +39 -11
  46. package/dist/frontend/lowering/lower-namespaces.js +166 -24
  47. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  48. package/dist/frontend/lowering/lower-server.js +211 -4
  49. package/dist/frontend/lowering/lower-server.js.map +1 -1
  50. package/dist/frontend/lowering/lower-stmts.d.ts +1 -5
  51. package/dist/frontend/lowering/lower-stmts.js +293 -10
  52. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  53. package/dist/frontend/lowering/lower-stream.js +178 -10
  54. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  55. package/dist/frontend/lowering/lowerer.d.ts +53 -1
  56. package/dist/frontend/lowering/lowerer.js +210 -19
  57. package/dist/frontend/lowering/lowerer.js.map +1 -1
  58. package/dist/frontend/lowering/surfaces.d.ts +44 -0
  59. package/dist/frontend/lowering/surfaces.js +234 -3
  60. package/dist/frontend/lowering/surfaces.js.map +1 -1
  61. package/dist/frontend/npm.d.ts +12 -0
  62. package/dist/frontend/npm.js +30 -0
  63. package/dist/frontend/npm.js.map +1 -1
  64. package/dist/frontend/program.d.ts +25 -0
  65. package/dist/frontend/program.js +144 -135
  66. package/dist/frontend/program.js.map +1 -1
  67. package/dist/frontend/shared.d.ts +1 -1
  68. package/dist/frontend/shared.js +1 -1
  69. package/dist/frontend/shared.js.map +1 -1
  70. package/dist/frontend/types.d.ts +13 -0
  71. package/dist/frontend/types.js +84 -7
  72. package/dist/frontend/types.js.map +1 -1
  73. package/dist/index.d.ts +2 -1
  74. package/dist/index.js +157 -12
  75. package/dist/index.js.map +1 -1
  76. package/dist/ir/nodes.d.ts +163 -13
  77. package/dist/ir/nodes.js +65 -6
  78. package/dist/ir/nodes.js.map +1 -1
  79. package/dist/ir/validate.js +64 -5
  80. package/dist/ir/validate.js.map +1 -1
  81. package/dist/library/fence-eval.d.ts +77 -0
  82. package/dist/library/fence-eval.js +395 -0
  83. package/dist/library/fence-eval.js.map +1 -0
  84. package/dist/library/int-infer.d.ts +119 -0
  85. package/dist/library/int-infer.js +1301 -0
  86. package/dist/library/int-infer.js.map +1 -0
  87. package/dist/library/int-infer.test.d.ts +1 -0
  88. package/dist/library/int-infer.test.js +279 -0
  89. package/dist/library/int-infer.test.js.map +1 -0
  90. package/dist/library/profile.d.ts +43 -6
  91. package/dist/library/profile.js +179 -31
  92. package/dist/library/profile.js.map +1 -1
  93. package/dist/library/sidecar.d.ts +23 -0
  94. package/dist/library/sidecar.js +150 -16
  95. package/dist/library/sidecar.js.map +1 -1
  96. package/package.json +2 -2
  97. package/surface-manifest.json +208 -10
@@ -0,0 +1,77 @@
1
+ import { type SurfaceEntryKind } from "../coverage/surface-manifest.js";
2
+ import { type ScrDiagnostic } from "../diagnostics/diagnostic.js";
3
+ import type { IrModule } from "../ir/nodes.js";
4
+ /** One raw fence declaration as the profile spelled it (validated for
5
+ * shape by the loader; resolved here against the manifest). */
6
+ export interface LibraryFenceDecl {
7
+ /** JSON path for exact-path refusals: `determinism.fences[2]`. */
8
+ path: string;
9
+ id?: string;
10
+ prefix?: string;
11
+ teaching?: string;
12
+ remediation?: string;
13
+ }
14
+ /** The IR facts that witness one surface's reach in the compiled graph.
15
+ * A surface is reached exactly when any listed fact appears. */
16
+ interface SurfaceDetector {
17
+ libFns?: readonly string[];
18
+ strMethods?: readonly string[];
19
+ arrMethods?: readonly string[];
20
+ mapMethods?: readonly string[];
21
+ setMethods?: readonly string[];
22
+ }
23
+ /** One manifest entry a fence covers, resolved and load-validated. */
24
+ export interface FencedSurface {
25
+ id: string;
26
+ name: string;
27
+ kind: SurfaceEntryKind;
28
+ /** The diagnostic code the manifest entry carries (every non-static
29
+ * entry has one) — the code whose refusal the fence teaching rides. */
30
+ code?: string;
31
+ /** Present exactly when the entry is static (it compiles, so the fence
32
+ * must deny it): the reach witness. Absent = the surface already
33
+ * refuses with `code` and the fence changes only the message. */
34
+ detector?: SurfaceDetector;
35
+ }
36
+ export interface ResolvedLibraryFence {
37
+ /** The declared selector, for messages: `id 'stdlib.math.random'` or
38
+ * `prefix 'node-builtin.fs.'`. */
39
+ declared: string;
40
+ teaching?: string;
41
+ remediation?: string;
42
+ surfaces: readonly FencedSurface[];
43
+ }
44
+ /** Resolve the profile's fence declarations against this compiler
45
+ * release's surface manifest. Every failure returns the exact-path detail
46
+ * the loader wraps as SC4001. Selector strictness is RATIFIED: an id or
47
+ * prefix matching nothing refuses; a covered static entry no detector can
48
+ * police refuses (loudly, never silently inert). Compile-time-folded
49
+ * constants refuse as `id` fences (the message says why) and are exempt
50
+ * under a `prefix` — the family sweep stays usable, and the fold means
51
+ * there is genuinely nothing at runtime to deny. */
52
+ export declare function resolveLibraryFences(decls: readonly LibraryFenceDecl[]): {
53
+ ok: true;
54
+ fences: ResolvedLibraryFence[];
55
+ } | {
56
+ ok: false;
57
+ detail: string;
58
+ };
59
+ /** The structural slice of LibraryProfile the fence machinery reads —
60
+ * kept structural so this module never value-imports the loader. */
61
+ export interface FenceProfileView {
62
+ name: string;
63
+ teachings: Readonly<Record<string, string>>;
64
+ fences: readonly ResolvedLibraryFence[];
65
+ }
66
+ /** Evaluate the profile's fences against the COMPILED module graph: every
67
+ * fenced static surface the graph reaches refuses as SC4008, anchored at
68
+ * the reaching construct, the fence's teaching attached as the attributed
69
+ * note. Unreached fences add nothing; a profile whose fences carry no
70
+ * detector-backed surface skips the walk entirely. */
71
+ export declare function evaluateLibraryFences(mod: IrModule, profile: FenceProfileView): ScrDiagnostic[];
72
+ /** Attach the profile's teaching text to every library-mode refusal it
73
+ * names — by code, by manifest id, or through a fence — as the visibly
74
+ * attributed `note`. Diagnostics already carrying a note (SC4008 threads
75
+ * its fence's teaching at mint time) pass through unchanged. */
76
+ export declare function decorateLibraryRefusals(diagnostics: ScrDiagnostic[], profile: FenceProfileView): ScrDiagnostic[];
77
+ export {};
@@ -0,0 +1,395 @@
1
+ /* Ask-5 determinism fences + the generalized teaching decoration.
2
+ *
3
+ * The profile's `determinism.fences` array denies surfaces BY SURFACE-
4
+ * MANIFEST ID (coverage/surface-manifest.ts — the compiler's one stable
5
+ * surface taxonomy; no new vocabulary). Resolution happens at profile
6
+ * load, against the manifest generated from this compiler's own tables:
7
+ *
8
+ * - an `id` names exactly one manifest entry; a `prefix` fences every
9
+ * entry it string-prefixes. An id or prefix matching NOTHING refuses
10
+ * loudly at load (ratified): fences pin to a compiler release's
11
+ * manifest, and a silently-inert fence is a footgun, so there is no
12
+ * forward-compatible acceptance of unknown selectors.
13
+ * - a fenced entry the static tier refuses anyway (status not "static")
14
+ * needs no new machinery: the surface's own refusal fires, and the
15
+ * fence's teaching rides it as the attributed note (spec §1: "changes
16
+ * only the message").
17
+ * - a fenced STATIC entry is policed against the COMPILED module graph:
18
+ * the emit pass lowers only reachability-discovered bodies, so the
19
+ * module IR *is* the reached graph — the same ground the sidecar's
20
+ * `deterministic` attestation stands on (ir/nodes.ts's
21
+ * moduleLibNondeterministicSurface). Fence evaluation reuses that
22
+ * posture with one generic walk collecting the reached surface facts
23
+ * (libCall spellings, str/arr/map/set intrinsic methods); each fenced
24
+ * entry then answers by table-derived detector. Unreached fences cost
25
+ * exactly this one walk — and no walk at all when no fence declares a
26
+ * detector-backed surface.
27
+ * - a fenced static entry with NO honest detector refuses at load,
28
+ * never accepted-and-ignored. Two families are named specifically:
29
+ * compile-time-folded constants (os.EOL, path.sep — the artifact
30
+ * performs no runtime read a fence could deny) and desugared surfaces
31
+ * (array map/filter/forEach and friends lower to plain loops with no
32
+ * distinct trace).
33
+ *
34
+ * Detectors derive MECHANICALLY from the same lowering tables the
35
+ * manifest projects from (frontend/lowering/surfaces.ts), so a table row
36
+ * added later grows the fenceable surface without hand maintenance. Two
37
+ * aliased-lowering facts are inherited from the tables and deliberate:
38
+ * string trimLeft/trimRight share trimStart/trimEnd's IR method, and
39
+ * querystring decode/encode share parse/stringify's libCall — fencing one
40
+ * spelling fences the operation.
41
+ *
42
+ * decorateLibraryRefusals is the generalized teaching rider (spec §2):
43
+ * profile text attaches to ANY library-mode refusal by diagnostic code
44
+ * (the ratified SC4004/SC4005 rider's keys, "async" shared-key fallback
45
+ * included), by manifest id (matched against the refusal's code plus the
46
+ * entry's surface name in the message; diagnostic-fence entries match on
47
+ * code alone — the entry IS the code family), or by a fence entry
48
+ * covering the refused surface. The text renders as the diagnostic's
49
+ * `note`, always prefixed with the profile's name — the tool's message
50
+ * stays the tool's. */
51
+ import { generateSurfaceManifest } from "../coverage/surface-manifest.js";
52
+ import { libFenceDiag } from "../diagnostics/diagnostic.js";
53
+ import { AMBIENT_SURFACE_FNS, BUILTIN_MODULE_CONSTS, BUILTIN_MODULE_FNS, BUILTIN_MODULE_FN_ALIASES, STATIC_MATH_FNS, STR_METHODS, } from "../frontend/lowering/surfaces.js";
54
+ import { compilerReleaseVersion } from "./sidecar.js";
55
+ let taxonomy = null;
56
+ function builtinRootId(mod) {
57
+ return `node-builtin.${mod.split("/").join(".")}`;
58
+ }
59
+ function fenceTaxonomy() {
60
+ if (taxonomy !== null)
61
+ return taxonomy;
62
+ const manifest = generateSurfaceManifest(compilerReleaseVersion());
63
+ const byId = new Map(manifest.entries.map((e) => [e.id, e]));
64
+ const builtinFns = new Map();
65
+ const builtinRoots = new Map();
66
+ const foldedIds = new Set();
67
+ for (const [mod, members] of Object.entries(BUILTIN_MODULE_FNS)) {
68
+ const root = new Set();
69
+ for (const [member, entry] of Object.entries(members)) {
70
+ if (entry === undefined)
71
+ continue;
72
+ const fns = new Set([entry.fn]);
73
+ // The bare-path and url tables rebind per TARGET platform
74
+ // (builtinModuleFnsOf): a fence on the bare id covers both flavors.
75
+ if (mod === "path") {
76
+ const w = BUILTIN_MODULE_FNS["path/win32"]?.[member];
77
+ if (w !== undefined)
78
+ fns.add(w.fn);
79
+ }
80
+ if (mod === "url" && member === "pathToFileURL")
81
+ fns.add("url.pathToFileURLWin32");
82
+ // Alternate spellings the dispatch special-cases around the table
83
+ // row (Buffer/fd/options forms) are the same surface.
84
+ for (const alias of BUILTIN_MODULE_FN_ALIASES[mod]?.[member] ?? [])
85
+ fns.add(alias);
86
+ builtinFns.set(`${builtinRootId(mod)}.${member}`, [...fns]);
87
+ for (const f of fns)
88
+ root.add(f);
89
+ }
90
+ if (root.size > 0)
91
+ builtinRoots.set(builtinRootId(mod), [...root]);
92
+ }
93
+ for (const [mod, members] of Object.entries(BUILTIN_MODULE_CONSTS)) {
94
+ for (const member of Object.keys(members))
95
+ foldedIds.add(`${builtinRootId(mod)}.${member}`);
96
+ }
97
+ const ambientFns = new Map(AMBIENT_SURFACE_FNS.map((row) => [row.id, row.fns]));
98
+ taxonomy = { byId, ids: manifest.entries.map((e) => e.id), builtinFns, builtinRoots, foldedIds, ambientFns };
99
+ return taxonomy;
100
+ }
101
+ /* ── classification: what policing a static entry means ───────────────── */
102
+ /** Array methods with a distinct IR trace (arrIntrinsic methods). `push`
103
+ * includes the spread spelling — `a.push(...xs)` lowers to pushSpread and
104
+ * is the same surface. The rest of ARRAY_METHODS desugars to plain loops. */
105
+ const ARR_DETECTABLE = {
106
+ push: ["push", "pushSpread"],
107
+ pop: ["pop"],
108
+ indexOf: ["indexOf"],
109
+ includes: ["includes"],
110
+ join: ["join"],
111
+ slice: ["slice"],
112
+ };
113
+ const MAP_DETECTABLE = new Set(["get", "set", "has", "delete", "clear"]);
114
+ const SET_DETECTABLE = new Set(["add", "has", "delete", "clear"]);
115
+ const DESUGARED_WHY = "it desugars at compile time into plain loops over iteration primitives, so the compiled graph carries no distinct trace to police";
116
+ function classifySurface(entry, tax) {
117
+ // Non-static entries already refuse with their own code wherever they
118
+ // are reached — the fence's teaching rides that refusal.
119
+ if (entry.status !== "static")
120
+ return { kind: "refusal" };
121
+ if (tax.foldedIds.has(entry.id)) {
122
+ return {
123
+ kind: "unfenceable",
124
+ why: "reads of it fold to a per-binary constant at compile time — the artifact performs no runtime read a fence could deny",
125
+ };
126
+ }
127
+ // Ambient dedicated-path surfaces (Date/perf_hooks/process): the row
128
+ // that projected the entry carries its reach witness.
129
+ const ambient = tax.ambientFns.get(entry.id);
130
+ if (ambient !== undefined)
131
+ return { kind: "detector", detector: { libFns: ambient } };
132
+ const builtinFns = tax.builtinFns.get(entry.id);
133
+ if (builtinFns !== undefined)
134
+ return { kind: "detector", detector: { libFns: builtinFns } };
135
+ const rootFns = tax.builtinRoots.get(entry.id);
136
+ if (rootFns !== undefined)
137
+ return { kind: "detector", detector: { libFns: rootFns } };
138
+ const [, family, member] = entry.id.split(".");
139
+ if (entry.id.startsWith("stdlib.") && family !== undefined && member !== undefined) {
140
+ if (family === "math") {
141
+ const fn = Object.hasOwn(STATIC_MATH_FNS, member) ? STATIC_MATH_FNS[member] : undefined;
142
+ if (fn !== undefined)
143
+ return { kind: "detector", detector: { libFns: [fn.fn] } };
144
+ }
145
+ if (family === "string") {
146
+ const m = Object.hasOwn(STR_METHODS, member) ? STR_METHODS[member] : undefined;
147
+ if (m !== undefined)
148
+ return { kind: "detector", detector: { strMethods: [m.method] } };
149
+ }
150
+ if (family === "array") {
151
+ const methods = Object.hasOwn(ARR_DETECTABLE, member) ? ARR_DETECTABLE[member] : undefined;
152
+ if (methods !== undefined)
153
+ return { kind: "detector", detector: { arrMethods: methods } };
154
+ return { kind: "unfenceable", why: DESUGARED_WHY };
155
+ }
156
+ if (family === "map") {
157
+ if (MAP_DETECTABLE.has(member))
158
+ return { kind: "detector", detector: { mapMethods: [member] } };
159
+ return { kind: "unfenceable", why: DESUGARED_WHY };
160
+ }
161
+ if (family === "set") {
162
+ if (SET_DETECTABLE.has(member))
163
+ return { kind: "detector", detector: { setMethods: [member] } };
164
+ return { kind: "unfenceable", why: DESUGARED_WHY };
165
+ }
166
+ }
167
+ if (entry.id.startsWith("syntax.")) {
168
+ return {
169
+ kind: "unfenceable",
170
+ why: "it lowers to the same IR as its expanded spelling, so the compiled graph carries no distinct trace to police",
171
+ };
172
+ }
173
+ if (entry.id.startsWith("node-builtin.")) {
174
+ return {
175
+ kind: "unfenceable",
176
+ why: "its lowered surface leaves no tabled per-call trace at this compiler release — fence the member entries the manifest projects instead",
177
+ };
178
+ }
179
+ return { kind: "unfenceable", why: "no fence detector exists for it at this compiler release" };
180
+ }
181
+ /* ── load-time resolution ──────────────────────────────────────────────── */
182
+ /** Resolve the profile's fence declarations against this compiler
183
+ * release's surface manifest. Every failure returns the exact-path detail
184
+ * the loader wraps as SC4001. Selector strictness is RATIFIED: an id or
185
+ * prefix matching nothing refuses; a covered static entry no detector can
186
+ * police refuses (loudly, never silently inert). Compile-time-folded
187
+ * constants refuse as `id` fences (the message says why) and are exempt
188
+ * under a `prefix` — the family sweep stays usable, and the fold means
189
+ * there is genuinely nothing at runtime to deny. */
190
+ export function resolveLibraryFences(decls) {
191
+ const tax = fenceTaxonomy();
192
+ const fences = [];
193
+ for (const d of decls) {
194
+ const surfaces = [];
195
+ const keep = (entry, cls) => {
196
+ surfaces.push({
197
+ id: entry.id,
198
+ name: entry.name,
199
+ kind: entry.kind,
200
+ ...(entry.code !== undefined ? { code: entry.code } : {}),
201
+ ...(cls.kind === "detector" ? { detector: cls.detector } : {}),
202
+ });
203
+ };
204
+ if (d.id !== undefined) {
205
+ const entry = tax.byId.get(d.id);
206
+ if (entry === undefined) {
207
+ return {
208
+ ok: false,
209
+ detail: `'${d.path}.id' names no entry in this compiler release's surface manifest ('${d.id}') — ` +
210
+ `fences pin to the release's manifest ids (the package ships surface-manifest.json), and an unknown id is refused, never accepted as inert`,
211
+ };
212
+ }
213
+ const cls = classifySurface(entry, tax);
214
+ if (cls.kind === "unfenceable") {
215
+ return { ok: false, detail: `'${d.path}.id' names '${d.id}', which cannot be fenced: ${cls.why}` };
216
+ }
217
+ keep(entry, cls);
218
+ }
219
+ else {
220
+ const covered = tax.ids.filter((id) => id.startsWith(d.prefix));
221
+ if (covered.length === 0) {
222
+ return {
223
+ ok: false,
224
+ detail: `'${d.path}.prefix' matches no entry in this compiler release's surface manifest ('${d.prefix}') — ` +
225
+ `fences pin to the release's manifest ids (the package ships surface-manifest.json), and an unknown prefix is refused, never accepted as inert`,
226
+ };
227
+ }
228
+ for (const id of covered) {
229
+ const entry = tax.byId.get(id);
230
+ const cls = classifySurface(entry, tax);
231
+ if (cls.kind === "unfenceable") {
232
+ if (tax.foldedIds.has(id))
233
+ continue; // the fold IS the exemption — see above
234
+ return { ok: false, detail: `'${d.path}.prefix' ('${d.prefix}') covers '${id}', which cannot be fenced: ${cls.why}` };
235
+ }
236
+ keep(entry, cls);
237
+ }
238
+ if (surfaces.length === 0) {
239
+ return {
240
+ ok: false,
241
+ detail: `'${d.path}.prefix' ('${d.prefix}') covers only compile-time-folded constants — there is nothing at runtime for the fence to deny`,
242
+ };
243
+ }
244
+ }
245
+ fences.push({
246
+ declared: d.id !== undefined ? `id '${d.id}'` : `prefix '${d.prefix}'`,
247
+ ...(d.teaching !== undefined ? { teaching: d.teaching } : {}),
248
+ ...(d.remediation !== undefined ? { remediation: d.remediation } : {}),
249
+ surfaces,
250
+ });
251
+ }
252
+ return { ok: true, fences };
253
+ }
254
+ /** One generic walk over the compiled module (the moduleLibAsyncSurface
255
+ * shape: nearest enclosing `loc` tracked so refusals anchor at the
256
+ * reaching construct), collecting every reached surface fact the fence
257
+ * detectors speak. First location per fact wins. */
258
+ function collectReachedSurfaces(mod) {
259
+ const reached = {
260
+ libFns: new Map(),
261
+ strMethods: new Map(),
262
+ arrMethods: new Map(),
263
+ mapMethods: new Map(),
264
+ setMethods: new Map(),
265
+ };
266
+ const note = (map, key, loc) => {
267
+ if (!map.has(key))
268
+ map.set(key, loc);
269
+ };
270
+ const entryLoc = { file: mod.sourceFile, start: 0, end: 0 };
271
+ const visit = (v, loc) => {
272
+ if (v === null || typeof v !== "object")
273
+ return;
274
+ if (Array.isArray(v)) {
275
+ for (const item of v)
276
+ visit(item, loc);
277
+ return;
278
+ }
279
+ const node = v;
280
+ const here = node.loc ?? loc;
281
+ if (typeof node.kind === "string") {
282
+ if (node.kind === "libCall" && typeof node.fn === "string")
283
+ note(reached.libFns, node.fn, here);
284
+ else if (typeof node.method === "string") {
285
+ if (node.kind === "strIntrinsic")
286
+ note(reached.strMethods, node.method, here);
287
+ else if (node.kind === "arrIntrinsic")
288
+ note(reached.arrMethods, node.method, here);
289
+ else if (node.kind === "mapIntrinsic")
290
+ note(reached.mapMethods, node.method, here);
291
+ else if (node.kind === "setIntrinsic")
292
+ note(reached.setMethods, node.method, here);
293
+ }
294
+ }
295
+ for (const key of Object.keys(v))
296
+ visit(v[key], here);
297
+ };
298
+ visit(mod, entryLoc);
299
+ return reached;
300
+ }
301
+ function detectorHit(reached, det) {
302
+ const scan = (facts, keys) => {
303
+ for (const k of keys ?? []) {
304
+ const loc = facts.get(k);
305
+ if (loc !== undefined)
306
+ return loc;
307
+ }
308
+ return null;
309
+ };
310
+ return (scan(reached.libFns, det.libFns) ??
311
+ scan(reached.strMethods, det.strMethods) ??
312
+ scan(reached.arrMethods, det.arrMethods) ??
313
+ scan(reached.mapMethods, det.mapMethods) ??
314
+ scan(reached.setMethods, det.setMethods));
315
+ }
316
+ /** Evaluate the profile's fences against the COMPILED module graph: every
317
+ * fenced static surface the graph reaches refuses as SC4008, anchored at
318
+ * the reaching construct, the fence's teaching attached as the attributed
319
+ * note. Unreached fences add nothing; a profile whose fences carry no
320
+ * detector-backed surface skips the walk entirely. */
321
+ export function evaluateLibraryFences(mod, profile) {
322
+ if (!profile.fences.some((f) => f.surfaces.some((s) => s.detector !== undefined)))
323
+ return [];
324
+ const reached = collectReachedSurfaces(mod);
325
+ const diags = [];
326
+ const seen = new Set();
327
+ for (const fence of profile.fences) {
328
+ for (const s of fence.surfaces) {
329
+ if (s.detector === undefined || seen.has(s.id))
330
+ continue;
331
+ const loc = detectorHit(reached, s.detector);
332
+ if (loc === null)
333
+ continue;
334
+ seen.add(s.id);
335
+ diags.push(libFenceDiag(profile.name, s.id, s.name, loc, s.code, fence.teaching));
336
+ }
337
+ }
338
+ return diags;
339
+ }
340
+ /* ── the generalized teaching rider ────────────────────────────────────── */
341
+ function surfaceMatchesDiag(surface, diag) {
342
+ if (surface.code === undefined || surface.code !== diag.code)
343
+ return false;
344
+ // A diagnostic-fence entry IS the code family; member entries must also
345
+ // appear by name in the refusal's message (SC2020/SC2012 refusals spell
346
+ // the surface exactly as the manifest names it).
347
+ return surface.kind === "diagnostic-fence" || diag.message.includes(surface.name);
348
+ }
349
+ function teachingForRefusal(profile, diag) {
350
+ // 1. Code-keyed teachings — the ratified SC4004/SC4005 rider's keys,
351
+ // "async" shared-key fallback included (profile.ts's profileTeaching
352
+ // rule, restated here to keep the import graph acyclic).
353
+ const direct = profile.teachings[diag.code] ??
354
+ (diag.code === "SC4004" || diag.code === "SC4005" ? profile.teachings["async"] : undefined);
355
+ if (direct !== undefined)
356
+ return direct;
357
+ // 2. Manifest-id-keyed teachings (dotted keys — embedder refusal-code
358
+ // tokens never carry dots; an id key resolves against the taxonomy and
359
+ // attaches where that surface's refusal fired).
360
+ for (const [key, text] of Object.entries(profile.teachings)) {
361
+ if (!key.includes("."))
362
+ continue;
363
+ const entry = fenceTaxonomy().byId.get(key);
364
+ if (entry !== undefined && surfaceMatchesDiag(entry, diag))
365
+ return text;
366
+ }
367
+ // 3. A fence covering the refused surface: the teaching rides the
368
+ // surface's own refusal (the non-static half of fence coverage).
369
+ for (const fence of profile.fences) {
370
+ if (fence.teaching === undefined)
371
+ continue;
372
+ for (const s of fence.surfaces) {
373
+ if (surfaceMatchesDiag(s, diag))
374
+ return fence.teaching;
375
+ }
376
+ }
377
+ return undefined;
378
+ }
379
+ /** Attach the profile's teaching text to every library-mode refusal it
380
+ * names — by code, by manifest id, or through a fence — as the visibly
381
+ * attributed `note`. Diagnostics already carrying a note (SC4008 threads
382
+ * its fence's teaching at mint time) pass through unchanged. */
383
+ export function decorateLibraryRefusals(diagnostics, profile) {
384
+ if (Object.keys(profile.teachings).length === 0 && profile.fences.length === 0)
385
+ return diagnostics;
386
+ return diagnostics.map((d) => {
387
+ if (d.note !== undefined)
388
+ return d;
389
+ const teaching = teachingForRefusal(profile, d);
390
+ if (teaching === undefined)
391
+ return d;
392
+ return { ...d, note: `from the '${profile.name}' profile: ${teaching}` };
393
+ });
394
+ }
395
+ //# sourceMappingURL=fence-eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fence-eval.js","sourceRoot":"","sources":["../../src/library/fence-eval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import type { IrModule, IrNumBinOp, SrcLoc } from "../ir/nodes.js";
2
+ export declare const SAFE_MAX: number;
3
+ export declare const SAFE_MIN: number;
4
+ /** The set of f64 values a binding may hold at a program point: a closed
5
+ * interval over the extended reals (`-0` normalized to 0 — the interval
6
+ * tracks mathematical value; zero's sign is an f64-interior observation
7
+ * with no boundary consequence), `whole` when every member is a finite
8
+ * integer-valued f64, `maybeNaN` when NaN may be in the set (NaN lives
9
+ * outside the interval, which describes only the numeric members), and
10
+ * the integer literal's source `spelling` for the representability check
11
+ * (propagates through copies and agreeing joins only; any arithmetic
12
+ * drops it — a computed value is a new number, not the author's
13
+ * literal). */
14
+ export interface AbsVal {
15
+ lo: number;
16
+ hi: number;
17
+ whole: boolean;
18
+ maybeNaN: boolean;
19
+ spelling?: string;
20
+ }
21
+ export declare function absVal(lo: number, hi: number, whole: boolean, maybeNaN: boolean, spelling?: string): AbsVal;
22
+ /** Any f64 a caller could pass — unbounded, not whole, NaN included. */
23
+ export declare const TOP: AbsVal;
24
+ /** The empty set (unreachable): lo > hi and no NaN. */
25
+ export declare const BOTTOM: AbsVal;
26
+ export declare const isBottom: (v: AbsVal) => boolean;
27
+ export declare const isSingleton: (v: AbsVal) => boolean;
28
+ export declare function constVal(value: number, spelling?: string): AbsVal;
29
+ /** Least upper bound: interval hull, wholeness/NaN pessimism, spelling
30
+ * kept only when both sides carry the same one. */
31
+ export declare function join(a: AbsVal, b: AbsVal): AbsVal;
32
+ export declare function sameVal(a: AbsVal, b: AbsVal): boolean;
33
+ export declare function widen(prev: AbsVal, next: AbsVal): AbsVal;
34
+ /** JS `~`: ToInt32, complement — whole, int32 range, whatever the input. */
35
+ export declare function transferBitNot(a: AbsVal): AbsVal;
36
+ export declare function transferNeg(a: AbsVal): AbsVal;
37
+ export declare function transferBin(op: IrNumBinOp, a: AbsVal, b: AbsVal): AbsVal;
38
+ /** The Math rounding family is the author's stated intent: every finite
39
+ * input maps to a whole output, so these discharge the WHOLENESS
40
+ * obligation. They do not discharge range (an unbounded input stays
41
+ * unbounded) or NaN (Math.trunc(NaN) is NaN — maybeNaN propagates). */
42
+ export declare function transferMathRound(fn: "trunc" | "floor" | "ceil" | "round", a: AbsVal): AbsVal;
43
+ export declare function transferAbs(a: AbsVal): AbsVal;
44
+ /** Math.min/max propagate NaN from ANY argument, exactly as JS does. */
45
+ export declare function transferMinMax(fn: "min" | "max", args: AbsVal[]): AbsVal;
46
+ export type IntClass = "i64" | "u64";
47
+ export type IntObligation = "representability" | "wholeness" | "range";
48
+ export interface IntVerdict {
49
+ /** The sidecar slot path (`Msg.count`, `Point.x`,
50
+ * `helpers.clamp.params[0]`, `exports.send.params[0]`). */
51
+ path: string;
52
+ cls: IntClass;
53
+ loc: SrcLoc;
54
+ outcome: "prove" | "refuse";
55
+ /** PROVE: the proven crossing range (the exact crossing value when the
56
+ * interval is a singleton); NaN/NaN for a vacuous (unreachable) proof. */
57
+ provenLo?: number;
58
+ provenHi?: number;
59
+ /** REFUSE: the failed obligation (the FIRST failure in the §2.4 order),
60
+ * the observed evidence, and the author's concrete fix. */
61
+ obligation?: IntObligation;
62
+ detail?: string;
63
+ fix?: string;
64
+ }
65
+ /** Does an integer literal's source spelling survive the trip through
66
+ * f64? Parse, convert, format back, compare (numeric separators were
67
+ * stripped by the frontend — they are spelling sugar, not value). */
68
+ export declare function spellingRoundTrips(spelling: string): boolean;
69
+ /** Check a converged abstract value against a slot's obligations, in the
70
+ * teaching-quality order: representability, then NaN, then range, then
71
+ * fractional wholeness — the FIRST failure names the refusal (a value
72
+ * both fractional and out of range hears about the more fundamental
73
+ * problem). */
74
+ export declare function checkBoundary(v: AbsVal, path: string, cls: IntClass, loc: SrcLoc): IntVerdict;
75
+ /** One function's declared integer slots: `params[i]` is the class of the
76
+ * i-th parameter (null = not integer-declared), `ret` the return's.
77
+ * `paramPaths`/`retPath` are the sidecar slot paths refusals carry. */
78
+ export interface FnIntSlots {
79
+ fnName: string;
80
+ params: (IntClass | null)[];
81
+ paramPaths: (string | null)[];
82
+ ret: IntClass | null;
83
+ retPath: string | null;
84
+ /** The plumbing classes of the NON-integer params (u8/u32/i32/f64/...):
85
+ * used to seed the callee's parameter environment precisely. */
86
+ paramSeeds: (AbsVal | null)[];
87
+ }
88
+ /** One record-field slot, resolved to an interned IR record shape: every
89
+ * program-side construction (recordLit) or write (recordSet) of `field`
90
+ * on shape `shapeId` must discharge the obligations. Shapes are interned
91
+ * STRUCTURALLY, so a second type with the identical field list shares the
92
+ * shape — and inherits the obligation, a sound over-approximation. */
93
+ export interface RecordIntSlot {
94
+ shapeId: string;
95
+ field: string;
96
+ cls: IntClass;
97
+ path: string;
98
+ }
99
+ export interface IntSlotConfig {
100
+ /** Keyed by IR function name. */
101
+ fns: Map<string, FnIntSlots>;
102
+ /** shapeId → field → slot. */
103
+ records: Map<string, Map<string, {
104
+ cls: IntClass;
105
+ path: string;
106
+ }>>;
107
+ }
108
+ export declare function hasIntSlots(cfg: IntSlotConfig): boolean;
109
+ /** The class seed for a declared parameter: what the slot's own contract
110
+ * proves about every value that ever arrives through it (internal calls
111
+ * are checked at their call sites; external calls range-check in the
112
+ * marshalling wrapper). */
113
+ export declare function classSeed(cls: string): AbsVal;
114
+ /** Run the inference over every function of a lowered library module and
115
+ * return one verdict per (obligation site) — internal call arguments into
116
+ * declared integer parameters, returns of declared integer returns, and
117
+ * writes into declared record-field slots. Callers turn REFUSE verdicts
118
+ * into diagnostics; PROVE verdicts carry the proven crossing range. */
119
+ export declare function checkLibraryIntegerSlots(mod: IrModule, cfg: IntSlotConfig): IntVerdict[];