@suss/recognize 0.31.2 → 0.33.0

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.
package/README.md CHANGED
@@ -35,10 +35,10 @@ implement the ops.
35
35
 
36
36
  ## More
37
37
 
38
- - [Write a pack](https://nimbuscloud-ai.github.io/suss/guides/writing-a-pack)
39
- - [How packs work](https://nimbuscloud-ai.github.io/suss/packs)
38
+ - [Write a pack](https://suss.sh/packs/write-a-pack)
39
+ - [How packs work](https://suss.sh/packs/what-a-pack-is)
40
40
  - [What a declaration compiles to](./DESIGN.md)
41
- - [Documentation](https://nimbuscloud-ai.github.io/suss/)
41
+ - [Documentation](https://suss.sh/)
42
42
  - [Source and issues](https://github.com/nimbuscloud-ai/suss)
43
43
 
44
44
  ![coverage](../../.github/badges/coverage-recognize.svg)
package/dist/ast.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CallOps } from '@suss/extractor';
2
- import { L as LinkFunction } from './chain-IogmSi0t.cjs';
2
+ import { L as LinkFunction } from './chain-CVG6Jnr-.cjs';
3
3
  import '@suss/behavioral-ir';
4
4
 
5
5
  /**
package/dist/ast.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CallOps } from '@suss/extractor';
2
- import { L as LinkFunction } from './chain-IogmSi0t.js';
2
+ import { L as LinkFunction } from './chain-CVG6Jnr-.js';
3
3
  import '@suss/behavioral-ir';
4
4
 
5
5
  /**
@@ -126,6 +126,17 @@ interface AccessPathLink {
126
126
  readonly asks: "accessPath";
127
127
  readonly argument: ArgumentPick;
128
128
  }
129
+ /**
130
+ * Which of the store's namespaces a call reached, when the call says
131
+ * rather than the pack. Most clients connect to one namespace and the
132
+ * pack states it once, but a BigQuery caller names the dataset on the
133
+ * way to the table, so a project reading two datasets would otherwise
134
+ * record both accesses under the same scope.
135
+ */
136
+ interface ScopeLink {
137
+ readonly asks: "scope";
138
+ readonly argument: ArgumentPick;
139
+ }
129
140
  /**
130
141
  * Where a call states the containers it reached, for a call that
131
142
  * reaches several at once. A batch or a transaction states them as a
@@ -172,7 +183,7 @@ interface InterpolatesLink {
172
183
  readonly from?: ReceiverOrigin;
173
184
  }
174
185
  /** One question in a chain, and the answer the pack gave for it. */
175
- type Link<TMeaning> = StartLink | SubjectLink | MethodsLink<TMeaning> | CallsLink<TMeaning> | ContainerLink | AccessPathLink | ContainersLink | InputLink | InterpolatesLink;
186
+ type Link<TMeaning> = StartLink | SubjectLink | MethodsLink<TMeaning> | CallsLink<TMeaning> | ContainerLink | AccessPathLink | ScopeLink | ContainersLink | InputLink | InterpolatesLink;
176
187
  /**
177
188
  * The meaning of a bare call of the tracked client itself. A store
178
189
  * hook is the case: `useAppStore((s) => s.bears)` reaches for no
@@ -305,8 +316,13 @@ interface SqlMethod {
305
316
  * Where the call states the statement. The pick's steps reach a call
306
317
  * beside this one, which is how a pack reads a statement handed to
307
318
  * `execute` as a tagged template rather than written on the call.
319
+ *
320
+ * A list is tried in order until one of the picks reaches text. One
321
+ * library takes the statement either way round: `query(sql)` and
322
+ * `query({ query: sql })` are the same call, and the pack says both
323
+ * rather than picking whichever its author happened to meet first.
308
324
  */
309
- readonly statement: OneArgument;
325
+ readonly statement: OneArgument | readonly OneArgument[];
310
326
  }
311
327
  /** What one method table can say a method does. */
312
328
  /** What one send method does, as the message-send ending reads it. */
@@ -477,4 +493,4 @@ interface Chain<TMeaning = MethodMeaning> {
477
493
  readonly example: string | null;
478
494
  }
479
495
 
480
- export type { ArgumentPick as A, StorageEnding as B, Chain as C, SubjectLink as D, Ending as E, FromReceiver as F, ToReceiver as G, UnitInvokeEnding as H, InterpolatesLink as I, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, OneArgument as O, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentsFrom as h, CallsLink as i, ContainerArgument as j, ContainerLink as k, ContainerRule as l, ContainersLink as m, InputLink as n, InputRule as o, Link as p, ManyIn as q, MatchStart as r, MessageSendEnding as s, MethodsLink as t, OneMessage as u, SelectorParamPick as v, SqlEnding as w, StartLink as x, StatedInputs as y, StatedRule as z };
496
+ export type { ArgumentPick as A, StatedRule as B, Chain as C, StorageEnding as D, Ending as E, FromReceiver as F, SubjectLink as G, ToReceiver as H, InterpolatesLink as I, UnitInvokeEnding as J, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, OneArgument as O, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentsFrom as h, CallsLink as i, ContainerArgument as j, ContainerLink as k, ContainerRule as l, ContainersLink as m, InputLink as n, InputRule as o, Link as p, ManyIn as q, MatchStart as r, MessageSendEnding as s, MethodsLink as t, OneMessage as u, ScopeLink as v, SelectorParamPick as w, SqlEnding as x, StartLink as y, StatedInputs as z };
@@ -126,6 +126,17 @@ interface AccessPathLink {
126
126
  readonly asks: "accessPath";
127
127
  readonly argument: ArgumentPick;
128
128
  }
129
+ /**
130
+ * Which of the store's namespaces a call reached, when the call says
131
+ * rather than the pack. Most clients connect to one namespace and the
132
+ * pack states it once, but a BigQuery caller names the dataset on the
133
+ * way to the table, so a project reading two datasets would otherwise
134
+ * record both accesses under the same scope.
135
+ */
136
+ interface ScopeLink {
137
+ readonly asks: "scope";
138
+ readonly argument: ArgumentPick;
139
+ }
129
140
  /**
130
141
  * Where a call states the containers it reached, for a call that
131
142
  * reaches several at once. A batch or a transaction states them as a
@@ -172,7 +183,7 @@ interface InterpolatesLink {
172
183
  readonly from?: ReceiverOrigin;
173
184
  }
174
185
  /** One question in a chain, and the answer the pack gave for it. */
175
- type Link<TMeaning> = StartLink | SubjectLink | MethodsLink<TMeaning> | CallsLink<TMeaning> | ContainerLink | AccessPathLink | ContainersLink | InputLink | InterpolatesLink;
186
+ type Link<TMeaning> = StartLink | SubjectLink | MethodsLink<TMeaning> | CallsLink<TMeaning> | ContainerLink | AccessPathLink | ScopeLink | ContainersLink | InputLink | InterpolatesLink;
176
187
  /**
177
188
  * The meaning of a bare call of the tracked client itself. A store
178
189
  * hook is the case: `useAppStore((s) => s.bears)` reaches for no
@@ -305,8 +316,13 @@ interface SqlMethod {
305
316
  * Where the call states the statement. The pick's steps reach a call
306
317
  * beside this one, which is how a pack reads a statement handed to
307
318
  * `execute` as a tagged template rather than written on the call.
319
+ *
320
+ * A list is tried in order until one of the picks reaches text. One
321
+ * library takes the statement either way round: `query(sql)` and
322
+ * `query({ query: sql })` are the same call, and the pack says both
323
+ * rather than picking whichever its author happened to meet first.
308
324
  */
309
- readonly statement: OneArgument;
325
+ readonly statement: OneArgument | readonly OneArgument[];
310
326
  }
311
327
  /** What one method table can say a method does. */
312
328
  /** What one send method does, as the message-send ending reads it. */
@@ -477,4 +493,4 @@ interface Chain<TMeaning = MethodMeaning> {
477
493
  readonly example: string | null;
478
494
  }
479
495
 
480
- export type { ArgumentPick as A, StorageEnding as B, Chain as C, SubjectLink as D, Ending as E, FromReceiver as F, ToReceiver as G, UnitInvokeEnding as H, InterpolatesLink as I, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, OneArgument as O, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentsFrom as h, CallsLink as i, ContainerArgument as j, ContainerLink as k, ContainerRule as l, ContainersLink as m, InputLink as n, InputRule as o, Link as p, ManyIn as q, MatchStart as r, MessageSendEnding as s, MethodsLink as t, OneMessage as u, SelectorParamPick as v, SqlEnding as w, StartLink as x, StatedInputs as y, StatedRule as z };
496
+ export type { ArgumentPick as A, StatedRule as B, Chain as C, StorageEnding as D, Ending as E, FromReceiver as F, SubjectLink as G, ToReceiver as H, InterpolatesLink as I, UnitInvokeEnding as J, KindAsAsked as K, LinkFunction as L, MethodMeaning as M, OneArgument as O, SqlMethod as S, ToArgument as T, UnitInvokeMethod as U, MessageSendMethod as a, MessageLocation as b, ChannelPart as c, CallStep as d, StorageMethod as e, AccessKind as f, AccessPathLink as g, ArgumentsFrom as h, CallsLink as i, ContainerArgument as j, ContainerLink as k, ContainerRule as l, ContainersLink as m, InputLink as n, InputRule as o, Link as p, ManyIn as q, MatchStart as r, MessageSendEnding as s, MethodsLink as t, OneMessage as u, ScopeLink as v, SelectorParamPick as w, SqlEnding as x, StartLink as y, StatedInputs as z };
package/dist/index.cjs CHANGED
@@ -224,7 +224,7 @@ function accessEffect(matched, access) {
224
224
  recognition,
225
225
  storageSystem: ending.system,
226
226
  ...ending.transport === void 0 ? {} : { transport: ending.transport },
227
- scope: ending.scope,
227
+ scope: scopeOf(chain, subject, unsettled) ?? ending.scope,
228
228
  container: reached.stated ? reached.container : containerOf(chain, selector, subject, unsettled),
229
229
  accessPath: accessPathOf(chain, subject, unsettled)
230
230
  }),
@@ -282,6 +282,10 @@ function accessPathOf(chain, subject, unsettled) {
282
282
  const link = linkIn(chain, "accessPath");
283
283
  return link === null ? null : namesAt(subject, link.argument, unsettled)[0] ?? null;
284
284
  }
285
+ function scopeOf(chain, subject, unsettled) {
286
+ const link = linkIn(chain, "scope");
287
+ return link === null ? null : namesAt(subject, link.argument, unsettled)[0] ?? null;
288
+ }
285
289
  function statedValue(subject, pick) {
286
290
  for (const ops of walk([subject], pick.of ?? [])) {
287
291
  const stated = ops.valueAt(pick.at);
@@ -485,12 +489,15 @@ function payloadOf(input, ending) {
485
489
  function sqlAccess(matched) {
486
490
  const { ops, subject, method, chain, recognition } = matched;
487
491
  const ending = chain.ending;
488
- const stated = statedValue(subject, matched.meaning.statement);
489
- const parts = stated?.parts() ?? null;
490
- if (stated === null || parts === null) {
492
+ const stated = statementIn(subject, matched.meaning.statement);
493
+ if (stated === null) {
491
494
  return null;
492
495
  }
493
- const statement = (0, import_sql.sqlFromParts)(parts, namesInHoles(chain, stated));
496
+ const statement = (0, import_sql.sqlFromParts)(
497
+ stated.parts,
498
+ namesInHoles(chain, stated.value),
499
+ settledHoles(stated.value)
500
+ );
494
501
  const accesses = (0, import_sql.readSqlAccess)(statement, { dialect: ending.dialect });
495
502
  return accesses.length === 0 ? null : accesses.map((access) => ({
496
503
  type: "interaction",
@@ -498,7 +505,10 @@ function sqlAccess(matched) {
498
505
  recognition,
499
506
  storageSystem: ending.system,
500
507
  ...ending.transport === void 0 ? {} : { transport: ending.transport },
501
- scope: ending.scope,
508
+ // A statement that qualifies its table says which namespace
509
+ // the access is in, and the pack's own scope is the fallback
510
+ // for a statement that leaves it out.
511
+ scope: access.qualifier[access.qualifier.length - 1] ?? ending.scope,
502
512
  container: access.table
503
513
  }),
504
514
  callee: ops.calleeText(),
@@ -511,6 +521,20 @@ function sqlAccess(matched) {
511
521
  }
512
522
  }));
513
523
  }
524
+ function statementIn(subject, says) {
525
+ const picks = Array.isArray(says) ? says : [says];
526
+ for (const pick of picks) {
527
+ const value = statedValue(subject, pick);
528
+ const parts = value?.parts() ?? null;
529
+ if (value !== null && parts !== null) {
530
+ return { value, parts };
531
+ }
532
+ }
533
+ return null;
534
+ }
535
+ function settledHoles(stated) {
536
+ return (stated.interpolated?.() ?? []).map((hole) => hole.name("nothing"));
537
+ }
514
538
  function namesInHoles(chain, stated) {
515
539
  const link = linkIn(chain, "interpolates");
516
540
  if (link === null) {
@@ -795,6 +819,7 @@ function chainFrom3(declared) {
795
819
  typeof says === "function" ? { asks: "container", from: says } : { asks: "container", argument: says }
796
820
  ),
797
821
  accessPath: (says) => adding({ asks: "accessPath", argument: says }),
822
+ scope: (says) => adding({ asks: "scope", argument: says }),
798
823
  containersIn: (says, options) => adding({
799
824
  asks: "containers",
800
825
  in: says,
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConstructedFrom, DeclaredBy, CallOps, InvocationRecognizer, PatternPack, UnsettledName, ReceiverOrigin, ProjectHelpers, PackDeclarations } from '@suss/extractor';
2
2
  export { CallOps, ConstructedFrom, DeclaredBy, DeclaredMatch, HelperDeclarations, HelperSink, HelperValue, OpsCarrier, PackDeclarations, PatternPack, ProjectHelper, ProjectHelpers, ReceiverOrigin, UnsettledName, ValueEntry, ValueOps } from '@suss/extractor';
3
- import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-IogmSi0t.cjs';
4
- export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as SelectorParamPick, w as SqlEnding, x as StartLink, y as StatedInputs, z as StatedRule, B as StorageEnding, D as SubjectLink, T as ToArgument, G as ToReceiver, H as UnitInvokeEnding } from './chain-IogmSi0t.cjs';
3
+ import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-CVG6Jnr-.cjs';
4
+ export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as ScopeLink, w as SelectorParamPick, x as SqlEnding, y as StartLink, z as StatedInputs, B as StatedRule, D as StorageEnding, G as SubjectLink, T as ToArgument, H as ToReceiver, J as UnitInvokeEnding } from './chain-CVG6Jnr-.cjs';
5
5
  import { Effect, MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
6
6
 
7
7
  /**
@@ -307,6 +307,12 @@ interface StorageCalls {
307
307
  container(says: ArgumentPick | LinkFunction<[readonly string[], CallOps], string | null>): StorageCalls;
308
308
  /** Which way into the container the call took, when it states one. */
309
309
  accessPath(says: ArgumentPick): StorageCalls;
310
+ /**
311
+ * Which namespace the call reached, when the call says rather than
312
+ * the pack. Without this every access records the scope the chain
313
+ * was built with.
314
+ */
315
+ scope(says: ArgumentPick): StorageCalls;
310
316
  /**
311
317
  * Where a call that reaches several containers at once states them.
312
318
  * Each entry becomes one effect, against the container its key says,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConstructedFrom, DeclaredBy, CallOps, InvocationRecognizer, PatternPack, UnsettledName, ReceiverOrigin, ProjectHelpers, PackDeclarations } from '@suss/extractor';
2
2
  export { CallOps, ConstructedFrom, DeclaredBy, DeclaredMatch, HelperDeclarations, HelperSink, HelperValue, OpsCarrier, PackDeclarations, PatternPack, ProjectHelper, ProjectHelpers, ReceiverOrigin, UnsettledName, ValueEntry, ValueOps } from '@suss/extractor';
3
- import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-IogmSi0t.js';
4
- export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as SelectorParamPick, w as SqlEnding, x as StartLink, y as StatedInputs, z as StatedRule, B as StorageEnding, D as SubjectLink, T as ToArgument, G as ToReceiver, H as UnitInvokeEnding } from './chain-IogmSi0t.js';
3
+ import { C as Chain, M as MethodMeaning, a as MessageSendMethod, b as MessageLocation, c as ChannelPart, S as SqlMethod, I as InterpolatesLink, d as CallStep, e as StorageMethod, A as ArgumentPick, L as LinkFunction, O as OneArgument, U as UnitInvokeMethod } from './chain-CVG6Jnr-.js';
4
+ export { f as AccessKind, g as AccessPathLink, h as ArgumentsFrom, i as CallsLink, j as ContainerArgument, k as ContainerLink, l as ContainerRule, m as ContainersLink, E as Ending, F as FromReceiver, n as InputLink, o as InputRule, K as KindAsAsked, p as Link, q as ManyIn, r as MatchStart, s as MessageSendEnding, t as MethodsLink, u as OneMessage, v as ScopeLink, w as SelectorParamPick, x as SqlEnding, y as StartLink, z as StatedInputs, B as StatedRule, D as StorageEnding, G as SubjectLink, T as ToArgument, H as ToReceiver, J as UnitInvokeEnding } from './chain-CVG6Jnr-.js';
5
5
  import { Effect, MessageBusSemantics, DeployableUnit } from '@suss/behavioral-ir';
6
6
 
7
7
  /**
@@ -307,6 +307,12 @@ interface StorageCalls {
307
307
  container(says: ArgumentPick | LinkFunction<[readonly string[], CallOps], string | null>): StorageCalls;
308
308
  /** Which way into the container the call took, when it states one. */
309
309
  accessPath(says: ArgumentPick): StorageCalls;
310
+ /**
311
+ * Which namespace the call reached, when the call says rather than
312
+ * the pack. Without this every access records the scope the chain
313
+ * was built with.
314
+ */
315
+ scope(says: ArgumentPick): StorageCalls;
310
316
  /**
311
317
  * Where a call that reaches several containers at once states them.
312
318
  * Each entry becomes one effect, against the container its key says,
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ function accessEffect(matched, access) {
192
192
  recognition,
193
193
  storageSystem: ending.system,
194
194
  ...ending.transport === void 0 ? {} : { transport: ending.transport },
195
- scope: ending.scope,
195
+ scope: scopeOf(chain, subject, unsettled) ?? ending.scope,
196
196
  container: reached.stated ? reached.container : containerOf(chain, selector, subject, unsettled),
197
197
  accessPath: accessPathOf(chain, subject, unsettled)
198
198
  }),
@@ -250,6 +250,10 @@ function accessPathOf(chain, subject, unsettled) {
250
250
  const link = linkIn(chain, "accessPath");
251
251
  return link === null ? null : namesAt(subject, link.argument, unsettled)[0] ?? null;
252
252
  }
253
+ function scopeOf(chain, subject, unsettled) {
254
+ const link = linkIn(chain, "scope");
255
+ return link === null ? null : namesAt(subject, link.argument, unsettled)[0] ?? null;
256
+ }
253
257
  function statedValue(subject, pick) {
254
258
  for (const ops of walk([subject], pick.of ?? [])) {
255
259
  const stated = ops.valueAt(pick.at);
@@ -453,12 +457,15 @@ function payloadOf(input, ending) {
453
457
  function sqlAccess(matched) {
454
458
  const { ops, subject, method, chain, recognition } = matched;
455
459
  const ending = chain.ending;
456
- const stated = statedValue(subject, matched.meaning.statement);
457
- const parts = stated?.parts() ?? null;
458
- if (stated === null || parts === null) {
460
+ const stated = statementIn(subject, matched.meaning.statement);
461
+ if (stated === null) {
459
462
  return null;
460
463
  }
461
- const statement = sqlFromParts(parts, namesInHoles(chain, stated));
464
+ const statement = sqlFromParts(
465
+ stated.parts,
466
+ namesInHoles(chain, stated.value),
467
+ settledHoles(stated.value)
468
+ );
462
469
  const accesses = readSqlAccess(statement, { dialect: ending.dialect });
463
470
  return accesses.length === 0 ? null : accesses.map((access) => ({
464
471
  type: "interaction",
@@ -466,7 +473,10 @@ function sqlAccess(matched) {
466
473
  recognition,
467
474
  storageSystem: ending.system,
468
475
  ...ending.transport === void 0 ? {} : { transport: ending.transport },
469
- scope: ending.scope,
476
+ // A statement that qualifies its table says which namespace
477
+ // the access is in, and the pack's own scope is the fallback
478
+ // for a statement that leaves it out.
479
+ scope: access.qualifier[access.qualifier.length - 1] ?? ending.scope,
470
480
  container: access.table
471
481
  }),
472
482
  callee: ops.calleeText(),
@@ -479,6 +489,20 @@ function sqlAccess(matched) {
479
489
  }
480
490
  }));
481
491
  }
492
+ function statementIn(subject, says) {
493
+ const picks = Array.isArray(says) ? says : [says];
494
+ for (const pick of picks) {
495
+ const value = statedValue(subject, pick);
496
+ const parts = value?.parts() ?? null;
497
+ if (value !== null && parts !== null) {
498
+ return { value, parts };
499
+ }
500
+ }
501
+ return null;
502
+ }
503
+ function settledHoles(stated) {
504
+ return (stated.interpolated?.() ?? []).map((hole) => hole.name("nothing"));
505
+ }
482
506
  function namesInHoles(chain, stated) {
483
507
  const link = linkIn(chain, "interpolates");
484
508
  if (link === null) {
@@ -763,6 +787,7 @@ function chainFrom3(declared) {
763
787
  typeof says === "function" ? { asks: "container", from: says } : { asks: "container", argument: says }
764
788
  ),
765
789
  accessPath: (says) => adding({ asks: "accessPath", argument: says }),
790
+ scope: (says) => adding({ asks: "scope", argument: says }),
766
791
  containersIn: (says, options) => adding({
767
792
  asks: "containers",
768
793
  in: says,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/recognize",
3
- "version": "0.31.2",
3
+ "version": "0.33.0",
4
4
  "type": "module",
5
5
  "description": "Teach suss to read a library you use, by writing a pack as data rather than code, which any language adapter can run.",
6
6
  "keywords": [
@@ -51,9 +51,9 @@
51
51
  "typecheck": "tsc --noEmit"
52
52
  },
53
53
  "dependencies": {
54
- "@suss/behavioral-ir": "0.31.2",
55
- "@suss/extractor": "0.31.2",
56
- "@suss/sql": "0.31.2"
54
+ "@suss/behavioral-ir": "0.33.0",
55
+ "@suss/extractor": "0.33.0",
56
+ "@suss/sql": "0.33.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "tsup": "*",