@prisma/orm-framework 8.0.0-rc.14-dev.16 → 8.0.0-rc.14-dev.18

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 (73) hide show
  1. package/dist/{authoring-Bn_5zI9q.mjs → authoring-C8hxYYQI.mjs} +3 -21
  2. package/dist/authoring-C8hxYYQI.mjs.map +1 -0
  3. package/dist/{authoring-DTZsvKV7.d.mts → authoring-CQOFIHhF.d.mts} +4 -20
  4. package/dist/{authoring-DTZsvKV7.d.mts.map → authoring-CQOFIHhF.d.mts.map} +1 -1
  5. package/dist/binder-CQGFQCuK-DrdVszQh.d.mts +452 -0
  6. package/dist/binder-CQGFQCuK-DrdVszQh.d.mts.map +1 -0
  7. package/dist/{components-DgQX4ccF.d.mts → components-DFA65tWf.d.mts} +2 -2
  8. package/dist/{components-DgQX4ccF.d.mts.map → components-DFA65tWf.d.mts.map} +1 -1
  9. package/dist/components.d.mts +11 -11
  10. package/dist/components.mjs +4 -4
  11. package/dist/components__authoring.d.mts +4 -4
  12. package/dist/components__authoring.mjs +3 -3
  13. package/dist/components__components.d.mts +2 -2
  14. package/dist/components__control.d.mts +3 -3
  15. package/dist/components__control.mjs +2 -2
  16. package/dist/components__execution.d.mts +1 -1
  17. package/dist/components__psl-ast.d.mts +3 -3
  18. package/dist/{config-types-CcK2xcMX.d.mts → config-types-DDNiQ3jk.d.mts} +8 -4
  19. package/dist/config-types-DDNiQ3jk.d.mts.map +1 -0
  20. package/dist/config.d.mts +1 -1
  21. package/dist/config__config-types.d.mts +1 -1
  22. package/dist/contract-authoring.d.mts +2 -2
  23. package/dist/contract-authoring.mjs +1 -1
  24. package/dist/{control-qWBPmuvX.d.mts → control-B059zyD4.d.mts} +10 -6
  25. package/dist/{control-qWBPmuvX.d.mts.map → control-B059zyD4.d.mts.map} +1 -1
  26. package/dist/{control-uVHmDgha.mjs → control-DEcjDcjA.mjs} +2 -2
  27. package/dist/{control-uVHmDgha.mjs.map → control-DEcjDcjA.mjs.map} +1 -1
  28. package/dist/{declarations-C0VwsVFX-24_6w6Lb.mjs → declarations-C0VwsVFX-BcP1Nyv4.mjs} +2 -2
  29. package/dist/{declarations-C0VwsVFX-24_6w6Lb.mjs.map → declarations-C0VwsVFX-BcP1Nyv4.mjs.map} +1 -1
  30. package/dist/errors.d.mts +1 -1
  31. package/dist/errors__execution.d.mts +1 -1
  32. package/dist/{execution-DHFIqFJC.d.mts → execution-D5L9gHoo.d.mts} +2 -2
  33. package/dist/{execution-DHFIqFJC.d.mts.map → execution-D5L9gHoo.d.mts.map} +1 -1
  34. package/dist/{execution-BW3cjWqQ.d.mts → execution-NKU9_mZ4.d.mts} +2 -2
  35. package/dist/{execution-BW3cjWqQ.d.mts.map → execution-NKU9_mZ4.d.mts.map} +1 -1
  36. package/dist/{framework-authoring-CsVwBOxP-saf7NH7p.d.mts → framework-authoring-BLXTNi9g-CcRc8u9I.d.mts} +3 -12
  37. package/dist/{framework-authoring-CsVwBOxP-saf7NH7p.d.mts.map → framework-authoring-BLXTNi9g-CcRc8u9I.d.mts.map} +1 -1
  38. package/dist/{framework-components-DNtoaHTX-DWt4JeHF.d.mts → framework-components-CwclBqDh-CBGrY3Ry.d.mts} +4 -4
  39. package/dist/{framework-components-DNtoaHTX-DWt4JeHF.d.mts.map → framework-components-CwclBqDh-CBGrY3Ry.d.mts.map} +1 -1
  40. package/dist/{mutation-default-types--XIOgxCm-B6NmSBxF.d.mts → mutation-default-types-ZfKqVdmf-DATmLFpQ.d.mts} +3 -3
  41. package/dist/{mutation-default-types--XIOgxCm-B6NmSBxF.d.mts.map → mutation-default-types-ZfKqVdmf-DATmLFpQ.d.mts.map} +1 -1
  42. package/dist/{parse-DqMTVHCw-Cw1RjDIQ.d.mts → parse-DqMTVHCw-DqqgVEUq.d.mts} +6 -6
  43. package/dist/{parse-DqMTVHCw-Cw1RjDIQ.d.mts.map → parse-DqMTVHCw-DqqgVEUq.d.mts.map} +1 -1
  44. package/dist/{parse-EvT3Ac9q-j7zYLB_6.mjs → parse-EvT3Ac9q-B0Nxq52v.mjs} +2 -2
  45. package/dist/{parse-EvT3Ac9q-j7zYLB_6.mjs.map → parse-EvT3Ac9q-B0Nxq52v.mjs.map} +1 -1
  46. package/dist/{psl-ast-CAA6nJRp-DIk-wyX1.d.mts → psl-ast-CPxYIxM1-XHoHPgRO.d.mts} +3 -3
  47. package/dist/{psl-ast-CAA6nJRp-DIk-wyX1.d.mts.map → psl-ast-CPxYIxM1-XHoHPgRO.d.mts.map} +1 -1
  48. package/dist/psl-ast-DA_tKWiL.d.mts +2 -0
  49. package/dist/psl-parser.d.mts +10 -320
  50. package/dist/psl-parser.d.mts.map +1 -1
  51. package/dist/psl-parser.mjs +1388 -1328
  52. package/dist/psl-parser.mjs.map +1 -1
  53. package/dist/psl-parser__format.d.mts +1 -1
  54. package/dist/psl-parser__format.mjs +2 -2
  55. package/dist/psl-parser__interpret.d.mts +21 -32
  56. package/dist/psl-parser__interpret.d.mts.map +1 -1
  57. package/dist/psl-parser__interpret.mjs +28 -40
  58. package/dist/psl-parser__interpret.mjs.map +1 -1
  59. package/dist/psl-parser__syntax.d.mts +1 -1
  60. package/dist/psl-parser__syntax.mjs +2 -2
  61. package/dist/psl-printer.d.mts +4 -4
  62. package/dist/psl-printer.mjs +1 -1
  63. package/dist/{temporal-presets-UGhnJIuo-DCoJ3HJj.d.mts → temporal-presets-DKHiZVPP-DLAr--Pb.d.mts} +4 -4
  64. package/dist/{temporal-presets-UGhnJIuo-DCoJ3HJj.d.mts.map → temporal-presets-DKHiZVPP-DLAr--Pb.d.mts.map} +1 -1
  65. package/dist/{temporal-presets-DsGuaFyT-DWzKyja_.mjs → temporal-presets-DzBBD4St-BaL1QaZ7.mjs} +3 -16
  66. package/dist/temporal-presets-DzBBD4St-BaL1QaZ7.mjs.map +1 -0
  67. package/package.json +15 -15
  68. package/dist/authoring-Bn_5zI9q.mjs.map +0 -1
  69. package/dist/config-types-CcK2xcMX.d.mts.map +0 -1
  70. package/dist/psl-ast-irbNZ93U.d.mts +0 -2
  71. package/dist/symbol-table-DZDTpkQ7-BrBUqb4g.d.mts +0 -126
  72. package/dist/symbol-table-DZDTpkQ7-BrBUqb4g.d.mts.map +0 -1
  73. package/dist/temporal-presets-DsGuaFyT-DWzKyja_.mjs.map +0 -1
@@ -1,20 +1,12 @@
1
1
  import { t as blindCast } from "./casts-DpaahrlC-Bd5n2coI.mjs";
2
2
  import { t as InternalError } from "./internal-error-ChGYPVpq-DhUD05u0.mjs";
3
3
  import { a as or, i as okVoid, n as notOk, r as ok, t as and } from "./result-8OXF26MN.mjs";
4
- import { C as isAuthoringTypeConstructorDescriptor, S as isAuthoringPslBlockDescriptor, x as isAuthoringModelAttributeDescriptor } from "./temporal-presets-DsGuaFyT-DWzKyja_.mjs";
4
+ import { b as isAuthoringModelAttributeDescriptor, x as isAuthoringPslBlockDescriptor } from "./temporal-presets-DzBBD4St-BaL1QaZ7.mjs";
5
5
  import { a as flatPslModels, c as namespacePslExtensionBlocks } from "./psl-ast-CyvE6CR-.mjs";
6
6
  import { n as isPslIdentifier } from "./tokenizer-BMz7z2KR-J0yZ4im3.mjs";
7
- import { C as TaggedLiteralExprAst, S as StringLiteralExprAst, T as TypesBlockAst, _ as NumberLiteralExprAst, a as CompositeTypeDeclarationAst, d as IdentifierAst, g as NamespaceDeclarationAst, i as BooleanLiteralExprAst, l as FunctionCallAst, m as ModelDeclarationAst, t as ArrayLiteralAst, u as GenericBlockDeclarationAst, y as ObjectLiteralExprAst } from "./declarations-C0VwsVFX-24_6w6Lb.mjs";
7
+ import { C as TaggedLiteralExprAst, S as StringLiteralExprAst, T as TypesBlockAst, _ as NumberLiteralExprAst, a as CompositeTypeDeclarationAst, d as IdentifierAst, g as NamespaceDeclarationAst, i as BooleanLiteralExprAst, l as FunctionCallAst, m as ModelDeclarationAst, t as ArrayLiteralAst, u as GenericBlockDeclarationAst, y as ObjectLiteralExprAst } from "./declarations-C0VwsVFX-BcP1Nyv4.mjs";
8
8
  import { a as mapPslDiagnostics, c as readResolvedAttributes, i as keywordPslSpan, l as readResolvedConstructorCall, n as diagnosticFromSpan, o as nodePslSpan, r as diagnosticSource, s as readResolvedAttribute, t as createPslDiagnosticCollector } from "./resolve-GE34dgM6-D33m6YEw.mjs";
9
- //#region ../../../1-framework/2-authoring/psl-parser/dist/index.mjs
10
- function getPositionalArgument(attribute, index = 0) {
11
- return attribute.args.filter((arg) => arg.kind === "positional")[index]?.value;
12
- }
13
- function parseQuotedStringLiteral(value) {
14
- const match = value.trim().match(/^(['"])(.*)\1$/);
15
- if (!match) return void 0;
16
- return match[2] ?? "";
17
- }
9
+ //#region ../../../1-framework/2-authoring/psl-parser/dist/symbol-table-0DYRY2eQ.mjs
18
10
  function* modelAttributeDescriptors(namespace) {
19
11
  for (const value of Object.values(namespace)) {
20
12
  if (isAuthoringModelAttributeDescriptor(value)) {
@@ -37,1216 +29,1514 @@ function assembleAttributeSpecs(contributions) {
37
29
  field: Object.freeze({ ...contributions.attributeSpecs.field })
38
30
  }));
39
31
  }
40
- function blockAttribute(name, config) {
41
- return {
42
- level: "block",
43
- name,
44
- documentation: config.documentation,
45
- positional: config.positional ?? [],
46
- named: config.named ?? {},
47
- ...config.refine !== void 0 ? { refine: config.refine } : {}
48
- };
32
+ function resolveDescribeUnsupportedAttribute(pslDiagnostics) {
33
+ if (pslDiagnostics?.describeUnsupportedAttribute === void 0) return;
34
+ return blindCast(pslDiagnostics.describeUnsupportedAttribute);
49
35
  }
50
- const ATTRIBUTE_DIAGNOSTIC_CODE = "PSL_INVALID_ATTRIBUTE_SYNTAX";
51
- function leafDiagnostic(ctx, node, message, code = ATTRIBUTE_DIAGNOSTIC_CODE) {
52
- return {
53
- code,
54
- message,
55
- ...diagnosticSource(ctx.sources, node.syntax).at(nodePslSpan(node.syntax, ctx.sources))
56
- };
36
+ function resolveDescribeUnresolvedType(pslDiagnostics) {
37
+ if (pslDiagnostics?.describeUnresolvedType === void 0) return;
38
+ return blindCast(pslDiagnostics.describeUnresolvedType);
57
39
  }
58
- function bool() {
40
+ function blockSpecFactoryOf(descriptor) {
41
+ return blindCast(descriptor.spec);
42
+ }
43
+ function isContributedTypeDescriptor(value) {
44
+ return "kind" in value && (value.kind === "typeConstructor" || value.kind === "fieldPreset");
45
+ }
46
+ function mergeContributedTypes(...namespaces) {
47
+ const merged = {};
48
+ for (const namespace of namespaces) for (const [name, value] of Object.entries(namespace)) {
49
+ const existing = Object.hasOwn(merged, name) ? merged[name] : void 0;
50
+ merged[name] = existing !== void 0 && !isContributedTypeDescriptor(existing) && !isContributedTypeDescriptor(value) ? mergeContributedTypes(existing, value) : value;
51
+ }
52
+ return merged;
53
+ }
54
+ function contributedTypeScope(contributedTypes) {
55
+ const members = collect(contributedTypes, []);
59
56
  return {
60
- kind: "bool",
61
- label: "boolean",
62
- parse: (arg, ctx) => {
63
- const literal = BooleanLiteralExprAst.cast(arg.syntax);
64
- if (literal !== void 0) {
65
- const value = literal.value();
66
- if (value !== void 0) return ok(value);
67
- }
68
- return notOk([leafDiagnostic(ctx, arg, "Expected a boolean literal")]);
57
+ lookup(name) {
58
+ return members.get(name);
59
+ },
60
+ entries() {
61
+ return members.entries();
69
62
  }
70
63
  };
71
64
  }
72
- const references = /* @__PURE__ */ new WeakMap();
73
- function entityReference(resolution) {
74
- switch (resolution.kind) {
75
- case "model":
76
- case "compositeType":
77
- case "namedType":
78
- case "block": return interned(resolution.symbol, resolution.namespace);
79
- default: return;
65
+ function collect(namespace, prefix) {
66
+ const members = /* @__PURE__ */ new Map();
67
+ for (const [name, value] of Object.entries(namespace)) {
68
+ const path = [...prefix, name];
69
+ members.set(name, isContributedTypeDescriptor(value) ? {
70
+ kind: "contributedType",
71
+ name,
72
+ path,
73
+ descriptor: value
74
+ } : {
75
+ kind: "contributedNamespace",
76
+ name,
77
+ path,
78
+ members: collect(value, path)
79
+ });
80
80
  }
81
+ return members;
81
82
  }
82
- function interned(declaration, namespace) {
83
- const existing = references.get(declaration);
84
- if (existing !== void 0) return existing;
85
- const reference = {
86
- declaration,
87
- namespace
88
- };
89
- references.set(declaration, reference);
90
- return reference;
83
+ function findBlockDescriptor(descriptors, keyword) {
84
+ if (descriptors === void 0) return void 0;
85
+ for (const value of Object.values(descriptors)) {
86
+ if (value === void 0) continue;
87
+ if (isAuthoringPslBlockDescriptor(value)) {
88
+ if (value.keyword === keyword) return value;
89
+ continue;
90
+ }
91
+ const nested = findBlockDescriptor(value, keyword);
92
+ if (nested !== void 0) return nested;
93
+ }
91
94
  }
92
- function matchesSelector(reference, expected) {
93
- const declaration = reference.declaration;
94
- if (declaration.kind !== expected.kind) return false;
95
- return expected.kind !== "block" || declaration.kind === "block" && declaration.keyword === expected.keyword;
95
+ function* recordNames(...records) {
96
+ for (const record of records) yield* Object.keys(record);
96
97
  }
97
- function describeResolution(resolution) {
98
- switch (resolution.kind) {
99
- case "block": return resolution.symbol.keyword;
100
- case "contributedType": return "scalar type";
101
- case "crossSpace": return "cross-space reference";
102
- case "unresolved": return "unresolved name";
103
- default: return resolution.kind;
98
+ var Scope = class {
99
+ parent;
100
+ constructor(parent) {
101
+ this.parent = parent;
104
102
  }
105
- }
106
- function entityRef(expected) {
107
- const label = `${expected.kind === "block" ? expected.keyword : expected.kind} reference`;
108
- return {
109
- kind: "entityRef",
110
- label,
111
- expected,
112
- parse: (arg, ctx) => {
113
- const name = IdentifierAst.cast(arg.syntax)?.name();
114
- if (name === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
115
- const resolution = ctx.binder.symbolForNode(arg.syntax);
116
- if (resolution === void 0 || resolution.kind === "unresolved") return notOk([]);
117
- const reference = entityReference(resolution);
118
- if (reference === void 0 || !matchesSelector(reference, expected)) return notOk([leafDiagnostic(ctx, arg, `Expected ${label} "${name}", found ${describeResolution(resolution)}`)]);
119
- return ok(reference);
103
+ *entries() {
104
+ const seen = /* @__PURE__ */ new Set();
105
+ for (const name of this.ownNames()) {
106
+ if (seen.has(name)) continue;
107
+ seen.add(name);
108
+ const resolution = this.lookup(name);
109
+ if (resolution !== void 0) yield [name, resolution];
120
110
  }
111
+ for (const entry of this.parent?.entries() ?? []) if (!seen.has(entry[0])) yield entry;
112
+ }
113
+ };
114
+ function contributedResolution(member) {
115
+ return member.kind === "contributedType" ? {
116
+ kind: "contributedType",
117
+ symbol: member
118
+ } : {
119
+ kind: "contributedNamespace",
120
+ symbol: member
121
121
  };
122
122
  }
123
- function parseFieldName(arg, ctx) {
124
- const identifier = IdentifierAst.cast(arg.syntax);
125
- if (identifier === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
126
- const name = identifier.name();
127
- if (name === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
128
- const resolution = ctx.binder.symbolForNode(arg.syntax);
129
- if (resolution === void 0) return notOk([]);
130
- if (resolution.kind === "field") return ok(resolution.symbol.name);
131
- if (resolution.kind === "crossSpace") return ok(name);
132
- return notOk([]);
133
- }
134
- function fieldRef() {
135
- return {
136
- kind: "fieldRef",
137
- label: "field name",
138
- parse: parseFieldName
123
+ function namespaceMember(namespace, name) {
124
+ const model = namespace.models[name];
125
+ if (model !== void 0) return {
126
+ kind: "model",
127
+ symbol: model,
128
+ namespace
139
129
  };
140
- }
141
- function referencedFieldRef() {
142
- return {
143
- kind: "referencedFieldRef",
144
- label: "field name",
145
- parse: parseFieldName
130
+ const compositeType = namespace.compositeTypes[name];
131
+ if (compositeType !== void 0) return {
132
+ kind: "compositeType",
133
+ symbol: compositeType,
134
+ namespace
135
+ };
136
+ const block = namespace.blocks[name];
137
+ if (block !== void 0) return {
138
+ kind: "block",
139
+ symbol: block,
140
+ namespace
146
141
  };
147
142
  }
148
- function interpretArgs(args, spec, ctx, span, sourceNode) {
149
- let outcome = okVoid();
150
- const output = {};
151
- const seen = /* @__PURE__ */ new Set();
152
- let positionalSlot = 0;
153
- let reportedExcess = false;
154
- for (const arg of args) {
155
- const name = arg.name()?.name();
156
- let key;
157
- let param;
158
- if (name === void 0) {
159
- const posParam = spec.positional[positionalSlot];
160
- if (posParam === void 0) {
161
- if (!reportedExcess) {
162
- outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received too many positional arguments`, ctx, span, sourceNode)]));
163
- reportedExcess = true;
164
- }
165
- continue;
166
- }
167
- positionalSlot += 1;
168
- key = posParam.key;
169
- param = posParam.type;
170
- } else {
171
- const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : void 0;
172
- if (namedParam === void 0) {
173
- outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received unknown argument "${name}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
174
- continue;
175
- }
176
- key = name;
177
- param = namedParam.type;
178
- }
179
- if (seen.has(key)) {
180
- outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received duplicate argument "${key}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
181
- continue;
182
- }
183
- seen.add(key);
184
- const result = parseArgValue(arg, param, ctx);
185
- if (result.ok) output[key] = result.value;
186
- outcome = and(outcome, result);
143
+ var ContributedScope = class extends Scope {
144
+ #registry;
145
+ constructor(registry) {
146
+ super(void 0);
147
+ this.#registry = registry;
187
148
  }
188
- const finalized = /* @__PURE__ */ new Set();
189
- const finalizeAbsentKey = (key, positionalParam, namedParam) => {
190
- if (finalized.has(key) || seen.has(key)) return;
191
- finalized.add(key);
192
- const effective = namedParam ?? positionalParam;
193
- if (effective === void 0) return;
194
- if (isOptionalArgType(effective)) {
195
- if (effective.hasDefault) output[key] = effective.defaultValue;
196
- return;
197
- }
198
- outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" is missing required argument "${key}"`, ctx, span, sourceNode)]));
199
- };
200
- for (const param of spec.positional) {
201
- const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : void 0;
202
- finalizeAbsentKey(param.key, param.type, namedParam?.type);
149
+ lookup(name) {
150
+ const member = this.#registry.lookup(name);
151
+ return member === void 0 ? void 0 : contributedResolution(member);
203
152
  }
204
- for (const key of Object.keys(spec.named)) finalizeAbsentKey(key, void 0, spec.named[key]?.type);
205
- if (!outcome.ok) return notOk(outcome.failure);
206
- return ok(output);
207
- }
208
- function interpretAttribute(attrNode, spec, ctx) {
209
- const attributeSpan = nodePslSpan(attrNode.syntax, ctx.sources);
210
- const bound = interpretArgs(attrNode.argList()?.args() ?? [], spec, ctx, attributeSpan, attrNode.syntax);
211
- if (!bound.ok) return notOk(bound.failure);
212
- const value = blindCast(bound.value);
213
- if (spec.refine !== void 0) {
214
- const refineDiagnostics = spec.refine(value, ctx, attrNode);
215
- if (refineDiagnostics.length > 0) return notOk(refineDiagnostics);
153
+ *ownNames() {
154
+ for (const [name] of this.#registry.entries()) yield name;
155
+ }
156
+ };
157
+ var DocumentScope = class extends Scope {
158
+ #records;
159
+ constructor(records, parent) {
160
+ super(parent);
161
+ this.#records = records;
162
+ }
163
+ lookup(name) {
164
+ const records = this.#records;
165
+ const model = records.models[name];
166
+ if (model !== void 0) return {
167
+ kind: "model",
168
+ symbol: model
169
+ };
170
+ const compositeType = records.compositeTypes[name];
171
+ if (compositeType !== void 0) return {
172
+ kind: "compositeType",
173
+ symbol: compositeType
174
+ };
175
+ const namedType = records.namedTypes[name];
176
+ if (namedType !== void 0) return {
177
+ kind: "namedType",
178
+ symbol: namedType
179
+ };
180
+ const block = records.blocks[name];
181
+ if (block !== void 0) return {
182
+ kind: "block",
183
+ symbol: block
184
+ };
185
+ const namespace = records.namespaces[name];
186
+ if (namespace !== void 0) return {
187
+ kind: "namespace",
188
+ symbol: namespace
189
+ };
190
+ return this.parent?.lookup(name);
191
+ }
192
+ ownNames() {
193
+ const records = this.#records;
194
+ return recordNames(records.models, records.compositeTypes, records.namedTypes, records.blocks, records.namespaces);
195
+ }
196
+ };
197
+ var NamespaceScope = class extends Scope {
198
+ #namespace;
199
+ constructor(namespace, parent) {
200
+ super(parent);
201
+ this.#namespace = namespace;
202
+ }
203
+ lookup(name) {
204
+ return namespaceMember(this.#namespace, name) ?? this.parent?.lookup(name);
205
+ }
206
+ ownNames() {
207
+ const namespace = this.#namespace;
208
+ return recordNames(namespace.models, namespace.compositeTypes, namespace.blocks);
209
+ }
210
+ };
211
+ function contributedScope(registry) {
212
+ return new ContributedScope(registry);
213
+ }
214
+ function documentScope(records, parent) {
215
+ return new DocumentScope(records, parent);
216
+ }
217
+ function namedTypeBaseScope(records, parent) {
218
+ return new DocumentScope({
219
+ ...records,
220
+ namedTypes: {}
221
+ }, parent);
222
+ }
223
+ function namespaceScope(namespace, parent) {
224
+ return new NamespaceScope(namespace, parent);
225
+ }
226
+ function isNamespaceLike(resolution) {
227
+ return resolution.kind === "namespace" || resolution.kind === "contributedNamespace";
228
+ }
229
+ function* memberEntries(qualifier) {
230
+ if (qualifier.kind === "contributedNamespace") {
231
+ for (const [name, member] of qualifier.symbol.members) yield [name, contributedResolution(member)];
232
+ return;
233
+ }
234
+ yield* new NamespaceScope(qualifier.symbol, void 0).entries();
235
+ }
236
+ function lookupMember(qualifier, name) {
237
+ if (qualifier.kind === "contributedNamespace") {
238
+ const member = qualifier.symbol.members.get(name);
239
+ return member === void 0 ? void 0 : contributedResolution(member);
240
+ }
241
+ return namespaceMember(qualifier.symbol, name);
242
+ }
243
+ const PSL_UNRESOLVED_REFERENCE = "PSL_UNRESOLVED_REFERENCE";
244
+ function typeReferenceNode(symbol) {
245
+ return symbol.node.typeAnnotation()?.name()?.syntax;
246
+ }
247
+ function contributedTypeOf(resolution, binder) {
248
+ const base = resolution?.kind === "namedType" ? typeReferenceNode(resolution.symbol) : void 0;
249
+ const target = base === void 0 ? resolution : binder.symbolForNode(base);
250
+ return target?.kind === "contributedType" ? target.symbol : void 0;
251
+ }
252
+ var PslBinder = class {
253
+ #declarations;
254
+ #references;
255
+ #documentScope;
256
+ #scopes;
257
+ constructor(declarations, references, documentScope, scopes) {
258
+ this.#declarations = declarations;
259
+ this.#references = references;
260
+ this.#documentScope = documentScope;
261
+ this.#scopes = scopes;
262
+ }
263
+ declaredSymbol(node) {
264
+ return this.#declarations.get(node);
265
+ }
266
+ symbolForNode(node) {
267
+ return this.#references.get(node);
268
+ }
269
+ scopeAt(node) {
270
+ return node.findAncestor((ancestor) => this.#scopes.get(ancestor)) ?? this.#documentScope;
271
+ }
272
+ };
273
+ var ScopeStack = class {
274
+ #base;
275
+ #scopes;
276
+ constructor(base) {
277
+ this.#base = base;
278
+ this.#scopes = [base];
279
+ }
280
+ current() {
281
+ return this.#scopes[this.#scopes.length - 1] ?? this.#base;
282
+ }
283
+ push(scope) {
284
+ this.#scopes.push(scope);
285
+ }
286
+ pop() {
287
+ this.#scopes.pop();
288
+ }
289
+ };
290
+ function walkEntities(symbolTable, stack, binder, visit) {
291
+ const { topLevel } = symbolTable;
292
+ for (const entity of Object.values(topLevel.models)) visit(entity);
293
+ for (const entity of Object.values(topLevel.compositeTypes)) visit(entity);
294
+ for (const namespace of Object.values(topLevel.namespaces)) {
295
+ stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
296
+ for (const entity of Object.values(namespace.models)) visit(entity);
297
+ for (const entity of Object.values(namespace.compositeTypes)) visit(entity);
298
+ stack.pop();
299
+ }
300
+ }
301
+ function createBinder(input) {
302
+ const { symbolTable, sources, context } = input;
303
+ const contributions = context.authoringContributions;
304
+ const describeUnsupportedAttributeFactory = resolveDescribeUnsupportedAttribute(context.pslDiagnostics);
305
+ const describeUnresolvedTypeFactory = resolveDescribeUnresolvedType(context.pslDiagnostics);
306
+ return bind({
307
+ sources,
308
+ symbolTable,
309
+ contributedTypes: mergeContributedTypes(contributions.field, contributions.type),
310
+ attributeSpecs: assembleAttributeSpecs(contributions),
311
+ pslBlockDescriptors: contributions.pslBlockDescriptors,
312
+ controlMutationDefaults: {
313
+ defaultFunctionRegistry: context.controlMutationDefaults.defaultFunctionRegistry,
314
+ dataTypeEntries: contributions.dataTypes
315
+ },
316
+ ...describeUnsupportedAttributeFactory !== void 0 ? { describeUnsupportedAttribute: describeUnsupportedAttributeFactory(sources) } : {},
317
+ ...describeUnresolvedTypeFactory !== void 0 ? { describeUnresolvedType: describeUnresolvedTypeFactory(contributions) } : {}
318
+ });
319
+ }
320
+ function bind(options) {
321
+ const { sources, symbolTable, contributedTypes, attributeSpecs, controlMutationDefaults, describeUnsupportedAttribute, describeUnresolvedType } = options;
322
+ const pslBlockDescriptors = options.pslBlockDescriptors ?? {};
323
+ const contributed = contributedScope(contributedTypeScope(contributedTypes));
324
+ const document = documentScope(symbolTable.topLevel, contributed);
325
+ const stack = new ScopeStack(document);
326
+ const scopes = /* @__PURE__ */ new WeakMap();
327
+ const declarations = /* @__PURE__ */ new WeakMap();
328
+ const references = /* @__PURE__ */ new WeakMap();
329
+ const diagnostics = [];
330
+ const binder = new PslBinder(declarations, references, document, scopes);
331
+ const baseScope = namedTypeBaseScope(symbolTable.topLevel, contributed);
332
+ for (const symbol of Object.values(symbolTable.topLevel.namedTypes)) {
333
+ declarations.set(symbol.node.syntax, symbol);
334
+ const name = symbol.node.typeAnnotation()?.name();
335
+ const outcome = resolveTypeReference(name, baseScope);
336
+ if (name === void 0 || outcome === void 0) continue;
337
+ references.set(name.syntax, outcome.resolution);
338
+ }
339
+ for (const symbol of Object.values(symbolTable.topLevel.blocks)) declarations.set(symbol.node.syntax, symbol);
340
+ for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
341
+ const scope = namespaceScope(namespace, document);
342
+ for (const declaration of namespace.declarations) {
343
+ declarations.set(declaration.node.syntax, namespace);
344
+ scopes.set(declaration.node.syntax, scope);
345
+ }
346
+ for (const symbol of Object.values(namespace.blocks)) declarations.set(symbol.node.syntax, symbol);
347
+ }
348
+ walkEntities(symbolTable, stack, binder, (entity) => {
349
+ declarations.set(entity.node.syntax, entity);
350
+ for (const field of Object.values(entity.fields)) {
351
+ declarations.set(field.node.syntax, field);
352
+ const node = typeReferenceNode(field);
353
+ if (node === void 0) continue;
354
+ const outcome = resolveTypeReference(field.node.typeAnnotation()?.name(), stack.current(), (written) => describeUnresolvedType?.({
355
+ field,
356
+ owner: entity,
357
+ written
358
+ }));
359
+ if (outcome === void 0) continue;
360
+ references.set(node, outcome.resolution);
361
+ if (outcome.message !== void 0) diagnostics.push({
362
+ code: PSL_UNRESOLVED_REFERENCE,
363
+ message: outcome.message,
364
+ data: {
365
+ reference: "type",
366
+ name: outcome.name,
367
+ constructorCall: field.typeConstructor !== void 0
368
+ },
369
+ ...diagnosticSource(sources, node).at()
370
+ });
371
+ }
372
+ });
373
+ walkEntities(symbolTable, stack, binder, (entity) => {
374
+ const context = {
375
+ owner: entity,
376
+ scope: stack.current(),
377
+ references,
378
+ diagnostics,
379
+ symbolTable,
380
+ sources,
381
+ describeUnsupportedAttribute
382
+ };
383
+ const specContext = entity.kind === "model" ? {
384
+ symbols: symbolTable,
385
+ model: entity,
386
+ controlMutationDefaults
387
+ } : void 0;
388
+ bindAttributes(entity, entity.attributes, attributeSpecs.model, (factory) => specContext === void 0 ? void 0 : factory(specContext), {
389
+ ...context,
390
+ field: void 0
391
+ });
392
+ for (const field of Object.values(entity.fields)) bindAttributes(field, field.attributes, attributeSpecs.field, (factory) => {
393
+ if (specContext === void 0) return void 0;
394
+ const node = typeReferenceNode(field);
395
+ const typeResolution = node === void 0 ? void 0 : references.get(node);
396
+ return factory({
397
+ ...specContext,
398
+ field,
399
+ typeResolution
400
+ });
401
+ }, {
402
+ ...context,
403
+ field
404
+ });
405
+ });
406
+ const blockContext = {
407
+ pslBlockDescriptors,
408
+ symbolTable,
409
+ sources,
410
+ references,
411
+ diagnostics
412
+ };
413
+ const bindBlocks = (blocks) => {
414
+ const context = {
415
+ ...blockContext,
416
+ scope: stack.current()
417
+ };
418
+ for (const block of Object.values(blocks)) bindBlock(block, context);
419
+ };
420
+ bindBlocks(symbolTable.topLevel.blocks);
421
+ for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
422
+ stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
423
+ bindBlocks(namespace.blocks);
424
+ stack.pop();
425
+ }
426
+ return {
427
+ binder,
428
+ diagnostics
429
+ };
430
+ }
431
+ function bindBlock(block, ctx) {
432
+ const descriptor = findBlockDescriptor(ctx.pslBlockDescriptors, block.keyword);
433
+ if (descriptor === void 0) return;
434
+ const spec = blockSpecFactoryOf(descriptor)({
435
+ symbols: ctx.symbolTable,
436
+ block
437
+ });
438
+ for (const entry of block.node.entries()) {
439
+ const key = entry.key()?.name();
440
+ if (key === void 0) continue;
441
+ const rule = spec.mode === "struct" ? Object.hasOwn(spec.parameters, key) ? spec.parameters[key]?.type : void 0 : spec.value.type;
442
+ const value = entry.value();
443
+ if (rule === void 0 || value === void 0) continue;
444
+ bindExpression(rule, value, ctx);
445
+ }
446
+ const attributeSpecs = descriptor.attributes ?? {};
447
+ if (Object.keys(attributeSpecs).length === 0) return;
448
+ for (const attribute of readResolvedAttributes(block.node.attributes(), ctx.sources)) {
449
+ const factory = attributeSpecs[attribute.name];
450
+ if (factory === void 0) continue;
451
+ bindArguments(attribute, blindCast(factory)({
452
+ symbols: ctx.symbolTable,
453
+ block
454
+ }), ctx);
455
+ }
456
+ }
457
+ function bindExpression(rule, expression, ctx, modelContext) {
458
+ const trial = tryBindExpression(rule, expression, ctx, modelContext);
459
+ for (const [node, resolution] of trial.references) ctx.references.set(node, resolution);
460
+ ctx.diagnostics.push(...trial.diagnostics.values());
461
+ }
462
+ function tryBindExpression(rule, expression, ctx, modelContext) {
463
+ const references = /* @__PURE__ */ new Map();
464
+ const diagnostics = /* @__PURE__ */ new Map();
465
+ switch (rule.kind) {
466
+ case "oneOf":
467
+ for (const alternative of rule.alternatives) {
468
+ const trial = tryBindExpression(alternative, expression, ctx, modelContext);
469
+ if (trial.matched) return trial;
470
+ for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
471
+ for (const [node, resolution] of trial.references) if (resolution.kind === "unresolved") references.set(node, resolution);
472
+ }
473
+ return {
474
+ matched: false,
475
+ references,
476
+ diagnostics
477
+ };
478
+ case "list":
479
+ case "record": {
480
+ const children = rule.kind === "list" ? ArrayLiteralAst.cast(expression.syntax)?.elements() : recordValues(expression);
481
+ if (children === void 0) return {
482
+ matched: false,
483
+ references,
484
+ diagnostics
485
+ };
486
+ let matched = true;
487
+ for (const child of children) {
488
+ const trial = tryBindExpression(rule.of, child, ctx, modelContext);
489
+ matched = trial.matched && matched;
490
+ for (const [node, resolution] of trial.references) references.set(node, resolution);
491
+ for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
492
+ }
493
+ return {
494
+ matched,
495
+ references,
496
+ diagnostics
497
+ };
498
+ }
499
+ case "funcCall": {
500
+ const call = FunctionCallAst.cast(expression.syntax);
501
+ const name = call?.name();
502
+ if (call === void 0 || name === void 0 || name.dot() !== void 0 || name.colon() !== void 0 || name.identifier()?.name() !== rule.name) return {
503
+ matched: false,
504
+ references,
505
+ diagnostics
506
+ };
507
+ let matched = true;
508
+ let positional = 0;
509
+ for (const arg of call.args()) {
510
+ const key = arg.name()?.name();
511
+ const parameter = argumentParameter(rule.signature, key, key === void 0 ? positional++ : positional);
512
+ const value = arg.value();
513
+ if (parameter === void 0 || value === void 0) {
514
+ matched = false;
515
+ continue;
516
+ }
517
+ const trial = tryBindExpression(parameter.type, value, ctx, modelContext);
518
+ matched = trial.matched && matched;
519
+ for (const [node, resolution] of trial.references) references.set(node, resolution);
520
+ for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
521
+ }
522
+ return {
523
+ matched,
524
+ references,
525
+ diagnostics
526
+ };
527
+ }
528
+ case "entityRef": {
529
+ const node = expression.syntax;
530
+ const name = IdentifierAst.cast(node)?.name();
531
+ if (name === void 0) return {
532
+ matched: false,
533
+ references,
534
+ diagnostics
535
+ };
536
+ const failures = [];
537
+ const resolution = resolveEntity(name, node, {
538
+ ...ctx,
539
+ diagnostics: failures
540
+ });
541
+ references.set(node, resolution);
542
+ for (const diagnostic of failures) diagnostics.set(node, diagnostic);
543
+ return {
544
+ matched: resolution.kind !== "unresolved",
545
+ references,
546
+ diagnostics
547
+ };
548
+ }
549
+ case "fieldRef": {
550
+ const node = expression.syntax;
551
+ const name = IdentifierAst.cast(node)?.name();
552
+ if (name === void 0 || modelContext === void 0) return {
553
+ matched: false,
554
+ references,
555
+ diagnostics
556
+ };
557
+ const failures = [];
558
+ const resolution = resolveOwnerField(name, node, {
559
+ ...modelContext,
560
+ diagnostics: failures
561
+ });
562
+ references.set(node, resolution);
563
+ for (const diagnostic of failures) diagnostics.set(node, diagnostic);
564
+ return {
565
+ matched: resolution.kind !== "unresolved",
566
+ references,
567
+ diagnostics
568
+ };
569
+ }
570
+ case "referencedFieldRef": {
571
+ const node = expression.syntax;
572
+ const name = IdentifierAst.cast(node)?.name();
573
+ if (name === void 0 || modelContext === void 0) return {
574
+ matched: false,
575
+ references,
576
+ diagnostics
577
+ };
578
+ const failures = [];
579
+ const resolution = resolveReferencedField(name, node, {
580
+ ...modelContext,
581
+ diagnostics: failures
582
+ });
583
+ references.set(node, resolution);
584
+ for (const diagnostic of failures) diagnostics.set(node, diagnostic);
585
+ return {
586
+ matched: resolution.kind !== "unresolved",
587
+ references,
588
+ diagnostics
589
+ };
590
+ }
591
+ default: return {
592
+ matched: true,
593
+ references,
594
+ diagnostics
595
+ };
216
596
  }
217
- return ok(value);
218
- }
219
- function parseArgValue(arg, argType, ctx) {
220
- const value = arg.value();
221
- if (value === void 0) return notOk([diagnostic("Attribute argument is missing a value", ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]);
222
- return argType.parse(value, ctx);
223
597
  }
224
- function isOptionalArgType(param) {
225
- return "optional" in param && param.optional === true;
598
+ function recordValues(expression) {
599
+ const record = ObjectLiteralExprAst.cast(expression.syntax);
600
+ if (record === void 0) return void 0;
601
+ return (function* () {
602
+ for (const field of record.fields()) {
603
+ const value = field.value();
604
+ if (value !== void 0) yield value;
605
+ }
606
+ })();
226
607
  }
227
- function diagnostic(message, ctx, span, sourceNode) {
608
+ function bindAttributes(holder, attributes, specs, instantiate, ctx) {
609
+ const declared = holder.node.attributes();
610
+ const nodes = Array.from(declared);
611
+ const level = holder.kind === "field" ? "field" : "model";
612
+ attributes.forEach((attribute, index) => {
613
+ const factory = own(specs, attribute.name);
614
+ if (factory === void 0) {
615
+ const diagnostic = ctx.describeUnsupportedAttribute?.({
616
+ attribute,
617
+ level,
618
+ owner: ctx.owner,
619
+ field: level === "field" ? ctx.field : void 0
620
+ });
621
+ if (diagnostic !== void 0) ctx.diagnostics.push(diagnostic);
622
+ return;
623
+ }
624
+ const spec = instantiate(factory);
625
+ if (spec === void 0) return;
626
+ const nameNode = nodes[index]?.name()?.syntax;
627
+ if (nameNode !== void 0) ctx.references.set(nameNode, {
628
+ kind: "attribute",
629
+ symbol: {
630
+ kind: "attribute",
631
+ name: attribute.name,
632
+ level,
633
+ spec
634
+ }
635
+ });
636
+ bindArguments(attribute, spec, ctx, ctx);
637
+ });
638
+ }
639
+ function bindArguments(attribute, spec, ctx, modelContext) {
640
+ let positional = 0;
641
+ for (const arg of attribute.args) {
642
+ const parameter = argumentParameter(spec, arg.name, arg.name === void 0 ? positional++ : positional);
643
+ if (parameter === void 0 || arg.expression === void 0) continue;
644
+ bindExpression(parameter.type, arg.expression, ctx, modelContext);
645
+ }
646
+ }
647
+ function argumentParameter(spec, name, position) {
648
+ if (name === void 0) return spec.positional?.[position];
649
+ return spec.named === void 0 ? void 0 : own(spec.named, name);
650
+ }
651
+ function resolveOwnerField(name, node, ctx) {
652
+ const field = ctx.owner.fields[name];
653
+ if (field !== void 0) return {
654
+ kind: "field",
655
+ symbol: field
656
+ };
657
+ report(`Cannot find field "${name}" on "${ctx.owner.name}"`, node, ctx, "field");
658
+ return {
659
+ kind: "unresolved",
660
+ name
661
+ };
662
+ }
663
+ function resolveReferencedField(name, node, ctx) {
664
+ const declaring = ctx.field;
665
+ if (declaring === void 0) return {
666
+ kind: "unresolved",
667
+ name
668
+ };
669
+ if (declaring.typeContractSpaceId !== void 0) return { kind: "crossSpace" };
670
+ const typeNode = typeReferenceNode(declaring);
671
+ const field = targetFields(typeNode === void 0 ? void 0 : ctx.references.get(typeNode))?.[name];
672
+ if (field !== void 0) return {
673
+ kind: "field",
674
+ symbol: field
675
+ };
676
+ report(`Cannot find field "${name}" on the type of "${ctx.owner.name}.${declaring.name}"`, node, ctx, "field");
677
+ return {
678
+ kind: "unresolved",
679
+ name
680
+ };
681
+ }
682
+ function targetFields(target) {
683
+ if (target === void 0) return void 0;
684
+ if (target.kind === "model" || target.kind === "compositeType") return target.symbol.fields;
685
+ }
686
+ function resolveEntity(name, node, ctx) {
687
+ const found = ctx.scope.lookup(name);
688
+ if (found === void 0) {
689
+ report(`Cannot find entity "${name}"`, node, ctx, "entity");
690
+ return {
691
+ kind: "unresolved",
692
+ name
693
+ };
694
+ }
695
+ return found;
696
+ }
697
+ function report(message, node, ctx, reference) {
698
+ ctx.diagnostics.push({
699
+ code: PSL_UNRESOLVED_REFERENCE,
700
+ message,
701
+ data: { reference },
702
+ ...diagnosticSource(ctx.sources, node).at()
703
+ });
704
+ }
705
+ function resolveTypeReference(reference, scope, describeUnresolved) {
706
+ if (reference === void 0 || reference.isOverQualified()) return void 0;
707
+ if (reference.space() !== void 0) return { resolution: { kind: "crossSpace" } };
708
+ const name = reference.identifier()?.name();
709
+ if (name === void 0 || name === "") return void 0;
710
+ const namespaceId = reference.namespace()?.name();
711
+ const found = namespaceId === void 0 ? scope.lookup(name) : qualifiedMember(namespaceId, name, scope);
712
+ if (found === void 0) {
713
+ const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
714
+ const message = describeUnresolved?.(written) ?? `Cannot find type "${written}"`;
715
+ return {
716
+ resolution: {
717
+ kind: "unresolved",
718
+ name: written
719
+ },
720
+ message,
721
+ name: written
722
+ };
723
+ }
724
+ if ("badQualifier" in found) return {
725
+ resolution: {
726
+ kind: "unresolved",
727
+ name: found.qualifier
728
+ },
729
+ message: found.badQualifier,
730
+ name: found.qualifier
731
+ };
732
+ if (found.kind === "namespace" || found.kind === "contributedNamespace") {
733
+ const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
734
+ return {
735
+ resolution: found,
736
+ message: `"${written}" is a namespace; a type reference must name a model, composite type, enum, or named type`,
737
+ name: written
738
+ };
739
+ }
740
+ return { resolution: found };
741
+ }
742
+ function qualifiedMember(namespaceId, name, scope) {
743
+ const qualifier = scope.lookup(namespaceId);
744
+ if (qualifier === void 0) return void 0;
745
+ if (!isNamespaceLike(qualifier)) return {
746
+ badQualifier: `"${namespaceId}" is ${describeQualifier(qualifier)}, not a namespace`,
747
+ qualifier: namespaceId
748
+ };
749
+ return lookupMember(qualifier, name);
750
+ }
751
+ function describeQualifier(resolution) {
752
+ switch (resolution.kind) {
753
+ case "model": return "a model";
754
+ case "compositeType": return "a composite type";
755
+ case "namedType": return "a named type";
756
+ case "block": return `${resolution.symbol.keyword === "enum" ? "an" : "a"} ${resolution.symbol.keyword}`;
757
+ default: return "a scalar type";
758
+ }
759
+ }
760
+ function own(record, name) {
761
+ return Object.hasOwn(record, name) ? record[name] : void 0;
762
+ }
763
+ /**
764
+ * Owns duplicate-declaration detection for all PSL scopes; downstream consumers
765
+ * should consume first-wins symbols rather than re-emitting duplicate diagnostics.
766
+ */
767
+ function buildSymbolTable(options) {
768
+ const { documents, sources } = options;
769
+ const diagnostics = [];
770
+ const namespaces = Object.create(null);
771
+ const namedTypes = Object.create(null);
772
+ const blocks = Object.create(null);
773
+ const models = Object.create(null);
774
+ const compositeTypes = Object.create(null);
775
+ const topLevelNames = /* @__PURE__ */ new Set();
776
+ for (const document of documents) {
777
+ const sourceFile = sources.sourceFileFor(document.syntax);
778
+ const claim = (taken, name) => {
779
+ const text = name?.name();
780
+ if (text === void 0) return void 0;
781
+ if (taken.has(text)) {
782
+ const range = nameRange(name, sources);
783
+ if (range) diagnostics.push({
784
+ code: "PSL_DUPLICATE_DECLARATION",
785
+ message: `Duplicate declaration of "${text}"`,
786
+ filename: sourceFile.filename,
787
+ range
788
+ });
789
+ return;
790
+ }
791
+ taken.add(text);
792
+ return text;
793
+ };
794
+ for (const declaration of document.declarations()) if (declaration instanceof ModelDeclarationAst) {
795
+ const name = claim(topLevelNames, declaration.name());
796
+ if (name !== void 0) models[name] = buildModel(name, declaration, sources, diagnostics);
797
+ } else if (declaration instanceof CompositeTypeDeclarationAst) {
798
+ const name = claim(topLevelNames, declaration.name());
799
+ if (name !== void 0) compositeTypes[name] = buildCompositeType(name, declaration, sources, diagnostics);
800
+ } else if (declaration instanceof GenericBlockDeclarationAst) {
801
+ const name = claim(topLevelNames, declaration.name());
802
+ if (name !== void 0) blocks[name] = buildBlock(name, declaration, sources);
803
+ } else if (declaration instanceof NamespaceDeclarationAst) {
804
+ const declaredName = declaration.name()?.name();
805
+ if (declaredName === void 0) continue;
806
+ let namespace = namespaces[declaredName];
807
+ if (namespace === void 0) {
808
+ const name = claim(topLevelNames, declaration.name());
809
+ if (name === void 0) continue;
810
+ namespace = {
811
+ kind: "namespace",
812
+ name,
813
+ declarations: [{
814
+ node: declaration,
815
+ span: nodePslSpan(declaration.syntax, sources)
816
+ }],
817
+ models: Object.create(null),
818
+ compositeTypes: Object.create(null),
819
+ blocks: Object.create(null)
820
+ };
821
+ namespaces[name] = namespace;
822
+ } else namespace.declarations.push({
823
+ node: declaration,
824
+ span: nodePslSpan(declaration.syntax, sources)
825
+ });
826
+ extendNamespace(namespace, declaration, diagnostics, sources);
827
+ } else if (declaration instanceof TypesBlockAst) for (const binding of declaration.declarations()) {
828
+ const name = claim(topLevelNames, binding.name());
829
+ if (name === void 0) continue;
830
+ const resolved = resolveNamedTypeBinding(binding, sources);
831
+ namedTypes[name] = {
832
+ kind: "namedType",
833
+ name,
834
+ node: binding,
835
+ span: nodePslSpan(binding.syntax, sources),
836
+ ...resolved
837
+ };
838
+ }
839
+ }
228
840
  return {
229
- code: ATTRIBUTE_DIAGNOSTIC_CODE,
230
- message,
231
- ...diagnosticSource(ctx.sources, sourceNode).at(span)
841
+ symbolTable: { topLevel: {
842
+ namespaces,
843
+ namedTypes,
844
+ blocks,
845
+ models,
846
+ compositeTypes
847
+ } },
848
+ diagnostics
232
849
  };
233
850
  }
234
- function funcCall(name, sig) {
851
+ function buildModel(name, node, sources, diagnostics) {
235
852
  return {
236
- kind: "funcCall",
237
- label: `${name}()`,
853
+ kind: "model",
238
854
  name,
239
- signature: sig,
240
- parse: (arg, ctx) => {
241
- const guard = matchCallee(arg, name, ctx);
242
- if (!guard.ok) return guard;
243
- const span = nodePslSpan(guard.value.syntax, ctx.sources);
244
- const bound = interpretArgs(guard.value.args(), {
245
- name,
246
- positional: sig.positional ?? [],
247
- named: sig.named ?? {}
248
- }, ctx, span, guard.value.syntax);
249
- if (!bound.ok) return notOk(bound.failure);
250
- return ok({
251
- fn: name,
252
- span,
253
- args: bound.value
254
- });
255
- }
855
+ node,
856
+ span: nodePslSpan(node.syntax, sources),
857
+ fields: buildFields(name, node.fields(), sources, diagnostics),
858
+ attributes: readResolvedAttributes(node.attributes(), sources)
256
859
  };
257
860
  }
258
- function matchCallee(arg, name, ctx) {
259
- const call = FunctionCallAst.cast(arg.syntax);
260
- if (call === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
261
- const qname = call.name();
262
- if (qname === void 0 || qname.dot() !== void 0 || qname.colon() !== void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
263
- const calleeName = qname.identifier()?.token()?.text;
264
- if (calleeName === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
265
- if (calleeName !== name) return notOk([leafDiagnostic(ctx, arg, `Expected ${name}()`)]);
266
- return ok(call);
267
- }
268
- function identifier(name, options) {
269
- const label = name ?? "identifier";
861
+ function buildCompositeType(name, node, sources, diagnostics) {
270
862
  return {
271
- kind: "identifier",
272
- label,
863
+ kind: "compositeType",
273
864
  name,
274
- documentation: options?.documentation ?? "",
275
- parse: (arg, ctx) => {
276
- const value = IdentifierAst.cast(arg.syntax)?.name();
277
- if (value !== void 0 && (name === void 0 || value === name)) return ok(value);
278
- return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
279
- }
865
+ node,
866
+ span: nodePslSpan(node.syntax, sources),
867
+ fields: buildFields(name, node.fields(), sources, diagnostics),
868
+ attributes: readResolvedAttributes(node.attributes(), sources)
280
869
  };
281
870
  }
282
- function int(opts) {
283
- const min = opts?.min;
284
- const max = opts?.max;
871
+ function buildBlock(name, node, sources) {
285
872
  return {
286
- kind: "int",
287
- label: "integer",
288
- ...min === void 0 ? {} : { min },
289
- ...max === void 0 ? {} : { max },
290
- parse: (arg, ctx) => {
291
- const literal = NumberLiteralExprAst.cast(arg.syntax);
292
- if (literal !== void 0) {
293
- const value = literal.value();
294
- if (value !== void 0 && Number.isInteger(value)) {
295
- if ((min === void 0 || value >= min) && (max === void 0 || value <= max)) return ok(value);
296
- return notOk([leafDiagnostic(ctx, arg, rangeMessage(min, max))]);
297
- }
298
- }
299
- return notOk([leafDiagnostic(ctx, arg, "Expected an integer literal")]);
300
- }
873
+ kind: "block",
874
+ name,
875
+ keyword: node.keyword()?.text ?? "",
876
+ node,
877
+ span: nodePslSpan(node.syntax, sources)
301
878
  };
302
879
  }
303
- function rangeMessage(min, max) {
304
- if (min !== void 0 && max !== void 0) return `Expected an integer between ${min} and ${max}`;
305
- if (min !== void 0) return `Expected an integer greater than or equal to ${min}`;
306
- return `Expected an integer less than or equal to ${max}`;
307
- }
308
- /**
309
- * Reads an opaque JSON object from a quoted JSON string — the ADR's one text-encoded surface
310
- * exception (e.g. an index `filter` / `weights` argument). The string is decoded by the parser,
311
- * then JSON-parsed; a non-object (array/scalar) or invalid JSON is a diagnostic.
312
- */
313
- function json() {
314
- return {
315
- kind: "json",
316
- label: "JSON object",
317
- parse: (arg, ctx) => {
318
- const literal = StringLiteralExprAst.cast(arg.syntax);
319
- if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a JSON object string")]);
320
- const raw = literal.value();
321
- if (raw !== void 0) try {
322
- const parsed = JSON.parse(raw);
323
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return ok(blindCast(parsed));
324
- } catch {}
325
- return notOk([leafDiagnostic(ctx, arg, "Expected a valid JSON object")]);
880
+ function extendNamespace(namespace, node, diagnostics, sources) {
881
+ const { models, compositeTypes, blocks } = namespace;
882
+ for (const member of node.declarations()) {
883
+ const memberName = member.name()?.name();
884
+ if (memberName === void 0) continue;
885
+ if (Object.hasOwn(models, memberName) || Object.hasOwn(compositeTypes, memberName) || Object.hasOwn(blocks, memberName)) {
886
+ const range = nameRange(member.name(), sources);
887
+ if (range) diagnostics.push({
888
+ code: "PSL_DUPLICATE_DECLARATION",
889
+ message: `Duplicate declaration of "${memberName}"`,
890
+ filename: sources.sourceFileFor(member.syntax).filename,
891
+ range
892
+ });
893
+ continue;
326
894
  }
327
- };
895
+ if (member instanceof ModelDeclarationAst) models[memberName] = buildModel(memberName, member, sources, diagnostics);
896
+ else if (member instanceof CompositeTypeDeclarationAst) compositeTypes[memberName] = buildCompositeType(memberName, member, sources, diagnostics);
897
+ else if (member instanceof GenericBlockDeclarationAst) blocks[memberName] = buildBlock(memberName, member, sources);
898
+ }
328
899
  }
329
- function list(of, opts) {
330
- const allowEmpty = opts?.allowEmpty ?? true;
331
- const unique = opts?.unique ?? false;
332
- return {
333
- kind: "list",
334
- label: opts?.label ?? (of.label.includes(" | ") ? `(${of.label})[]` : `${of.label}[]`),
335
- of,
336
- allowEmpty,
337
- unique,
338
- parse: (arg, ctx) => {
339
- const literal = ArrayLiteralAst.cast(arg.syntax);
340
- if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);
341
- const parsed = [];
342
- let outcome = okVoid();
343
- let count = 0;
344
- for (const element of literal.elements()) {
345
- count += 1;
346
- const result = of.parse(element, ctx);
347
- if (result.ok) parsed.push({
348
- node: element,
349
- value: result.value
350
- });
351
- outcome = and(outcome, result);
352
- }
353
- if (!allowEmpty && count === 0) outcome = and(outcome, notOk([leafDiagnostic(ctx, arg, "Expected a non-empty list")]));
354
- if (unique) {
355
- const seen = /* @__PURE__ */ new Set();
356
- for (const { node, value } of parsed) if (seen.has(value)) outcome = and(outcome, notOk([leafDiagnostic(ctx, node, "Duplicate list entry")]));
357
- else seen.add(value);
358
- }
359
- if (!outcome.ok) return notOk(outcome.failure);
360
- return ok(parsed.map((entry) => entry.value));
900
+ function buildFields(ownerName, fields, sources, diagnostics) {
901
+ const result = Object.create(null);
902
+ for (const field of fields) {
903
+ const nameNode = field.name();
904
+ const name = nameNode?.name();
905
+ if (name === void 0) continue;
906
+ if (Object.hasOwn(result, name)) {
907
+ const range = nameRange(nameNode, sources);
908
+ if (range) diagnostics.push({
909
+ code: "PSL_DUPLICATE_DECLARATION",
910
+ message: `Duplicate declaration of "${name}"`,
911
+ filename: sources.sourceFileFor(field.syntax).filename,
912
+ range
913
+ });
914
+ continue;
361
915
  }
362
- };
916
+ result[name] = buildField(ownerName, name, field, sources, diagnostics);
917
+ }
918
+ return result;
363
919
  }
364
- function oneOf(...alts) {
365
- const label = alts.map((alt) => alt.label).join(" | ");
920
+ function buildField(ownerName, name, node, sources, diagnostics) {
921
+ const attributes = readResolvedAttributes(node.attributes(), sources);
922
+ const span = nodePslSpan(node.syntax, sources);
923
+ const annotation = node.typeAnnotation();
924
+ const typeName = annotation?.name();
925
+ if (typeName?.isOverQualified()) {
926
+ const path = typeName.path();
927
+ diagnostics.push({
928
+ code: "PSL_INVALID_QUALIFIED_TYPE",
929
+ message: `Field "${ownerName}.${name}" has an invalid qualified type "${path.join(".")}"; use at most one namespace qualifier (e.g. "ns.TypeName")`,
930
+ filename: sources.sourceFileFor(typeName.syntax).filename,
931
+ range: nodeRange(typeName.syntax, sources)
932
+ });
933
+ return {
934
+ kind: "field",
935
+ name,
936
+ node,
937
+ span,
938
+ typeName: path[path.length - 1] ?? "",
939
+ optional: false,
940
+ list: false,
941
+ elementOptional: false,
942
+ malformedType: true,
943
+ attributes
944
+ };
945
+ }
946
+ const typeConstructor = annotation?.isConstructor() ? readResolvedConstructorCall(annotation, sources) : void 0;
947
+ const typeNamespaceId = typeName?.namespace()?.name();
948
+ const typeContractSpaceId = typeName?.space()?.name();
366
949
  return {
367
- kind: "oneOf",
368
- label,
369
- alternatives: alts,
370
- parse: (arg, ctx) => {
371
- const [head, ...tail] = blindCast(alts);
372
- let rejection = head.parse(arg, ctx);
373
- if (rejection.ok) return rejection;
374
- for (const alt of tail) {
375
- const result = alt.parse(arg, ctx);
376
- if (result.ok) return result;
377
- rejection = or(rejection, result);
378
- }
379
- if (!rejection.ok && rejection.failure.length === 0) return notOk([]);
380
- return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
381
- }
950
+ kind: "field",
951
+ name,
952
+ node,
953
+ span,
954
+ typeName: typeName?.identifier()?.name() ?? "",
955
+ ...typeNamespaceId !== void 0 ? { typeNamespaceId } : {},
956
+ ...typeContractSpaceId !== void 0 ? { typeContractSpaceId } : {},
957
+ optional: annotation?.isOptional() ?? false,
958
+ list: annotation?.isList() ?? false,
959
+ elementOptional: annotation?.isElementOptional() ?? false,
960
+ ...typeConstructor !== void 0 ? { typeConstructor } : {},
961
+ attributes
382
962
  };
383
963
  }
384
- function record(of) {
964
+ function resolveNamedTypeBinding(node, sources) {
965
+ const annotation = node.typeAnnotation();
966
+ const isConstructor = annotation?.isConstructor() ?? false;
967
+ const baseType = annotation?.name()?.identifier()?.name();
968
+ const typeConstructor = readResolvedConstructorCall(annotation, sources);
385
969
  return {
386
- kind: "record",
387
- label: `{ [key]: ${of.label} }`,
388
- of,
389
- parse: (arg, ctx) => {
390
- const literal = ObjectLiteralExprAst.cast(arg.syntax);
391
- if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected an object literal")]);
392
- const entries = [];
393
- const keys = /* @__PURE__ */ new Set();
394
- let outcome = okVoid();
395
- for (const field of Array.from(literal.fields())) {
396
- const key = field.keyName();
397
- if (key === void 0) {
398
- outcome = and(outcome, notOk([leafDiagnostic(ctx, field, "Expected a key")]));
399
- continue;
400
- }
401
- const value = field.value();
402
- if (value === void 0) {
403
- outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Expected a value for key "${key}"`)]));
404
- continue;
405
- }
406
- const parsed = of.parse(value, ctx);
407
- if (!parsed.ok) {
408
- outcome = and(outcome, parsed);
409
- continue;
410
- }
411
- if (keys.has(key)) {
412
- outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Duplicate key "${key}"`)]));
413
- continue;
414
- }
415
- keys.add(key);
416
- entries.push([key, parsed.value]);
417
- }
418
- if (!outcome.ok) return notOk(outcome.failure);
419
- return ok(Object.fromEntries(entries));
420
- }
970
+ isConstructor,
971
+ ...!isConstructor && baseType !== void 0 ? { baseType } : {},
972
+ ...typeConstructor !== void 0 ? { typeConstructor } : {},
973
+ attributes: readResolvedAttributes(node.attributes(), sources)
421
974
  };
422
975
  }
423
- function str(value) {
424
- if (value === void 0) return {
425
- kind: "str",
426
- label: "string",
427
- value: void 0,
428
- parse: (arg, ctx) => {
429
- const literal = StringLiteralExprAst.cast(arg.syntax);
430
- if (literal !== void 0) {
431
- const parsed = literal.value();
432
- if (parsed !== void 0) return ok(parsed);
433
- }
434
- return notOk([leafDiagnostic(ctx, arg, "Expected a string literal")]);
435
- }
976
+ function nameRange(name, sources) {
977
+ if (name === void 0) return void 0;
978
+ const sourceFile = sources.sourceFileFor(name.syntax);
979
+ for (const token of name.syntax.tokens()) if (token.kind === "Ident") return {
980
+ start: sourceFile.positionAt(token.offset),
981
+ end: sourceFile.positionAt(token.offset + token.text.length)
436
982
  };
983
+ }
984
+ function nodeRange(node, sources) {
985
+ const sourceFile = sources.sourceFileFor(node);
986
+ const start = node.offset;
987
+ const end = start + node.green.textLength;
437
988
  return {
438
- kind: "str",
439
- label: JSON.stringify(value),
440
- value,
441
- parse: (arg, ctx) => {
442
- const literal = StringLiteralExprAst.cast(arg.syntax);
443
- if (literal !== void 0) {
444
- if (literal.value() === value) return ok(value);
445
- }
446
- return notOk([leafDiagnostic(ctx, arg, `Expected ${JSON.stringify(value)}`)]);
447
- }
989
+ start: sourceFile.positionAt(start),
990
+ end: sourceFile.positionAt(end)
448
991
  };
449
992
  }
450
- function jsonValue() {
451
- const self = {
452
- kind: "oneOf",
453
- label: "JSON value",
454
- get alternatives() {
455
- return composed.alternatives;
456
- },
457
- parse: (arg, ctx) => composed.parse(arg, ctx)
458
- };
459
- const composed = oneOf(str(), finiteNumber(), bool(), jsonNull(), list(self), record(self));
460
- return self;
993
+ //#endregion
994
+ //#region ../../../1-framework/2-authoring/psl-parser/dist/index.mjs
995
+ function getPositionalArgument(attribute, index = 0) {
996
+ return attribute.args.filter((arg) => arg.kind === "positional")[index]?.value;
461
997
  }
462
- function finiteNumber() {
998
+ function parseQuotedStringLiteral(value) {
999
+ const match = value.trim().match(/^(['"])(.*)\1$/);
1000
+ if (!match) return void 0;
1001
+ return match[2] ?? "";
1002
+ }
1003
+ function blockAttribute(name, config) {
463
1004
  return {
464
- kind: "num",
465
- value: void 0,
466
- label: "number",
467
- parse: (arg, ctx) => {
468
- const value = NumberLiteralExprAst.cast(arg.syntax)?.value();
469
- if (value === void 0 || Number.isNaN(value) || !Number.isFinite(value)) return notOk([leafDiagnostic(ctx, arg, "Expected a finite number literal")]);
470
- return ok(value);
471
- }
1005
+ level: "block",
1006
+ name,
1007
+ documentation: config.documentation,
1008
+ positional: config.positional ?? [],
1009
+ named: config.named ?? {},
1010
+ ...config.refine !== void 0 ? { refine: config.refine } : {}
472
1011
  };
473
1012
  }
474
- function jsonNull() {
1013
+ const ATTRIBUTE_DIAGNOSTIC_CODE = "PSL_INVALID_ATTRIBUTE_SYNTAX";
1014
+ function leafDiagnostic(ctx, node, message, code = ATTRIBUTE_DIAGNOSTIC_CODE) {
475
1015
  return {
476
- kind: "null",
477
- label: "null",
478
- parse: (arg, ctx) => {
479
- if (IdentifierAst.cast(arg.syntax)?.name() === "null") return ok(null);
480
- return notOk([leafDiagnostic(ctx, arg, "Expected null")]);
481
- }
1016
+ code,
1017
+ message,
1018
+ ...diagnosticSource(ctx.sources, node.syntax).at(nodePslSpan(node.syntax, ctx.sources))
482
1019
  };
483
1020
  }
484
- function num(value) {
485
- if (value === void 0) return {
486
- kind: "num",
487
- label: "number",
488
- value: void 0,
489
- parse: (arg, ctx) => {
490
- const literal = NumberLiteralExprAst.cast(arg.syntax);
491
- if (literal !== void 0) {
492
- const parsed = literal.value();
493
- if (parsed !== void 0) return ok(parsed);
494
- }
495
- return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
496
- }
497
- };
1021
+ function bool() {
498
1022
  return {
499
- kind: "num",
500
- label: String(value),
501
- value,
1023
+ kind: "bool",
1024
+ label: "boolean",
502
1025
  parse: (arg, ctx) => {
503
- const literal = NumberLiteralExprAst.cast(arg.syntax);
1026
+ const literal = BooleanLiteralExprAst.cast(arg.syntax);
504
1027
  if (literal !== void 0) {
505
- if (literal.value() === value) return ok(value);
1028
+ const value = literal.value();
1029
+ if (value !== void 0) return ok(value);
506
1030
  }
507
- return notOk([leafDiagnostic(ctx, arg, `Expected ${value}`)]);
1031
+ return notOk([leafDiagnostic(ctx, arg, "Expected a boolean literal")]);
508
1032
  }
509
1033
  };
510
1034
  }
511
- /** A number literal kept as its source text, for consumers that must not round it through a JS number. */
512
- function numLiteral() {
513
- return {
514
- kind: "num",
515
- label: "number",
516
- value: void 0,
517
- parse: (arg, ctx) => {
518
- const text = NumberLiteralExprAst.cast(arg.syntax)?.token()?.text;
519
- if (text !== void 0) return ok({ text });
520
- return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
521
- }
1035
+ const references = /* @__PURE__ */ new WeakMap();
1036
+ function entityReference(resolution) {
1037
+ switch (resolution.kind) {
1038
+ case "model":
1039
+ case "compositeType":
1040
+ case "namedType":
1041
+ case "block": return interned(resolution.symbol, resolution.namespace);
1042
+ default: return;
1043
+ }
1044
+ }
1045
+ function interned(declaration, namespace) {
1046
+ const existing = references.get(declaration);
1047
+ if (existing !== void 0) return existing;
1048
+ const reference = {
1049
+ declaration,
1050
+ namespace
522
1051
  };
1052
+ references.set(declaration, reference);
1053
+ return reference;
523
1054
  }
524
- /**
525
- * A `` tag`...` ``, `tag"..."`, or `tag'...'` argument. `tags` and `documentation` describe the
526
- * registered tags for tooling; parsing accepts any tag.
527
- */
528
- function taggedLiteral(tags, options) {
1055
+ function matchesSelector(reference, expected) {
1056
+ const declaration = reference.declaration;
1057
+ if (declaration.kind !== expected.kind) return false;
1058
+ return expected.kind !== "block" || declaration.kind === "block" && declaration.keyword === expected.keyword;
1059
+ }
1060
+ function describeResolution(resolution) {
1061
+ switch (resolution.kind) {
1062
+ case "block": return resolution.symbol.keyword;
1063
+ case "contributedType": return "scalar type";
1064
+ case "crossSpace": return "cross-space reference";
1065
+ case "unresolved": return "unresolved name";
1066
+ default: return resolution.kind;
1067
+ }
1068
+ }
1069
+ function entityRef(expected) {
1070
+ const label = `${expected.kind === "block" ? expected.keyword : expected.kind} reference`;
529
1071
  return {
530
- kind: "taggedLiteral",
531
- label: `${tags[0] ?? "tag"}\`...\``,
532
- tags,
533
- documentation: options.documentation,
1072
+ kind: "entityRef",
1073
+ label,
1074
+ expected,
534
1075
  parse: (arg, ctx) => {
535
- const literal = TaggedLiteralExprAst.cast(arg.syntax);
536
- if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a tagged literal")]);
537
- return ok({
538
- tag: literal.tagName(),
539
- canonicalization: literal.canonicalization(),
540
- span: nodePslSpan(literal.syntax, ctx.sources)
541
- });
1076
+ const name = IdentifierAst.cast(arg.syntax)?.name();
1077
+ if (name === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
1078
+ const resolution = ctx.binder.symbolForNode(arg.syntax);
1079
+ if (resolution === void 0 || resolution.kind === "unresolved") return notOk([]);
1080
+ const reference = entityReference(resolution);
1081
+ if (reference === void 0 || !matchesSelector(reference, expected)) return notOk([leafDiagnostic(ctx, arg, `Expected ${label} "${name}", found ${describeResolution(resolution)}`)]);
1082
+ return ok(reference);
542
1083
  }
543
1084
  };
544
1085
  }
545
- function fieldAttribute(name, config) {
546
- return {
547
- level: "field",
548
- name,
549
- documentation: config.documentation,
550
- positional: config.positional ?? [],
551
- named: Object.assign(Object.create(null), config.named),
552
- ...config.refine !== void 0 ? { refine: config.refine } : {}
553
- };
1086
+ function parseFieldName(arg, ctx) {
1087
+ const identifier = IdentifierAst.cast(arg.syntax);
1088
+ if (identifier === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
1089
+ const name = identifier.name();
1090
+ if (name === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
1091
+ const resolution = ctx.binder.symbolForNode(arg.syntax);
1092
+ if (resolution === void 0) return notOk([]);
1093
+ if (resolution.kind === "field") return ok(resolution.symbol.name);
1094
+ if (resolution.kind === "crossSpace") return ok(name);
1095
+ return notOk([]);
554
1096
  }
555
- function modelAttribute(name, config) {
1097
+ function fieldRef() {
556
1098
  return {
557
- level: "model",
558
- name,
559
- documentation: config.documentation,
560
- positional: config.positional ?? [],
561
- named: Object.assign(Object.create(null), config.named),
562
- ...config.refine !== void 0 ? { refine: config.refine } : {}
1099
+ kind: "fieldRef",
1100
+ label: "field name",
1101
+ parse: parseFieldName
563
1102
  };
564
1103
  }
565
- function optional(type, ...rest) {
566
- if (rest.length === 0) return {
567
- ...type,
568
- optional: true,
569
- hasDefault: false
570
- };
1104
+ function referencedFieldRef() {
571
1105
  return {
572
- ...type,
573
- optional: true,
574
- hasDefault: true,
575
- defaultValue: rest[0]
1106
+ kind: "referencedFieldRef",
1107
+ label: "field name",
1108
+ parse: parseFieldName
576
1109
  };
577
1110
  }
578
- function blockSpecFactoryOf(descriptor) {
579
- return blindCast(descriptor.spec);
580
- }
581
- const scopes = /* @__PURE__ */ new WeakMap();
582
- function contributedTypeScope(typeConstructors) {
583
- const existing = scopes.get(typeConstructors);
584
- if (existing !== void 0) return existing;
585
- const members = collect(typeConstructors, []);
586
- const created = {
587
- lookup(name) {
588
- return members.get(name);
589
- },
590
- entries() {
591
- return members.entries();
1111
+ function interpretArgs(args, spec, ctx, span, sourceNode) {
1112
+ let outcome = okVoid();
1113
+ const output = {};
1114
+ const seen = /* @__PURE__ */ new Set();
1115
+ let positionalSlot = 0;
1116
+ let reportedExcess = false;
1117
+ for (const arg of args) {
1118
+ const name = arg.name()?.name();
1119
+ let key;
1120
+ let param;
1121
+ if (name === void 0) {
1122
+ const posParam = spec.positional[positionalSlot];
1123
+ if (posParam === void 0) {
1124
+ if (!reportedExcess) {
1125
+ outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received too many positional arguments`, ctx, span, sourceNode)]));
1126
+ reportedExcess = true;
1127
+ }
1128
+ continue;
1129
+ }
1130
+ positionalSlot += 1;
1131
+ key = posParam.key;
1132
+ param = posParam.type;
1133
+ } else {
1134
+ const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : void 0;
1135
+ if (namedParam === void 0) {
1136
+ outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received unknown argument "${name}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
1137
+ continue;
1138
+ }
1139
+ key = name;
1140
+ param = namedParam.type;
592
1141
  }
593
- };
594
- scopes.set(typeConstructors, created);
595
- return created;
596
- }
597
- function collect(namespace, prefix) {
598
- const members = /* @__PURE__ */ new Map();
599
- for (const [name, value] of Object.entries(namespace)) {
600
- const path = [...prefix, name];
601
- members.set(name, isAuthoringTypeConstructorDescriptor(value) ? {
602
- kind: "contributedType",
603
- name,
604
- path,
605
- descriptor: value
606
- } : {
607
- kind: "contributedNamespace",
608
- name,
609
- path,
610
- members: collect(value, path)
611
- });
612
- }
613
- return members;
614
- }
615
- function findBlockDescriptor(descriptors, keyword) {
616
- if (descriptors === void 0) return void 0;
617
- for (const value of Object.values(descriptors)) {
618
- if (value === void 0) continue;
619
- if (isAuthoringPslBlockDescriptor(value)) {
620
- if (value.keyword === keyword) return value;
1142
+ if (seen.has(key)) {
1143
+ outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received duplicate argument "${key}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
621
1144
  continue;
622
1145
  }
623
- const nested = findBlockDescriptor(value, keyword);
624
- if (nested !== void 0) return nested;
625
- }
626
- }
627
- function* recordNames(...records) {
628
- for (const record of records) yield* Object.keys(record);
629
- }
630
- var Scope = class {
631
- parent;
632
- constructor(parent) {
633
- this.parent = parent;
1146
+ seen.add(key);
1147
+ const result = parseArgValue(arg, param, ctx);
1148
+ if (result.ok) output[key] = result.value;
1149
+ outcome = and(outcome, result);
634
1150
  }
635
- *entries() {
636
- const seen = /* @__PURE__ */ new Set();
637
- for (const name of this.ownNames()) {
638
- if (seen.has(name)) continue;
639
- seen.add(name);
640
- const resolution = this.lookup(name);
641
- if (resolution !== void 0) yield [name, resolution];
1151
+ const finalized = /* @__PURE__ */ new Set();
1152
+ const finalizeAbsentKey = (key, positionalParam, namedParam) => {
1153
+ if (finalized.has(key) || seen.has(key)) return;
1154
+ finalized.add(key);
1155
+ const effective = namedParam ?? positionalParam;
1156
+ if (effective === void 0) return;
1157
+ if (isOptionalArgType(effective)) {
1158
+ if (effective.hasDefault) output[key] = effective.defaultValue;
1159
+ return;
642
1160
  }
643
- for (const entry of this.parent?.entries() ?? []) if (!seen.has(entry[0])) yield entry;
644
- }
645
- };
646
- function contributedResolution(member) {
647
- return member.kind === "contributedType" ? {
648
- kind: "contributedType",
649
- symbol: member
650
- } : {
651
- kind: "contributedNamespace",
652
- symbol: member
653
- };
654
- }
655
- function namespaceMember(namespace, name) {
656
- const model = namespace.models[name];
657
- if (model !== void 0) return {
658
- kind: "model",
659
- symbol: model,
660
- namespace
661
- };
662
- const compositeType = namespace.compositeTypes[name];
663
- if (compositeType !== void 0) return {
664
- kind: "compositeType",
665
- symbol: compositeType,
666
- namespace
667
- };
668
- const block = namespace.blocks[name];
669
- if (block !== void 0) return {
670
- kind: "block",
671
- symbol: block,
672
- namespace
1161
+ outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" is missing required argument "${key}"`, ctx, span, sourceNode)]));
673
1162
  };
674
- }
675
- var ContributedScope = class extends Scope {
676
- #registry;
677
- constructor(registry) {
678
- super(void 0);
679
- this.#registry = registry;
680
- }
681
- lookup(name) {
682
- const member = this.#registry.lookup(name);
683
- return member === void 0 ? void 0 : contributedResolution(member);
684
- }
685
- *ownNames() {
686
- for (const [name] of this.#registry.entries()) yield name;
687
- }
688
- };
689
- var DocumentScope = class extends Scope {
690
- #records;
691
- constructor(records, parent) {
692
- super(parent);
693
- this.#records = records;
694
- }
695
- lookup(name) {
696
- const records = this.#records;
697
- const model = records.models[name];
698
- if (model !== void 0) return {
699
- kind: "model",
700
- symbol: model
701
- };
702
- const compositeType = records.compositeTypes[name];
703
- if (compositeType !== void 0) return {
704
- kind: "compositeType",
705
- symbol: compositeType
706
- };
707
- const namedType = records.namedTypes[name];
708
- if (namedType !== void 0) return {
709
- kind: "namedType",
710
- symbol: namedType
711
- };
712
- const block = records.blocks[name];
713
- if (block !== void 0) return {
714
- kind: "block",
715
- symbol: block
716
- };
717
- const namespace = records.namespaces[name];
718
- if (namespace !== void 0) return {
719
- kind: "namespace",
720
- symbol: namespace
721
- };
722
- return this.parent?.lookup(name);
723
- }
724
- ownNames() {
725
- const records = this.#records;
726
- return recordNames(records.models, records.compositeTypes, records.namedTypes, records.blocks, records.namespaces);
727
- }
728
- };
729
- var NamespaceScope = class extends Scope {
730
- #namespace;
731
- constructor(namespace, parent) {
732
- super(parent);
733
- this.#namespace = namespace;
734
- }
735
- lookup(name) {
736
- return namespaceMember(this.#namespace, name) ?? this.parent?.lookup(name);
737
- }
738
- ownNames() {
739
- const namespace = this.#namespace;
740
- return recordNames(namespace.models, namespace.compositeTypes, namespace.blocks);
1163
+ for (const param of spec.positional) {
1164
+ const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : void 0;
1165
+ finalizeAbsentKey(param.key, param.type, namedParam?.type);
741
1166
  }
742
- };
743
- function contributedScope(registry) {
744
- return new ContributedScope(registry);
745
- }
746
- function documentScope(records, parent) {
747
- return new DocumentScope(records, parent);
748
- }
749
- function namespaceScope(namespace, parent) {
750
- return new NamespaceScope(namespace, parent);
751
- }
752
- function isNamespaceLike(resolution) {
753
- return resolution.kind === "namespace" || resolution.kind === "contributedNamespace";
1167
+ for (const key of Object.keys(spec.named)) finalizeAbsentKey(key, void 0, spec.named[key]?.type);
1168
+ if (!outcome.ok) return notOk(outcome.failure);
1169
+ return ok(output);
754
1170
  }
755
- function* memberEntries(qualifier) {
756
- if (qualifier.kind === "contributedNamespace") {
757
- for (const [name, member] of qualifier.symbol.members) yield [name, contributedResolution(member)];
758
- return;
1171
+ function interpretAttribute(attrNode, spec, ctx) {
1172
+ const attributeSpan = nodePslSpan(attrNode.syntax, ctx.sources);
1173
+ const bound = interpretArgs(attrNode.argList()?.args() ?? [], spec, ctx, attributeSpan, attrNode.syntax);
1174
+ if (!bound.ok) return notOk(bound.failure);
1175
+ const value = blindCast(bound.value);
1176
+ if (spec.refine !== void 0) {
1177
+ const refineDiagnostics = spec.refine(value, ctx, attrNode);
1178
+ if (refineDiagnostics.length > 0) return notOk(refineDiagnostics);
759
1179
  }
760
- yield* new NamespaceScope(qualifier.symbol, void 0).entries();
1180
+ return ok(value);
761
1181
  }
762
- function lookupMember(qualifier, name) {
763
- if (qualifier.kind === "contributedNamespace") {
764
- const member = qualifier.symbol.members.get(name);
765
- return member === void 0 ? void 0 : contributedResolution(member);
766
- }
767
- return namespaceMember(qualifier.symbol, name);
1182
+ function parseArgValue(arg, argType, ctx) {
1183
+ const value = arg.value();
1184
+ if (value === void 0) return notOk([diagnostic("Attribute argument is missing a value", ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]);
1185
+ return argType.parse(value, ctx);
768
1186
  }
769
- const PSL_UNRESOLVED_REFERENCE = "PSL_UNRESOLVED_REFERENCE";
770
- function typeReferenceNode(symbol) {
771
- return symbol.node.typeAnnotation()?.name()?.syntax;
1187
+ function isOptionalArgType(param) {
1188
+ return "optional" in param && param.optional === true;
772
1189
  }
773
- var PslBinder = class {
774
- #declarations;
775
- #references;
776
- #documentScope;
777
- #scopes;
778
- constructor(declarations, references, documentScope, scopes) {
779
- this.#declarations = declarations;
780
- this.#references = references;
781
- this.#documentScope = documentScope;
782
- this.#scopes = scopes;
783
- }
784
- declaredSymbol(node) {
785
- return this.#declarations.get(node);
786
- }
787
- symbolForNode(node) {
788
- return this.#references.get(node);
789
- }
790
- scopeAt(node) {
791
- return node.findAncestor((ancestor) => this.#scopes.get(ancestor)) ?? this.#documentScope;
792
- }
793
- };
794
- var ScopeStack = class {
795
- #base;
796
- #scopes;
797
- constructor(base) {
798
- this.#base = base;
799
- this.#scopes = [base];
800
- }
801
- current() {
802
- return this.#scopes[this.#scopes.length - 1] ?? this.#base;
803
- }
804
- push(scope) {
805
- this.#scopes.push(scope);
806
- }
807
- pop() {
808
- this.#scopes.pop();
809
- }
810
- };
811
- function walkEntities(symbolTable, stack, binder, visit) {
812
- const { topLevel } = symbolTable;
813
- for (const entity of Object.values(topLevel.models)) visit(entity);
814
- for (const entity of Object.values(topLevel.compositeTypes)) visit(entity);
815
- for (const namespace of Object.values(topLevel.namespaces)) {
816
- stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
817
- for (const entity of Object.values(namespace.models)) visit(entity);
818
- for (const entity of Object.values(namespace.compositeTypes)) visit(entity);
819
- stack.pop();
820
- }
1190
+ function diagnostic(message, ctx, span, sourceNode) {
1191
+ return {
1192
+ code: ATTRIBUTE_DIAGNOSTIC_CODE,
1193
+ message,
1194
+ ...diagnosticSource(ctx.sources, sourceNode).at(span)
1195
+ };
821
1196
  }
822
- function createBinder(options) {
823
- const { sources, symbolTable, typeConstructors, attributeSpecs, controlMutationDefaults, describeUnsupportedAttribute } = options;
824
- const pslBlockDescriptors = options.pslBlockDescriptors ?? {};
825
- const document = documentScope(symbolTable.topLevel, contributedScope(contributedTypeScope(typeConstructors)));
826
- const stack = new ScopeStack(document);
827
- const scopes = /* @__PURE__ */ new WeakMap();
828
- const declarations = /* @__PURE__ */ new WeakMap();
829
- const references = /* @__PURE__ */ new WeakMap();
830
- const diagnostics = [];
831
- const binder = new PslBinder(declarations, references, document, scopes);
832
- for (const symbol of Object.values(symbolTable.topLevel.namedTypes)) {
833
- declarations.set(symbol.node.syntax, symbol);
834
- const name = symbol.node.typeAnnotation()?.name();
835
- const outcome = resolveTypeReference(name, document);
836
- if (name !== void 0 && outcome !== void 0) references.set(name.syntax, outcome.resolution);
837
- }
838
- for (const symbol of Object.values(symbolTable.topLevel.blocks)) declarations.set(symbol.node.syntax, symbol);
839
- for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
840
- const scope = namespaceScope(namespace, document);
841
- for (const declaration of namespace.declarations) {
842
- declarations.set(declaration.node.syntax, namespace);
843
- scopes.set(declaration.node.syntax, scope);
844
- }
845
- for (const symbol of Object.values(namespace.blocks)) declarations.set(symbol.node.syntax, symbol);
846
- }
847
- walkEntities(symbolTable, stack, binder, (entity) => {
848
- declarations.set(entity.node.syntax, entity);
849
- for (const field of Object.values(entity.fields)) {
850
- declarations.set(field.node.syntax, field);
851
- const node = typeReferenceNode(field);
852
- if (node === void 0) continue;
853
- const outcome = resolveTypeReference(field.node.typeAnnotation()?.name(), stack.current());
854
- if (outcome === void 0) continue;
855
- references.set(node, outcome.resolution);
856
- if (outcome.message !== void 0) diagnostics.push({
857
- code: PSL_UNRESOLVED_REFERENCE,
858
- message: outcome.message,
859
- data: {
860
- reference: "type",
861
- name: outcome.name,
862
- constructorCall: field.typeConstructor !== void 0
863
- },
864
- ...diagnosticSource(sources, node).at()
1197
+ function funcCall(name, sig) {
1198
+ return {
1199
+ kind: "funcCall",
1200
+ label: `${name}()`,
1201
+ name,
1202
+ signature: sig,
1203
+ parse: (arg, ctx) => {
1204
+ const guard = matchCallee(arg, name, ctx);
1205
+ if (!guard.ok) return guard;
1206
+ const span = nodePslSpan(guard.value.syntax, ctx.sources);
1207
+ const bound = interpretArgs(guard.value.args(), {
1208
+ name,
1209
+ positional: sig.positional ?? [],
1210
+ named: sig.named ?? {}
1211
+ }, ctx, span, guard.value.syntax);
1212
+ if (!bound.ok) return notOk(bound.failure);
1213
+ return ok({
1214
+ fn: name,
1215
+ span,
1216
+ args: bound.value
865
1217
  });
866
1218
  }
867
- });
868
- walkEntities(symbolTable, stack, binder, (entity) => {
869
- const context = {
870
- owner: entity,
871
- scope: stack.current(),
872
- references,
873
- diagnostics,
874
- symbolTable,
875
- sources,
876
- describeUnsupportedAttribute
877
- };
878
- const specContext = entity.kind === "model" ? {
879
- symbols: symbolTable,
880
- model: entity,
881
- controlMutationDefaults
882
- } : void 0;
883
- bindAttributes(entity, entity.attributes, attributeSpecs.model, (factory) => specContext === void 0 ? void 0 : factory(specContext), {
884
- ...context,
885
- field: void 0
886
- });
887
- for (const field of Object.values(entity.fields)) bindAttributes(field, field.attributes, attributeSpecs.field, (factory) => specContext === void 0 ? void 0 : factory({
888
- ...specContext,
889
- field
890
- }), {
891
- ...context,
892
- field
893
- });
894
- });
895
- const blockContext = {
896
- pslBlockDescriptors,
897
- symbolTable,
898
- sources,
899
- references,
900
- diagnostics
901
1219
  };
902
- const bindBlocks = (blocks) => {
903
- const context = {
904
- ...blockContext,
905
- scope: stack.current()
906
- };
907
- for (const block of Object.values(blocks)) bindBlock(block, context);
1220
+ }
1221
+ function matchCallee(arg, name, ctx) {
1222
+ const call = FunctionCallAst.cast(arg.syntax);
1223
+ if (call === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
1224
+ const qname = call.name();
1225
+ if (qname === void 0 || qname.dot() !== void 0 || qname.colon() !== void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
1226
+ const calleeName = qname.identifier()?.token()?.text;
1227
+ if (calleeName === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
1228
+ if (calleeName !== name) return notOk([leafDiagnostic(ctx, arg, `Expected ${name}()`)]);
1229
+ return ok(call);
1230
+ }
1231
+ function identifier(name, options) {
1232
+ const label = name ?? "identifier";
1233
+ return {
1234
+ kind: "identifier",
1235
+ label,
1236
+ name,
1237
+ documentation: options?.documentation ?? "",
1238
+ parse: (arg, ctx) => {
1239
+ const value = IdentifierAst.cast(arg.syntax)?.name();
1240
+ if (value !== void 0 && (name === void 0 || value === name)) return ok(value);
1241
+ return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
1242
+ }
908
1243
  };
909
- bindBlocks(symbolTable.topLevel.blocks);
910
- for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
911
- stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
912
- bindBlocks(namespace.blocks);
913
- stack.pop();
914
- }
1244
+ }
1245
+ function int(opts) {
1246
+ const min = opts?.min;
1247
+ const max = opts?.max;
1248
+ return {
1249
+ kind: "int",
1250
+ label: "integer",
1251
+ ...min === void 0 ? {} : { min },
1252
+ ...max === void 0 ? {} : { max },
1253
+ parse: (arg, ctx) => {
1254
+ const literal = NumberLiteralExprAst.cast(arg.syntax);
1255
+ if (literal !== void 0) {
1256
+ const value = literal.value();
1257
+ if (value !== void 0 && Number.isInteger(value)) {
1258
+ if ((min === void 0 || value >= min) && (max === void 0 || value <= max)) return ok(value);
1259
+ return notOk([leafDiagnostic(ctx, arg, rangeMessage(min, max))]);
1260
+ }
1261
+ }
1262
+ return notOk([leafDiagnostic(ctx, arg, "Expected an integer literal")]);
1263
+ }
1264
+ };
1265
+ }
1266
+ function rangeMessage(min, max) {
1267
+ if (min !== void 0 && max !== void 0) return `Expected an integer between ${min} and ${max}`;
1268
+ if (min !== void 0) return `Expected an integer greater than or equal to ${min}`;
1269
+ return `Expected an integer less than or equal to ${max}`;
1270
+ }
1271
+ /**
1272
+ * Reads an opaque JSON object from a quoted JSON string — the ADR's one text-encoded surface
1273
+ * exception (e.g. an index `filter` / `weights` argument). The string is decoded by the parser,
1274
+ * then JSON-parsed; a non-object (array/scalar) or invalid JSON is a diagnostic.
1275
+ */
1276
+ function json() {
915
1277
  return {
916
- binder,
917
- diagnostics
1278
+ kind: "json",
1279
+ label: "JSON object",
1280
+ parse: (arg, ctx) => {
1281
+ const literal = StringLiteralExprAst.cast(arg.syntax);
1282
+ if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a JSON object string")]);
1283
+ const raw = literal.value();
1284
+ if (raw !== void 0) try {
1285
+ const parsed = JSON.parse(raw);
1286
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return ok(blindCast(parsed));
1287
+ } catch {}
1288
+ return notOk([leafDiagnostic(ctx, arg, "Expected a valid JSON object")]);
1289
+ }
918
1290
  };
919
1291
  }
920
- function bindBlock(block, ctx) {
921
- const descriptor = findBlockDescriptor(ctx.pslBlockDescriptors, block.keyword);
922
- if (descriptor === void 0) return;
923
- const spec = blockSpecFactoryOf(descriptor)({
924
- symbols: ctx.symbolTable,
925
- block
926
- });
927
- for (const entry of block.node.entries()) {
928
- const key = entry.key()?.name();
929
- if (key === void 0) continue;
930
- const rule = spec.mode === "struct" ? Object.hasOwn(spec.parameters, key) ? spec.parameters[key]?.type : void 0 : spec.value.type;
931
- const value = entry.value();
932
- if (rule === void 0 || value === void 0) continue;
933
- bindExpression(rule, value, ctx);
934
- }
935
- const attributeSpecs = descriptor.attributes ?? {};
936
- if (Object.keys(attributeSpecs).length === 0) return;
937
- for (const attribute of readResolvedAttributes(block.node.attributes(), ctx.sources)) {
938
- const factory = attributeSpecs[attribute.name];
939
- if (factory === void 0) continue;
940
- bindArguments(attribute, blindCast(factory)({
941
- symbols: ctx.symbolTable,
942
- block
943
- }), ctx);
944
- }
945
- }
946
- function bindExpression(rule, expression, ctx, modelContext) {
947
- const trial = tryBindExpression(rule, expression, ctx, modelContext);
948
- for (const [node, resolution] of trial.references) ctx.references.set(node, resolution);
949
- ctx.diagnostics.push(...trial.diagnostics.values());
950
- }
951
- function tryBindExpression(rule, expression, ctx, modelContext) {
952
- const references = /* @__PURE__ */ new Map();
953
- const diagnostics = /* @__PURE__ */ new Map();
954
- switch (rule.kind) {
955
- case "oneOf":
956
- for (const alternative of rule.alternatives) {
957
- const trial = tryBindExpression(alternative, expression, ctx, modelContext);
958
- if (trial.matched) return trial;
959
- for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
960
- for (const [node, resolution] of trial.references) if (resolution.kind === "unresolved") references.set(node, resolution);
1292
+ function list(of, opts) {
1293
+ const allowEmpty = opts?.allowEmpty ?? true;
1294
+ const unique = opts?.unique ?? false;
1295
+ return {
1296
+ kind: "list",
1297
+ label: opts?.label ?? (of.label.includes(" | ") ? `(${of.label})[]` : `${of.label}[]`),
1298
+ of,
1299
+ allowEmpty,
1300
+ unique,
1301
+ parse: (arg, ctx) => {
1302
+ const literal = ArrayLiteralAst.cast(arg.syntax);
1303
+ if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);
1304
+ const parsed = [];
1305
+ let outcome = okVoid();
1306
+ let count = 0;
1307
+ for (const element of literal.elements()) {
1308
+ count += 1;
1309
+ const result = of.parse(element, ctx);
1310
+ if (result.ok) parsed.push({
1311
+ node: element,
1312
+ value: result.value
1313
+ });
1314
+ outcome = and(outcome, result);
961
1315
  }
962
- return {
963
- matched: false,
964
- references,
965
- diagnostics
966
- };
967
- case "list":
968
- case "record": {
969
- const children = rule.kind === "list" ? ArrayLiteralAst.cast(expression.syntax)?.elements() : recordValues(expression);
970
- if (children === void 0) return {
971
- matched: false,
972
- references,
973
- diagnostics
974
- };
975
- let matched = true;
976
- for (const child of children) {
977
- const trial = tryBindExpression(rule.of, child, ctx, modelContext);
978
- matched = trial.matched && matched;
979
- for (const [node, resolution] of trial.references) references.set(node, resolution);
980
- for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
1316
+ if (!allowEmpty && count === 0) outcome = and(outcome, notOk([leafDiagnostic(ctx, arg, "Expected a non-empty list")]));
1317
+ if (unique) {
1318
+ const seen = /* @__PURE__ */ new Set();
1319
+ for (const { node, value } of parsed) if (seen.has(value)) outcome = and(outcome, notOk([leafDiagnostic(ctx, node, "Duplicate list entry")]));
1320
+ else seen.add(value);
981
1321
  }
982
- return {
983
- matched,
984
- references,
985
- diagnostics
986
- };
1322
+ if (!outcome.ok) return notOk(outcome.failure);
1323
+ return ok(parsed.map((entry) => entry.value));
987
1324
  }
988
- case "funcCall": {
989
- const call = FunctionCallAst.cast(expression.syntax);
990
- const name = call?.name();
991
- if (call === void 0 || name === void 0 || name.dot() !== void 0 || name.colon() !== void 0 || name.identifier()?.name() !== rule.name) return {
992
- matched: false,
993
- references,
994
- diagnostics
995
- };
996
- let matched = true;
997
- let positional = 0;
998
- for (const arg of call.args()) {
999
- const key = arg.name()?.name();
1000
- const parameter = argumentParameter(rule.signature, key, key === void 0 ? positional++ : positional);
1001
- const value = arg.value();
1002
- if (parameter === void 0 || value === void 0) {
1003
- matched = false;
1004
- continue;
1005
- }
1006
- const trial = tryBindExpression(parameter.type, value, ctx, modelContext);
1007
- matched = trial.matched && matched;
1008
- for (const [node, resolution] of trial.references) references.set(node, resolution);
1009
- for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
1325
+ };
1326
+ }
1327
+ function oneOf(...alts) {
1328
+ const label = alts.map((alt) => alt.label).join(" | ");
1329
+ return {
1330
+ kind: "oneOf",
1331
+ label,
1332
+ alternatives: alts,
1333
+ parse: (arg, ctx) => {
1334
+ const [head, ...tail] = blindCast(alts);
1335
+ let rejection = head.parse(arg, ctx);
1336
+ if (rejection.ok) return rejection;
1337
+ for (const alt of tail) {
1338
+ const result = alt.parse(arg, ctx);
1339
+ if (result.ok) return result;
1340
+ rejection = or(rejection, result);
1010
1341
  }
1011
- return {
1012
- matched,
1013
- references,
1014
- diagnostics
1015
- };
1016
- }
1017
- case "entityRef": {
1018
- const node = expression.syntax;
1019
- const name = IdentifierAst.cast(node)?.name();
1020
- if (name === void 0) return {
1021
- matched: false,
1022
- references,
1023
- diagnostics
1024
- };
1025
- const failures = [];
1026
- const resolution = resolveEntity(name, node, {
1027
- ...ctx,
1028
- diagnostics: failures
1029
- });
1030
- references.set(node, resolution);
1031
- for (const diagnostic of failures) diagnostics.set(node, diagnostic);
1032
- return {
1033
- matched: resolution.kind !== "unresolved",
1034
- references,
1035
- diagnostics
1036
- };
1037
- }
1038
- case "fieldRef": {
1039
- const node = expression.syntax;
1040
- const name = IdentifierAst.cast(node)?.name();
1041
- if (name === void 0 || modelContext === void 0) return {
1042
- matched: false,
1043
- references,
1044
- diagnostics
1045
- };
1046
- const failures = [];
1047
- const resolution = resolveOwnerField(name, node, {
1048
- ...modelContext,
1049
- diagnostics: failures
1050
- });
1051
- references.set(node, resolution);
1052
- for (const diagnostic of failures) diagnostics.set(node, diagnostic);
1053
- return {
1054
- matched: resolution.kind !== "unresolved",
1055
- references,
1056
- diagnostics
1057
- };
1058
- }
1059
- case "referencedFieldRef": {
1060
- const node = expression.syntax;
1061
- const name = IdentifierAst.cast(node)?.name();
1062
- if (name === void 0 || modelContext === void 0) return {
1063
- matched: false,
1064
- references,
1065
- diagnostics
1066
- };
1067
- const failures = [];
1068
- const resolution = resolveReferencedField(name, node, {
1069
- ...modelContext,
1070
- diagnostics: failures
1071
- });
1072
- references.set(node, resolution);
1073
- for (const diagnostic of failures) diagnostics.set(node, diagnostic);
1074
- return {
1075
- matched: resolution.kind !== "unresolved",
1076
- references,
1077
- diagnostics
1078
- };
1342
+ if (!rejection.ok && rejection.failure.length === 0) return notOk([]);
1343
+ return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
1079
1344
  }
1080
- default: return {
1081
- matched: true,
1082
- references,
1083
- diagnostics
1084
- };
1085
- }
1345
+ };
1086
1346
  }
1087
- function recordValues(expression) {
1088
- const record = ObjectLiteralExprAst.cast(expression.syntax);
1089
- if (record === void 0) return void 0;
1090
- return (function* () {
1091
- for (const field of record.fields()) {
1092
- const value = field.value();
1093
- if (value !== void 0) yield value;
1347
+ function record(of) {
1348
+ return {
1349
+ kind: "record",
1350
+ label: `{ [key]: ${of.label} }`,
1351
+ of,
1352
+ parse: (arg, ctx) => {
1353
+ const literal = ObjectLiteralExprAst.cast(arg.syntax);
1354
+ if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected an object literal")]);
1355
+ const entries = [];
1356
+ const keys = /* @__PURE__ */ new Set();
1357
+ let outcome = okVoid();
1358
+ for (const field of Array.from(literal.fields())) {
1359
+ const key = field.keyName();
1360
+ if (key === void 0) {
1361
+ outcome = and(outcome, notOk([leafDiagnostic(ctx, field, "Expected a key")]));
1362
+ continue;
1363
+ }
1364
+ const value = field.value();
1365
+ if (value === void 0) {
1366
+ outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Expected a value for key "${key}"`)]));
1367
+ continue;
1368
+ }
1369
+ const parsed = of.parse(value, ctx);
1370
+ if (!parsed.ok) {
1371
+ outcome = and(outcome, parsed);
1372
+ continue;
1373
+ }
1374
+ if (keys.has(key)) {
1375
+ outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Duplicate key "${key}"`)]));
1376
+ continue;
1377
+ }
1378
+ keys.add(key);
1379
+ entries.push([key, parsed.value]);
1380
+ }
1381
+ if (!outcome.ok) return notOk(outcome.failure);
1382
+ return ok(Object.fromEntries(entries));
1094
1383
  }
1095
- })();
1384
+ };
1096
1385
  }
1097
- function bindAttributes(holder, attributes, specs, instantiate, ctx) {
1098
- const declared = holder.node.attributes();
1099
- const nodes = Array.from(declared);
1100
- const level = holder.kind === "field" ? "field" : "model";
1101
- attributes.forEach((attribute, index) => {
1102
- const factory = own(specs, attribute.name);
1103
- if (factory === void 0) {
1104
- const diagnostic = ctx.describeUnsupportedAttribute?.({
1105
- attribute,
1106
- level,
1107
- owner: ctx.owner,
1108
- field: level === "field" ? ctx.field : void 0
1109
- });
1110
- if (diagnostic !== void 0) ctx.diagnostics.push(diagnostic);
1111
- return;
1386
+ function str(value) {
1387
+ if (value === void 0) return {
1388
+ kind: "str",
1389
+ label: "string",
1390
+ value: void 0,
1391
+ parse: (arg, ctx) => {
1392
+ const literal = StringLiteralExprAst.cast(arg.syntax);
1393
+ if (literal !== void 0) {
1394
+ const parsed = literal.value();
1395
+ if (parsed !== void 0) return ok(parsed);
1396
+ }
1397
+ return notOk([leafDiagnostic(ctx, arg, "Expected a string literal")]);
1112
1398
  }
1113
- const spec = instantiate(factory);
1114
- if (spec === void 0) return;
1115
- const nameNode = nodes[index]?.name()?.syntax;
1116
- if (nameNode !== void 0) ctx.references.set(nameNode, {
1117
- kind: "attribute",
1118
- symbol: {
1119
- kind: "attribute",
1120
- name: attribute.name,
1121
- level,
1122
- spec
1399
+ };
1400
+ return {
1401
+ kind: "str",
1402
+ label: JSON.stringify(value),
1403
+ value,
1404
+ parse: (arg, ctx) => {
1405
+ const literal = StringLiteralExprAst.cast(arg.syntax);
1406
+ if (literal !== void 0) {
1407
+ if (literal.value() === value) return ok(value);
1123
1408
  }
1124
- });
1125
- bindArguments(attribute, spec, ctx, ctx);
1126
- });
1127
- }
1128
- function bindArguments(attribute, spec, ctx, modelContext) {
1129
- let positional = 0;
1130
- for (const arg of attribute.args) {
1131
- const parameter = argumentParameter(spec, arg.name, arg.name === void 0 ? positional++ : positional);
1132
- if (parameter === void 0 || arg.expression === void 0) continue;
1133
- bindExpression(parameter.type, arg.expression, ctx, modelContext);
1134
- }
1135
- }
1136
- function argumentParameter(spec, name, position) {
1137
- if (name === void 0) return spec.positional?.[position];
1138
- return spec.named === void 0 ? void 0 : own(spec.named, name);
1409
+ return notOk([leafDiagnostic(ctx, arg, `Expected ${JSON.stringify(value)}`)]);
1410
+ }
1411
+ };
1139
1412
  }
1140
- function resolveOwnerField(name, node, ctx) {
1141
- const field = ctx.owner.fields[name];
1142
- if (field !== void 0) return {
1143
- kind: "field",
1144
- symbol: field
1413
+ function jsonValue() {
1414
+ const self = {
1415
+ kind: "oneOf",
1416
+ label: "JSON value",
1417
+ get alternatives() {
1418
+ return composed.alternatives;
1419
+ },
1420
+ parse: (arg, ctx) => composed.parse(arg, ctx)
1145
1421
  };
1146
- report(`Cannot find field "${name}" on "${ctx.owner.name}"`, node, ctx, "field");
1422
+ const composed = oneOf(str(), finiteNumber(), bool(), jsonNull(), list(self), record(self));
1423
+ return self;
1424
+ }
1425
+ function finiteNumber() {
1147
1426
  return {
1148
- kind: "unresolved",
1149
- name
1427
+ kind: "num",
1428
+ value: void 0,
1429
+ label: "number",
1430
+ parse: (arg, ctx) => {
1431
+ const value = NumberLiteralExprAst.cast(arg.syntax)?.value();
1432
+ if (value === void 0 || Number.isNaN(value) || !Number.isFinite(value)) return notOk([leafDiagnostic(ctx, arg, "Expected a finite number literal")]);
1433
+ return ok(value);
1434
+ }
1150
1435
  };
1151
1436
  }
1152
- function resolveReferencedField(name, node, ctx) {
1153
- const declaring = ctx.field;
1154
- if (declaring === void 0) return {
1155
- kind: "unresolved",
1156
- name
1437
+ function jsonNull() {
1438
+ return {
1439
+ kind: "null",
1440
+ label: "null",
1441
+ parse: (arg, ctx) => {
1442
+ if (IdentifierAst.cast(arg.syntax)?.name() === "null") return ok(null);
1443
+ return notOk([leafDiagnostic(ctx, arg, "Expected null")]);
1444
+ }
1157
1445
  };
1158
- if (declaring.typeContractSpaceId !== void 0) return { kind: "crossSpace" };
1159
- const typeNode = typeReferenceNode(declaring);
1160
- const field = targetFields(typeNode === void 0 ? void 0 : ctx.references.get(typeNode))?.[name];
1161
- if (field !== void 0) return {
1162
- kind: "field",
1163
- symbol: field
1446
+ }
1447
+ function num(value) {
1448
+ if (value === void 0) return {
1449
+ kind: "num",
1450
+ label: "number",
1451
+ value: void 0,
1452
+ parse: (arg, ctx) => {
1453
+ const literal = NumberLiteralExprAst.cast(arg.syntax);
1454
+ if (literal !== void 0) {
1455
+ const parsed = literal.value();
1456
+ if (parsed !== void 0) return ok(parsed);
1457
+ }
1458
+ return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
1459
+ }
1164
1460
  };
1165
- report(`Cannot find field "${name}" on the type of "${ctx.owner.name}.${declaring.name}"`, node, ctx, "field");
1166
1461
  return {
1167
- kind: "unresolved",
1168
- name
1462
+ kind: "num",
1463
+ label: String(value),
1464
+ value,
1465
+ parse: (arg, ctx) => {
1466
+ const literal = NumberLiteralExprAst.cast(arg.syntax);
1467
+ if (literal !== void 0) {
1468
+ if (literal.value() === value) return ok(value);
1469
+ }
1470
+ return notOk([leafDiagnostic(ctx, arg, `Expected ${value}`)]);
1471
+ }
1169
1472
  };
1170
1473
  }
1171
- function targetFields(target) {
1172
- if (target === void 0) return void 0;
1173
- if (target.kind === "model" || target.kind === "compositeType") return target.symbol.fields;
1174
- }
1175
- function resolveEntity(name, node, ctx) {
1176
- const found = ctx.scope.lookup(name);
1177
- if (found === void 0) {
1178
- report(`Cannot find entity "${name}"`, node, ctx, "entity");
1179
- return {
1180
- kind: "unresolved",
1181
- name
1182
- };
1183
- }
1184
- return found;
1474
+ /** A number literal kept as its source text, for consumers that must not round it through a JS number. */
1475
+ function numLiteral() {
1476
+ return {
1477
+ kind: "num",
1478
+ label: "number",
1479
+ value: void 0,
1480
+ parse: (arg, ctx) => {
1481
+ const text = NumberLiteralExprAst.cast(arg.syntax)?.token()?.text;
1482
+ if (text !== void 0) return ok({ text });
1483
+ return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
1484
+ }
1485
+ };
1185
1486
  }
1186
- function report(message, node, ctx, reference) {
1187
- ctx.diagnostics.push({
1188
- code: PSL_UNRESOLVED_REFERENCE,
1189
- message,
1190
- data: { reference },
1191
- ...diagnosticSource(ctx.sources, node).at()
1192
- });
1487
+ /**
1488
+ * A `` tag`...` ``, `tag"..."`, or `tag'...'` argument. `tags` and `documentation` describe the
1489
+ * registered tags for tooling; parsing accepts any tag.
1490
+ */
1491
+ function taggedLiteral(tags, options) {
1492
+ return {
1493
+ kind: "taggedLiteral",
1494
+ label: `${tags[0] ?? "tag"}\`...\``,
1495
+ tags,
1496
+ documentation: options.documentation,
1497
+ parse: (arg, ctx) => {
1498
+ const literal = TaggedLiteralExprAst.cast(arg.syntax);
1499
+ if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a tagged literal")]);
1500
+ return ok({
1501
+ tag: literal.tagName(),
1502
+ canonicalization: literal.canonicalization(),
1503
+ span: nodePslSpan(literal.syntax, ctx.sources)
1504
+ });
1505
+ }
1506
+ };
1193
1507
  }
1194
- function resolveTypeReference(reference, scope) {
1195
- if (reference === void 0 || reference.isOverQualified()) return void 0;
1196
- if (reference.space() !== void 0) return { resolution: { kind: "crossSpace" } };
1197
- const name = reference.identifier()?.name();
1198
- if (name === void 0 || name === "") return void 0;
1199
- const namespaceId = reference.namespace()?.name();
1200
- const found = namespaceId === void 0 ? scope.lookup(name) : qualifiedMember(namespaceId, name, scope);
1201
- if (found === void 0) {
1202
- const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
1203
- return {
1204
- resolution: {
1205
- kind: "unresolved",
1206
- name: written
1207
- },
1208
- message: `Cannot find type "${written}"`,
1209
- name: written
1210
- };
1211
- }
1212
- if ("badQualifier" in found) return {
1213
- resolution: {
1214
- kind: "unresolved",
1215
- name: found.qualifier
1216
- },
1217
- message: found.badQualifier,
1218
- name: found.qualifier
1508
+ function fieldAttribute(name, config) {
1509
+ return {
1510
+ level: "field",
1511
+ name,
1512
+ documentation: config.documentation,
1513
+ positional: config.positional ?? [],
1514
+ named: Object.assign(Object.create(null), config.named),
1515
+ ...config.refine !== void 0 ? { refine: config.refine } : {}
1219
1516
  };
1220
- if (found.kind === "namespace" || found.kind === "contributedNamespace") {
1221
- const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
1222
- return {
1223
- resolution: found,
1224
- message: `"${written}" is a namespace; a type reference must name a model, composite type, enum, or named type`,
1225
- name: written
1226
- };
1227
- }
1228
- return { resolution: found };
1229
1517
  }
1230
- function qualifiedMember(namespaceId, name, scope) {
1231
- const qualifier = scope.lookup(namespaceId);
1232
- if (qualifier === void 0) return void 0;
1233
- if (!isNamespaceLike(qualifier)) return {
1234
- badQualifier: `"${namespaceId}" is ${describeQualifier(qualifier)}, not a namespace`,
1235
- qualifier: namespaceId
1518
+ function modelAttribute(name, config) {
1519
+ return {
1520
+ level: "model",
1521
+ name,
1522
+ documentation: config.documentation,
1523
+ positional: config.positional ?? [],
1524
+ named: Object.assign(Object.create(null), config.named),
1525
+ ...config.refine !== void 0 ? { refine: config.refine } : {}
1236
1526
  };
1237
- return lookupMember(qualifier, name);
1238
- }
1239
- function describeQualifier(resolution) {
1240
- switch (resolution.kind) {
1241
- case "model": return "a model";
1242
- case "compositeType": return "a composite type";
1243
- case "namedType": return "a named type";
1244
- case "block": return `${resolution.symbol.keyword === "enum" ? "an" : "a"} ${resolution.symbol.keyword}`;
1245
- default: return "a scalar type";
1246
- }
1247
1527
  }
1248
- function own(record, name) {
1249
- return Object.hasOwn(record, name) ? record[name] : void 0;
1528
+ function optional(type, ...rest) {
1529
+ if (rest.length === 0) return {
1530
+ ...type,
1531
+ optional: true,
1532
+ hasDefault: false
1533
+ };
1534
+ return {
1535
+ ...type,
1536
+ optional: true,
1537
+ hasDefault: true,
1538
+ defaultValue: rest[0]
1539
+ };
1250
1540
  }
1251
1541
  function structBlock(config) {
1252
1542
  return {
@@ -1483,237 +1773,7 @@ function isPrismaNextSchema(text) {
1483
1773
  function renameLegacyDirective(text) {
1484
1774
  return text.replace(DIRECTIVE, (whole, lead, name, trail) => name === LEGACY_NAME ? `${lead}prisma-8${trail}` : whole);
1485
1775
  }
1486
- /**
1487
- * Owns duplicate-declaration detection for all PSL scopes; downstream consumers
1488
- * should consume first-wins symbols rather than re-emitting duplicate diagnostics.
1489
- */
1490
- function buildSymbolTable(options) {
1491
- const { documents, sources } = options;
1492
- const diagnostics = [];
1493
- const namespaces = Object.create(null);
1494
- const namedTypes = Object.create(null);
1495
- const blocks = Object.create(null);
1496
- const models = Object.create(null);
1497
- const compositeTypes = Object.create(null);
1498
- const topLevelNames = /* @__PURE__ */ new Set();
1499
- for (const document of documents) {
1500
- const sourceFile = sources.sourceFileFor(document.syntax);
1501
- const claim = (taken, name) => {
1502
- const text = name?.name();
1503
- if (text === void 0) return void 0;
1504
- if (taken.has(text)) {
1505
- const range = nameRange(name, sources);
1506
- if (range) diagnostics.push({
1507
- code: "PSL_DUPLICATE_DECLARATION",
1508
- message: `Duplicate declaration of "${text}"`,
1509
- filename: sourceFile.filename,
1510
- range
1511
- });
1512
- return;
1513
- }
1514
- taken.add(text);
1515
- return text;
1516
- };
1517
- for (const declaration of document.declarations()) if (declaration instanceof ModelDeclarationAst) {
1518
- const name = claim(topLevelNames, declaration.name());
1519
- if (name !== void 0) models[name] = buildModel(name, declaration, sources, diagnostics);
1520
- } else if (declaration instanceof CompositeTypeDeclarationAst) {
1521
- const name = claim(topLevelNames, declaration.name());
1522
- if (name !== void 0) compositeTypes[name] = buildCompositeType(name, declaration, sources, diagnostics);
1523
- } else if (declaration instanceof GenericBlockDeclarationAst) {
1524
- const name = claim(topLevelNames, declaration.name());
1525
- if (name !== void 0) blocks[name] = buildBlock(name, declaration, sources);
1526
- } else if (declaration instanceof NamespaceDeclarationAst) {
1527
- const declaredName = declaration.name()?.name();
1528
- if (declaredName === void 0) continue;
1529
- let namespace = namespaces[declaredName];
1530
- if (namespace === void 0) {
1531
- const name = claim(topLevelNames, declaration.name());
1532
- if (name === void 0) continue;
1533
- namespace = {
1534
- kind: "namespace",
1535
- name,
1536
- declarations: [{
1537
- node: declaration,
1538
- span: nodePslSpan(declaration.syntax, sources)
1539
- }],
1540
- models: Object.create(null),
1541
- compositeTypes: Object.create(null),
1542
- blocks: Object.create(null)
1543
- };
1544
- namespaces[name] = namespace;
1545
- } else namespace.declarations.push({
1546
- node: declaration,
1547
- span: nodePslSpan(declaration.syntax, sources)
1548
- });
1549
- extendNamespace(namespace, declaration, diagnostics, sources);
1550
- } else if (declaration instanceof TypesBlockAst) for (const binding of declaration.declarations()) {
1551
- const name = claim(topLevelNames, binding.name());
1552
- if (name === void 0) continue;
1553
- const resolved = resolveNamedTypeBinding(binding, sources);
1554
- namedTypes[name] = {
1555
- kind: "namedType",
1556
- name,
1557
- node: binding,
1558
- span: nodePslSpan(binding.syntax, sources),
1559
- ...resolved
1560
- };
1561
- }
1562
- }
1563
- return {
1564
- symbolTable: { topLevel: {
1565
- namespaces,
1566
- namedTypes,
1567
- blocks,
1568
- models,
1569
- compositeTypes
1570
- } },
1571
- diagnostics
1572
- };
1573
- }
1574
- function buildModel(name, node, sources, diagnostics) {
1575
- return {
1576
- kind: "model",
1577
- name,
1578
- node,
1579
- span: nodePslSpan(node.syntax, sources),
1580
- fields: buildFields(name, node.fields(), sources, diagnostics),
1581
- attributes: readResolvedAttributes(node.attributes(), sources)
1582
- };
1583
- }
1584
- function buildCompositeType(name, node, sources, diagnostics) {
1585
- return {
1586
- kind: "compositeType",
1587
- name,
1588
- node,
1589
- span: nodePslSpan(node.syntax, sources),
1590
- fields: buildFields(name, node.fields(), sources, diagnostics),
1591
- attributes: readResolvedAttributes(node.attributes(), sources)
1592
- };
1593
- }
1594
- function buildBlock(name, node, sources) {
1595
- return {
1596
- kind: "block",
1597
- name,
1598
- keyword: node.keyword()?.text ?? "",
1599
- node,
1600
- span: nodePslSpan(node.syntax, sources)
1601
- };
1602
- }
1603
- function extendNamespace(namespace, node, diagnostics, sources) {
1604
- const { models, compositeTypes, blocks } = namespace;
1605
- for (const member of node.declarations()) {
1606
- const memberName = member.name()?.name();
1607
- if (memberName === void 0) continue;
1608
- if (Object.hasOwn(models, memberName) || Object.hasOwn(compositeTypes, memberName) || Object.hasOwn(blocks, memberName)) {
1609
- const range = nameRange(member.name(), sources);
1610
- if (range) diagnostics.push({
1611
- code: "PSL_DUPLICATE_DECLARATION",
1612
- message: `Duplicate declaration of "${memberName}"`,
1613
- filename: sources.sourceFileFor(member.syntax).filename,
1614
- range
1615
- });
1616
- continue;
1617
- }
1618
- if (member instanceof ModelDeclarationAst) models[memberName] = buildModel(memberName, member, sources, diagnostics);
1619
- else if (member instanceof CompositeTypeDeclarationAst) compositeTypes[memberName] = buildCompositeType(memberName, member, sources, diagnostics);
1620
- else if (member instanceof GenericBlockDeclarationAst) blocks[memberName] = buildBlock(memberName, member, sources);
1621
- }
1622
- }
1623
- function buildFields(ownerName, fields, sources, diagnostics) {
1624
- const result = Object.create(null);
1625
- for (const field of fields) {
1626
- const nameNode = field.name();
1627
- const name = nameNode?.name();
1628
- if (name === void 0) continue;
1629
- if (Object.hasOwn(result, name)) {
1630
- const range = nameRange(nameNode, sources);
1631
- if (range) diagnostics.push({
1632
- code: "PSL_DUPLICATE_DECLARATION",
1633
- message: `Duplicate declaration of "${name}"`,
1634
- filename: sources.sourceFileFor(field.syntax).filename,
1635
- range
1636
- });
1637
- continue;
1638
- }
1639
- result[name] = buildField(ownerName, name, field, sources, diagnostics);
1640
- }
1641
- return result;
1642
- }
1643
- function buildField(ownerName, name, node, sources, diagnostics) {
1644
- const attributes = readResolvedAttributes(node.attributes(), sources);
1645
- const span = nodePslSpan(node.syntax, sources);
1646
- const annotation = node.typeAnnotation();
1647
- const typeName = annotation?.name();
1648
- if (typeName?.isOverQualified()) {
1649
- const path = typeName.path();
1650
- diagnostics.push({
1651
- code: "PSL_INVALID_QUALIFIED_TYPE",
1652
- message: `Field "${ownerName}.${name}" has an invalid qualified type "${path.join(".")}"; use at most one namespace qualifier (e.g. "ns.TypeName")`,
1653
- filename: sources.sourceFileFor(typeName.syntax).filename,
1654
- range: nodeRange(typeName.syntax, sources)
1655
- });
1656
- return {
1657
- kind: "field",
1658
- name,
1659
- node,
1660
- span,
1661
- typeName: path[path.length - 1] ?? "",
1662
- optional: false,
1663
- list: false,
1664
- elementOptional: false,
1665
- malformedType: true,
1666
- attributes
1667
- };
1668
- }
1669
- const typeConstructor = annotation?.isConstructor() ? readResolvedConstructorCall(annotation, sources) : void 0;
1670
- const typeNamespaceId = typeName?.namespace()?.name();
1671
- const typeContractSpaceId = typeName?.space()?.name();
1672
- return {
1673
- kind: "field",
1674
- name,
1675
- node,
1676
- span,
1677
- typeName: typeName?.identifier()?.name() ?? "",
1678
- ...typeNamespaceId !== void 0 ? { typeNamespaceId } : {},
1679
- ...typeContractSpaceId !== void 0 ? { typeContractSpaceId } : {},
1680
- optional: annotation?.isOptional() ?? false,
1681
- list: annotation?.isList() ?? false,
1682
- elementOptional: annotation?.isElementOptional() ?? false,
1683
- ...typeConstructor !== void 0 ? { typeConstructor } : {},
1684
- attributes
1685
- };
1686
- }
1687
- function resolveNamedTypeBinding(node, sources) {
1688
- const annotation = node.typeAnnotation();
1689
- const isConstructor = annotation?.isConstructor() ?? false;
1690
- const baseType = annotation?.name()?.identifier()?.name();
1691
- const typeConstructor = readResolvedConstructorCall(annotation, sources);
1692
- return {
1693
- isConstructor,
1694
- ...!isConstructor && baseType !== void 0 ? { baseType } : {},
1695
- ...typeConstructor !== void 0 ? { typeConstructor } : {},
1696
- attributes: readResolvedAttributes(node.attributes(), sources)
1697
- };
1698
- }
1699
- function nameRange(name, sources) {
1700
- if (name === void 0) return void 0;
1701
- const sourceFile = sources.sourceFileFor(name.syntax);
1702
- for (const token of name.syntax.tokens()) if (token.kind === "Ident") return {
1703
- start: sourceFile.positionAt(token.offset),
1704
- end: sourceFile.positionAt(token.offset + token.text.length)
1705
- };
1706
- }
1707
- function nodeRange(node, sources) {
1708
- const sourceFile = sources.sourceFileFor(node);
1709
- const start = node.offset;
1710
- const end = start + node.green.textLength;
1711
- return {
1712
- start: sourceFile.positionAt(start),
1713
- end: sourceFile.positionAt(end)
1714
- };
1715
- }
1716
1776
  //#endregion
1717
- export { NAME_THE_PSL_SOURCE_LOSES, PSL_UNRESOLVED_REFERENCE, assembleAttributeSpecs, blockAttribute, blockSpecFactoryOf, bool, buildSymbolTable, createBinder, createPslDiagnosticCollector, diagnosticFromSpan, diagnosticSource, entityRef, entityReference, fieldAttribute, fieldRef, findBlockDescriptor, flatPslModels, funcCall, getPositionalArgument, identifier, int, interpretArgs, interpretAttribute, interpretExtensionBlock, interpretExtensionBlockAttributes, interpretExtensionBlocks, isNamespaceLike, isPrismaNextSchema, isPslIdentifier, json, jsonValue, keywordPslSpan, leafDiagnostic, list, mapBlock, mapPslDiagnostics, matchesSelector, memberEntries, modelAttribute, namespacePslExtensionBlocks, nodePslSpan, num, numLiteral, oneOf, optional, parseQuotedStringLiteral, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, record, referencedFieldRef, renameLegacyDirective, str, structBlock, taggedLiteral, typeReferenceNode };
1777
+ export { NAME_THE_PSL_SOURCE_LOSES, PSL_UNRESOLVED_REFERENCE, assembleAttributeSpecs, blockAttribute, blockSpecFactoryOf, bool, buildSymbolTable, contributedTypeOf, createBinder, createPslDiagnosticCollector, diagnosticFromSpan, diagnosticSource, entityRef, entityReference, fieldAttribute, fieldRef, findBlockDescriptor, flatPslModels, funcCall, getPositionalArgument, identifier, int, interpretArgs, interpretAttribute, interpretExtensionBlock, interpretExtensionBlockAttributes, interpretExtensionBlocks, isNamespaceLike, isPrismaNextSchema, isPslIdentifier, json, jsonValue, keywordPslSpan, leafDiagnostic, list, mapBlock, mapPslDiagnostics, matchesSelector, memberEntries, modelAttribute, namespacePslExtensionBlocks, nodePslSpan, num, numLiteral, oneOf, optional, parseQuotedStringLiteral, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, record, referencedFieldRef, renameLegacyDirective, str, structBlock, taggedLiteral, typeReferenceNode };
1718
1778
 
1719
1779
  //# sourceMappingURL=psl-parser.mjs.map