@primmel/primmel 1.21.11 → 1.21.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/check-allowlist.d.ts +12 -0
- package/dist/src/check-allowlist.d.ts.map +1 -1
- package/dist/src/check-allowlist.js +35 -4
- package/dist/src/check-allowlist.js.map +1 -1
- package/dist/src/check-rules.d.ts.map +1 -1
- package/dist/src/check-rules.js +30 -0
- package/dist/src/check-rules.js.map +1 -1
- package/dist/src/check.d.ts +38 -0
- package/dist/src/check.d.ts.map +1 -1
- package/dist/src/check.js +1127 -4
- package/dist/src/check.js.map +1 -1
- package/dist/src/export/retrieval.d.ts +9 -1
- package/dist/src/export/retrieval.d.ts.map +1 -1
- package/dist/src/export/retrieval.js +29 -0
- package/dist/src/export/retrieval.js.map +1 -1
- package/dist/src/expressions/index.d.ts +69 -0
- package/dist/src/expressions/index.d.ts.map +1 -0
- package/dist/src/expressions/index.js +342 -0
- package/dist/src/expressions/index.js.map +1 -0
- package/dist/src/fmt.d.ts +11 -0
- package/dist/src/fmt.d.ts.map +1 -0
- package/dist/src/fmt.js +71 -0
- package/dist/src/fmt.js.map +1 -0
- package/dist/src/ser-des/config/calculation.d.ts.map +1 -1
- package/dist/src/ser-des/config/calculation.js +46 -0
- package/dist/src/ser-des/config/calculation.js.map +1 -1
- package/dist/src/ser-des/config/competenceKind.d.ts.map +1 -1
- package/dist/src/ser-des/config/competenceKind.js +9 -20
- package/dist/src/ser-des/config/competenceKind.js.map +1 -1
- package/dist/src/ser-des/config/conformanceTest.d.ts.map +1 -1
- package/dist/src/ser-des/config/conformanceTest.js +33 -6
- package/dist/src/ser-des/config/conformanceTest.js.map +1 -1
- package/dist/src/ser-des/config/constraint.d.ts.map +1 -1
- package/dist/src/ser-des/config/constraint.js +24 -2
- package/dist/src/ser-des/config/constraint.js.map +1 -1
- package/dist/src/ser-des/config/index.d.ts +7 -0
- package/dist/src/ser-des/config/index.d.ts.map +1 -1
- package/dist/src/ser-des/config/index.js +50 -0
- package/dist/src/ser-des/config/index.js.map +1 -1
- package/dist/src/ser-des/config/lmlAligned.d.ts +16 -0
- package/dist/src/ser-des/config/lmlAligned.d.ts.map +1 -0
- package/dist/src/ser-des/config/lmlAligned.js +337 -0
- package/dist/src/ser-des/config/lmlAligned.js.map +1 -0
- package/dist/src/ser-des/config/packageManifest.d.ts.map +1 -1
- package/dist/src/ser-des/config/packageManifest.js +3 -0
- package/dist/src/ser-des/config/packageManifest.js.map +1 -1
- package/dist/src/ser-des/config/process.d.ts.map +1 -1
- package/dist/src/ser-des/config/process.js +192 -0
- package/dist/src/ser-des/config/process.js.map +1 -1
- package/dist/src/ser-des/config/provision.d.ts.map +1 -1
- package/dist/src/ser-des/config/provision.js +59 -16
- package/dist/src/ser-des/config/provision.js.map +1 -1
- package/dist/src/ser-des/config/requirement.d.ts.map +1 -1
- package/dist/src/ser-des/config/requirement.js +123 -7
- package/dist/src/ser-des/config/requirement.js.map +1 -1
- package/dist/src/ser-des/config/symbol.d.ts.map +1 -1
- package/dist/src/ser-des/config/symbol.js +21 -0
- package/dist/src/ser-des/config/symbol.js.map +1 -1
- package/dist/src/ser-des/config/table.d.ts.map +1 -1
- package/dist/src/ser-des/config/table.js +7 -0
- package/dist/src/ser-des/config/table.js.map +1 -1
- package/dist/src/ser-des/config/uncertaintyBudget.d.ts +5 -0
- package/dist/src/ser-des/config/uncertaintyBudget.d.ts.map +1 -0
- package/dist/src/ser-des/config/uncertaintyBudget.js +211 -0
- package/dist/src/ser-des/config/uncertaintyBudget.js.map +1 -0
- package/dist/src/ser-des/config/verdict.d.ts.map +1 -1
- package/dist/src/ser-des/config/verdict.js +12 -2
- package/dist/src/ser-des/config/verdict.js.map +1 -1
- package/dist/src/ser-des/dump.d.ts.map +1 -1
- package/dist/src/ser-des/dump.js +46 -0
- package/dist/src/ser-des/dump.js.map +1 -1
- package/dist/src/ser-des/expression-carrier.d.ts +17 -0
- package/dist/src/ser-des/expression-carrier.d.ts.map +1 -0
- package/dist/src/ser-des/expression-carrier.js +72 -0
- package/dist/src/ser-des/expression-carrier.js.map +1 -0
- package/dist/src/ser-des/package.d.ts.map +1 -1
- package/dist/src/ser-des/package.js +54 -4
- package/dist/src/ser-des/package.js.map +1 -1
- package/dist/src/ser-des/parse.d.ts.map +1 -1
- package/dist/src/ser-des/parse.js +36 -2
- package/dist/src/ser-des/parse.js.map +1 -1
- package/dist/src/ser-des/shape-front-end.d.ts.map +1 -1
- package/dist/src/ser-des/shape-front-end.js +24 -5
- package/dist/src/ser-des/shape-front-end.js.map +1 -1
- package/dist/src/ser-des/types.d.ts +10 -0
- package/dist/src/ser-des/types.d.ts.map +1 -1
- package/dist/src/text-coverage.d.ts.map +1 -1
- package/dist/src/text-coverage.js +52 -0
- package/dist/src/text-coverage.js.map +1 -1
- package/dist/src/types/Calculation.d.ts +14 -0
- package/dist/src/types/Calculation.d.ts.map +1 -1
- package/dist/src/types/CompetenceKind.d.ts +6 -14
- package/dist/src/types/CompetenceKind.d.ts.map +1 -1
- package/dist/src/types/ConformanceTest.d.ts +5 -1
- package/dist/src/types/ConformanceTest.d.ts.map +1 -1
- package/dist/src/types/Constraint.d.ts +10 -1
- package/dist/src/types/Constraint.d.ts.map +1 -1
- package/dist/src/types/LmlAligned.d.ts +76 -0
- package/dist/src/types/LmlAligned.d.ts.map +1 -0
- package/dist/src/types/LmlAligned.js +8 -0
- package/dist/src/types/LmlAligned.js.map +1 -0
- package/dist/src/types/Package.d.ts +7 -0
- package/dist/src/types/Package.d.ts.map +1 -1
- package/dist/src/types/Requirement.d.ts +33 -0
- package/dist/src/types/Requirement.d.ts.map +1 -1
- package/dist/src/types/Standard.d.ts +12 -0
- package/dist/src/types/Standard.d.ts.map +1 -1
- package/dist/src/types/Symbol.d.ts +8 -0
- package/dist/src/types/Symbol.d.ts.map +1 -1
- package/dist/src/types/UncertaintyBudget.d.ts +68 -0
- package/dist/src/types/UncertaintyBudget.d.ts.map +1 -0
- package/dist/src/types/UncertaintyBudget.js +3 -0
- package/dist/src/types/UncertaintyBudget.js.map +1 -0
- package/dist/src/types/Verdict.d.ts +3 -1
- package/dist/src/types/Verdict.d.ts.map +1 -1
- package/dist/src/types/process.d.ts +52 -1
- package/dist/src/types/process.d.ts.map +1 -1
- package/dist-browser/index.mjs +2320 -1447
- package/dist-cli/primmel.mjs +2936 -92
- package/package.json +1 -1
package/dist-cli/primmel.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// scripts/check.mts
|
|
4
|
-
import { existsSync as existsSync8, readdirSync as
|
|
5
|
-
import { join as
|
|
4
|
+
import { existsSync as existsSync8, readdirSync as readdirSync8, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
|
|
5
|
+
import { join as join10 } from "node:path";
|
|
6
6
|
|
|
7
7
|
// src/check.ts
|
|
8
8
|
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
@@ -200,16 +200,44 @@ function parse(mmelString, parsers, options = {}) {
|
|
|
200
200
|
continue;
|
|
201
201
|
}
|
|
202
202
|
if (cfg.takesID) {
|
|
203
|
-
|
|
203
|
+
let formatTok;
|
|
204
|
+
if (cfg.takesFormat) {
|
|
205
|
+
const f = tokens[i++];
|
|
206
|
+
if (!["xml", "yaml", "json", "toml", "csv"].includes(f.value)) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Parsing error: mapping. Unknown format "${f.value}" at line ${f.start.line} col ${f.start.col} (xml, yaml, json, toml, csv)`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
formatTok = f;
|
|
212
|
+
}
|
|
213
|
+
if (i + 1 >= tokens.length) {
|
|
204
214
|
throw new Error(
|
|
205
215
|
`Keyword "${tok.value}" at line ${tok.start.line} col ${tok.start.col} expects an ID and payload, but only ${tokens.length - i + 1} token(s) remain.`
|
|
206
216
|
);
|
|
207
217
|
}
|
|
208
218
|
const idTok = tokens[i++];
|
|
219
|
+
if (cfg.optionalTypedId && tokens[i]?.value === ":") {
|
|
220
|
+
const typeTok = tokens[i + 1];
|
|
221
|
+
const blockTok = tokens[i + 2];
|
|
222
|
+
if (!typeTok || !blockTok) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
`Keyword "${tok.value}" at line ${tok.start.line} col ${tok.start.col} expects a type and payload, but too few token(s) remain.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
i += 3;
|
|
228
|
+
declarations.push({
|
|
229
|
+
keyword: tok.value,
|
|
230
|
+
id: idTok.value,
|
|
231
|
+
payload: `: ${typeTok.value} ${blockTok.value}`,
|
|
232
|
+
start: tok.start,
|
|
233
|
+
end: blockTok.end
|
|
234
|
+
});
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
209
237
|
const payloadTok = tokens[i++];
|
|
210
238
|
declarations.push({
|
|
211
239
|
keyword: tok.value,
|
|
212
|
-
id: idTok.value,
|
|
240
|
+
id: formatTok ? `${formatTok.value}:${idTok.value}` : idTok.value,
|
|
213
241
|
payload: payloadTok.value,
|
|
214
242
|
start: tok.start,
|
|
215
243
|
end: payloadTok.end
|
|
@@ -269,6 +297,11 @@ function parseDeclarations(declarations, parsers, options = {}) {
|
|
|
269
297
|
calculations: {},
|
|
270
298
|
verdicts: {},
|
|
271
299
|
referenceMaterials: {},
|
|
300
|
+
wireMappings: {},
|
|
301
|
+
stringFormats: {},
|
|
302
|
+
namespaces: {},
|
|
303
|
+
datums: {},
|
|
304
|
+
checks: {},
|
|
272
305
|
testPointSets: {},
|
|
273
306
|
commonTestConditions: {},
|
|
274
307
|
competenceKinds: {},
|
|
@@ -277,6 +310,7 @@ function parseDeclarations(declarations, parsers, options = {}) {
|
|
|
277
310
|
schemeTypes: {},
|
|
278
311
|
predicates: {},
|
|
279
312
|
constraints: {},
|
|
313
|
+
uncertaintyBudgets: {},
|
|
280
314
|
discrepancyRecords: {},
|
|
281
315
|
stateMachines: {},
|
|
282
316
|
conformanceTests: {},
|
|
@@ -2495,6 +2529,369 @@ var parseMetadata = function(token) {
|
|
|
2495
2529
|
return ctx;
|
|
2496
2530
|
};
|
|
2497
2531
|
};
|
|
2532
|
+
var dumpMetadata = function(meta) {
|
|
2533
|
+
let out = "metadata {\n";
|
|
2534
|
+
out += ' title "' + escapeString(meta.title) + '"\n';
|
|
2535
|
+
out += ' schema "' + escapeString(meta.schema) + '"\n';
|
|
2536
|
+
out += ' edition "' + escapeString(meta.edition) + '"\n';
|
|
2537
|
+
out += ' author "' + escapeString(meta.author) + '"\n';
|
|
2538
|
+
out += ' namespace "' + escapeString(meta.namespace) + '"\n';
|
|
2539
|
+
out += ' shortname "' + escapeString(meta.shortname ?? "") + '"\n';
|
|
2540
|
+
out += "}\n";
|
|
2541
|
+
return out;
|
|
2542
|
+
};
|
|
2543
|
+
|
|
2544
|
+
// src/expressions/index.ts
|
|
2545
|
+
var OPERATORS = [
|
|
2546
|
+
"->",
|
|
2547
|
+
"<=",
|
|
2548
|
+
">=",
|
|
2549
|
+
"!=",
|
|
2550
|
+
"\u2260",
|
|
2551
|
+
"<",
|
|
2552
|
+
">",
|
|
2553
|
+
"=",
|
|
2554
|
+
"+",
|
|
2555
|
+
"-",
|
|
2556
|
+
"*",
|
|
2557
|
+
"/",
|
|
2558
|
+
"(",
|
|
2559
|
+
")",
|
|
2560
|
+
",",
|
|
2561
|
+
".",
|
|
2562
|
+
"|"
|
|
2563
|
+
];
|
|
2564
|
+
var NAV_OPS = /* @__PURE__ */ new Set(["forAll", "exists", "select"]);
|
|
2565
|
+
function lex(src) {
|
|
2566
|
+
const tokens = [];
|
|
2567
|
+
let i = 0;
|
|
2568
|
+
while (i < src.length) {
|
|
2569
|
+
const c = src[i];
|
|
2570
|
+
if (/\s/.test(c)) {
|
|
2571
|
+
i += 1;
|
|
2572
|
+
continue;
|
|
2573
|
+
}
|
|
2574
|
+
if (c === "'") {
|
|
2575
|
+
let j = i + 1;
|
|
2576
|
+
while (j < src.length && src[j] !== "'") {
|
|
2577
|
+
j += 1;
|
|
2578
|
+
}
|
|
2579
|
+
if (j >= src.length) {
|
|
2580
|
+
throw new Error(`expression: unterminated string at offset ${i}`);
|
|
2581
|
+
}
|
|
2582
|
+
tokens.push({ kind: "str", value: src.slice(i + 1, j) });
|
|
2583
|
+
i = j + 1;
|
|
2584
|
+
continue;
|
|
2585
|
+
}
|
|
2586
|
+
if (/[0-9]/.test(c)) {
|
|
2587
|
+
let j = i;
|
|
2588
|
+
while (j < src.length && /[0-9.]/.test(src[j])) {
|
|
2589
|
+
j += 1;
|
|
2590
|
+
}
|
|
2591
|
+
tokens.push({ kind: "num", value: Number(src.slice(i, j)) });
|
|
2592
|
+
i = j;
|
|
2593
|
+
continue;
|
|
2594
|
+
}
|
|
2595
|
+
if (/[A-Za-z_]/.test(c)) {
|
|
2596
|
+
let j = i;
|
|
2597
|
+
while (j < src.length && /[A-Za-z0-9_.]/.test(src[j])) {
|
|
2598
|
+
j += 1;
|
|
2599
|
+
}
|
|
2600
|
+
tokens.push({ kind: "name", value: src.slice(i, j) });
|
|
2601
|
+
i = j;
|
|
2602
|
+
continue;
|
|
2603
|
+
}
|
|
2604
|
+
const two = src.slice(i, i + 2);
|
|
2605
|
+
if (OPERATORS.includes(two)) {
|
|
2606
|
+
tokens.push({ kind: "op", value: two });
|
|
2607
|
+
i += 2;
|
|
2608
|
+
continue;
|
|
2609
|
+
}
|
|
2610
|
+
if (OPERATORS.includes(c)) {
|
|
2611
|
+
tokens.push({ kind: "op", value: c });
|
|
2612
|
+
i += 1;
|
|
2613
|
+
continue;
|
|
2614
|
+
}
|
|
2615
|
+
throw new Error(`expression: unexpected character "${c}" at offset ${i}`);
|
|
2616
|
+
}
|
|
2617
|
+
return tokens;
|
|
2618
|
+
}
|
|
2619
|
+
var BINARY_LEVELS = [
|
|
2620
|
+
["implies"],
|
|
2621
|
+
["or"],
|
|
2622
|
+
["xor"],
|
|
2623
|
+
["and"],
|
|
2624
|
+
["<=", ">=", "<", ">", "=", "!=", "\u2260"],
|
|
2625
|
+
["+", "-"],
|
|
2626
|
+
["*", "/"]
|
|
2627
|
+
];
|
|
2628
|
+
var WORD_BINOPS = /* @__PURE__ */ new Set(["implies", "or", "xor", "and"]);
|
|
2629
|
+
var ExprParser = class {
|
|
2630
|
+
tokens;
|
|
2631
|
+
pos = 0;
|
|
2632
|
+
constructor(tokens) {
|
|
2633
|
+
this.tokens = tokens;
|
|
2634
|
+
}
|
|
2635
|
+
peek() {
|
|
2636
|
+
return this.tokens[this.pos];
|
|
2637
|
+
}
|
|
2638
|
+
take() {
|
|
2639
|
+
const tok = this.tokens[this.pos];
|
|
2640
|
+
if (tok === void 0) {
|
|
2641
|
+
throw new Error("expression: unexpected end");
|
|
2642
|
+
}
|
|
2643
|
+
this.pos += 1;
|
|
2644
|
+
return tok;
|
|
2645
|
+
}
|
|
2646
|
+
parse() {
|
|
2647
|
+
const ast = this.parseLevel(0);
|
|
2648
|
+
if (this.pos !== this.tokens.length) {
|
|
2649
|
+
throw new Error(`expression: trailing tokens at position ${this.pos}`);
|
|
2650
|
+
}
|
|
2651
|
+
return ast;
|
|
2652
|
+
}
|
|
2653
|
+
parseLevel(level) {
|
|
2654
|
+
if (level >= BINARY_LEVELS.length) {
|
|
2655
|
+
return this.parseUnary();
|
|
2656
|
+
}
|
|
2657
|
+
let left = this.parseLevel(level + 1);
|
|
2658
|
+
for (; ; ) {
|
|
2659
|
+
const tok = this.peek();
|
|
2660
|
+
const op = tok?.kind === "op" ? tok.value : tok?.kind === "name" && WORD_BINOPS.has(tok.value) ? tok.value : void 0;
|
|
2661
|
+
if (op === void 0 || !BINARY_LEVELS[level].includes(op)) {
|
|
2662
|
+
return left;
|
|
2663
|
+
}
|
|
2664
|
+
this.take();
|
|
2665
|
+
const right = this.parseLevel(level + 1);
|
|
2666
|
+
left = { type: "binop", op, left, right };
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
parseUnary() {
|
|
2670
|
+
const tok = this.peek();
|
|
2671
|
+
if (tok?.kind === "name" && (tok.value === "not" || tok.value === "-")) {
|
|
2672
|
+
this.take();
|
|
2673
|
+
return { type: "unop", op: tok.value, operand: this.parseUnary() };
|
|
2674
|
+
}
|
|
2675
|
+
if (tok?.kind === "op" && tok.value === "-") {
|
|
2676
|
+
this.take();
|
|
2677
|
+
return { type: "unop", op: "-", operand: this.parseUnary() };
|
|
2678
|
+
}
|
|
2679
|
+
return this.parsePrimary();
|
|
2680
|
+
}
|
|
2681
|
+
parsePrimary() {
|
|
2682
|
+
const tok = this.take();
|
|
2683
|
+
if (tok.kind === "num") {
|
|
2684
|
+
return { type: "num", value: tok.value };
|
|
2685
|
+
}
|
|
2686
|
+
if (tok.kind === "str") {
|
|
2687
|
+
return { type: "str", value: tok.value };
|
|
2688
|
+
}
|
|
2689
|
+
if (tok.kind === "op" && tok.value === "(") {
|
|
2690
|
+
const inner = this.parseLevel(0);
|
|
2691
|
+
const close = this.take();
|
|
2692
|
+
if (close.kind !== "op" || close.value !== ")") {
|
|
2693
|
+
throw new Error("expression: expected closing parenthesis");
|
|
2694
|
+
}
|
|
2695
|
+
return inner;
|
|
2696
|
+
}
|
|
2697
|
+
if (tok.kind === "name") {
|
|
2698
|
+
const segs = [tok.value];
|
|
2699
|
+
while (this.peek()?.kind === "op" && this.peek().value === ".") {
|
|
2700
|
+
this.take();
|
|
2701
|
+
const seg = this.take();
|
|
2702
|
+
if (seg.kind !== "name") {
|
|
2703
|
+
throw new Error('expression: expected a path segment after "."');
|
|
2704
|
+
}
|
|
2705
|
+
segs.push(seg.value);
|
|
2706
|
+
}
|
|
2707
|
+
const next = this.peek();
|
|
2708
|
+
if (next?.kind === "op" && next.value === "(" && !WORD_BINOPS.has(segs[0])) {
|
|
2709
|
+
this.take();
|
|
2710
|
+
const args2 = [];
|
|
2711
|
+
const closing = this.peek();
|
|
2712
|
+
if (closing?.kind === "op" && closing.value === ")") {
|
|
2713
|
+
this.take();
|
|
2714
|
+
return { type: "call", callee: segs.join("."), args: args2 };
|
|
2715
|
+
}
|
|
2716
|
+
for (; ; ) {
|
|
2717
|
+
args2.push(this.parseLevel(0));
|
|
2718
|
+
const sep = this.peek();
|
|
2719
|
+
if (sep?.kind === "op" && sep.value === ",") {
|
|
2720
|
+
this.take();
|
|
2721
|
+
continue;
|
|
2722
|
+
}
|
|
2723
|
+
break;
|
|
2724
|
+
}
|
|
2725
|
+
const close = this.take();
|
|
2726
|
+
if (close.kind !== "op" || close.value !== ")") {
|
|
2727
|
+
throw new Error("expression: expected closing parenthesis");
|
|
2728
|
+
}
|
|
2729
|
+
return { type: "call", callee: segs.join("."), args: args2 };
|
|
2730
|
+
}
|
|
2731
|
+
const arrow = this.peek();
|
|
2732
|
+
if (arrow?.kind === "op" && arrow.value === "->") {
|
|
2733
|
+
this.take();
|
|
2734
|
+
const opTok = this.take();
|
|
2735
|
+
if (opTok.kind !== "name" || !NAV_OPS.has(opTok.value)) {
|
|
2736
|
+
throw new Error(
|
|
2737
|
+
"expression: expected a collection iterator (forAll | exists | select)"
|
|
2738
|
+
);
|
|
2739
|
+
}
|
|
2740
|
+
if (this.peek()?.kind !== "op" || this.peek().value !== "(") {
|
|
2741
|
+
throw new Error("expression: expected ( after the iterator");
|
|
2742
|
+
}
|
|
2743
|
+
this.take();
|
|
2744
|
+
const varTok = this.take();
|
|
2745
|
+
if (varTok.kind !== "name") {
|
|
2746
|
+
throw new Error("expression: expected the lambda parameter");
|
|
2747
|
+
}
|
|
2748
|
+
if (this.peek()?.kind !== "op" || this.peek().value !== "|") {
|
|
2749
|
+
throw new Error("expression: expected | after the parameter");
|
|
2750
|
+
}
|
|
2751
|
+
this.take();
|
|
2752
|
+
const body = this.parseLevel(0);
|
|
2753
|
+
const close = this.take();
|
|
2754
|
+
if (close.kind !== "op" || close.value !== ")") {
|
|
2755
|
+
throw new Error("expression: expected closing parenthesis");
|
|
2756
|
+
}
|
|
2757
|
+
return {
|
|
2758
|
+
type: "nav",
|
|
2759
|
+
source: segs.join("."),
|
|
2760
|
+
op: opTok.value,
|
|
2761
|
+
var: varTok.value,
|
|
2762
|
+
body
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
return { type: "name", path: segs };
|
|
2766
|
+
}
|
|
2767
|
+
throw new Error(`expression: unexpected token "${String(tok.value)}"`);
|
|
2768
|
+
}
|
|
2769
|
+
};
|
|
2770
|
+
function parseExpression(src) {
|
|
2771
|
+
return new ExprParser(lex(src)).parse();
|
|
2772
|
+
}
|
|
2773
|
+
function canonicalizeExpression(raw) {
|
|
2774
|
+
const body = raw.trim();
|
|
2775
|
+
if (body.length === 0) {
|
|
2776
|
+
throw new Error("expression: the block is empty");
|
|
2777
|
+
}
|
|
2778
|
+
return renderExpression(parseExpression(body));
|
|
2779
|
+
}
|
|
2780
|
+
function freeIdentifiers(ast) {
|
|
2781
|
+
const out = { names: [], calls: [] };
|
|
2782
|
+
const walk = (node, bound) => {
|
|
2783
|
+
switch (node.type) {
|
|
2784
|
+
case "num":
|
|
2785
|
+
return;
|
|
2786
|
+
case "str":
|
|
2787
|
+
return;
|
|
2788
|
+
case "name": {
|
|
2789
|
+
if (bound.has(node.path[0].split(".")[0])) {
|
|
2790
|
+
return;
|
|
2791
|
+
}
|
|
2792
|
+
out.names.push(node.path.join("."));
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
case "call":
|
|
2796
|
+
out.calls.push(node.callee);
|
|
2797
|
+
for (const a of node.args) {
|
|
2798
|
+
walk(a, bound);
|
|
2799
|
+
}
|
|
2800
|
+
return;
|
|
2801
|
+
case "unop":
|
|
2802
|
+
walk(node.operand, bound);
|
|
2803
|
+
return;
|
|
2804
|
+
case "binop":
|
|
2805
|
+
walk(node.left, bound);
|
|
2806
|
+
walk(node.right, bound);
|
|
2807
|
+
return;
|
|
2808
|
+
case "nav": {
|
|
2809
|
+
const inner = new Set(bound);
|
|
2810
|
+
inner.add(node["var"]);
|
|
2811
|
+
walk({ type: "name", path: [node.source] }, bound);
|
|
2812
|
+
walk(node.body, inner);
|
|
2813
|
+
return;
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
};
|
|
2817
|
+
walk(ast, /* @__PURE__ */ new Set());
|
|
2818
|
+
return out;
|
|
2819
|
+
}
|
|
2820
|
+
function renderExpression(ast) {
|
|
2821
|
+
switch (ast.type) {
|
|
2822
|
+
case "num":
|
|
2823
|
+
return String(ast.value);
|
|
2824
|
+
case "str":
|
|
2825
|
+
return "'" + ast.value + "'";
|
|
2826
|
+
case "name":
|
|
2827
|
+
return ast.path.join(".");
|
|
2828
|
+
case "call":
|
|
2829
|
+
return ast.callee + "(" + ast.args.map(renderExpression).join(", ") + ")";
|
|
2830
|
+
case "unop": {
|
|
2831
|
+
const inner = renderExpression(ast.operand);
|
|
2832
|
+
return ast.op + (ast.operand.type === "binop" ? " (" + inner + ")" : " " + inner);
|
|
2833
|
+
}
|
|
2834
|
+
case "nav":
|
|
2835
|
+
return ast.source + " -> " + ast.op + "(" + ast["var"] + " | " + renderExpression(ast.body) + ")";
|
|
2836
|
+
case "binop":
|
|
2837
|
+
return renderExpression(ast.left) + " " + ast.op + " " + renderExpression(ast.right);
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
// src/ser-des/expression-carrier.ts
|
|
2842
|
+
function readExpressionCarrier(token, what) {
|
|
2843
|
+
if (token.startsWith("{")) {
|
|
2844
|
+
try {
|
|
2845
|
+
return {
|
|
2846
|
+
source: canonicalizeExpression(unwrapBlock(token)),
|
|
2847
|
+
inline: true
|
|
2848
|
+
};
|
|
2849
|
+
} catch (e) {
|
|
2850
|
+
throw new Error(
|
|
2851
|
+
`Parsing error: ${what}: ${e.message ?? String(e)}`
|
|
2852
|
+
);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
if (token.length >= 2 && token.charAt(0) === '"') {
|
|
2856
|
+
return {
|
|
2857
|
+
source: unescapeString(token.substr(1, token.length - 2)),
|
|
2858
|
+
inline: false
|
|
2859
|
+
};
|
|
2860
|
+
}
|
|
2861
|
+
return { source: token, inline: false };
|
|
2862
|
+
}
|
|
2863
|
+
function dumpExpressionBlock(keyword, source, indent) {
|
|
2864
|
+
const body = source.split("\n").map((l) => indent + " " + l).join("\n");
|
|
2865
|
+
return indent + keyword + " {\n" + body + "\n" + indent + "}\n";
|
|
2866
|
+
}
|
|
2867
|
+
function readArgsBlock(token) {
|
|
2868
|
+
const at = tokenize(token);
|
|
2869
|
+
const args2 = [];
|
|
2870
|
+
let k = 0;
|
|
2871
|
+
while (k < at.length) {
|
|
2872
|
+
const name = unescapeStringOrBare(at[k++]);
|
|
2873
|
+
if (k >= at.length) {
|
|
2874
|
+
throw new Error(`limit args: "${name}" binds to nothing`);
|
|
2875
|
+
}
|
|
2876
|
+
if (at[k] !== "<-") {
|
|
2877
|
+
throw new Error(
|
|
2878
|
+
`limit args: expected "<-" after "${name}" (name <- source)`
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
k += 1;
|
|
2882
|
+
if (k >= at.length) {
|
|
2883
|
+
throw new Error(`limit args: "${name}" binds to nothing`);
|
|
2884
|
+
}
|
|
2885
|
+
args2.push({ name, source: unescapeStringOrBare(at[k++]) });
|
|
2886
|
+
}
|
|
2887
|
+
return args2;
|
|
2888
|
+
}
|
|
2889
|
+
function unescapeStringOrBare(t) {
|
|
2890
|
+
if (t.length >= 2 && t.charAt(0) === '"' && t.charAt(t.length - 1) === '"') {
|
|
2891
|
+
return unescapeString(t.substr(1, t.length - 2));
|
|
2892
|
+
}
|
|
2893
|
+
return t;
|
|
2894
|
+
}
|
|
2498
2895
|
|
|
2499
2896
|
// src/ser-des/config/quantity.ts
|
|
2500
2897
|
var NUMERIC = /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/;
|
|
@@ -2987,10 +3384,20 @@ var STEP_KINDS = /* @__PURE__ */ new Set([
|
|
|
2987
3384
|
"timer_event",
|
|
2988
3385
|
"signal_event"
|
|
2989
3386
|
]);
|
|
3387
|
+
function parseCallBindings(block) {
|
|
3388
|
+
return parseParamList(unwrapBlock(block)).map((pr) => ({
|
|
3389
|
+
param: pr.name,
|
|
3390
|
+
bind: pr.type
|
|
3391
|
+
}));
|
|
3392
|
+
}
|
|
2990
3393
|
function parseStepBody(id, kind, block) {
|
|
2991
3394
|
const step = {
|
|
2992
3395
|
id,
|
|
2993
3396
|
kind,
|
|
3397
|
+
signatureBlock: "",
|
|
3398
|
+
sigInputs: [],
|
|
3399
|
+
sigOutputs: [],
|
|
3400
|
+
completion: "",
|
|
2994
3401
|
executor: "",
|
|
2995
3402
|
role: "",
|
|
2996
3403
|
capture: "",
|
|
@@ -3260,6 +3667,112 @@ var parseProcess = function(id, data) {
|
|
|
3260
3667
|
result._relations.page = value();
|
|
3261
3668
|
} else if (keyword === "validate_provision") {
|
|
3262
3669
|
result._relations.provision = tokenizePackage(value());
|
|
3670
|
+
} else if (keyword === "step" || keyword === "binding") {
|
|
3671
|
+
const sid = stripWrapping(value());
|
|
3672
|
+
const blockTok = value();
|
|
3673
|
+
if (keyword === "step") {
|
|
3674
|
+
const raw = blockTok !== void 0 && blockTok.startsWith("{") ? unwrapBlock(blockTok) : blockTok ?? "";
|
|
3675
|
+
const st = {
|
|
3676
|
+
id: sid,
|
|
3677
|
+
kind: "action",
|
|
3678
|
+
executor: "",
|
|
3679
|
+
role: "",
|
|
3680
|
+
capture: "",
|
|
3681
|
+
reads: [],
|
|
3682
|
+
writes: [],
|
|
3683
|
+
fires: "",
|
|
3684
|
+
calls: "",
|
|
3685
|
+
callIn: [],
|
|
3686
|
+
callOut: [],
|
|
3687
|
+
wait: "",
|
|
3688
|
+
period: "",
|
|
3689
|
+
signal: "",
|
|
3690
|
+
signatureBlock: raw,
|
|
3691
|
+
sigInputs: [],
|
|
3692
|
+
sigOutputs: [],
|
|
3693
|
+
completion: "",
|
|
3694
|
+
description: ""
|
|
3695
|
+
};
|
|
3696
|
+
const tt = tokenizePackage(raw);
|
|
3697
|
+
let ti = 0;
|
|
3698
|
+
while (ti < tt.length) {
|
|
3699
|
+
const tc = tt[ti++];
|
|
3700
|
+
if (ti >= tt.length) {
|
|
3701
|
+
break;
|
|
3702
|
+
}
|
|
3703
|
+
if (tc === "inputs" || tc === "outputs") {
|
|
3704
|
+
const pairs = parseParamList(unwrapBlock(tt[ti++]));
|
|
3705
|
+
const names = pairs.map((pr) => pr.name);
|
|
3706
|
+
if (tc === "inputs") {
|
|
3707
|
+
st.sigInputs = names;
|
|
3708
|
+
} else {
|
|
3709
|
+
st.sigOutputs = names;
|
|
3710
|
+
}
|
|
3711
|
+
} else if (tc === "requires") {
|
|
3712
|
+
const ids = tokenizePackage(unwrapBlock(tt[ti++])).map(stripWrapping).filter((x) => x.length > 0);
|
|
3713
|
+
(result.stepRequires ??= []).push(...ids);
|
|
3714
|
+
} else if (tc === "completion") {
|
|
3715
|
+
if (tt[ti] === "check") {
|
|
3716
|
+
ti += 1;
|
|
3717
|
+
st.completionGate = stripWrapping(tt[ti++]);
|
|
3718
|
+
const bt = tokenizePackage(unwrapBlock(tt[ti++]));
|
|
3719
|
+
let bi = 0;
|
|
3720
|
+
while (bi < bt.length) {
|
|
3721
|
+
const bc = bt[bi++];
|
|
3722
|
+
if (bi >= bt.length) {
|
|
3723
|
+
break;
|
|
3724
|
+
}
|
|
3725
|
+
if (bc === "expression") {
|
|
3726
|
+
const c = readExpressionCarrier(
|
|
3727
|
+
bt[bi++],
|
|
3728
|
+
"step completion"
|
|
3729
|
+
);
|
|
3730
|
+
st.completion = c.source;
|
|
3731
|
+
st.completionBound = c.inline || void 0;
|
|
3732
|
+
} else {
|
|
3733
|
+
bi = skipUnknownEntry(bt, bi);
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
} else {
|
|
3737
|
+
const c = readExpressionCarrier(tt[ti++], "step completion");
|
|
3738
|
+
st.completion = c.source;
|
|
3739
|
+
st.completionBound = c.inline || void 0;
|
|
3740
|
+
}
|
|
3741
|
+
} else if (tc === "calls") {
|
|
3742
|
+
st.calls = stripWrapping(tt[ti++]);
|
|
3743
|
+
if (ti < tt.length && tt[ti] === "with") {
|
|
3744
|
+
const wt = tokenize(unwrapBlock(tt[ti++]));
|
|
3745
|
+
let wk = 0;
|
|
3746
|
+
while (wk < wt.length) {
|
|
3747
|
+
const wc = wt[wk++];
|
|
3748
|
+
if (wk >= wt.length) {
|
|
3749
|
+
break;
|
|
3750
|
+
}
|
|
3751
|
+
if (wc === "in") {
|
|
3752
|
+
st.callIn.push(...parseCallBindings(wt[wk++]));
|
|
3753
|
+
} else if (wc === "out") {
|
|
3754
|
+
st.callOut.push(...parseCallBindings(wt[wk++]));
|
|
3755
|
+
} else {
|
|
3756
|
+
unwrapBlock(wt[wk++]);
|
|
3757
|
+
}
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
} else if (tc === "description") {
|
|
3761
|
+
st.description = stripWrapping(tt[ti++]);
|
|
3762
|
+
} else {
|
|
3763
|
+
ti = skipUnknownEntry(tt, ti);
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
(result.steps ??= []).push(st);
|
|
3767
|
+
} else {
|
|
3768
|
+
(result.bindings ??= []).push({
|
|
3769
|
+
id: sid,
|
|
3770
|
+
block: blockTok !== void 0 && blockTok.startsWith("{") ? unwrapBlock(blockTok) : blockTok ?? ""
|
|
3771
|
+
});
|
|
3772
|
+
}
|
|
3773
|
+
} else if (keyword === "requires") {
|
|
3774
|
+
const inner = tokenizePackage(unwrapBlock(value()));
|
|
3775
|
+
(result.stepRequires ??= []).push(...inner.map(stripWrapping));
|
|
3263
3776
|
} else if (keyword === "validate_measurement") {
|
|
3264
3777
|
result.measure = tokenizePackage(value()).map((x) => unwrapBlock(x));
|
|
3265
3778
|
} else if (keyword === "output") {
|
|
@@ -3417,6 +3930,25 @@ var resolveProcess = function(ctx, unresolved) {
|
|
|
3417
3930
|
}
|
|
3418
3931
|
return p;
|
|
3419
3932
|
};
|
|
3933
|
+
function indentBlock(block) {
|
|
3934
|
+
return block.split("\n").map((line) => line ? " " + line : line).join("\n");
|
|
3935
|
+
}
|
|
3936
|
+
function dumpProcessTree(process2, lookup, nested = false) {
|
|
3937
|
+
let out = dumpProcess(process2, { nested });
|
|
3938
|
+
if (process2.children.length > 0) {
|
|
3939
|
+
const childBlocks = [];
|
|
3940
|
+
for (const childId of process2.children) {
|
|
3941
|
+
const child = lookup.get(childId);
|
|
3942
|
+
if (child) {
|
|
3943
|
+
childBlocks.push(indentBlock(dumpProcessTree(child, lookup, true)));
|
|
3944
|
+
}
|
|
3945
|
+
}
|
|
3946
|
+
if (childBlocks.length > 0) {
|
|
3947
|
+
out = out.replace(/\n}\n$/, "\n" + childBlocks.join("\n") + "}\n");
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
return out;
|
|
3951
|
+
}
|
|
3420
3952
|
function dumpParamList(params) {
|
|
3421
3953
|
return params.map(
|
|
3422
3954
|
(p) => p.name + (p.type ? " : " + p.type : "") + (p.initial !== void 0 ? " = " + dumpQuantityValue(p.initial) : "")
|
|
@@ -3531,6 +4063,26 @@ var dumpProcess = function(process2, ctx) {
|
|
|
3531
4063
|
if (process2.machineSteps && process2.machineSteps.length > 0) {
|
|
3532
4064
|
out += " machine_steps { " + process2.machineSteps.map(dumpBareSafe).join(" ") + " }\n";
|
|
3533
4065
|
}
|
|
4066
|
+
for (const st of process2.steps ?? []) {
|
|
4067
|
+
if (st.signatureBlock) {
|
|
4068
|
+
const lines = st.signatureBlock.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
4069
|
+
out += " step " + st.id + " {\n";
|
|
4070
|
+
for (const line of lines) {
|
|
4071
|
+
out += " " + line + "\n";
|
|
4072
|
+
}
|
|
4073
|
+
out += " }\n";
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
for (const b of process2.bindings ?? []) {
|
|
4077
|
+
out += " binding " + b.id + " {\n";
|
|
4078
|
+
for (const line of b.block.split("\n")) {
|
|
4079
|
+
out += line === "" ? "\n" : " " + line + "\n";
|
|
4080
|
+
}
|
|
4081
|
+
out += " }\n";
|
|
4082
|
+
}
|
|
4083
|
+
for (const req of process2.stepRequires ?? []) {
|
|
4084
|
+
out += " requires { " + req + " }\n";
|
|
4085
|
+
}
|
|
3534
4086
|
const inputIds = process2.inputRefs && process2.inputRefs.length > 0 ? process2.inputRefs : process2.input.map((r) => r.id);
|
|
3535
4087
|
if (inputIds.length > 0) {
|
|
3536
4088
|
out += " reference_data_registry {\n";
|
|
@@ -4720,22 +5272,58 @@ var parseProvision = function(id, data) {
|
|
|
4720
5272
|
ref: []
|
|
4721
5273
|
}
|
|
4722
5274
|
};
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
(
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
5275
|
+
const KNOWN = /* @__PURE__ */ new Set(["modality", "condition", "reference"]);
|
|
5276
|
+
const unwrapToken = (x) => {
|
|
5277
|
+
if (x.length >= 2 && x.startsWith('"') && x.endsWith('"')) {
|
|
5278
|
+
return unescapeString(x.slice(1, -1));
|
|
5279
|
+
}
|
|
5280
|
+
if (x.length >= 2 && x.startsWith("{") && x.endsWith("}")) {
|
|
5281
|
+
return unwrapBlock(x);
|
|
5282
|
+
}
|
|
5283
|
+
return x;
|
|
5284
|
+
};
|
|
5285
|
+
const t = tokenizePackage(data);
|
|
5286
|
+
let i = 0;
|
|
5287
|
+
while (i < t.length) {
|
|
5288
|
+
const keyword = t[i++];
|
|
5289
|
+
if (keyword === "modality") {
|
|
5290
|
+
if (i >= t.length) {
|
|
5291
|
+
throw new Error(
|
|
5292
|
+
`Parsing error: provision. ID ${id}: Expecting value for modality`
|
|
5293
|
+
);
|
|
4734
5294
|
}
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
5295
|
+
result.modality = t[i++];
|
|
5296
|
+
continue;
|
|
5297
|
+
}
|
|
5298
|
+
if (keyword === "condition") {
|
|
5299
|
+
if (i >= t.length) {
|
|
5300
|
+
throw new Error(
|
|
5301
|
+
`Parsing error: provision. ID ${id}: Expecting value for condition`
|
|
5302
|
+
);
|
|
5303
|
+
}
|
|
5304
|
+
result.condition = unwrapToken(t[i++]);
|
|
5305
|
+
continue;
|
|
5306
|
+
}
|
|
5307
|
+
if (keyword === "reference") {
|
|
5308
|
+
if (i >= t.length) {
|
|
5309
|
+
throw new Error(
|
|
5310
|
+
`Parsing error: provision. ID ${id}: Expecting value for reference`
|
|
5311
|
+
);
|
|
5312
|
+
}
|
|
5313
|
+
result._relations.ref = tokenizePackage(t[i++]);
|
|
5314
|
+
continue;
|
|
5315
|
+
}
|
|
5316
|
+
const rest = [];
|
|
5317
|
+
while (i < t.length && !KNOWN.has(t[i])) {
|
|
5318
|
+
rest.push(t[i++]);
|
|
5319
|
+
}
|
|
5320
|
+
if (rest.length === 0) {
|
|
5321
|
+
result.subject.set(keyword, "");
|
|
5322
|
+
break;
|
|
5323
|
+
}
|
|
5324
|
+
const value = rest.map(unwrapToken).join(" ");
|
|
5325
|
+
result.subject.set(keyword, value);
|
|
5326
|
+
}
|
|
4739
5327
|
return (ctx) => {
|
|
4740
5328
|
ctx.provisions[id] = result;
|
|
4741
5329
|
return ctx;
|
|
@@ -4754,7 +5342,8 @@ var resolveProvision = function(ctx, unresolved) {
|
|
|
4754
5342
|
var dumpProvision = function(pro) {
|
|
4755
5343
|
let out = "provision " + pro.id + " {\n";
|
|
4756
5344
|
pro.subject.forEach((value, key) => {
|
|
4757
|
-
|
|
5345
|
+
const v = value.includes(" ") ? `"${escapeString(value)}"` : value;
|
|
5346
|
+
out += " " + key + " " + v + "\n";
|
|
4758
5347
|
});
|
|
4759
5348
|
out += ' condition "' + escapeString(pro.condition) + '"\n';
|
|
4760
5349
|
if (pro.modality !== "") {
|
|
@@ -5233,6 +5822,11 @@ function parseColumnDefs(block) {
|
|
|
5233
5822
|
if (!name) {
|
|
5234
5823
|
break;
|
|
5235
5824
|
}
|
|
5825
|
+
if (i < t.length && t[i] === "{") {
|
|
5826
|
+
throw new Error(
|
|
5827
|
+
`Parsing error: table. Column "${name}": the old columns dialect (colN { name ... type ... }) is retired \u2014 write the canonical form: ${name === "" ? "name" : name}: type "unit"`
|
|
5828
|
+
);
|
|
5829
|
+
}
|
|
5236
5830
|
if (i < t.length && t[i] === ":") {
|
|
5237
5831
|
i++;
|
|
5238
5832
|
}
|
|
@@ -6658,6 +7252,7 @@ var parseSymbol = function(id, data) {
|
|
|
6658
7252
|
type: "number",
|
|
6659
7253
|
unit: "1",
|
|
6660
7254
|
latex: "",
|
|
7255
|
+
renders: [],
|
|
6661
7256
|
values: [],
|
|
6662
7257
|
series: null,
|
|
6663
7258
|
kind: "",
|
|
@@ -6709,6 +7304,20 @@ var parseSymbol = function(id, data) {
|
|
|
6709
7304
|
result.unit = unwrapped(value);
|
|
6710
7305
|
} else if (command === "latex") {
|
|
6711
7306
|
result.latex = unwrapped(value);
|
|
7307
|
+
} else if (command === "render") {
|
|
7308
|
+
const notation = stripWrapping(value());
|
|
7309
|
+
const text = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
7310
|
+
if (!result.renders) {
|
|
7311
|
+
result.renders = [];
|
|
7312
|
+
}
|
|
7313
|
+
if (["asciimath", "latex", "unicodemath", "mathml", "omml"].includes(
|
|
7314
|
+
notation
|
|
7315
|
+
)) {
|
|
7316
|
+
result.renders.push({ notation, text });
|
|
7317
|
+
if (notation === "latex" && !result.latex) {
|
|
7318
|
+
result.latex = text;
|
|
7319
|
+
}
|
|
7320
|
+
}
|
|
6712
7321
|
} else if (command === "values") {
|
|
6713
7322
|
const v = value();
|
|
6714
7323
|
result.values = v.startsWith("{") ? tokenizePackage(v).map(stripWrapping) : [stripWrapping(v)];
|
|
@@ -6789,6 +7398,9 @@ var dumpSymbol = function(s) {
|
|
|
6789
7398
|
if (s.latex) {
|
|
6790
7399
|
out += ' latex "' + escapeString(s.latex) + '"\n';
|
|
6791
7400
|
}
|
|
7401
|
+
for (const r of s.renders ?? []) {
|
|
7402
|
+
out += " render " + r.notation + ' "' + escapeString(r.text) + '"\n';
|
|
7403
|
+
}
|
|
6792
7404
|
if (s.values.length > 0) {
|
|
6793
7405
|
out += " values { " + s.values.map(dumpBareSafe).join(" ") + " }\n";
|
|
6794
7406
|
}
|
|
@@ -6934,6 +7546,23 @@ var parseCalculation = function(id, data) {
|
|
|
6934
7546
|
result.description = unwrapBlock(t[i++]);
|
|
6935
7547
|
} else if (command === "expression") {
|
|
6936
7548
|
result.expression = unwrapBlock(t[i++]);
|
|
7549
|
+
} else if (command === "math") {
|
|
7550
|
+
const inner = tokenizePackage(unwrapBlock(t[i++]));
|
|
7551
|
+
let notation = "";
|
|
7552
|
+
let formula = "";
|
|
7553
|
+
let j = 0;
|
|
7554
|
+
while (j < inner.length) {
|
|
7555
|
+
const k = inner[j++];
|
|
7556
|
+
if (j >= inner.length) {
|
|
7557
|
+
break;
|
|
7558
|
+
}
|
|
7559
|
+
if (k === "notation") {
|
|
7560
|
+
notation = stripWrapping(inner[j++]);
|
|
7561
|
+
} else if (k === "formula") {
|
|
7562
|
+
formula = stripWrapping(inner[j++]);
|
|
7563
|
+
}
|
|
7564
|
+
}
|
|
7565
|
+
result.math = { notation, formula };
|
|
6937
7566
|
} else if (command === "reference") {
|
|
6938
7567
|
result._relations.ref = tokenizePackage(t[i++]);
|
|
6939
7568
|
} else if (command === "ref") {
|
|
@@ -7250,6 +7879,23 @@ function parseVariant(vid, block, calcId) {
|
|
|
7250
7879
|
variant.params = tokenize(stripWrapping(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
|
|
7251
7880
|
} else if (cmd === "expression") {
|
|
7252
7881
|
variant.expression = stripWrapping(t[i++]);
|
|
7882
|
+
} else if (cmd === "math") {
|
|
7883
|
+
const inner = tokenizePackage(unwrapBlock(t[i++]));
|
|
7884
|
+
let notation = "";
|
|
7885
|
+
let formula = "";
|
|
7886
|
+
let j = 0;
|
|
7887
|
+
while (j < inner.length) {
|
|
7888
|
+
const k = inner[j++];
|
|
7889
|
+
if (j >= inner.length) {
|
|
7890
|
+
break;
|
|
7891
|
+
}
|
|
7892
|
+
if (k === "notation") {
|
|
7893
|
+
notation = stripWrapping(inner[j++]);
|
|
7894
|
+
} else if (k === "formula") {
|
|
7895
|
+
formula = stripWrapping(inner[j++]);
|
|
7896
|
+
}
|
|
7897
|
+
}
|
|
7898
|
+
variant.math = { notation, formula };
|
|
7253
7899
|
} else if (cmd === "lookup") {
|
|
7254
7900
|
variant.lookup = parseLookup(unwrapBlock(t[i++]));
|
|
7255
7901
|
} else if (cmd === "profile") {
|
|
@@ -7390,6 +8036,12 @@ var dumpCalculation = function(c) {
|
|
|
7390
8036
|
if (c.expression) {
|
|
7391
8037
|
out += ' expression "' + escapeString(c.expression) + '"\n';
|
|
7392
8038
|
}
|
|
8039
|
+
if (c.math) {
|
|
8040
|
+
out += " math {\n";
|
|
8041
|
+
out += " notation " + c.math.notation + "\n";
|
|
8042
|
+
out += ' formula "' + escapeString(c.math.formula) + '"\n';
|
|
8043
|
+
out += " }\n";
|
|
8044
|
+
}
|
|
7393
8045
|
if (c.params && c.params.length > 0) {
|
|
7394
8046
|
out += " params { " + c.params.join(" ") + " }\n";
|
|
7395
8047
|
}
|
|
@@ -8568,7 +9220,7 @@ function parseRequiredCompetence(block) {
|
|
|
8568
9220
|
const entry = {
|
|
8569
9221
|
kind: stripWrapping(t[i++]),
|
|
8570
9222
|
range: null,
|
|
8571
|
-
|
|
9223
|
+
methodRef: "",
|
|
8572
9224
|
resolution: null,
|
|
8573
9225
|
stability: null,
|
|
8574
9226
|
description: ""
|
|
@@ -8601,8 +9253,8 @@ function parseRequiredCompetence(block) {
|
|
|
8601
9253
|
}
|
|
8602
9254
|
}
|
|
8603
9255
|
entry.range = range;
|
|
8604
|
-
} else if (cc === "
|
|
8605
|
-
entry.
|
|
9256
|
+
} else if (cc === "method_ref") {
|
|
9257
|
+
entry.methodRef = stripWrapping(ct[j++]);
|
|
8606
9258
|
} else if (cc === "resolution") {
|
|
8607
9259
|
entry.resolution = readQuantity(unwrapBlock(ct[j++]));
|
|
8608
9260
|
} else if (cc === "stability") {
|
|
@@ -8645,8 +9297,8 @@ function dumpRequiredCompetence(entries) {
|
|
|
8645
9297
|
line += ' unit "' + escapeString(e.range.unit) + '" }\n';
|
|
8646
9298
|
out += line;
|
|
8647
9299
|
}
|
|
8648
|
-
if (e.
|
|
8649
|
-
out +=
|
|
9300
|
+
if (e.methodRef) {
|
|
9301
|
+
out += " method_ref " + e.methodRef + "\n";
|
|
8650
9302
|
}
|
|
8651
9303
|
out += dumpQuantity("resolution", e.resolution);
|
|
8652
9304
|
out += dumpQuantity("stability", e.stability);
|
|
@@ -8669,8 +9321,7 @@ var parseCompetenceKind = function(id, data) {
|
|
|
8669
9321
|
id,
|
|
8670
9322
|
label: "",
|
|
8671
9323
|
definition: "",
|
|
8672
|
-
source: null
|
|
8673
|
-
methodStandards: []
|
|
9324
|
+
source: null
|
|
8674
9325
|
};
|
|
8675
9326
|
const t = tokenizePackage(data);
|
|
8676
9327
|
let i = 0;
|
|
@@ -8687,14 +9338,6 @@ var parseCompetenceKind = function(id, data) {
|
|
|
8687
9338
|
result.definition = readValue(t[i++]);
|
|
8688
9339
|
} else if (keyword === "source") {
|
|
8689
9340
|
result.source = readSource(unwrapBlock(t[i++]));
|
|
8690
|
-
} else if (keyword === "method_standard") {
|
|
8691
|
-
const stdId = stripWrapping(t[i++]);
|
|
8692
|
-
if (i >= t.length) {
|
|
8693
|
-
throw new Error(
|
|
8694
|
-
`Parsing error: competence_kind. ID ${id}: Expecting title for method_standard ${stdId}`
|
|
8695
|
-
);
|
|
8696
|
-
}
|
|
8697
|
-
result.methodStandards.push({ id: stdId, title: readValue(t[i++]) });
|
|
8698
9341
|
} else if (keyword === "ref") {
|
|
8699
9342
|
const rr = parseRef(t, i, stripWrapping, unwrapBlock);
|
|
8700
9343
|
if (!foldRefIntoLegacy(result, rr.ref)) {
|
|
@@ -8725,9 +9368,6 @@ var dumpCompetenceKind = function(k) {
|
|
|
8725
9368
|
if (k.source && (k.source.doc || k.source.clause)) {
|
|
8726
9369
|
out += ' source { doc "' + escapeString(k.source.doc) + '" clause "' + escapeString(k.source.clause) + '"' + (k.source.fragment ? ' fragment "' + escapeString(k.source.fragment) + '"' : "") + " }\n";
|
|
8727
9370
|
}
|
|
8728
|
-
for (const ms of k.methodStandards) {
|
|
8729
|
-
out += " method_standard " + ms.id + ' "' + escapeString(ms.title) + '"\n';
|
|
8730
|
-
}
|
|
8731
9371
|
out += dumpCorrespondences(
|
|
8732
9372
|
k.correspondences,
|
|
8733
9373
|
" ",
|
|
@@ -8788,7 +9428,9 @@ function parseTestVariables(block) {
|
|
|
8788
9428
|
} else if (vc === "source") {
|
|
8789
9429
|
v.source = stripWrapping(vt[j++]);
|
|
8790
9430
|
} else if (vc === "derivation") {
|
|
8791
|
-
|
|
9431
|
+
const c = readExpressionCarrier(vt[j++], "test variable derivation");
|
|
9432
|
+
v.derivation = c.source;
|
|
9433
|
+
v.derivationBound = c.inline || void 0;
|
|
8792
9434
|
} else if (vc === "description") {
|
|
8793
9435
|
v.description = stripWrapping(vt[j++]);
|
|
8794
9436
|
} else if (vc === "item_type") {
|
|
@@ -8848,7 +9490,9 @@ function parsePreconditions(block) {
|
|
|
8848
9490
|
break;
|
|
8849
9491
|
}
|
|
8850
9492
|
if (pc === "check") {
|
|
8851
|
-
|
|
9493
|
+
const c = readExpressionCarrier(pt[j++], "precondition check");
|
|
9494
|
+
p.check = c.source;
|
|
9495
|
+
p.checkBound = c.inline || void 0;
|
|
8852
9496
|
} else if (pc === "description") {
|
|
8853
9497
|
p.description = stripWrapping(pt[j++]);
|
|
8854
9498
|
} else if (pc === "on_violation") {
|
|
@@ -9614,8 +10258,17 @@ var dumpConformanceTest = function(ct) {
|
|
|
9614
10258
|
if (v.source) {
|
|
9615
10259
|
line += "source " + v.source + " ";
|
|
9616
10260
|
}
|
|
10261
|
+
let derivationBlock = "";
|
|
9617
10262
|
if (v.derivation) {
|
|
9618
|
-
|
|
10263
|
+
if (v.derivationBound) {
|
|
10264
|
+
derivationBlock = dumpExpressionBlock(
|
|
10265
|
+
"derivation",
|
|
10266
|
+
v.derivation,
|
|
10267
|
+
" "
|
|
10268
|
+
);
|
|
10269
|
+
} else {
|
|
10270
|
+
line += 'derivation "' + escapeString(v.derivation) + '" ';
|
|
10271
|
+
}
|
|
9619
10272
|
}
|
|
9620
10273
|
if (v.description) {
|
|
9621
10274
|
line += 'description "' + escapeString(v.description) + '" ';
|
|
@@ -9642,7 +10295,11 @@ var dumpConformanceTest = function(ct) {
|
|
|
9642
10295
|
}
|
|
9643
10296
|
line += pv + "} ";
|
|
9644
10297
|
}
|
|
9645
|
-
|
|
10298
|
+
if (derivationBlock) {
|
|
10299
|
+
out += line + "\n" + derivationBlock + " }\n";
|
|
10300
|
+
} else {
|
|
10301
|
+
out += line + "}\n";
|
|
10302
|
+
}
|
|
9646
10303
|
}
|
|
9647
10304
|
out += " }\n";
|
|
9648
10305
|
}
|
|
@@ -9670,8 +10327,13 @@ var dumpConformanceTest = function(ct) {
|
|
|
9670
10327
|
out += " preconditions {\n";
|
|
9671
10328
|
for (const p of ct.preconditions) {
|
|
9672
10329
|
let line = " precondition " + p.id + " { ";
|
|
10330
|
+
let checkBlock = "";
|
|
9673
10331
|
if (p.check) {
|
|
9674
|
-
|
|
10332
|
+
if (p.checkBound) {
|
|
10333
|
+
checkBlock = dumpExpressionBlock("check", p.check, " ");
|
|
10334
|
+
} else {
|
|
10335
|
+
line += 'check "' + escapeString(p.check) + '" ';
|
|
10336
|
+
}
|
|
9675
10337
|
}
|
|
9676
10338
|
if (p.description) {
|
|
9677
10339
|
line += 'description "' + escapeString(p.description) + '" ';
|
|
@@ -9680,7 +10342,11 @@ var dumpConformanceTest = function(ct) {
|
|
|
9680
10342
|
if (p.onUnresolvable) {
|
|
9681
10343
|
line += "on_unresolvable " + p.onUnresolvable + " ";
|
|
9682
10344
|
}
|
|
9683
|
-
|
|
10345
|
+
if (checkBlock) {
|
|
10346
|
+
out += line + "\n" + checkBlock + " }\n";
|
|
10347
|
+
} else {
|
|
10348
|
+
out += line + "}\n";
|
|
10349
|
+
}
|
|
9684
10350
|
}
|
|
9685
10351
|
out += " }\n";
|
|
9686
10352
|
}
|
|
@@ -10045,7 +10711,9 @@ var parseVerdict = function(id, data) {
|
|
|
10045
10711
|
} else if (keyword === "behavior") {
|
|
10046
10712
|
result.behavior = value();
|
|
10047
10713
|
} else if (keyword === "derive" || keyword === "expression") {
|
|
10048
|
-
|
|
10714
|
+
const c = readExpressionCarrier(value(), "verdict derive");
|
|
10715
|
+
result.derive = c.source;
|
|
10716
|
+
result.deriveBound = c.inline || void 0;
|
|
10049
10717
|
} else if (keyword === "inputs" || keyword === "uses") {
|
|
10050
10718
|
result.inputs = readIdList3(value());
|
|
10051
10719
|
} else if (keyword === "series_reduction") {
|
|
@@ -10103,7 +10771,11 @@ var dumpVerdict = function(v) {
|
|
|
10103
10771
|
out += " }\n";
|
|
10104
10772
|
}
|
|
10105
10773
|
if (v.derive) {
|
|
10106
|
-
|
|
10774
|
+
if (v.deriveBound) {
|
|
10775
|
+
out += dumpExpressionBlock("derive", v.derive, " ");
|
|
10776
|
+
} else {
|
|
10777
|
+
out += ' derive "' + escapeString(v.derive) + '"\n';
|
|
10778
|
+
}
|
|
10107
10779
|
}
|
|
10108
10780
|
if (v.inputs.length > 0) {
|
|
10109
10781
|
out += " inputs { " + v.inputs.join(" ") + " }\n";
|
|
@@ -10706,8 +11378,15 @@ var parseConstraint = function(id, data) {
|
|
|
10706
11378
|
result.stereotype = stripWrapping(t[i++]);
|
|
10707
11379
|
} else if (keyword === "name") {
|
|
10708
11380
|
result.name = readValue2(t[i++]);
|
|
11381
|
+
} else if (keyword === "args") {
|
|
11382
|
+
if (!result.args) {
|
|
11383
|
+
result.args = [];
|
|
11384
|
+
}
|
|
11385
|
+
result.args.push(...readArgsBlock(unwrapBlock(t[i++])));
|
|
10709
11386
|
} else if (keyword === "check") {
|
|
10710
|
-
|
|
11387
|
+
const c = readExpressionCarrier(t[i++], "constraint check");
|
|
11388
|
+
result.check = c.source;
|
|
11389
|
+
result.checkBound = c.inline || void 0;
|
|
10711
11390
|
} else if (keyword === "violation_meaning") {
|
|
10712
11391
|
result.violationMeaning = readValue2(t[i++]);
|
|
10713
11392
|
} else if (keyword === "on_violation") {
|
|
@@ -10741,8 +11420,19 @@ var dumpConstraint = function(c) {
|
|
|
10741
11420
|
if (c.name) {
|
|
10742
11421
|
out += ' name "' + escapeString(c.name) + '"\n';
|
|
10743
11422
|
}
|
|
11423
|
+
if ((c.args ?? []).length > 0) {
|
|
11424
|
+
out += " args {\n";
|
|
11425
|
+
for (const a of c.args ?? []) {
|
|
11426
|
+
out += " " + a.name + " <- " + a.source + "\n";
|
|
11427
|
+
}
|
|
11428
|
+
out += " }\n";
|
|
11429
|
+
}
|
|
10744
11430
|
if (c.check) {
|
|
10745
|
-
|
|
11431
|
+
if (c.checkBound) {
|
|
11432
|
+
out += dumpExpressionBlock("check", c.check, " ");
|
|
11433
|
+
} else {
|
|
11434
|
+
out += ' check "' + escapeString(c.check) + '"\n';
|
|
11435
|
+
}
|
|
10746
11436
|
}
|
|
10747
11437
|
if (c.violationMeaning) {
|
|
10748
11438
|
out += ' violation_meaning "' + escapeString(c.violationMeaning) + '"\n';
|
|
@@ -10761,6 +11451,169 @@ var dumpConstraint = function(c) {
|
|
|
10761
11451
|
return out;
|
|
10762
11452
|
};
|
|
10763
11453
|
|
|
11454
|
+
// src/ser-des/config/uncertaintyBudget.ts
|
|
11455
|
+
var DISTRIBUTIONS = /* @__PURE__ */ new Set([
|
|
11456
|
+
"rectangular",
|
|
11457
|
+
"triangular",
|
|
11458
|
+
"normal",
|
|
11459
|
+
"ushape"
|
|
11460
|
+
]);
|
|
11461
|
+
function readComponent(block) {
|
|
11462
|
+
const c = {
|
|
11463
|
+
id: "",
|
|
11464
|
+
type: "B",
|
|
11465
|
+
series: "",
|
|
11466
|
+
distribution: "",
|
|
11467
|
+
halfWidth: "",
|
|
11468
|
+
unit: "",
|
|
11469
|
+
source: null,
|
|
11470
|
+
description: ""
|
|
11471
|
+
};
|
|
11472
|
+
const t = tokenizePackage(block);
|
|
11473
|
+
let i = 0;
|
|
11474
|
+
while (i < t.length) {
|
|
11475
|
+
const kw = t[i++];
|
|
11476
|
+
if (i >= t.length) {
|
|
11477
|
+
throw new Error(
|
|
11478
|
+
`Parsing error: uncertainty_budget component. ID ${c.id}: Expecting value for ${kw}`
|
|
11479
|
+
);
|
|
11480
|
+
}
|
|
11481
|
+
if (kw === "type") {
|
|
11482
|
+
const v = stripWrapping(t[i++]);
|
|
11483
|
+
if (v !== "A" && v !== "B") {
|
|
11484
|
+
throw new Error(
|
|
11485
|
+
`Parsing error: uncertainty_budget component. ID ${c.id}: unknown type "${v}" (A evaluates the statistics of a series; B states a distribution)`
|
|
11486
|
+
);
|
|
11487
|
+
}
|
|
11488
|
+
c.type = v;
|
|
11489
|
+
} else if (kw === "series") {
|
|
11490
|
+
c.series = stripWrapping(t[i++]);
|
|
11491
|
+
} else if (kw === "distribution") {
|
|
11492
|
+
const v = stripWrapping(t[i++]);
|
|
11493
|
+
if (!DISTRIBUTIONS.has(v)) {
|
|
11494
|
+
throw new Error(
|
|
11495
|
+
`Parsing error: uncertainty_budget component. ID ${c.id}: unknown distribution "${v}" (rectangular | triangular | normal | ushape)`
|
|
11496
|
+
);
|
|
11497
|
+
}
|
|
11498
|
+
c.distribution = v;
|
|
11499
|
+
} else if (kw === "half_width") {
|
|
11500
|
+
c.halfWidth = stripWrapping(t[i++]);
|
|
11501
|
+
} else if (kw === "unit") {
|
|
11502
|
+
c.unit = stripWrapping(t[i++]);
|
|
11503
|
+
} else if (kw === "description") {
|
|
11504
|
+
c.description = stripWrapping(t[i++]);
|
|
11505
|
+
} else if (kw === "source") {
|
|
11506
|
+
c.source = readSource(unwrapBlock(t[i++]));
|
|
11507
|
+
} else {
|
|
11508
|
+
i = skipUnknownValue(t, i, kw);
|
|
11509
|
+
}
|
|
11510
|
+
}
|
|
11511
|
+
return c;
|
|
11512
|
+
}
|
|
11513
|
+
var parseUncertaintyBudget = function(id, data) {
|
|
11514
|
+
const result = {
|
|
11515
|
+
id,
|
|
11516
|
+
target: "",
|
|
11517
|
+
coverageK: "",
|
|
11518
|
+
components: [],
|
|
11519
|
+
source: null
|
|
11520
|
+
};
|
|
11521
|
+
const t = tokenizePackage(data);
|
|
11522
|
+
let i = 0;
|
|
11523
|
+
while (i < t.length) {
|
|
11524
|
+
const kw = t[i++];
|
|
11525
|
+
if (i >= t.length) {
|
|
11526
|
+
throw new Error(
|
|
11527
|
+
`Parsing error: uncertainty_budget. ID ${id}: Expecting value for ${kw}`
|
|
11528
|
+
);
|
|
11529
|
+
}
|
|
11530
|
+
if (kw === "target") {
|
|
11531
|
+
result.target = stripWrapping(t[i++]);
|
|
11532
|
+
} else if (kw === "coverage") {
|
|
11533
|
+
const head = stripWrapping(t[i++]);
|
|
11534
|
+
if (head !== "k") {
|
|
11535
|
+
throw new Error(
|
|
11536
|
+
`Parsing error: uncertainty_budget. ID ${id}: coverage states its factor \u2014 coverage k <number>`
|
|
11537
|
+
);
|
|
11538
|
+
}
|
|
11539
|
+
result.coverageK = stripWrapping(t[i++]);
|
|
11540
|
+
} else if (kw === "component") {
|
|
11541
|
+
if (t[i].startsWith("{")) {
|
|
11542
|
+
throw new Error(
|
|
11543
|
+
`Parsing error: uncertainty_budget. ID ${id}: a component carries an id \u2014 component <id> { \u2026 }`
|
|
11544
|
+
);
|
|
11545
|
+
}
|
|
11546
|
+
const cid = stripWrapping(t[i++]);
|
|
11547
|
+
const c = readComponent(unwrapBlock(t[i++]));
|
|
11548
|
+
c.id = cid;
|
|
11549
|
+
result.components.push(c);
|
|
11550
|
+
} else if (kw === "source") {
|
|
11551
|
+
result.source = readSource(unwrapBlock(t[i++]));
|
|
11552
|
+
} else if (kw === "ref") {
|
|
11553
|
+
const rr = parseRef(t, i, stripWrapping, unwrapBlock);
|
|
11554
|
+
if (!foldRefIntoLegacy(result, rr.ref)) {
|
|
11555
|
+
(result.refs ??= []).push(rr.ref);
|
|
11556
|
+
}
|
|
11557
|
+
i = rr.next;
|
|
11558
|
+
} else if (kw === "corresponds") {
|
|
11559
|
+
const cc = parseCorresponds(t, i, stripWrapping);
|
|
11560
|
+
(result.correspondences ??= []).push(cc.corr);
|
|
11561
|
+
i = cc.next;
|
|
11562
|
+
} else {
|
|
11563
|
+
i = skipUnknownValue(t, i, kw);
|
|
11564
|
+
}
|
|
11565
|
+
}
|
|
11566
|
+
return (ctx) => {
|
|
11567
|
+
ctx.uncertaintyBudgets[id] = result;
|
|
11568
|
+
return ctx;
|
|
11569
|
+
};
|
|
11570
|
+
};
|
|
11571
|
+
var dumpUncertaintyBudget = function(b) {
|
|
11572
|
+
let out = "uncertainty_budget " + b.id + " {\n";
|
|
11573
|
+
if (b.target) {
|
|
11574
|
+
out += " target " + b.target + "\n";
|
|
11575
|
+
}
|
|
11576
|
+
if (b.coverageK) {
|
|
11577
|
+
out += " coverage k " + b.coverageK + "\n";
|
|
11578
|
+
}
|
|
11579
|
+
for (const c of b.components) {
|
|
11580
|
+
out += " component " + c.id + " {\n";
|
|
11581
|
+
out += " type " + c.type + "\n";
|
|
11582
|
+
if (c.type === "A" && c.series) {
|
|
11583
|
+
out += " series " + c.series + "\n";
|
|
11584
|
+
}
|
|
11585
|
+
if (c.type === "B") {
|
|
11586
|
+
if (c.distribution) {
|
|
11587
|
+
out += " distribution " + c.distribution + "\n";
|
|
11588
|
+
}
|
|
11589
|
+
if (c.halfWidth) {
|
|
11590
|
+
out += " half_width " + c.halfWidth + "\n";
|
|
11591
|
+
}
|
|
11592
|
+
if (c.unit) {
|
|
11593
|
+
out += ' unit "' + escapeString(c.unit) + '"\n';
|
|
11594
|
+
}
|
|
11595
|
+
}
|
|
11596
|
+
if (c.description) {
|
|
11597
|
+
out += ' description "' + escapeString(c.description) + '"\n';
|
|
11598
|
+
}
|
|
11599
|
+
if (c.source && (c.source.doc || c.source.clause)) {
|
|
11600
|
+
out += ' source { doc "' + escapeString(c.source.doc) + '" clause "' + escapeString(c.source.clause) + '"' + (c.source.fragment ? ' fragment "' + escapeString(c.source.fragment) + '"' : "") + " }\n";
|
|
11601
|
+
}
|
|
11602
|
+
out += " }\n";
|
|
11603
|
+
}
|
|
11604
|
+
if (b.source && (b.source.doc || b.source.clause)) {
|
|
11605
|
+
out += ' source { doc "' + escapeString(b.source.doc) + '" clause "' + escapeString(b.source.clause) + '"' + (b.source.fragment ? ' fragment "' + escapeString(b.source.fragment) + '"' : "") + " }\n";
|
|
11606
|
+
}
|
|
11607
|
+
out += dumpCorrespondences(
|
|
11608
|
+
b.correspondences,
|
|
11609
|
+
" ",
|
|
11610
|
+
escapeString,
|
|
11611
|
+
dumpBareSafe
|
|
11612
|
+
);
|
|
11613
|
+
out += "}\n";
|
|
11614
|
+
return out;
|
|
11615
|
+
};
|
|
11616
|
+
|
|
10764
11617
|
// src/ser-des/config/discrepancyRecord.ts
|
|
10765
11618
|
var VALID_STATUSES = ["open", "resolved"];
|
|
10766
11619
|
var parseDiscrepancyRecord = function(id, data) {
|
|
@@ -11109,8 +11962,8 @@ function readAccepts(block) {
|
|
|
11109
11962
|
}
|
|
11110
11963
|
return accepts;
|
|
11111
11964
|
}
|
|
11112
|
-
function
|
|
11113
|
-
|
|
11965
|
+
function blankLimit() {
|
|
11966
|
+
return {
|
|
11114
11967
|
expression: "",
|
|
11115
11968
|
uses: [],
|
|
11116
11969
|
modality: "",
|
|
@@ -11121,15 +11974,51 @@ function readLimit(block) {
|
|
|
11121
11974
|
acceptance: null,
|
|
11122
11975
|
sourceDiscrepancy: null
|
|
11123
11976
|
};
|
|
11124
|
-
|
|
11125
|
-
|
|
11977
|
+
}
|
|
11978
|
+
function readLimit(block) {
|
|
11979
|
+
const limit = blankLimit();
|
|
11980
|
+
readLegacyLimitFields(tokenize(block), limit, 0);
|
|
11981
|
+
return limit;
|
|
11982
|
+
}
|
|
11983
|
+
function readExpressionBlock(raw) {
|
|
11984
|
+
return canonicalizeExpression(raw);
|
|
11985
|
+
}
|
|
11986
|
+
function readLegacyLimitFields(t, limit, start) {
|
|
11987
|
+
let i = start;
|
|
11126
11988
|
while (i < t.length) {
|
|
11127
11989
|
const cmd = t[i++];
|
|
11128
11990
|
if (i >= t.length) {
|
|
11129
11991
|
break;
|
|
11130
11992
|
}
|
|
11131
|
-
if (cmd === "
|
|
11132
|
-
limit.
|
|
11993
|
+
if (cmd === "args") {
|
|
11994
|
+
if (!limit.args) {
|
|
11995
|
+
limit.args = [];
|
|
11996
|
+
}
|
|
11997
|
+
const at = tokenize(unwrapBlock(t[i++]));
|
|
11998
|
+
let k = 0;
|
|
11999
|
+
while (k < at.length) {
|
|
12000
|
+
const name = stripWrapping(at[k++]);
|
|
12001
|
+
const arrow = at[k];
|
|
12002
|
+
if (arrow !== "<-") {
|
|
12003
|
+
throw new Error(
|
|
12004
|
+
`limit args: expected "<-" after "${name}" (name <- source)`
|
|
12005
|
+
);
|
|
12006
|
+
}
|
|
12007
|
+
k += 1;
|
|
12008
|
+
if (k >= at.length) {
|
|
12009
|
+
throw new Error(`limit args: "${name}" binds to nothing`);
|
|
12010
|
+
}
|
|
12011
|
+
const source = stripWrapping(at[k++]);
|
|
12012
|
+
limit.args.push({ name, source });
|
|
12013
|
+
}
|
|
12014
|
+
} else if (cmd === "expression") {
|
|
12015
|
+
const value = t[i++];
|
|
12016
|
+
if (value.startsWith("{")) {
|
|
12017
|
+
limit.argsBound = true;
|
|
12018
|
+
limit.expression = readExpressionBlock(unwrapBlock(value));
|
|
12019
|
+
} else {
|
|
12020
|
+
limit.expression = stripWrapping(value);
|
|
12021
|
+
}
|
|
11133
12022
|
} else if (cmd === "uses") {
|
|
11134
12023
|
limit.uses = readIdList4(t[i++]);
|
|
11135
12024
|
} else if (cmd === "modality") {
|
|
@@ -11166,7 +12055,6 @@ function readLimit(block) {
|
|
|
11166
12055
|
i = skipUnknownValue(t, i, cmd);
|
|
11167
12056
|
}
|
|
11168
12057
|
}
|
|
11169
|
-
return limit;
|
|
11170
12058
|
}
|
|
11171
12059
|
function readSubjects(block) {
|
|
11172
12060
|
const out = [];
|
|
@@ -11378,6 +12266,52 @@ var parseRequirement = function(id, data) {
|
|
|
11378
12266
|
};
|
|
11379
12267
|
};
|
|
11380
12268
|
function dumpLimit(limit) {
|
|
12269
|
+
if (limit.argsBound) {
|
|
12270
|
+
let out2 = " limit {\n";
|
|
12271
|
+
if ((limit.args ?? []).length > 0) {
|
|
12272
|
+
out2 += " args {\n";
|
|
12273
|
+
for (const a of limit.args ?? []) {
|
|
12274
|
+
out2 += " " + a.name + " <- " + a.source + "\n";
|
|
12275
|
+
}
|
|
12276
|
+
out2 += " }\n";
|
|
12277
|
+
}
|
|
12278
|
+
out2 += " expression {\n";
|
|
12279
|
+
for (const line of limit.expression.split("\n")) {
|
|
12280
|
+
out2 += " " + line + "\n";
|
|
12281
|
+
}
|
|
12282
|
+
out2 += " }\n";
|
|
12283
|
+
if (limit.modality) {
|
|
12284
|
+
out2 += " modality " + limit.modality + "\n";
|
|
12285
|
+
}
|
|
12286
|
+
if (limit.relativeTo) {
|
|
12287
|
+
out2 += " relative_to " + limit.relativeTo + "\n";
|
|
12288
|
+
}
|
|
12289
|
+
if (limit.notes) {
|
|
12290
|
+
out2 += ' notes "' + escapeString(limit.notes) + '"\n';
|
|
12291
|
+
}
|
|
12292
|
+
if (limit.accepts) {
|
|
12293
|
+
const a = limit.accepts;
|
|
12294
|
+
let line = " accepts { verdict " + a.verdict;
|
|
12295
|
+
if (a.op) {
|
|
12296
|
+
line += " op " + a.op;
|
|
12297
|
+
}
|
|
12298
|
+
if (a.limit) {
|
|
12299
|
+
line += ' limit "' + escapeString(a.limit) + '"';
|
|
12300
|
+
}
|
|
12301
|
+
if (a.sourceDiscrepancy) {
|
|
12302
|
+
line += " " + dumpSourceDiscrepancy(a.sourceDiscrepancy, "");
|
|
12303
|
+
}
|
|
12304
|
+
out2 += line + " }\n";
|
|
12305
|
+
}
|
|
12306
|
+
if (limit.acceptance) {
|
|
12307
|
+
out2 += dumpAcceptance(limit.acceptance, " ") + "\n";
|
|
12308
|
+
}
|
|
12309
|
+
if (limit.sourceDiscrepancy) {
|
|
12310
|
+
out2 += dumpSourceDiscrepancy(limit.sourceDiscrepancy, " ") + "\n";
|
|
12311
|
+
}
|
|
12312
|
+
out2 += " }\n";
|
|
12313
|
+
return out2;
|
|
12314
|
+
}
|
|
11381
12315
|
let out = " limit {\n";
|
|
11382
12316
|
if (limit.expression) {
|
|
11383
12317
|
out += ' expression "' + escapeString(limit.expression) + '"\n';
|
|
@@ -11541,8 +12475,12 @@ var parseRequirementClass = function(id, data) {
|
|
|
11541
12475
|
subject: "",
|
|
11542
12476
|
guidance: "",
|
|
11543
12477
|
dependencies: [],
|
|
11544
|
-
referenceIds: []
|
|
12478
|
+
referenceIds: [],
|
|
12479
|
+
limit: null,
|
|
12480
|
+
members: []
|
|
11545
12481
|
};
|
|
12482
|
+
const nestedParsers = [];
|
|
12483
|
+
const members = [];
|
|
11546
12484
|
const t = tokenizePackage(data);
|
|
11547
12485
|
let i = 0;
|
|
11548
12486
|
while (i < t.length) {
|
|
@@ -11566,11 +12504,24 @@ var parseRequirementClass = function(id, data) {
|
|
|
11566
12504
|
result.dependencies = readIdList4(t[i++]);
|
|
11567
12505
|
} else if (cmd === "reference") {
|
|
11568
12506
|
result.referenceIds = readIdList4(t[i++]);
|
|
12507
|
+
} else if (cmd === "limit") {
|
|
12508
|
+
result.limit = readLimit(unwrapBlock(t[i++]));
|
|
12509
|
+
} else if (cmd === "requirement") {
|
|
12510
|
+
const childId = stripWrapping(t[i++]);
|
|
12511
|
+
const childBlock = t[i++];
|
|
12512
|
+
const childParse = parseRequirement(childId, unwrapBlock(childBlock));
|
|
12513
|
+
nestedParsers.push(childParse);
|
|
12514
|
+
members.push(childId);
|
|
11569
12515
|
} else {
|
|
11570
12516
|
i = skipUnknownValue(t, i, cmd);
|
|
11571
12517
|
}
|
|
11572
12518
|
}
|
|
11573
12519
|
return (ctx) => {
|
|
12520
|
+
const c = ctx;
|
|
12521
|
+
for (const parse2 of nestedParsers) {
|
|
12522
|
+
parse2(c);
|
|
12523
|
+
}
|
|
12524
|
+
result.members = members;
|
|
11574
12525
|
ctx.requirementClasses[id] = result;
|
|
11575
12526
|
return ctx;
|
|
11576
12527
|
};
|
|
@@ -11595,6 +12546,9 @@ var dumpRequirementClass = function(rc) {
|
|
|
11595
12546
|
if (rc.referenceIds.length > 0) {
|
|
11596
12547
|
out += " reference { " + rc.referenceIds.join(" ") + " }\n";
|
|
11597
12548
|
}
|
|
12549
|
+
if (rc.limit) {
|
|
12550
|
+
out += dumpLimit(rc.limit);
|
|
12551
|
+
}
|
|
11598
12552
|
out += "}\n";
|
|
11599
12553
|
return out;
|
|
11600
12554
|
};
|
|
@@ -11663,6 +12617,8 @@ var parsePackage = function(data) {
|
|
|
11663
12617
|
manifest.title = stripWrapping(t[i++]);
|
|
11664
12618
|
} else if (cmd === "version") {
|
|
11665
12619
|
manifest.version = stripWrapping(t[i++]);
|
|
12620
|
+
} else if (cmd === "language") {
|
|
12621
|
+
manifest.language = stripWrapping(t[i++]);
|
|
11666
12622
|
} else if (cmd === "editions") {
|
|
11667
12623
|
manifest.editions = readList(t[i++]);
|
|
11668
12624
|
} else if (cmd === "baseUrn" || cmd === "base_urn") {
|
|
@@ -18875,6 +19831,298 @@ var dumpPartAnnex = function(a) {
|
|
|
18875
19831
|
return out;
|
|
18876
19832
|
};
|
|
18877
19833
|
|
|
19834
|
+
// src/ser-des/config/lmlAligned.ts
|
|
19835
|
+
var MATH_NOTATIONS = ["asciimath", "latex", "unicodemath", "mathml", "omml"];
|
|
19836
|
+
var MAPPING_FORMATS = ["xml", "yaml", "json", "toml", "csv"];
|
|
19837
|
+
function splitMappingId(id) {
|
|
19838
|
+
const at = id.indexOf(":");
|
|
19839
|
+
const format = at === -1 ? "xml" : id.slice(0, at);
|
|
19840
|
+
return { format, target: at === -1 ? id : id.slice(at + 1) };
|
|
19841
|
+
}
|
|
19842
|
+
var parseWireMapping = function(id, data) {
|
|
19843
|
+
const { format, target } = splitMappingId(id);
|
|
19844
|
+
const out = {
|
|
19845
|
+
id,
|
|
19846
|
+
format,
|
|
19847
|
+
target,
|
|
19848
|
+
element: "",
|
|
19849
|
+
namespaceRef: "",
|
|
19850
|
+
content: "",
|
|
19851
|
+
mixed: false,
|
|
19852
|
+
renderNil: null,
|
|
19853
|
+
entries: [],
|
|
19854
|
+
source: null
|
|
19855
|
+
};
|
|
19856
|
+
forEachEntry(
|
|
19857
|
+
data,
|
|
19858
|
+
(command, value, peek) => {
|
|
19859
|
+
if (command === "element") {
|
|
19860
|
+
out.element = stripWrapping(value());
|
|
19861
|
+
} else if (command === "namespace") {
|
|
19862
|
+
out.namespaceRef = stripWrapping(value());
|
|
19863
|
+
} else if (command === "mixed_content") {
|
|
19864
|
+
value();
|
|
19865
|
+
out.mixed = true;
|
|
19866
|
+
} else if (command === "render_nil") {
|
|
19867
|
+
out.renderNil = stripWrapping(value()) === "true";
|
|
19868
|
+
} else if (command === "map_content") {
|
|
19869
|
+
out.content = stripWrapping(value());
|
|
19870
|
+
} else if (command === "map_element" || command === "map_attribute" || command === "map") {
|
|
19871
|
+
const wire = stripWrapping(value());
|
|
19872
|
+
const name = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
19873
|
+
const kind = command === "map_element" ? "element" : command === "map_attribute" ? "attribute" : "map";
|
|
19874
|
+
out.entries.push({ kind, wire, name, modifier: "" });
|
|
19875
|
+
} else if (command === "map_key" || command === "map_value") {
|
|
19876
|
+
const modifier = stripWrapping(value());
|
|
19877
|
+
const name = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
19878
|
+
out.entries.push({ kind: "map", wire: command, name, modifier });
|
|
19879
|
+
} else {
|
|
19880
|
+
return false;
|
|
19881
|
+
}
|
|
19882
|
+
return true;
|
|
19883
|
+
},
|
|
19884
|
+
{ construct: "mapping", id }
|
|
19885
|
+
);
|
|
19886
|
+
return (ctx) => {
|
|
19887
|
+
ctx.wireMappings[id] = out;
|
|
19888
|
+
return ctx;
|
|
19889
|
+
};
|
|
19890
|
+
};
|
|
19891
|
+
var dumpWireMapping = function(w) {
|
|
19892
|
+
const lines = [`mapping ${w.format} ${w.target} {`];
|
|
19893
|
+
if (w.element) {
|
|
19894
|
+
lines.push(` element "${escapeString(w.element)}"`);
|
|
19895
|
+
}
|
|
19896
|
+
if (w.namespaceRef) {
|
|
19897
|
+
lines.push(` namespace ${w.namespaceRef}`);
|
|
19898
|
+
}
|
|
19899
|
+
for (const e of w.entries) {
|
|
19900
|
+
if (e.kind === "map" && e.modifier) {
|
|
19901
|
+
lines.push(` ${e.wire} ${e.modifier} ${e.name}`);
|
|
19902
|
+
} else {
|
|
19903
|
+
const kw = e.kind === "element" ? "map_element" : e.kind === "attribute" ? "map_attribute" : "map";
|
|
19904
|
+
lines.push(` ${kw} "${escapeString(e.wire)}" ${e.name}`);
|
|
19905
|
+
}
|
|
19906
|
+
}
|
|
19907
|
+
if (w.content) {
|
|
19908
|
+
lines.push(` map_content ${w.content}`);
|
|
19909
|
+
}
|
|
19910
|
+
if (w.mixed) {
|
|
19911
|
+
lines.push(` mixed_content`);
|
|
19912
|
+
}
|
|
19913
|
+
if (w.renderNil !== null) {
|
|
19914
|
+
lines.push(` render_nil ${w.renderNil}`);
|
|
19915
|
+
}
|
|
19916
|
+
lines.push("}");
|
|
19917
|
+
return lines.join("\n");
|
|
19918
|
+
};
|
|
19919
|
+
var parseStringFormat = function(rawId, data) {
|
|
19920
|
+
if (!rawId.startsWith(":")) {
|
|
19921
|
+
throw new Error(
|
|
19922
|
+
`Parsing error: string_format. ID ${rawId}: the registered format name carries the colon sigil (string_format :${rawId})`
|
|
19923
|
+
);
|
|
19924
|
+
}
|
|
19925
|
+
const id = rawId.slice(1);
|
|
19926
|
+
const out = { id, artifact: "", root: "", source: null };
|
|
19927
|
+
forEachEntry(
|
|
19928
|
+
data,
|
|
19929
|
+
(command, value) => {
|
|
19930
|
+
if (command === "artifact") {
|
|
19931
|
+
out.artifact = stripWrapping(value());
|
|
19932
|
+
} else if (command === "root") {
|
|
19933
|
+
out.root = stripWrapping(value());
|
|
19934
|
+
} else {
|
|
19935
|
+
return false;
|
|
19936
|
+
}
|
|
19937
|
+
return true;
|
|
19938
|
+
},
|
|
19939
|
+
{ construct: "string_format", id }
|
|
19940
|
+
);
|
|
19941
|
+
return (ctx) => {
|
|
19942
|
+
ctx.stringFormats[id] = out;
|
|
19943
|
+
return ctx;
|
|
19944
|
+
};
|
|
19945
|
+
};
|
|
19946
|
+
var dumpStringFormat = function(f) {
|
|
19947
|
+
return [
|
|
19948
|
+
`string_format :${f.id} {`,
|
|
19949
|
+
` artifact "${escapeString(f.artifact)}"`,
|
|
19950
|
+
` root "${escapeString(f.root)}"`,
|
|
19951
|
+
"}"
|
|
19952
|
+
].join("\n");
|
|
19953
|
+
};
|
|
19954
|
+
var parseNamespace = function(id, data) {
|
|
19955
|
+
const out = {
|
|
19956
|
+
id,
|
|
19957
|
+
uri: "",
|
|
19958
|
+
prefix: "",
|
|
19959
|
+
isDefault: false,
|
|
19960
|
+
source: null
|
|
19961
|
+
};
|
|
19962
|
+
forEachEntry(
|
|
19963
|
+
data,
|
|
19964
|
+
(command, value) => {
|
|
19965
|
+
if (command === "uri") {
|
|
19966
|
+
out.uri = stripWrapping(value());
|
|
19967
|
+
} else if (command === "prefix") {
|
|
19968
|
+
out.prefix = stripWrapping(value());
|
|
19969
|
+
} else if (command === "default") {
|
|
19970
|
+
value();
|
|
19971
|
+
out.isDefault = true;
|
|
19972
|
+
} else {
|
|
19973
|
+
return false;
|
|
19974
|
+
}
|
|
19975
|
+
return true;
|
|
19976
|
+
},
|
|
19977
|
+
{ construct: "namespace", id }
|
|
19978
|
+
);
|
|
19979
|
+
return (ctx) => {
|
|
19980
|
+
ctx.namespaces[id] = out;
|
|
19981
|
+
return ctx;
|
|
19982
|
+
};
|
|
19983
|
+
};
|
|
19984
|
+
var dumpNamespace = function(d) {
|
|
19985
|
+
const lines = [`namespace ${d.id} {`, ` uri "${escapeString(d.uri)}"`];
|
|
19986
|
+
if (d.prefix) {
|
|
19987
|
+
lines.push(` prefix "${escapeString(d.prefix)}"`);
|
|
19988
|
+
}
|
|
19989
|
+
if (d.isDefault) {
|
|
19990
|
+
lines.push(` default`);
|
|
19991
|
+
}
|
|
19992
|
+
lines.push("}");
|
|
19993
|
+
return lines.join("\n");
|
|
19994
|
+
};
|
|
19995
|
+
var parseDatum = function(id, raw) {
|
|
19996
|
+
const data = raw.replace(/^\s*:\s*\S+\s*/, "");
|
|
19997
|
+
const out = {
|
|
19998
|
+
id,
|
|
19999
|
+
type: "",
|
|
20000
|
+
unit: "",
|
|
20001
|
+
quantityKind: "",
|
|
20002
|
+
origin: "declared",
|
|
20003
|
+
scope: "",
|
|
20004
|
+
renders: [],
|
|
20005
|
+
label: "",
|
|
20006
|
+
description: "",
|
|
20007
|
+
source: null
|
|
20008
|
+
};
|
|
20009
|
+
forEachEntry(
|
|
20010
|
+
data,
|
|
20011
|
+
(command, value, peek) => {
|
|
20012
|
+
if (command === "render") {
|
|
20013
|
+
const notation = stripWrapping(value());
|
|
20014
|
+
const text = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
20015
|
+
if (MATH_NOTATIONS.includes(notation)) {
|
|
20016
|
+
out.renders.push({ notation, text });
|
|
20017
|
+
}
|
|
20018
|
+
} else if (command === "label") {
|
|
20019
|
+
out.label = stripWrapping(value());
|
|
20020
|
+
} else if (command === "description") {
|
|
20021
|
+
const v = value();
|
|
20022
|
+
out.description = v.startsWith("{") ? unwrapBlock(v) : stripWrapping(v);
|
|
20023
|
+
} else if (command === "unit") {
|
|
20024
|
+
out.unit = stripWrapping(value());
|
|
20025
|
+
} else if (command === "quantity_kind") {
|
|
20026
|
+
out.quantityKind = stripWrapping(value());
|
|
20027
|
+
} else if (command === "origin") {
|
|
20028
|
+
const o = stripWrapping(value());
|
|
20029
|
+
if (["declared", "design-fixed", "observed", "computed"].includes(o)) {
|
|
20030
|
+
out.origin = o;
|
|
20031
|
+
}
|
|
20032
|
+
} else if (command === "scope") {
|
|
20033
|
+
out.scope = stripWrapping(value());
|
|
20034
|
+
} else {
|
|
20035
|
+
return false;
|
|
20036
|
+
}
|
|
20037
|
+
return true;
|
|
20038
|
+
},
|
|
20039
|
+
{ construct: "datum", id }
|
|
20040
|
+
);
|
|
20041
|
+
return (ctx) => {
|
|
20042
|
+
ctx.datums[id] = out;
|
|
20043
|
+
return ctx;
|
|
20044
|
+
};
|
|
20045
|
+
};
|
|
20046
|
+
var dumpDatum = function(x) {
|
|
20047
|
+
const lines = [`datum ${x.id}${x.type ? ` : ${x.type}` : ""} {`];
|
|
20048
|
+
if (x.quantityKind) {
|
|
20049
|
+
lines.push(` quantity_kind ${x.quantityKind}`);
|
|
20050
|
+
}
|
|
20051
|
+
if (x.unit) {
|
|
20052
|
+
lines.push(` unit ${x.unit}`);
|
|
20053
|
+
}
|
|
20054
|
+
if (x.origin !== "declared") {
|
|
20055
|
+
lines.push(` origin ${x.origin}`);
|
|
20056
|
+
}
|
|
20057
|
+
if (x.scope) {
|
|
20058
|
+
lines.push(` scope ${x.scope}`);
|
|
20059
|
+
}
|
|
20060
|
+
for (const r of x.renders) {
|
|
20061
|
+
lines.push(` render ${r.notation} "${escapeString(r.text)}"`);
|
|
20062
|
+
}
|
|
20063
|
+
if (x.label) {
|
|
20064
|
+
lines.push(` label "${escapeString(x.label)}"`);
|
|
20065
|
+
}
|
|
20066
|
+
if (x.description) {
|
|
20067
|
+
lines.push(` description { ${x.description} }`);
|
|
20068
|
+
}
|
|
20069
|
+
lines.push("}");
|
|
20070
|
+
return lines.join("\n");
|
|
20071
|
+
};
|
|
20072
|
+
var parseCheck = function(id, data) {
|
|
20073
|
+
const out = {
|
|
20074
|
+
id,
|
|
20075
|
+
inputs: [],
|
|
20076
|
+
expression: "",
|
|
20077
|
+
operator: "",
|
|
20078
|
+
threshold: "",
|
|
20079
|
+
source: null
|
|
20080
|
+
};
|
|
20081
|
+
forEachEntry(
|
|
20082
|
+
data,
|
|
20083
|
+
(command, value, peek) => {
|
|
20084
|
+
if (command === "inputs") {
|
|
20085
|
+
const block = value();
|
|
20086
|
+
const inner = block.startsWith("{") ? tokenizePackage(unwrapBlock(block)) : [];
|
|
20087
|
+
out.inputs = inner.map((x) => stripWrapping(x));
|
|
20088
|
+
} else if (command === "expression") {
|
|
20089
|
+
out.expression = stripWrapping(value());
|
|
20090
|
+
} else if (command === "operator") {
|
|
20091
|
+
out.operator = stripWrapping(value());
|
|
20092
|
+
} else if (command === "threshold") {
|
|
20093
|
+
const v = value();
|
|
20094
|
+
out.threshold = v.startsWith("{") ? unwrapBlock(v) : stripWrapping(v);
|
|
20095
|
+
} else {
|
|
20096
|
+
return false;
|
|
20097
|
+
}
|
|
20098
|
+
void peek;
|
|
20099
|
+
return true;
|
|
20100
|
+
},
|
|
20101
|
+
{ construct: "check", id }
|
|
20102
|
+
);
|
|
20103
|
+
return (ctx) => {
|
|
20104
|
+
ctx.checks[id] = out;
|
|
20105
|
+
return ctx;
|
|
20106
|
+
};
|
|
20107
|
+
};
|
|
20108
|
+
var dumpCheck = function(x) {
|
|
20109
|
+
const lines = [`check ${x.id} {`];
|
|
20110
|
+
if (x.inputs.length) {
|
|
20111
|
+
lines.push(` inputs { ${x.inputs.join(" ")} }`);
|
|
20112
|
+
}
|
|
20113
|
+
if (x.expression) {
|
|
20114
|
+
lines.push(` expression "${escapeString(x.expression)}"`);
|
|
20115
|
+
}
|
|
20116
|
+
if (x.operator) {
|
|
20117
|
+
lines.push(` operator ${x.operator}`);
|
|
20118
|
+
}
|
|
20119
|
+
if (x.threshold) {
|
|
20120
|
+
lines.push(` threshold ${x.threshold}`);
|
|
20121
|
+
}
|
|
20122
|
+
lines.push("}");
|
|
20123
|
+
return lines.join("\n");
|
|
20124
|
+
};
|
|
20125
|
+
|
|
18878
20126
|
// src/ser-des/config/index.ts
|
|
18879
20127
|
function defineConstruct(def) {
|
|
18880
20128
|
return def;
|
|
@@ -19250,6 +20498,14 @@ var CONSTRUCTS = [
|
|
|
19250
20498
|
parse: parseConstraint,
|
|
19251
20499
|
dump: dumpConstraint
|
|
19252
20500
|
}),
|
|
20501
|
+
// The uncertainty budgets (register W5 — the GUM plane's language side)
|
|
20502
|
+
defineConstruct({
|
|
20503
|
+
keyword: "uncertainty_budget",
|
|
20504
|
+
field: "uncertaintyBudgets",
|
|
20505
|
+
takesID: true,
|
|
20506
|
+
parse: parseUncertaintyBudget,
|
|
20507
|
+
dump: dumpUncertaintyBudget
|
|
20508
|
+
}),
|
|
19253
20509
|
// Corpus-level source-discrepancy records (TODO.roadmap/54 — gap 13's
|
|
19254
20510
|
// corpus-level extension of the source_discrepancy facet)
|
|
19255
20511
|
defineConstruct({
|
|
@@ -19538,7 +20794,45 @@ var CONSTRUCTS = [
|
|
|
19538
20794
|
// Primmel v3.2 consumption constructs (TODO.primmel/11; MN 114 clause
|
|
19539
20795
|
// 10.6): the top-level applicability dimension (one grammar with the
|
|
19540
20796
|
// instrument's inline dimension blocks, two placements).
|
|
19541
|
-
dimensionConstruct
|
|
20797
|
+
dimensionConstruct,
|
|
20798
|
+
// ── the LML-aligned substrate (TODO.lang-gaps; Annex F) ─────────
|
|
20799
|
+
defineConstruct({
|
|
20800
|
+
keyword: "mapping",
|
|
20801
|
+
field: "wireMappings",
|
|
20802
|
+
takesID: true,
|
|
20803
|
+
takesFormat: true,
|
|
20804
|
+
parse: parseWireMapping,
|
|
20805
|
+
dump: dumpWireMapping
|
|
20806
|
+
}),
|
|
20807
|
+
defineConstruct({
|
|
20808
|
+
keyword: "string_format",
|
|
20809
|
+
field: "stringFormats",
|
|
20810
|
+
takesID: true,
|
|
20811
|
+
parse: parseStringFormat,
|
|
20812
|
+
dump: dumpStringFormat
|
|
20813
|
+
}),
|
|
20814
|
+
defineConstruct({
|
|
20815
|
+
keyword: "namespace",
|
|
20816
|
+
field: "namespaces",
|
|
20817
|
+
takesID: true,
|
|
20818
|
+
parse: parseNamespace,
|
|
20819
|
+
dump: dumpNamespace
|
|
20820
|
+
}),
|
|
20821
|
+
defineConstruct({
|
|
20822
|
+
keyword: "datum",
|
|
20823
|
+
field: "datums",
|
|
20824
|
+
takesID: true,
|
|
20825
|
+
optionalTypedId: true,
|
|
20826
|
+
parse: parseDatum,
|
|
20827
|
+
dump: dumpDatum
|
|
20828
|
+
}),
|
|
20829
|
+
defineConstruct({
|
|
20830
|
+
keyword: "check",
|
|
20831
|
+
field: "checks",
|
|
20832
|
+
takesID: true,
|
|
20833
|
+
parse: parseCheck,
|
|
20834
|
+
dump: dumpCheck
|
|
20835
|
+
})
|
|
19542
20836
|
];
|
|
19543
20837
|
function buildParserConfig(constructs) {
|
|
19544
20838
|
const out = {};
|
|
@@ -19548,6 +20842,8 @@ function buildParserConfig(constructs) {
|
|
|
19548
20842
|
}
|
|
19549
20843
|
const entry = {
|
|
19550
20844
|
takesID: c.takesID,
|
|
20845
|
+
takesFormat: c.takesFormat,
|
|
20846
|
+
optionalTypedId: c.optionalTypedId,
|
|
19551
20847
|
parse: c.parse,
|
|
19552
20848
|
field: c.field,
|
|
19553
20849
|
...c.deprecated ? { deprecated: c.deprecated } : {}
|
|
@@ -19774,6 +21070,9 @@ function loadPackageInternal(dir, options = {}, withProvenance = false) {
|
|
|
19774
21070
|
return composePackage(dir, options, manifest, withProvenance);
|
|
19775
21071
|
}
|
|
19776
21072
|
const parseOptions = withProvenance ? { ...options, withProvenance: true } : options;
|
|
21073
|
+
if (manifest?.language) {
|
|
21074
|
+
parseOptions.strict = true;
|
|
21075
|
+
}
|
|
19777
21076
|
const ctx = parse(joinChunks(chunks), PARSER_CONFIG, parseOptions);
|
|
19778
21077
|
if (manifest) {
|
|
19779
21078
|
ctx.packageManifest = manifest;
|
|
@@ -19857,6 +21156,11 @@ var MERGE_FIELDS = [
|
|
|
19857
21156
|
"calculations",
|
|
19858
21157
|
"verdicts",
|
|
19859
21158
|
"referenceMaterials",
|
|
21159
|
+
"wireMappings",
|
|
21160
|
+
"stringFormats",
|
|
21161
|
+
"namespaces",
|
|
21162
|
+
"datums",
|
|
21163
|
+
"checks",
|
|
19860
21164
|
"testPointSets",
|
|
19861
21165
|
"commonTestConditions",
|
|
19862
21166
|
"competenceKinds",
|
|
@@ -19866,6 +21170,7 @@ var MERGE_FIELDS = [
|
|
|
19866
21170
|
"schemeActivityKinds",
|
|
19867
21171
|
"schemeTypes",
|
|
19868
21172
|
"constraints",
|
|
21173
|
+
"uncertaintyBudgets",
|
|
19869
21174
|
"discrepancyRecords",
|
|
19870
21175
|
"stateMachines",
|
|
19871
21176
|
"conformanceTests",
|
|
@@ -20097,7 +21402,12 @@ function composePackage(rootDir, options, rootManifest, withProvenance = false)
|
|
|
20097
21402
|
const ctxs = /* @__PURE__ */ new Map();
|
|
20098
21403
|
const pkgChunks = /* @__PURE__ */ new Map();
|
|
20099
21404
|
for (const id of order) {
|
|
20100
|
-
const
|
|
21405
|
+
const pkgOptions = { ...parseOptions };
|
|
21406
|
+
const pkgManifest = manifests.get(id);
|
|
21407
|
+
if (pkgManifest?.language) {
|
|
21408
|
+
pkgOptions.strict = true;
|
|
21409
|
+
}
|
|
21410
|
+
const parsed = parsePackageContent(dirs.get(id), pkgOptions);
|
|
20101
21411
|
ctxs.set(id, parsed.ctx);
|
|
20102
21412
|
pkgChunks.set(id, parsed.chunks);
|
|
20103
21413
|
}
|
|
@@ -20196,7 +21506,21 @@ function composePackage(rootDir, options, rootManifest, withProvenance = false)
|
|
|
20196
21506
|
for (const id of order) {
|
|
20197
21507
|
const m = manifests.get(id);
|
|
20198
21508
|
for (const req of m.requires ?? []) {
|
|
20199
|
-
const
|
|
21509
|
+
const at = req.indexOf(":");
|
|
21510
|
+
const scoped = at > 0 ? { pkg: req.slice(0, at), token: req.slice(at + 1) } : null;
|
|
21511
|
+
let scopedProvides = null;
|
|
21512
|
+
if (scoped && !order.includes(scoped.pkg)) {
|
|
21513
|
+
try {
|
|
21514
|
+
const dir = locate(scoped.pkg);
|
|
21515
|
+
if (dir) {
|
|
21516
|
+
const rm = readPackageManifest(dir);
|
|
21517
|
+
scopedProvides = rm.provides ?? [];
|
|
21518
|
+
manifests.set(scoped.pkg, rm);
|
|
21519
|
+
}
|
|
21520
|
+
} catch {
|
|
21521
|
+
}
|
|
21522
|
+
}
|
|
21523
|
+
const satisfied = scoped ? order.includes(scoped.pkg) ? (manifests.get(scoped.pkg).provides ?? []).includes(scoped.token) : (scopedProvides ?? []).includes(scoped.token) : order.some(
|
|
20200
21524
|
(other) => other !== id && (other === req || (manifests.get(other).provides ?? []).includes(req))
|
|
20201
21525
|
);
|
|
20202
21526
|
if (!satisfied) {
|
|
@@ -22005,6 +23329,176 @@ var CHECK_RULES = [
|
|
|
22005
23329
|
"normal",
|
|
22006
23330
|
"the MMEL v2 validation parity (the rename contract \u2014 TODO.editor/41)"
|
|
22007
23331
|
),
|
|
23332
|
+
// ── the LML-aligned substrate (TODO.lang-gaps; the spec's validation
|
|
23333
|
+
// contract, language-v3 §16) ── The five constructs (mapping /
|
|
23334
|
+
// string_format / namespace / datum / check) carry their declared
|
|
23335
|
+
// data; the checker does the discipline. C163 is the release
|
|
23336
|
+
// classification contract — it runs over `primmel diff --exit-code`
|
|
23337
|
+
// (the existing diff classifier, src/model-diff.ts), so its catalog
|
|
23338
|
+
// entry documents the contract the CLI already enforces; no second
|
|
23339
|
+
// implementation lives here. C165/C166 are RESERVED for the
|
|
23340
|
+
// calculation math plane (the formula identifier bindings and the
|
|
23341
|
+
// Plurimath-conformant parse) — catalogued, not faked.
|
|
23342
|
+
R(
|
|
23343
|
+
"C158",
|
|
23344
|
+
"prose-quarantine",
|
|
23345
|
+
"base",
|
|
23346
|
+
"error",
|
|
23347
|
+
"normal",
|
|
23348
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23349
|
+
),
|
|
23350
|
+
R(
|
|
23351
|
+
"C159",
|
|
23352
|
+
"urn-only-refs",
|
|
23353
|
+
"base",
|
|
23354
|
+
"error",
|
|
23355
|
+
"normal",
|
|
23356
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23357
|
+
),
|
|
23358
|
+
R(
|
|
23359
|
+
"C160",
|
|
23360
|
+
"signature-closure",
|
|
23361
|
+
"base",
|
|
23362
|
+
"error",
|
|
23363
|
+
"normal",
|
|
23364
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23365
|
+
),
|
|
23366
|
+
R(
|
|
23367
|
+
"C161",
|
|
23368
|
+
"check-surface",
|
|
23369
|
+
"base",
|
|
23370
|
+
"error",
|
|
23371
|
+
"normal",
|
|
23372
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23373
|
+
),
|
|
23374
|
+
R(
|
|
23375
|
+
"C162",
|
|
23376
|
+
"namespace-coherence",
|
|
23377
|
+
"base",
|
|
23378
|
+
"error",
|
|
23379
|
+
"normal",
|
|
23380
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23381
|
+
),
|
|
23382
|
+
R(
|
|
23383
|
+
"C163",
|
|
23384
|
+
"change-levels",
|
|
23385
|
+
"base",
|
|
23386
|
+
"error",
|
|
23387
|
+
"normal",
|
|
23388
|
+
"the LML-aligned validation contract (language-v3 \xA716) \u2014 runs over `primmel diff --exit-code` (src/model-diff.ts, the diff classifier)"
|
|
23389
|
+
),
|
|
23390
|
+
R(
|
|
23391
|
+
"C164",
|
|
23392
|
+
"wire-mapping-coverage",
|
|
23393
|
+
"base",
|
|
23394
|
+
"error",
|
|
23395
|
+
"normal",
|
|
23396
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23397
|
+
),
|
|
23398
|
+
R(
|
|
23399
|
+
"C165",
|
|
23400
|
+
"math-symbols-declared",
|
|
23401
|
+
"quantities",
|
|
23402
|
+
"warning",
|
|
23403
|
+
"normal",
|
|
23404
|
+
"RESERVED for the calculation math plane (language-v3 \xA716) \u2014 the formula identifier bindings"
|
|
23405
|
+
),
|
|
23406
|
+
R(
|
|
23407
|
+
"C166",
|
|
23408
|
+
"math-parses",
|
|
23409
|
+
"quantities",
|
|
23410
|
+
"warning",
|
|
23411
|
+
"normal",
|
|
23412
|
+
"RESERVED for the calculation math plane (language-v3 \xA716) \u2014 the Plurimath-conformant parse (plurimath-ts)"
|
|
23413
|
+
),
|
|
23414
|
+
R(
|
|
23415
|
+
"C167",
|
|
23416
|
+
"qualified-unit-reference",
|
|
23417
|
+
"quantities",
|
|
23418
|
+
"error",
|
|
23419
|
+
"normal",
|
|
23420
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23421
|
+
),
|
|
23422
|
+
R(
|
|
23423
|
+
"C168",
|
|
23424
|
+
"method-ref-resolves",
|
|
23425
|
+
"process",
|
|
23426
|
+
"error",
|
|
23427
|
+
"normal",
|
|
23428
|
+
"a conformance test method_ref names a process to be realized \u2014 bare in-package, or scoped <package>:<id> resolved read-only through the locator; never a bibliographic standard id"
|
|
23429
|
+
),
|
|
23430
|
+
R(
|
|
23431
|
+
"C169",
|
|
23432
|
+
"provenance-clause-resolves",
|
|
23433
|
+
"base",
|
|
23434
|
+
"error",
|
|
23435
|
+
"normal",
|
|
23436
|
+
"a provenance binding citing a shipped document lands on a real fragment or sentence of that document \u2014 nothing linked to air"
|
|
23437
|
+
),
|
|
23438
|
+
R(
|
|
23439
|
+
"C170",
|
|
23440
|
+
"edition-lineage-declared",
|
|
23441
|
+
"base",
|
|
23442
|
+
"error",
|
|
23443
|
+
"normal",
|
|
23444
|
+
"a package declaring more than one edition carries edition-mapping.json (primmel-edition-mapping/1) naming both edition states \u2014 the cross-edition linkage is an artifact, never implicit"
|
|
23445
|
+
),
|
|
23446
|
+
R(
|
|
23447
|
+
"C171",
|
|
23448
|
+
"expression-identifiers-resolve",
|
|
23449
|
+
"base",
|
|
23450
|
+
"error",
|
|
23451
|
+
"normal",
|
|
23452
|
+
"every identifier inside a limit expression, derivation, or derive resolves to a declared name in scope \u2014 the formula is the executable core, nothing in it is air"
|
|
23453
|
+
),
|
|
23454
|
+
R(
|
|
23455
|
+
"C172",
|
|
23456
|
+
"requirement-algebra-resolves",
|
|
23457
|
+
"base",
|
|
23458
|
+
"error",
|
|
23459
|
+
"normal",
|
|
23460
|
+
"containment is conjunction; a requirement class limit (the law) names its contained members with the OCL booleans \u2014 and/or/xor/implies \u2014 and every member appears in the law"
|
|
23461
|
+
),
|
|
23462
|
+
R(
|
|
23463
|
+
"C176",
|
|
23464
|
+
"language-declared-wellformed",
|
|
23465
|
+
"base",
|
|
23466
|
+
"error",
|
|
23467
|
+
"normal",
|
|
23468
|
+
"a declared language generation is well-formed (v<major>[.<minor>]); the declaration makes the package parse strictly \u2014 unknown keywords are errors"
|
|
23469
|
+
),
|
|
23470
|
+
R(
|
|
23471
|
+
"C179",
|
|
23472
|
+
"uncertainty-budget-resolves",
|
|
23473
|
+
"base",
|
|
23474
|
+
"error",
|
|
23475
|
+
"normal",
|
|
23476
|
+
"an uncertainty budget targets a declared verdict; a Type A component names a declared captured series, a Type B component states its distribution and half-width; the coverage factor is a positive number"
|
|
23477
|
+
),
|
|
23478
|
+
R(
|
|
23479
|
+
"C173",
|
|
23480
|
+
"step-plane-refs-resolve",
|
|
23481
|
+
"process",
|
|
23482
|
+
"error",
|
|
23483
|
+
"normal",
|
|
23484
|
+
"a signature step's completion is one expression over the step's own declared ios; the calls bindings resolve the callee's declared signature; the dot-descent process:step.io resolves to a declared io"
|
|
23485
|
+
),
|
|
23486
|
+
R(
|
|
23487
|
+
"C177",
|
|
23488
|
+
"kind-coherence",
|
|
23489
|
+
"base",
|
|
23490
|
+
"error",
|
|
23491
|
+
"normal",
|
|
23492
|
+
"a comparison in an inline expression sets operands of the same declared quantity kind \u2014 the kinds from the args' declared sources; unknown-kind and bare-number operands never conflict"
|
|
23493
|
+
),
|
|
23494
|
+
R(
|
|
23495
|
+
"C178",
|
|
23496
|
+
"legacy-carrier-deprecated",
|
|
23497
|
+
"base",
|
|
23498
|
+
"warning",
|
|
23499
|
+
"normal",
|
|
23500
|
+
"a package declaring the deprecation generation carries quoted ocl{\u2026} expression carriers \u2014 the inline blocks (expression { \u2026 }, derive { \u2026 }, derivation { \u2026 }, check { \u2026 }) are the only forward form"
|
|
23501
|
+
),
|
|
22008
23502
|
// ── mapping (TODO.roadmap/04) ─────────────────────────────────────
|
|
22009
23503
|
R(
|
|
22010
23504
|
"C21",
|
|
@@ -23488,6 +24982,22 @@ var EMPTY = {
|
|
|
23488
24982
|
textCoverageBudgetReason: null,
|
|
23489
24983
|
entries: []
|
|
23490
24984
|
};
|
|
24985
|
+
function issueElementId(message) {
|
|
24986
|
+
const m = message.match(/^[a-z_]+ ([^:\s][^:]*):/);
|
|
24987
|
+
return m ? m[1] : "";
|
|
24988
|
+
}
|
|
24989
|
+
function entryMatches(entry, issue) {
|
|
24990
|
+
if (issue.check !== entry.rule) {
|
|
24991
|
+
return false;
|
|
24992
|
+
}
|
|
24993
|
+
if (!globMatch(entry.match, issue.message)) {
|
|
24994
|
+
return false;
|
|
24995
|
+
}
|
|
24996
|
+
if (entry.id !== void 0) {
|
|
24997
|
+
return globMatch(entry.id, issueElementId(issue.message));
|
|
24998
|
+
}
|
|
24999
|
+
return true;
|
|
25000
|
+
}
|
|
23491
25001
|
function globMatch(glob, text) {
|
|
23492
25002
|
const re = new RegExp(
|
|
23493
25003
|
"^" + glob.split("*").map(escapeRegExp).join("[\\s\\S]*") + "$"
|
|
@@ -23587,6 +25097,8 @@ function parseEntry2(block) {
|
|
|
23587
25097
|
entry.rule = value;
|
|
23588
25098
|
} else if (key === "match") {
|
|
23589
25099
|
entry.match = value;
|
|
25100
|
+
} else if (key === "id") {
|
|
25101
|
+
entry.id = value;
|
|
23590
25102
|
} else if (key === "reason") {
|
|
23591
25103
|
entry.reason = value;
|
|
23592
25104
|
} else if (key === "audit_ref") {
|
|
@@ -23605,6 +25117,13 @@ function validateEntry(entry) {
|
|
|
23605
25117
|
message: `${ALLOWLIST_FILENAME}: entry${label} names ${entry.rule ? `unknown rule "${entry.rule}"` : "no rule"} \u2014 every allowlist entry names a real rule id (allowlist-malformed)`
|
|
23606
25118
|
});
|
|
23607
25119
|
}
|
|
25120
|
+
if (entry.id !== void 0 && entry.id === "") {
|
|
25121
|
+
issues.push({
|
|
25122
|
+
check: "C56",
|
|
25123
|
+
severity: "error",
|
|
25124
|
+
message: `${ALLOWLIST_FILENAME}: entry for rule "${entry.rule}" has an empty id glob \u2014 the structured key pins the element identity or is absent (allowlist-malformed)`
|
|
25125
|
+
});
|
|
25126
|
+
}
|
|
23608
25127
|
if (!entry.match) {
|
|
23609
25128
|
issues.push({
|
|
23610
25129
|
check: "C56",
|
|
@@ -23640,7 +25159,7 @@ function applyAllowlist(issues, allowlist, activeRules) {
|
|
|
23640
25159
|
}
|
|
23641
25160
|
let matched = false;
|
|
23642
25161
|
for (const issue of out) {
|
|
23643
|
-
if (
|
|
25162
|
+
if (entryMatches(entry, issue)) {
|
|
23644
25163
|
issue.known = true;
|
|
23645
25164
|
matched = true;
|
|
23646
25165
|
}
|
|
@@ -23705,7 +25224,7 @@ function applyProviderAllowlists(issues, providers, activeRules) {
|
|
|
23705
25224
|
}
|
|
23706
25225
|
let matched = false;
|
|
23707
25226
|
for (const issue of out) {
|
|
23708
|
-
if (!issue.known &&
|
|
25227
|
+
if (!issue.known && entryMatches(entry, issue)) {
|
|
23709
25228
|
issue.known = true;
|
|
23710
25229
|
matched = true;
|
|
23711
25230
|
}
|
|
@@ -24044,6 +25563,40 @@ function computeTextCoverage(standard, manifests, config) {
|
|
|
24044
25563
|
}
|
|
24045
25564
|
const documents = [];
|
|
24046
25565
|
const matchedAllowanceSentences = /* @__PURE__ */ new Map();
|
|
25566
|
+
for (const manifest of manifests) {
|
|
25567
|
+
const urn = manifest.document.urn;
|
|
25568
|
+
const fragments = /* @__PURE__ */ new Set();
|
|
25569
|
+
const addresses = /* @__PURE__ */ new Set();
|
|
25570
|
+
for (const s of manifest.sentences) {
|
|
25571
|
+
fragments.add(s.fragment);
|
|
25572
|
+
addresses.add(s.address);
|
|
25573
|
+
}
|
|
25574
|
+
for (const b of bindings) {
|
|
25575
|
+
if (b.doc !== urn) {
|
|
25576
|
+
continue;
|
|
25577
|
+
}
|
|
25578
|
+
if (fragments.has(b.fragmentPath) || addresses.has(b.fragmentPath)) {
|
|
25579
|
+
continue;
|
|
25580
|
+
}
|
|
25581
|
+
const prefix = b.fragmentPath + ".";
|
|
25582
|
+
let resolved = false;
|
|
25583
|
+
for (const f of fragments) {
|
|
25584
|
+
if (f.startsWith(prefix) || b.fragmentPath.startsWith(f + "/")) {
|
|
25585
|
+
resolved = true;
|
|
25586
|
+
break;
|
|
25587
|
+
}
|
|
25588
|
+
}
|
|
25589
|
+
if (resolved) {
|
|
25590
|
+
continue;
|
|
25591
|
+
}
|
|
25592
|
+
const subpart = /^(table|figure|annex)-/.test(b.fragmentPath);
|
|
25593
|
+
configIssues.push({
|
|
25594
|
+
check: "C169",
|
|
25595
|
+
severity: subpart ? "warning" : "error",
|
|
25596
|
+
message: `provenance binding ${b.doc}#${b.fragmentPath} (${b.element}, ${b.kind}) names no fragment or sentence of the shipped document \u2014 ${subpart ? "a bare subpart citation the clause-only harvest cannot verify" : "linked to air"} (provenance-clause-resolves)`
|
|
25597
|
+
});
|
|
25598
|
+
}
|
|
25599
|
+
}
|
|
24047
25600
|
for (const manifest of manifests) {
|
|
24048
25601
|
const urn = manifest.document.urn;
|
|
24049
25602
|
const sentences = manifest.sentences;
|
|
@@ -24442,6 +25995,7 @@ function checkPackage(dir, options = {}) {
|
|
|
24442
25995
|
issues.push(...checkDimensions(standard));
|
|
24443
25996
|
issues.push(...checkReferences(standard));
|
|
24444
25997
|
issues.push(...checkVerdictChains(standard));
|
|
25998
|
+
issues.push(...checkLmlAligned(standard));
|
|
24445
25999
|
issues.push(...checkClosedDerivations(standard));
|
|
24446
26000
|
issues.push(...checkAttestations(standard));
|
|
24447
26001
|
issues.push(...checkTypedPayloads(standard));
|
|
@@ -24526,9 +26080,12 @@ function checkPackage(dir, options = {}) {
|
|
|
24526
26080
|
};
|
|
24527
26081
|
(form.fields ?? []).forEach(checkField);
|
|
24528
26082
|
}
|
|
26083
|
+
const classIds = new Set(
|
|
26084
|
+
(standard.requirementClasses ?? []).map((rc) => rc.id)
|
|
26085
|
+
);
|
|
24529
26086
|
for (const t of standard.conformanceTests ?? []) {
|
|
24530
26087
|
for (const target of t.targets ?? []) {
|
|
24531
|
-
if (!reqIds.has(target)) {
|
|
26088
|
+
if (!reqIds.has(target) && !classIds.has(target)) {
|
|
24532
26089
|
err(
|
|
24533
26090
|
"C2",
|
|
24534
26091
|
`conformance test ${t.id}: target "${target}" is not a declared requirement`
|
|
@@ -24685,9 +26242,19 @@ function checkPackage(dir, options = {}) {
|
|
|
24685
26242
|
}
|
|
24686
26243
|
}
|
|
24687
26244
|
const covered = /* @__PURE__ */ new Set();
|
|
26245
|
+
const classMembers = /* @__PURE__ */ new Map();
|
|
26246
|
+
for (const rc of standard.requirementClasses ?? []) {
|
|
26247
|
+
classMembers.set(rc.id, rc.members ?? []);
|
|
26248
|
+
}
|
|
26249
|
+
const coverWithMembers = (id) => {
|
|
26250
|
+
covered.add(id);
|
|
26251
|
+
for (const m of classMembers.get(id) ?? []) {
|
|
26252
|
+
covered.add(m);
|
|
26253
|
+
}
|
|
26254
|
+
};
|
|
24688
26255
|
for (const t of standard.conformanceTests ?? []) {
|
|
24689
26256
|
for (const target of t.targets ?? []) {
|
|
24690
|
-
|
|
26257
|
+
coverWithMembers(target);
|
|
24691
26258
|
}
|
|
24692
26259
|
}
|
|
24693
26260
|
const provisioned = /* @__PURE__ */ new Set();
|
|
@@ -24726,6 +26293,989 @@ function checkPackage(dir, options = {}) {
|
|
|
24726
26293
|
warn("C5", `conformance test ${t.id}: targets no requirement`);
|
|
24727
26294
|
}
|
|
24728
26295
|
}
|
|
26296
|
+
const OCL_WORDS = /* @__PURE__ */ new Set([
|
|
26297
|
+
"and",
|
|
26298
|
+
"or",
|
|
26299
|
+
"not",
|
|
26300
|
+
"xor",
|
|
26301
|
+
"implies",
|
|
26302
|
+
"if",
|
|
26303
|
+
"then",
|
|
26304
|
+
"else",
|
|
26305
|
+
"endif",
|
|
26306
|
+
"true",
|
|
26307
|
+
"false",
|
|
26308
|
+
"null",
|
|
26309
|
+
"invalid",
|
|
26310
|
+
"abs",
|
|
26311
|
+
"max",
|
|
26312
|
+
"min",
|
|
26313
|
+
"floor",
|
|
26314
|
+
"ceil",
|
|
26315
|
+
"mod",
|
|
26316
|
+
"div",
|
|
26317
|
+
"round",
|
|
26318
|
+
"sqrt",
|
|
26319
|
+
"exp",
|
|
26320
|
+
"ln",
|
|
26321
|
+
"log",
|
|
26322
|
+
"sum",
|
|
26323
|
+
"count",
|
|
26324
|
+
"exists",
|
|
26325
|
+
"forall",
|
|
26326
|
+
"oclIsUndefined",
|
|
26327
|
+
"oclIsKindOf",
|
|
26328
|
+
"oclIsTypeOf",
|
|
26329
|
+
"String",
|
|
26330
|
+
"Integer",
|
|
26331
|
+
"Real",
|
|
26332
|
+
"Boolean",
|
|
26333
|
+
"Set",
|
|
26334
|
+
"Bag",
|
|
26335
|
+
"Sequence",
|
|
26336
|
+
"Collection",
|
|
26337
|
+
// the subject-chain roots: every expression reads the dispatch
|
|
26338
|
+
// context through them — context, never air
|
|
26339
|
+
"sample",
|
|
26340
|
+
"family",
|
|
26341
|
+
"group",
|
|
26342
|
+
"model",
|
|
26343
|
+
"instrument",
|
|
26344
|
+
"specimen",
|
|
26345
|
+
"max_of",
|
|
26346
|
+
"min_of",
|
|
26347
|
+
"mean_of",
|
|
26348
|
+
"stddev_of",
|
|
26349
|
+
"count_of"
|
|
26350
|
+
]);
|
|
26351
|
+
const globalExprNames = new Set(
|
|
26352
|
+
[
|
|
26353
|
+
...(standard.symbols ?? []).map((s) => s.id),
|
|
26354
|
+
...(standard.symbols ?? []).map((s) => s.id.split("/").pop() ?? ""),
|
|
26355
|
+
...(standard.datums ?? []).map((d) => d.id),
|
|
26356
|
+
...(standard.verdicts ?? []).map((v) => v.id),
|
|
26357
|
+
// the lookup tables: a dotted helper call's OBJECT is declared here —
|
|
26358
|
+
// the method name rides the declared object
|
|
26359
|
+
...(standard.tables ?? []).map((v) => v.id),
|
|
26360
|
+
// the subject anatomy: a declared attribute is a declaration
|
|
26361
|
+
...(standard.attributeDefinitions ?? []).map((a) => a.id),
|
|
26362
|
+
...(standard.attributeDefinitions ?? []).map(
|
|
26363
|
+
(a) => a.id.split("/").pop() ?? ""
|
|
26364
|
+
),
|
|
26365
|
+
// the calculations: a derivation may call a declared calculation
|
|
26366
|
+
// (twin-cert's lookupMPE) — the callable registry
|
|
26367
|
+
...(standard.calculations ?? []).map((c) => c.id),
|
|
26368
|
+
...(standard.calculations ?? []).map((c) => c.id.split("/").pop() ?? "")
|
|
26369
|
+
].filter((x) => x !== "")
|
|
26370
|
+
);
|
|
26371
|
+
const symbolKinds = /* @__PURE__ */ new Map();
|
|
26372
|
+
for (const s of standard.symbols ?? []) {
|
|
26373
|
+
if (s.quantityKind) {
|
|
26374
|
+
symbolKinds.set(s.id, s.quantityKind);
|
|
26375
|
+
symbolKinds.set(s.id.split("/").pop() ?? "", s.quantityKind);
|
|
26376
|
+
}
|
|
26377
|
+
}
|
|
26378
|
+
const attributeKinds = /* @__PURE__ */ new Map();
|
|
26379
|
+
for (const a of standard.attributeDefinitions ?? []) {
|
|
26380
|
+
if (a.quantityKind) {
|
|
26381
|
+
attributeKinds.set(a.id, a.quantityKind);
|
|
26382
|
+
attributeKinds.set(
|
|
26383
|
+
a.id.split("/").pop() ?? "",
|
|
26384
|
+
a.quantityKind
|
|
26385
|
+
);
|
|
26386
|
+
}
|
|
26387
|
+
}
|
|
26388
|
+
const verdictKinds = /* @__PURE__ */ new Map();
|
|
26389
|
+
for (const v of standard.verdicts ?? []) {
|
|
26390
|
+
if (v.quantityKind) {
|
|
26391
|
+
verdictKinds.set(v.id, v.quantityKind);
|
|
26392
|
+
}
|
|
26393
|
+
}
|
|
26394
|
+
const tableColumnTypes = /* @__PURE__ */ new Map();
|
|
26395
|
+
for (const t of standard.tables ?? []) {
|
|
26396
|
+
const cols = /* @__PURE__ */ new Map();
|
|
26397
|
+
for (const c of t.columnDefs ?? []) {
|
|
26398
|
+
cols.set(c.name, (c.type || "").toLowerCase());
|
|
26399
|
+
}
|
|
26400
|
+
if (cols.size > 0) {
|
|
26401
|
+
tableColumnTypes.set(t.id, cols);
|
|
26402
|
+
}
|
|
26403
|
+
}
|
|
26404
|
+
const bare = (q) => q.split(":").pop() ?? q;
|
|
26405
|
+
const usesCovers = (uses, id) => uses.some((u) => {
|
|
26406
|
+
const tail = bare(u.replace(/\./g, ":"));
|
|
26407
|
+
return u === id || tail === id || u.endsWith("." + id);
|
|
26408
|
+
});
|
|
26409
|
+
const exprIds = (expr) => {
|
|
26410
|
+
const paths = expr.match(/[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*/g) ?? [];
|
|
26411
|
+
const out = [];
|
|
26412
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26413
|
+
for (const p of paths) {
|
|
26414
|
+
if (p.includes(".")) {
|
|
26415
|
+
const segs = p.split(".");
|
|
26416
|
+
if (globalExprNames.has(segs[0])) {
|
|
26417
|
+
continue;
|
|
26418
|
+
}
|
|
26419
|
+
const finalSeg = segs[segs.length - 1];
|
|
26420
|
+
if (!seen.has(p)) {
|
|
26421
|
+
seen.add(p);
|
|
26422
|
+
if (!OCL_WORDS.has(finalSeg)) {
|
|
26423
|
+
out.push(finalSeg);
|
|
26424
|
+
}
|
|
26425
|
+
}
|
|
26426
|
+
continue;
|
|
26427
|
+
}
|
|
26428
|
+
if (!OCL_WORDS.has(p) && !seen.has(p)) {
|
|
26429
|
+
seen.add(p);
|
|
26430
|
+
out.push(p);
|
|
26431
|
+
}
|
|
26432
|
+
}
|
|
26433
|
+
return out;
|
|
26434
|
+
};
|
|
26435
|
+
const unresolvedIn = (expr, scope, uses) => {
|
|
26436
|
+
const scopeSet = /* @__PURE__ */ new Set([...scope, ...globalExprNames]);
|
|
26437
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26438
|
+
const out = [];
|
|
26439
|
+
for (const id of exprIds(expr)) {
|
|
26440
|
+
if (seen.has(id)) {
|
|
26441
|
+
continue;
|
|
26442
|
+
}
|
|
26443
|
+
seen.add(id);
|
|
26444
|
+
if (OCL_WORDS.has(id) || scopeSet.has(id) || usesCovers(uses, id)) {
|
|
26445
|
+
continue;
|
|
26446
|
+
}
|
|
26447
|
+
out.push(id);
|
|
26448
|
+
}
|
|
26449
|
+
return out;
|
|
26450
|
+
};
|
|
26451
|
+
const mappedCalcIds = /* @__PURE__ */ new Set();
|
|
26452
|
+
{
|
|
26453
|
+
const mapsTo = standard.packageManifest?.mapsTo ?? [];
|
|
26454
|
+
for (const target of mapsTo) {
|
|
26455
|
+
if (!options.resolvePackage) {
|
|
26456
|
+
continue;
|
|
26457
|
+
}
|
|
26458
|
+
try {
|
|
26459
|
+
const depDir = options.resolvePackage(target);
|
|
26460
|
+
if (!depDir) {
|
|
26461
|
+
continue;
|
|
26462
|
+
}
|
|
26463
|
+
const dep = loadPackageWithIssues(depDir);
|
|
26464
|
+
for (const c of dep.standard?.calculations ?? []) {
|
|
26465
|
+
mappedCalcIds.add(c.id);
|
|
26466
|
+
mappedCalcIds.add(c.id.split("/").pop() ?? "");
|
|
26467
|
+
}
|
|
26468
|
+
} catch {
|
|
26469
|
+
}
|
|
26470
|
+
}
|
|
26471
|
+
for (const x of mappedCalcIds) {
|
|
26472
|
+
if (x !== "") {
|
|
26473
|
+
globalExprNames.add(x);
|
|
26474
|
+
}
|
|
26475
|
+
}
|
|
26476
|
+
}
|
|
26477
|
+
const INLINE_FUNCTION_WORDS = /* @__PURE__ */ new Set([
|
|
26478
|
+
"abs",
|
|
26479
|
+
"max",
|
|
26480
|
+
"min",
|
|
26481
|
+
"floor",
|
|
26482
|
+
"ceil",
|
|
26483
|
+
"round",
|
|
26484
|
+
"sqrt",
|
|
26485
|
+
"exp",
|
|
26486
|
+
"ln",
|
|
26487
|
+
"log",
|
|
26488
|
+
"mod",
|
|
26489
|
+
"sum",
|
|
26490
|
+
"count",
|
|
26491
|
+
"exists",
|
|
26492
|
+
"forall",
|
|
26493
|
+
// the series aggregations (register W4): the GUM type A vocabulary —
|
|
26494
|
+
// the statistics of a captured series; the evaluation is plurimath's
|
|
26495
|
+
"max_of",
|
|
26496
|
+
"min_of",
|
|
26497
|
+
"mean_of",
|
|
26498
|
+
"stddev_of",
|
|
26499
|
+
"count_of"
|
|
26500
|
+
]);
|
|
26501
|
+
const DECLARATION_KINDS = /* @__PURE__ */ new Set([
|
|
26502
|
+
"symbol",
|
|
26503
|
+
"table",
|
|
26504
|
+
"datum",
|
|
26505
|
+
"verdict",
|
|
26506
|
+
"attribute",
|
|
26507
|
+
"process"
|
|
26508
|
+
]);
|
|
26509
|
+
const CONTEXT_ROOTS = /* @__PURE__ */ new Set([
|
|
26510
|
+
"sample",
|
|
26511
|
+
"family",
|
|
26512
|
+
"group",
|
|
26513
|
+
"model",
|
|
26514
|
+
"instrument",
|
|
26515
|
+
"specimen"
|
|
26516
|
+
]);
|
|
26517
|
+
const checkInlineLimit = (ownerKind, ownerId, limit, memberScope) => {
|
|
26518
|
+
let ast;
|
|
26519
|
+
try {
|
|
26520
|
+
ast = parseExpression(limit.expression);
|
|
26521
|
+
} catch (e) {
|
|
26522
|
+
err(
|
|
26523
|
+
"C171",
|
|
26524
|
+
`${ownerKind} ${ownerId}: the inline limit expression does not parse \u2014 ${String(e.message ?? e)} (expression-identifiers-resolve)`
|
|
26525
|
+
);
|
|
26526
|
+
return;
|
|
26527
|
+
}
|
|
26528
|
+
const ids = freeIdentifiers(ast);
|
|
26529
|
+
const args2 = limit.args ?? [];
|
|
26530
|
+
const argNames = new Set(args2.map((a) => a.name));
|
|
26531
|
+
if (memberScope === null && args2.length === 0 && ids.names.some((n) => !n.includes("."))) {
|
|
26532
|
+
err(
|
|
26533
|
+
"C171",
|
|
26534
|
+
`${ownerKind} ${ownerId}: the inline limit declares no arguments \u2014 every identifier must bind explicitly, args { name <- <declaration> } (expression-identifiers-resolve)`
|
|
26535
|
+
);
|
|
26536
|
+
}
|
|
26537
|
+
for (const call of new Set(ids.calls)) {
|
|
26538
|
+
if (INLINE_FUNCTION_WORDS.has(call)) {
|
|
26539
|
+
continue;
|
|
26540
|
+
}
|
|
26541
|
+
if (call.includes(".")) {
|
|
26542
|
+
const root = call.split(".")[0];
|
|
26543
|
+
if (argNames.has(root) || root === "self" || CONTEXT_ROOTS.has(root)) {
|
|
26544
|
+
continue;
|
|
26545
|
+
}
|
|
26546
|
+
}
|
|
26547
|
+
if (argNames.has(call)) {
|
|
26548
|
+
continue;
|
|
26549
|
+
}
|
|
26550
|
+
err(
|
|
26551
|
+
"C171",
|
|
26552
|
+
`${ownerKind} ${ownerId}: the limit calls "${call}(\u2026)", which no argument binds and which is not in the expression function vocabulary (abs max min floor ceil round sqrt exp ln log mod sum count exists forall) \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26553
|
+
);
|
|
26554
|
+
}
|
|
26555
|
+
for (const id of new Set(ids.names)) {
|
|
26556
|
+
const root = id.split(".")[0];
|
|
26557
|
+
if (id.includes(".") && (root === "self" || argNames.has(root) || CONTEXT_ROOTS.has(root))) {
|
|
26558
|
+
continue;
|
|
26559
|
+
}
|
|
26560
|
+
if (argNames.has(id)) {
|
|
26561
|
+
continue;
|
|
26562
|
+
}
|
|
26563
|
+
if (memberScope !== null && memberScope.has(id)) {
|
|
26564
|
+
continue;
|
|
26565
|
+
}
|
|
26566
|
+
const lawScoped = memberScope !== null;
|
|
26567
|
+
const fix = lawScoped ? "the law composes the containment only \u2014 its identifiers are the members" : "add args { " + id + " <- <declaration> } or remove it";
|
|
26568
|
+
err(
|
|
26569
|
+
lawScoped ? "C172" : "C171",
|
|
26570
|
+
`${ownerKind} ${ownerId}: the limit expression names "${id}", which no argument binds \u2014 ${fix} (${lawScoped ? "requirement-algebra-resolves" : "expression-identifiers-resolve"})`
|
|
26571
|
+
);
|
|
26572
|
+
}
|
|
26573
|
+
for (const a of args2) {
|
|
26574
|
+
if (a.source.includes(":")) {
|
|
26575
|
+
const segs = a.source.split(":");
|
|
26576
|
+
if (segs.some((s) => s.length === 0)) {
|
|
26577
|
+
err(
|
|
26578
|
+
"C171",
|
|
26579
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 a binding is <kind>:<id> in this package or <package>:<kind>:<id> across a uses edge (expression-identifiers-resolve)`
|
|
26580
|
+
);
|
|
26581
|
+
continue;
|
|
26582
|
+
}
|
|
26583
|
+
if (segs.length === 2) {
|
|
26584
|
+
const [kind, id] = segs;
|
|
26585
|
+
if (kind === "process") {
|
|
26586
|
+
const segs2 = id.split(".");
|
|
26587
|
+
const proc = (standard.processes ?? []).find(
|
|
26588
|
+
(pp) => pp.id === segs2[0]
|
|
26589
|
+
);
|
|
26590
|
+
if (!proc) {
|
|
26591
|
+
err(
|
|
26592
|
+
"C171",
|
|
26593
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no declared process names \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26594
|
+
);
|
|
26595
|
+
} else if (segs2.length >= 2) {
|
|
26596
|
+
const stp = (proc.steps ?? []).find((ss) => ss.id === segs2[1]);
|
|
26597
|
+
if (!stp) {
|
|
26598
|
+
err(
|
|
26599
|
+
"C171",
|
|
26600
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 the process declares no step "${segs2[1]}" (expression-identifiers-resolve)`
|
|
26601
|
+
);
|
|
26602
|
+
} else if (segs2.length >= 3) {
|
|
26603
|
+
const io = segs2.slice(2).join(".");
|
|
26604
|
+
if (!(stp.sigInputs ?? []).includes(io) && !(stp.sigOutputs ?? []).includes(io)) {
|
|
26605
|
+
err(
|
|
26606
|
+
"C171",
|
|
26607
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 the step declares no io "${io}" (expression-identifiers-resolve)`
|
|
26608
|
+
);
|
|
26609
|
+
}
|
|
26610
|
+
}
|
|
26611
|
+
}
|
|
26612
|
+
continue;
|
|
26613
|
+
}
|
|
26614
|
+
if (kind !== "observable") {
|
|
26615
|
+
if (!DECLARATION_KINDS.has(kind)) {
|
|
26616
|
+
err(
|
|
26617
|
+
"C171",
|
|
26618
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 "${kind}" is not a declaration kind (symbol table datum verdict attribute observable) (expression-identifiers-resolve)`
|
|
26619
|
+
);
|
|
26620
|
+
continue;
|
|
26621
|
+
}
|
|
26622
|
+
const idRoot = id.split(".")[0];
|
|
26623
|
+
const idTail = id.split(".").pop() ?? id;
|
|
26624
|
+
if (!globalExprNames.has(id) && !globalExprNames.has(idRoot) && !globalExprNames.has(idTail)) {
|
|
26625
|
+
err(
|
|
26626
|
+
"C171",
|
|
26627
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no declared ${kind} names \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26628
|
+
);
|
|
26629
|
+
}
|
|
26630
|
+
}
|
|
26631
|
+
continue;
|
|
26632
|
+
}
|
|
26633
|
+
continue;
|
|
26634
|
+
}
|
|
26635
|
+
if (a.source === "self" || a.source.startsWith("self.")) {
|
|
26636
|
+
continue;
|
|
26637
|
+
}
|
|
26638
|
+
const bare2 = (q) => q.split(":").pop() ?? q;
|
|
26639
|
+
const sourceBare = bare2(a.source.replace(/\./g, ":"));
|
|
26640
|
+
if (memberScope !== null) {
|
|
26641
|
+
if (!memberScope.has(a.source) && !memberScope.has(sourceBare)) {
|
|
26642
|
+
err(
|
|
26643
|
+
"C172",
|
|
26644
|
+
`requirement class ${ownerId}: the law binds "${a.name}" to "${a.source}", which is not a contained member (requirement-algebra-resolves)`
|
|
26645
|
+
);
|
|
26646
|
+
}
|
|
26647
|
+
continue;
|
|
26648
|
+
}
|
|
26649
|
+
if (!globalExprNames.has(a.source) && !globalExprNames.has(sourceBare) && !usesCovers(limit.uses, sourceBare)) {
|
|
26650
|
+
err(
|
|
26651
|
+
"C171",
|
|
26652
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no symbol, datum, verdict, attribute, or uses entry declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26653
|
+
);
|
|
26654
|
+
}
|
|
26655
|
+
}
|
|
26656
|
+
const kindLabel = (k) => k === void 0 ? "an operand of unknown kind" : k === "TEXT" ? "text" : k === null ? "a bare number" : `the "${k}" quantity`;
|
|
26657
|
+
const argKindOf = (source) => {
|
|
26658
|
+
if (source.includes(":")) {
|
|
26659
|
+
const segs = source.split(":");
|
|
26660
|
+
if (segs.length !== 2) {
|
|
26661
|
+
return void 0;
|
|
26662
|
+
}
|
|
26663
|
+
const [kind, id] = segs;
|
|
26664
|
+
if (kind === "symbol") {
|
|
26665
|
+
return symbolKinds.get(id.split(".").pop() ?? id);
|
|
26666
|
+
}
|
|
26667
|
+
if (kind === "attribute") {
|
|
26668
|
+
return attributeKinds.get(id.split(".").pop() ?? id);
|
|
26669
|
+
}
|
|
26670
|
+
if (kind === "verdict") {
|
|
26671
|
+
return verdictKinds.get(id.split(".")[0]);
|
|
26672
|
+
}
|
|
26673
|
+
if (kind === "table") {
|
|
26674
|
+
const segs2 = id.split(".");
|
|
26675
|
+
const colType = segs2.length === 2 ? tableColumnTypes.get(segs2[0])?.get(segs2[1]) : void 0;
|
|
26676
|
+
return colType === "string" ? "TEXT" : void 0;
|
|
26677
|
+
}
|
|
26678
|
+
return void 0;
|
|
26679
|
+
}
|
|
26680
|
+
if (source === "self" || source.startsWith("self.")) {
|
|
26681
|
+
return void 0;
|
|
26682
|
+
}
|
|
26683
|
+
return symbolKinds.get(source) ?? attributeKinds.get(source) ?? void 0;
|
|
26684
|
+
};
|
|
26685
|
+
const kindConflicts = /* @__PURE__ */ new Set();
|
|
26686
|
+
const kindMixErr = (node, l, r) => {
|
|
26687
|
+
const key = renderExpression(node);
|
|
26688
|
+
if (kindConflicts.has(key)) {
|
|
26689
|
+
return;
|
|
26690
|
+
}
|
|
26691
|
+
kindConflicts.add(key);
|
|
26692
|
+
err(
|
|
26693
|
+
"C177",
|
|
26694
|
+
`${ownerKind} ${ownerId}: ${kindLabel(l)} is set against ${kindLabel(r)} in "${renderExpression(node)}" \u2014 the operands must share the quantity kind (kind-coherence)`
|
|
26695
|
+
);
|
|
26696
|
+
};
|
|
26697
|
+
const kindOf = (node) => {
|
|
26698
|
+
switch (node.type) {
|
|
26699
|
+
case "num":
|
|
26700
|
+
return null;
|
|
26701
|
+
case "str":
|
|
26702
|
+
return null;
|
|
26703
|
+
case "name": {
|
|
26704
|
+
const root = node.path[0];
|
|
26705
|
+
if (node.path.length > 1 && (root === "self" || CONTEXT_ROOTS.has(root))) {
|
|
26706
|
+
return void 0;
|
|
26707
|
+
}
|
|
26708
|
+
const arg = args2.find((a) => a.name === root);
|
|
26709
|
+
return arg ? argKindOf(arg.source) : void 0;
|
|
26710
|
+
}
|
|
26711
|
+
case "call": {
|
|
26712
|
+
if (node.callee.includes(".")) {
|
|
26713
|
+
return void 0;
|
|
26714
|
+
}
|
|
26715
|
+
const kinded = [
|
|
26716
|
+
"abs",
|
|
26717
|
+
"max",
|
|
26718
|
+
"min",
|
|
26719
|
+
"floor",
|
|
26720
|
+
"ceil",
|
|
26721
|
+
"round",
|
|
26722
|
+
"sqrt",
|
|
26723
|
+
"exp",
|
|
26724
|
+
"ln",
|
|
26725
|
+
"log",
|
|
26726
|
+
"mod"
|
|
26727
|
+
];
|
|
26728
|
+
if (!kinded.includes(node.callee)) {
|
|
26729
|
+
return null;
|
|
26730
|
+
}
|
|
26731
|
+
let acc = void 0;
|
|
26732
|
+
for (const a of node.args) {
|
|
26733
|
+
const k = kindOf(a);
|
|
26734
|
+
if (k === void 0) {
|
|
26735
|
+
continue;
|
|
26736
|
+
}
|
|
26737
|
+
if (acc === void 0 || acc === null) {
|
|
26738
|
+
acc = k;
|
|
26739
|
+
continue;
|
|
26740
|
+
}
|
|
26741
|
+
if (k !== void 0 && k !== null && k !== acc) {
|
|
26742
|
+
kindMixErr(node, acc, k);
|
|
26743
|
+
}
|
|
26744
|
+
}
|
|
26745
|
+
return acc;
|
|
26746
|
+
}
|
|
26747
|
+
case "unop":
|
|
26748
|
+
return node.op === "not" ? null : kindOf(node.operand);
|
|
26749
|
+
case "nav":
|
|
26750
|
+
return node.op === "select" ? void 0 : null;
|
|
26751
|
+
case "binop": {
|
|
26752
|
+
if (["<=", ">=", "<", ">", "=", "!=", "\u2260"].includes(node.op)) {
|
|
26753
|
+
const l2 = kindOf(node.left);
|
|
26754
|
+
const r2 = kindOf(node.right);
|
|
26755
|
+
if (l2 !== void 0 && r2 !== void 0 && l2 !== null && r2 !== null && l2 !== r2) {
|
|
26756
|
+
kindMixErr(node, l2, r2);
|
|
26757
|
+
}
|
|
26758
|
+
return null;
|
|
26759
|
+
}
|
|
26760
|
+
if (["and", "or", "xor", "implies"].includes(node.op)) {
|
|
26761
|
+
kindOf(node.left);
|
|
26762
|
+
kindOf(node.right);
|
|
26763
|
+
return null;
|
|
26764
|
+
}
|
|
26765
|
+
const l = kindOf(node.left);
|
|
26766
|
+
const r = kindOf(node.right);
|
|
26767
|
+
if (l !== void 0 && r !== void 0 && l !== null && r !== null && l !== r) {
|
|
26768
|
+
kindMixErr(node, l, r);
|
|
26769
|
+
}
|
|
26770
|
+
return l !== void 0 && l !== null ? l : r;
|
|
26771
|
+
}
|
|
26772
|
+
}
|
|
26773
|
+
};
|
|
26774
|
+
kindOf(ast);
|
|
26775
|
+
};
|
|
26776
|
+
for (const r of standard.requirements ?? []) {
|
|
26777
|
+
if (r.limit?.argsBound) {
|
|
26778
|
+
checkInlineLimit("requirement", r.id, r.limit, null);
|
|
26779
|
+
continue;
|
|
26780
|
+
}
|
|
26781
|
+
const expr = r.limit?.expression;
|
|
26782
|
+
if (!expr) {
|
|
26783
|
+
continue;
|
|
26784
|
+
}
|
|
26785
|
+
const ocl = expr.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26786
|
+
const uses = r.limit?.uses ?? [];
|
|
26787
|
+
for (const id of unresolvedIn(ocl, [], uses)) {
|
|
26788
|
+
err(
|
|
26789
|
+
"C171",
|
|
26790
|
+
`requirement ${r.id}: the limit expression names "${id}", which no uses entry, symbol, datum, or verdict declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26791
|
+
);
|
|
26792
|
+
}
|
|
26793
|
+
}
|
|
26794
|
+
const resolveInlineCarrier = (ownerKind, ownerId, what, src, scope) => {
|
|
26795
|
+
let ast;
|
|
26796
|
+
try {
|
|
26797
|
+
ast = parseExpression(src);
|
|
26798
|
+
} catch (e) {
|
|
26799
|
+
err(
|
|
26800
|
+
"C171",
|
|
26801
|
+
`${ownerKind} ${ownerId}: the ${what} does not parse \u2014 ${String(e.message ?? e)} (expression-identifiers-resolve)`
|
|
26802
|
+
);
|
|
26803
|
+
return;
|
|
26804
|
+
}
|
|
26805
|
+
const ids = freeIdentifiers(ast);
|
|
26806
|
+
for (const call of new Set(ids.calls)) {
|
|
26807
|
+
if (INLINE_FUNCTION_WORDS.has(call)) {
|
|
26808
|
+
continue;
|
|
26809
|
+
}
|
|
26810
|
+
if (call.includes(".")) {
|
|
26811
|
+
const root = call.split(".")[0];
|
|
26812
|
+
if (scope.has(root) || globalExprNames.has(root) || root === "self" || CONTEXT_ROOTS.has(root)) {
|
|
26813
|
+
continue;
|
|
26814
|
+
}
|
|
26815
|
+
}
|
|
26816
|
+
if (scope.has(call) || globalExprNames.has(call)) {
|
|
26817
|
+
continue;
|
|
26818
|
+
}
|
|
26819
|
+
err(
|
|
26820
|
+
"C171",
|
|
26821
|
+
`${ownerKind} ${ownerId}: the ${what} calls "${call}(\u2026)", which nothing declares and which is not in the expression function vocabulary \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26822
|
+
);
|
|
26823
|
+
}
|
|
26824
|
+
for (const id of new Set(ids.names)) {
|
|
26825
|
+
const root = id.split(".")[0];
|
|
26826
|
+
if (id.includes(".") && (scope.has(root) || root === "self" || CONTEXT_ROOTS.has(root))) {
|
|
26827
|
+
continue;
|
|
26828
|
+
}
|
|
26829
|
+
if (scope.has(id)) {
|
|
26830
|
+
continue;
|
|
26831
|
+
}
|
|
26832
|
+
if (globalExprNames.has(id) || globalExprNames.has(id.split(".").pop() ?? id)) {
|
|
26833
|
+
continue;
|
|
26834
|
+
}
|
|
26835
|
+
err(
|
|
26836
|
+
"C171",
|
|
26837
|
+
`${ownerKind} ${ownerId}: the ${what} names "${id}", which nothing in scope declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26838
|
+
);
|
|
26839
|
+
}
|
|
26840
|
+
};
|
|
26841
|
+
for (const v of standard.verdicts ?? []) {
|
|
26842
|
+
const expr = v.derive;
|
|
26843
|
+
if (!expr) {
|
|
26844
|
+
continue;
|
|
26845
|
+
}
|
|
26846
|
+
const inputs = v.inputs ?? [];
|
|
26847
|
+
if (v.deriveBound) {
|
|
26848
|
+
resolveInlineCarrier("verdict", v.id, "derive", expr, new Set(inputs));
|
|
26849
|
+
continue;
|
|
26850
|
+
}
|
|
26851
|
+
const ocl = expr.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26852
|
+
for (const id of unresolvedIn(ocl, inputs, [])) {
|
|
26853
|
+
err(
|
|
26854
|
+
"C171",
|
|
26855
|
+
`verdict ${v.id}: the derive expression names "${id}", which no input declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26856
|
+
);
|
|
26857
|
+
}
|
|
26858
|
+
}
|
|
26859
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
26860
|
+
const scope = (t.variables ?? []).map((v) => v.name);
|
|
26861
|
+
for (const v of t.variables ?? []) {
|
|
26862
|
+
if (!v.derivation) {
|
|
26863
|
+
continue;
|
|
26864
|
+
}
|
|
26865
|
+
if (v.derivationBound) {
|
|
26866
|
+
resolveInlineCarrier(
|
|
26867
|
+
"conformance test",
|
|
26868
|
+
t.id,
|
|
26869
|
+
`variable ${v.name}'s derivation`,
|
|
26870
|
+
v.derivation,
|
|
26871
|
+
new Set(scope)
|
|
26872
|
+
);
|
|
26873
|
+
continue;
|
|
26874
|
+
}
|
|
26875
|
+
const ocl = v.derivation.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26876
|
+
for (const id of unresolvedIn(ocl, scope, [])) {
|
|
26877
|
+
err(
|
|
26878
|
+
"C171",
|
|
26879
|
+
`conformance test ${t.id}: variable ${v.name}'s derivation names "${id}", which no sibling variable, symbol, datum, or verdict declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26880
|
+
);
|
|
26881
|
+
}
|
|
26882
|
+
}
|
|
26883
|
+
}
|
|
26884
|
+
for (const c of standard.constraints ?? []) {
|
|
26885
|
+
if (!c.checkBound || !c.check) {
|
|
26886
|
+
continue;
|
|
26887
|
+
}
|
|
26888
|
+
const cArgs = c.args ?? [];
|
|
26889
|
+
const cScope = new Set(cArgs.map((a) => a.name));
|
|
26890
|
+
for (const a of cArgs) {
|
|
26891
|
+
if (a.source.includes(":")) {
|
|
26892
|
+
const segs = a.source.split(":");
|
|
26893
|
+
if (segs.length === 2 && segs[0] !== "observable") {
|
|
26894
|
+
const [kind, id] = segs;
|
|
26895
|
+
if (!DECLARATION_KINDS.has(kind)) {
|
|
26896
|
+
err(
|
|
26897
|
+
"C171",
|
|
26898
|
+
`constraint ${c.id}: argument "${a.name}" binds to "${a.source}" \u2014 "${kind}" is not a declaration kind (expression-identifiers-resolve)`
|
|
26899
|
+
);
|
|
26900
|
+
} else {
|
|
26901
|
+
const idRoot = id.split(".")[0];
|
|
26902
|
+
const idTail = id.split(".").pop() ?? id;
|
|
26903
|
+
if (!globalExprNames.has(id) && !globalExprNames.has(idRoot) && !globalExprNames.has(idTail)) {
|
|
26904
|
+
err(
|
|
26905
|
+
"C171",
|
|
26906
|
+
`constraint ${c.id}: argument "${a.name}" binds to "${a.source}", which no declared ${kind} names \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26907
|
+
);
|
|
26908
|
+
}
|
|
26909
|
+
}
|
|
26910
|
+
}
|
|
26911
|
+
continue;
|
|
26912
|
+
}
|
|
26913
|
+
if (a.source === "self" || a.source.startsWith("self.")) {
|
|
26914
|
+
continue;
|
|
26915
|
+
}
|
|
26916
|
+
const bare2 = a.source.split(":").pop() ?? a.source;
|
|
26917
|
+
if (!globalExprNames.has(a.source) && !globalExprNames.has(bare2)) {
|
|
26918
|
+
err(
|
|
26919
|
+
"C171",
|
|
26920
|
+
`constraint ${c.id}: argument "${a.name}" binds to "${a.source}", which nothing declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26921
|
+
);
|
|
26922
|
+
}
|
|
26923
|
+
}
|
|
26924
|
+
resolveInlineCarrier("constraint", c.id, "check", c.check, cScope);
|
|
26925
|
+
try {
|
|
26926
|
+
const ast = parseExpression(c.check);
|
|
26927
|
+
const booleanTop = ast.type === "binop" && [
|
|
26928
|
+
"<=",
|
|
26929
|
+
">=",
|
|
26930
|
+
"<",
|
|
26931
|
+
">",
|
|
26932
|
+
"=",
|
|
26933
|
+
"!=",
|
|
26934
|
+
"\u2260",
|
|
26935
|
+
"and",
|
|
26936
|
+
"or",
|
|
26937
|
+
"xor",
|
|
26938
|
+
"implies"
|
|
26939
|
+
].includes(ast.op) || ast.type === "nav" && ["forAll", "exists"].includes(ast.op);
|
|
26940
|
+
if (!booleanTop) {
|
|
26941
|
+
err(
|
|
26942
|
+
"C84",
|
|
26943
|
+
`constraint ${c.id}: the check does not evaluate to a boolean \u2014 an invariant is one comparison or logical composition (constraint-shape)`
|
|
26944
|
+
);
|
|
26945
|
+
}
|
|
26946
|
+
} catch {
|
|
26947
|
+
}
|
|
26948
|
+
}
|
|
26949
|
+
const memberSet = /* @__PURE__ */ new Map();
|
|
26950
|
+
for (const rc of standard.requirementClasses ?? []) {
|
|
26951
|
+
memberSet.set(rc.id, new Set((rc.members ?? []).map(String)));
|
|
26952
|
+
}
|
|
26953
|
+
for (const rc of standard.requirementClasses ?? []) {
|
|
26954
|
+
const law = rc.limit?.expression;
|
|
26955
|
+
const members = memberSet.get(rc.id) ?? /* @__PURE__ */ new Set();
|
|
26956
|
+
if (!law) {
|
|
26957
|
+
continue;
|
|
26958
|
+
}
|
|
26959
|
+
if (rc.limit?.argsBound) {
|
|
26960
|
+
checkInlineLimit("requirement class", rc.id, rc.limit, members);
|
|
26961
|
+
const covered2 = /* @__PURE__ */ new Set();
|
|
26962
|
+
try {
|
|
26963
|
+
for (const n of freeIdentifiers(parseExpression(law)).names) {
|
|
26964
|
+
covered2.add(n);
|
|
26965
|
+
}
|
|
26966
|
+
} catch {
|
|
26967
|
+
}
|
|
26968
|
+
for (const a of rc.limit.args ?? []) {
|
|
26969
|
+
covered2.add(a.name);
|
|
26970
|
+
covered2.add(a.source);
|
|
26971
|
+
}
|
|
26972
|
+
for (const m of members) {
|
|
26973
|
+
if (!covered2.has(m)) {
|
|
26974
|
+
warn(
|
|
26975
|
+
"C172",
|
|
26976
|
+
`requirement class ${rc.id}: member ${m} does not appear in the law \u2014 either it is always-required (add it with \`and\`) or it is orphaned (requirement-algebra-resolves)`
|
|
26977
|
+
);
|
|
26978
|
+
}
|
|
26979
|
+
}
|
|
26980
|
+
continue;
|
|
26981
|
+
}
|
|
26982
|
+
const ocl = law.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26983
|
+
const ids = (ocl.match(/[A-Za-z_][A-Za-z0-9_]*/g) ?? []).filter(
|
|
26984
|
+
(x) => !OCL_WORDS.has(x)
|
|
26985
|
+
);
|
|
26986
|
+
const lawIds = /* @__PURE__ */ new Set();
|
|
26987
|
+
for (const id of ids) {
|
|
26988
|
+
lawIds.add(id);
|
|
26989
|
+
if (!members.has(id)) {
|
|
26990
|
+
err(
|
|
26991
|
+
"C172",
|
|
26992
|
+
`requirement class ${rc.id}: the law names "${id}", which is not a contained member \u2014 the algebra composes the containment only (requirement-algebra-resolves)`
|
|
26993
|
+
);
|
|
26994
|
+
}
|
|
26995
|
+
}
|
|
26996
|
+
for (const m of members) {
|
|
26997
|
+
if (!lawIds.has(m)) {
|
|
26998
|
+
warn(
|
|
26999
|
+
"C172",
|
|
27000
|
+
`requirement class ${rc.id}: member ${m} does not appear in the law \u2014 either it is always-required (add it with \`and\`) or it is orphaned (requirement-algebra-resolves)`
|
|
27001
|
+
);
|
|
27002
|
+
}
|
|
27003
|
+
}
|
|
27004
|
+
}
|
|
27005
|
+
const DEPRECATION_GENERATION = "v3.4";
|
|
27006
|
+
const generationRank = (g) => {
|
|
27007
|
+
const m = g.match(/^v(\d+)(?:\.(\d+))?$/);
|
|
27008
|
+
if (!m) {
|
|
27009
|
+
return -1;
|
|
27010
|
+
}
|
|
27011
|
+
return Number(m[1]) * 1e3 + Number(m[2] ?? "0");
|
|
27012
|
+
};
|
|
27013
|
+
try {
|
|
27014
|
+
const mf = readPackageManifest(dir);
|
|
27015
|
+
if (mf.language !== void 0) {
|
|
27016
|
+
if (!/^v\d+(\.\d+)?$/.test(mf.language)) {
|
|
27017
|
+
err(
|
|
27018
|
+
"C176",
|
|
27019
|
+
`the declared language "${mf.language}" is not a generation (v<major>[.<minor>]) (language-declared-wellformed)`
|
|
27020
|
+
);
|
|
27021
|
+
} else if (generationRank(mf.language) >= generationRank(DEPRECATION_GENERATION)) {
|
|
27022
|
+
let legacy = 0;
|
|
27023
|
+
for (const r of standard.requirements ?? []) {
|
|
27024
|
+
if (r.limit && !r.limit.argsBound && r.limit.expression) {
|
|
27025
|
+
legacy += 1;
|
|
27026
|
+
}
|
|
27027
|
+
}
|
|
27028
|
+
for (const v of standard.verdicts ?? []) {
|
|
27029
|
+
if (v.derive && !v.deriveBound) {
|
|
27030
|
+
legacy += 1;
|
|
27031
|
+
}
|
|
27032
|
+
}
|
|
27033
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
27034
|
+
for (const v of t.variables ?? []) {
|
|
27035
|
+
if (v.derivation && !v.derivationBound) {
|
|
27036
|
+
legacy += 1;
|
|
27037
|
+
}
|
|
27038
|
+
}
|
|
27039
|
+
for (const p of t.preconditions ?? []) {
|
|
27040
|
+
if (p.check && !p.checkBound) {
|
|
27041
|
+
legacy += 1;
|
|
27042
|
+
}
|
|
27043
|
+
}
|
|
27044
|
+
}
|
|
27045
|
+
for (const c of standard.constraints ?? []) {
|
|
27046
|
+
if (c.check && !c.checkBound) {
|
|
27047
|
+
legacy += 1;
|
|
27048
|
+
}
|
|
27049
|
+
}
|
|
27050
|
+
if (legacy > 0) {
|
|
27051
|
+
warn(
|
|
27052
|
+
"C178",
|
|
27053
|
+
`${legacy} quoted expression carrier${legacy === 1 ? "" : "s"} \u2014 the ocl{\u2026} string form is deprecated as of ${DEPRECATION_GENERATION}; migrate to the inline blocks (expression { \u2026 }, derive { \u2026 }, derivation { \u2026 }, check { \u2026 }) (legacy-carrier-deprecated)`
|
|
27054
|
+
);
|
|
27055
|
+
}
|
|
27056
|
+
}
|
|
27057
|
+
}
|
|
27058
|
+
} catch {
|
|
27059
|
+
}
|
|
27060
|
+
{
|
|
27061
|
+
const seriesVariables = /* @__PURE__ */ new Map();
|
|
27062
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
27063
|
+
for (const v of t.variables ?? []) {
|
|
27064
|
+
seriesVariables.set(v.name, v.series !== null);
|
|
27065
|
+
}
|
|
27066
|
+
}
|
|
27067
|
+
for (const b of standard.uncertaintyBudgets ?? []) {
|
|
27068
|
+
if (!b.target) {
|
|
27069
|
+
err(
|
|
27070
|
+
"C179",
|
|
27071
|
+
`uncertainty_budget ${b.id}: declares no target \u2014 the budget backs a declared verdict's measured quantity (uncertainty-budget-resolves)`
|
|
27072
|
+
);
|
|
27073
|
+
} else if (!(standard.verdicts ?? []).some((v) => v.id === b.target)) {
|
|
27074
|
+
err(
|
|
27075
|
+
"C179",
|
|
27076
|
+
`uncertainty_budget ${b.id}: target "${b.target}" is not a declared verdict \u2014 the budget backs a measured quantity the verdicts own (uncertainty-budget-resolves)`
|
|
27077
|
+
);
|
|
27078
|
+
}
|
|
27079
|
+
if (b.components.length === 0) {
|
|
27080
|
+
warn(
|
|
27081
|
+
"C179",
|
|
27082
|
+
`uncertainty_budget ${b.id}: declares no components \u2014 an empty budget states no uncertainty (uncertainty-budget-resolves)`
|
|
27083
|
+
);
|
|
27084
|
+
}
|
|
27085
|
+
if (b.coverageK && !(Number(b.coverageK) > 0)) {
|
|
27086
|
+
err(
|
|
27087
|
+
"C179",
|
|
27088
|
+
`uncertainty_budget ${b.id}: coverage k "${b.coverageK}" is not a positive number (uncertainty-budget-resolves)`
|
|
27089
|
+
);
|
|
27090
|
+
}
|
|
27091
|
+
for (const c of b.components) {
|
|
27092
|
+
if (c.type === "A") {
|
|
27093
|
+
if (!c.series) {
|
|
27094
|
+
err(
|
|
27095
|
+
"C179",
|
|
27096
|
+
`uncertainty_budget ${b.id}: component ${c.id} is Type A but names no series \u2014 the statistics compute from a declared captured series (uncertainty-budget-resolves)`
|
|
27097
|
+
);
|
|
27098
|
+
} else if (!seriesVariables.has(c.series)) {
|
|
27099
|
+
err(
|
|
27100
|
+
"C179",
|
|
27101
|
+
`uncertainty_budget ${b.id}: component ${c.id}'s series "${c.series}" is not a declared test variable (uncertainty-budget-resolves)`
|
|
27102
|
+
);
|
|
27103
|
+
} else if (!seriesVariables.get(c.series)) {
|
|
27104
|
+
err(
|
|
27105
|
+
"C179",
|
|
27106
|
+
`uncertainty_budget ${b.id}: component ${c.id}'s series "${c.series}" declares no series shape \u2014 a Type A evaluation needs the captured series' axes and cell (uncertainty-budget-resolves)`
|
|
27107
|
+
);
|
|
27108
|
+
}
|
|
27109
|
+
} else {
|
|
27110
|
+
if (!c.distribution) {
|
|
27111
|
+
err(
|
|
27112
|
+
"C179",
|
|
27113
|
+
`uncertainty_budget ${b.id}: component ${c.id} is Type B but states no distribution (uncertainty-budget-resolves)`
|
|
27114
|
+
);
|
|
27115
|
+
}
|
|
27116
|
+
if (!c.halfWidth) {
|
|
27117
|
+
err(
|
|
27118
|
+
"C179",
|
|
27119
|
+
`uncertainty_budget ${b.id}: component ${c.id} is Type B but states no half_width \u2014 the distribution spans a half-width (uncertainty-budget-resolves)`
|
|
27120
|
+
);
|
|
27121
|
+
}
|
|
27122
|
+
}
|
|
27123
|
+
}
|
|
27124
|
+
}
|
|
27125
|
+
}
|
|
27126
|
+
for (const p of standard.processes ?? []) {
|
|
27127
|
+
for (const st of p.steps ?? []) {
|
|
27128
|
+
if (!st.completion) {
|
|
27129
|
+
continue;
|
|
27130
|
+
}
|
|
27131
|
+
const ios = /* @__PURE__ */ new Set([...st.sigInputs, ...st.sigOutputs]);
|
|
27132
|
+
let ids;
|
|
27133
|
+
try {
|
|
27134
|
+
ids = freeIdentifiers(
|
|
27135
|
+
parseExpression(
|
|
27136
|
+
st.completion.replace(/^ocl\{/, "").replace(/\}$/, "")
|
|
27137
|
+
)
|
|
27138
|
+
);
|
|
27139
|
+
} catch (e) {
|
|
27140
|
+
err(
|
|
27141
|
+
"C173",
|
|
27142
|
+
`process ${p.id}: step "${st.id}" completion does not parse \u2014 ${String(e.message ?? e)} \u2014 the completion is one expression over the step's ios (step-plane-refs-resolve)`
|
|
27143
|
+
);
|
|
27144
|
+
continue;
|
|
27145
|
+
}
|
|
27146
|
+
for (const call of new Set(ids.calls)) {
|
|
27147
|
+
if (!INLINE_FUNCTION_WORDS.has(call)) {
|
|
27148
|
+
err(
|
|
27149
|
+
"C173",
|
|
27150
|
+
`process ${p.id}: step "${st.id}" completion calls "${call}(\u2026)", which is not in the expression function vocabulary (step-plane-refs-resolve)`
|
|
27151
|
+
);
|
|
27152
|
+
}
|
|
27153
|
+
}
|
|
27154
|
+
for (const id of new Set(ids.names)) {
|
|
27155
|
+
const root = id.split(".")[0];
|
|
27156
|
+
if (id.includes(".") && (root === "self" || CONTEXT_ROOTS.has(root))) {
|
|
27157
|
+
continue;
|
|
27158
|
+
}
|
|
27159
|
+
if (ios.has(id) || ios.has(root)) {
|
|
27160
|
+
continue;
|
|
27161
|
+
}
|
|
27162
|
+
err(
|
|
27163
|
+
"C173",
|
|
27164
|
+
`process ${p.id}: step "${st.id}" completion names "${id}", which is not a declared io of the step \u2014 the completion reads the step's own inputs and outputs (step-plane-refs-resolve)`
|
|
27165
|
+
);
|
|
27166
|
+
}
|
|
27167
|
+
}
|
|
27168
|
+
}
|
|
27169
|
+
try {
|
|
27170
|
+
const mf = readPackageManifest(dir);
|
|
27171
|
+
const eds = (mf.editions ?? []).map(String);
|
|
27172
|
+
if (eds.length > 1) {
|
|
27173
|
+
const map = JSON.parse(
|
|
27174
|
+
readFileSync5(join4(dir, "edition-mapping.json"), "utf8")
|
|
27175
|
+
);
|
|
27176
|
+
if (map.kind !== "primmel-edition-mapping/1") {
|
|
27177
|
+
err(
|
|
27178
|
+
"C170",
|
|
27179
|
+
`edition-mapping.json: kind "${String(map.kind)}" is not primmel-edition-mapping/1 (edition-lineage-declared)`
|
|
27180
|
+
);
|
|
27181
|
+
} else {
|
|
27182
|
+
const fromEd = map.from?.edition === void 0 ? void 0 : String(map.from.edition);
|
|
27183
|
+
const toEd = map.to?.edition === void 0 ? void 0 : String(map.to.edition);
|
|
27184
|
+
for (const [side, ed] of [
|
|
27185
|
+
["from", fromEd],
|
|
27186
|
+
["to", toEd]
|
|
27187
|
+
]) {
|
|
27188
|
+
if (!ed || !eds.includes(ed)) {
|
|
27189
|
+
err(
|
|
27190
|
+
"C170",
|
|
27191
|
+
`edition-mapping.json: the ${side} edition ${String(ed)} is not among the manifest's declared editions [${eds.join(", ")}] (edition-lineage-declared)`
|
|
27192
|
+
);
|
|
27193
|
+
}
|
|
27194
|
+
}
|
|
27195
|
+
}
|
|
27196
|
+
}
|
|
27197
|
+
} catch (e) {
|
|
27198
|
+
const code = e.code;
|
|
27199
|
+
if (code === "ENOENT") {
|
|
27200
|
+
const eds = (() => {
|
|
27201
|
+
try {
|
|
27202
|
+
return (readPackageManifest(dir).editions ?? []).map(
|
|
27203
|
+
String
|
|
27204
|
+
);
|
|
27205
|
+
} catch {
|
|
27206
|
+
return [];
|
|
27207
|
+
}
|
|
27208
|
+
})();
|
|
27209
|
+
if (eds.length > 1) {
|
|
27210
|
+
err(
|
|
27211
|
+
"C170",
|
|
27212
|
+
`the package declares ${eds.length} editions [${eds.join(", ")}] but ships no edition-mapping.json \u2014 the cross-edition linkage is an artifact, never implicit (edition-lineage-declared)`
|
|
27213
|
+
);
|
|
27214
|
+
}
|
|
27215
|
+
} else if (e instanceof SyntaxError) {
|
|
27216
|
+
err(
|
|
27217
|
+
"C170",
|
|
27218
|
+
`edition-mapping.json is not valid JSON: ${e.message} (edition-lineage-declared)`
|
|
27219
|
+
);
|
|
27220
|
+
}
|
|
27221
|
+
}
|
|
27222
|
+
const methodTargetIds = (s) => /* @__PURE__ */ new Set([
|
|
27223
|
+
...(s.processes ?? []).map((p) => p.id),
|
|
27224
|
+
...(s.conformanceTests ?? []).map((x) => x.id)
|
|
27225
|
+
]);
|
|
27226
|
+
const localMethodIds = methodTargetIds(standard);
|
|
27227
|
+
const scopedMethodIds = /* @__PURE__ */ new Map();
|
|
27228
|
+
const resolveCitation = (elemId, ref) => {
|
|
27229
|
+
const colon = ref.indexOf(":");
|
|
27230
|
+
if (colon <= 0) {
|
|
27231
|
+
if (!localMethodIds.has(ref)) {
|
|
27232
|
+
err(
|
|
27233
|
+
"C168",
|
|
27234
|
+
`${elemId}: the reference "${ref}" names no process or conformance test declared in this package (method-ref-resolves)`
|
|
27235
|
+
);
|
|
27236
|
+
}
|
|
27237
|
+
return;
|
|
27238
|
+
}
|
|
27239
|
+
if (!options.resolvePackage) {
|
|
27240
|
+
return;
|
|
27241
|
+
}
|
|
27242
|
+
const pkgId = ref.slice(0, colon);
|
|
27243
|
+
const localId = ref.slice(colon + 1);
|
|
27244
|
+
let ids = scopedMethodIds.get(pkgId);
|
|
27245
|
+
if (!ids) {
|
|
27246
|
+
ids = /* @__PURE__ */ new Set();
|
|
27247
|
+
try {
|
|
27248
|
+
const depDir = options.resolvePackage(pkgId);
|
|
27249
|
+
if (depDir) {
|
|
27250
|
+
const dep = loadPackageWithIssues(depDir);
|
|
27251
|
+
ids = methodTargetIds(dep.standard);
|
|
27252
|
+
}
|
|
27253
|
+
} catch {
|
|
27254
|
+
}
|
|
27255
|
+
scopedMethodIds.set(pkgId, ids);
|
|
27256
|
+
}
|
|
27257
|
+
if (!ids.has(localId)) {
|
|
27258
|
+
err(
|
|
27259
|
+
"C168",
|
|
27260
|
+
`${elemId}: the reference "${ref}" names no process or conformance test declared in package "${pkgId}" (method-ref-resolves)`
|
|
27261
|
+
);
|
|
27262
|
+
}
|
|
27263
|
+
};
|
|
27264
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
27265
|
+
const ref = t.methodRef;
|
|
27266
|
+
if (ref) {
|
|
27267
|
+
resolveCitation(t.id, ref);
|
|
27268
|
+
}
|
|
27269
|
+
}
|
|
27270
|
+
for (const pr of standard.processes ?? []) {
|
|
27271
|
+
const raw = pr;
|
|
27272
|
+
for (const st of raw.steps ?? []) {
|
|
27273
|
+
const call = st.calls || st.signatureBlock?.match(/\bcalls +([\w:/.-]+)/)?.[1];
|
|
27274
|
+
if (call) {
|
|
27275
|
+
resolveCitation(`${pr.id}/step/${st.id ?? ""}`, call);
|
|
27276
|
+
}
|
|
27277
|
+
}
|
|
27278
|
+
}
|
|
24729
27279
|
const ASPECT_FAMILY = {
|
|
24730
27280
|
metadata: "is",
|
|
24731
27281
|
provenance: "is",
|
|
@@ -25613,7 +28163,7 @@ function checkPackage(dir, options = {}) {
|
|
|
25613
28163
|
`constraint ${c.id}: stereotype "${c.stereotype || "(none)"}" \u2014 a constraint is always \xABinv\xBB, the subject's declaration-level invariant (constraint-shape)`
|
|
25614
28164
|
);
|
|
25615
28165
|
}
|
|
25616
|
-
if (!OCL_CHECK.test(c.check)) {
|
|
28166
|
+
if (!c.checkBound && !OCL_CHECK.test(c.check)) {
|
|
25617
28167
|
err(
|
|
25618
28168
|
"C84",
|
|
25619
28169
|
`constraint ${c.id}: check is not one OCL boolean expression ocl{\u2026} over the subject's declared anatomy (constraint-shape)`
|
|
@@ -28708,9 +31258,9 @@ function checkPackage(dir, options = {}) {
|
|
|
28708
31258
|
if (!dataclassByEntity.has(c.id)) {
|
|
28709
31259
|
dataclassByEntity.set(c.id, c);
|
|
28710
31260
|
}
|
|
28711
|
-
const
|
|
28712
|
-
if (!dataclassByEntity.has(
|
|
28713
|
-
dataclassByEntity.set(
|
|
31261
|
+
const bare2 = c.id.includes("#") ? c.id.slice(0, c.id.indexOf("#")) : c.id;
|
|
31262
|
+
if (!dataclassByEntity.has(bare2)) {
|
|
31263
|
+
dataclassByEntity.set(bare2, c);
|
|
28714
31264
|
}
|
|
28715
31265
|
}
|
|
28716
31266
|
const whereFields = (where) => {
|
|
@@ -30308,6 +32858,101 @@ function checkVerdictChains(standard) {
|
|
|
30308
32858
|
}
|
|
30309
32859
|
return issues;
|
|
30310
32860
|
}
|
|
32861
|
+
function checkLmlAligned(standard) {
|
|
32862
|
+
const issues = [];
|
|
32863
|
+
const err = (check, message) => issues.push({ check, severity: "error", message });
|
|
32864
|
+
const warn = (check, message) => issues.push({ check, severity: "warning", message });
|
|
32865
|
+
const namespaceIds = new Set((standard.namespaces ?? []).map((n) => n.id));
|
|
32866
|
+
const dataclassIds = /* @__PURE__ */ new Set();
|
|
32867
|
+
for (const c of standard.dataclasses ?? []) {
|
|
32868
|
+
dataclassIds.add(c.id);
|
|
32869
|
+
dataclassIds.add(c.id.replace(/#data$/, ""));
|
|
32870
|
+
}
|
|
32871
|
+
const symbolIds = new Set((standard.symbols ?? []).map((s) => s.id));
|
|
32872
|
+
const datumIds = new Set((standard.datums ?? []).map((d) => d.id));
|
|
32873
|
+
const CLAUSE_CITATION = /clause-\d|§\d/i;
|
|
32874
|
+
for (const d of standard.datums ?? []) {
|
|
32875
|
+
if (!d.description) {
|
|
32876
|
+
continue;
|
|
32877
|
+
}
|
|
32878
|
+
if (CLAUSE_CITATION.test(d.description)) {
|
|
32879
|
+
err(
|
|
32880
|
+
"C158",
|
|
32881
|
+
`datum ${d.id}: the description cites a clause \u2014 a reference in prose belongs in a urn reference, not the quarantined free text (prose-quarantine)`
|
|
32882
|
+
);
|
|
32883
|
+
} else if (d.description.includes("TODO.roadmap")) {
|
|
32884
|
+
warn(
|
|
32885
|
+
"C158",
|
|
32886
|
+
`datum ${d.id}: the description carries the unfinished-prose marker TODO.roadmap (prose-quarantine)`
|
|
32887
|
+
);
|
|
32888
|
+
}
|
|
32889
|
+
}
|
|
32890
|
+
for (const w of standard.wireMappings ?? []) {
|
|
32891
|
+
if (w.namespaceRef && !namespaceIds.has(w.namespaceRef)) {
|
|
32892
|
+
err(
|
|
32893
|
+
"C159",
|
|
32894
|
+
`mapping ${w.id}: namespace "${w.namespaceRef}" names no declared namespace block (urn-only-refs)`
|
|
32895
|
+
);
|
|
32896
|
+
}
|
|
32897
|
+
}
|
|
32898
|
+
for (const c of standard.checks ?? []) {
|
|
32899
|
+
for (const inp of c.inputs ?? []) {
|
|
32900
|
+
if (!(datumIds.has(inp) || symbolIds.has(inp))) {
|
|
32901
|
+
err(
|
|
32902
|
+
"C160",
|
|
32903
|
+
`check ${c.id}: input "${inp}" resolves to no declared datum or symbol \u2014 the check consumes an undeclared name (signature-closure)`
|
|
32904
|
+
);
|
|
32905
|
+
}
|
|
32906
|
+
}
|
|
32907
|
+
}
|
|
32908
|
+
for (const d of standard.datums ?? []) {
|
|
32909
|
+
for (const r of d.renders ?? []) {
|
|
32910
|
+
if (!MATH_NOTATIONS.includes(r.notation)) {
|
|
32911
|
+
err(
|
|
32912
|
+
"C161",
|
|
32913
|
+
`datum ${d.id}: render notation "${r.notation}" is outside the closed vocabulary (${MATH_NOTATIONS.join("|")}) (check-surface)`
|
|
32914
|
+
);
|
|
32915
|
+
}
|
|
32916
|
+
}
|
|
32917
|
+
}
|
|
32918
|
+
const metaNamespace = standard.meta?.namespace ?? "";
|
|
32919
|
+
if (metaNamespace && namespaceIds.size > 0 && !namespaceIds.has(metaNamespace)) {
|
|
32920
|
+
err(
|
|
32921
|
+
"C162",
|
|
32922
|
+
`metadata namespace "${metaNamespace}" names no declared namespace block (namespace-coherence)`
|
|
32923
|
+
);
|
|
32924
|
+
}
|
|
32925
|
+
for (const w of standard.wireMappings ?? []) {
|
|
32926
|
+
if (!MAPPING_FORMATS.includes(w.format)) {
|
|
32927
|
+
err(
|
|
32928
|
+
"C164",
|
|
32929
|
+
`mapping ${w.id}: format "${w.format}" is outside the wire vocabulary (${MAPPING_FORMATS.join("|")}) (wire-mapping-coverage)`
|
|
32930
|
+
);
|
|
32931
|
+
}
|
|
32932
|
+
if (dataclassIds.size > 0 && !dataclassIds.has(w.target)) {
|
|
32933
|
+
err(
|
|
32934
|
+
"C164",
|
|
32935
|
+
`mapping ${w.id}: the class "${w.target}" is no declared dataclass \u2014 a class serialized to a format carries the declared mapping (wire-mapping-coverage)`
|
|
32936
|
+
);
|
|
32937
|
+
}
|
|
32938
|
+
}
|
|
32939
|
+
const QUALIFIED_REF = /^[a-z]+:[A-Za-z0-9_-]+$/;
|
|
32940
|
+
for (const d of standard.datums ?? []) {
|
|
32941
|
+
if (d.unit && !QUALIFIED_REF.test(d.unit)) {
|
|
32942
|
+
err(
|
|
32943
|
+
"C167",
|
|
32944
|
+
`datum ${d.id}: unit "${d.unit}" is bare \u2014 a unit reference uses the qualified <namespace>:<id> form (si:\u2026, unitsdb:\u2026) (qualified-unit-reference)`
|
|
32945
|
+
);
|
|
32946
|
+
}
|
|
32947
|
+
if (d.quantityKind && !QUALIFIED_REF.test(d.quantityKind)) {
|
|
32948
|
+
err(
|
|
32949
|
+
"C167",
|
|
32950
|
+
`datum ${d.id}: quantity_kind "${d.quantityKind}" is bare \u2014 a quantity-kind reference uses the qualified <namespace>:<id> form (si:\u2026, unitsdb:\u2026) (qualified-unit-reference)`
|
|
32951
|
+
);
|
|
32952
|
+
}
|
|
32953
|
+
}
|
|
32954
|
+
return issues;
|
|
32955
|
+
}
|
|
30311
32956
|
function checkEditionLifecycle(dir, standard) {
|
|
30312
32957
|
const issues = [];
|
|
30313
32958
|
const err = (check, message) => issues.push({ check, severity: "error", message });
|
|
@@ -30509,6 +33154,143 @@ function findCycle(adj) {
|
|
|
30509
33154
|
return cycle;
|
|
30510
33155
|
}
|
|
30511
33156
|
|
|
33157
|
+
// src/fmt.ts
|
|
33158
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync3, writeFileSync } from "node:fs";
|
|
33159
|
+
import { join as join5 } from "node:path";
|
|
33160
|
+
|
|
33161
|
+
// src/ser-des/dump.ts
|
|
33162
|
+
function dump(model, dumpers) {
|
|
33163
|
+
let out = "";
|
|
33164
|
+
if (model.root !== null) {
|
|
33165
|
+
out += "root " + model.root.id + "\n\n";
|
|
33166
|
+
}
|
|
33167
|
+
out += dumpMetadata(model.meta) + "\n";
|
|
33168
|
+
const childIds = /* @__PURE__ */ new Set();
|
|
33169
|
+
for (const p of model.processes) {
|
|
33170
|
+
for (const c of p.children) {
|
|
33171
|
+
childIds.add(c);
|
|
33172
|
+
}
|
|
33173
|
+
}
|
|
33174
|
+
const processMap = new Map(model.processes.map((p) => [p.id, p]));
|
|
33175
|
+
const memberIds = /* @__PURE__ */ new Set();
|
|
33176
|
+
for (const rc of model.requirementClasses ?? []) {
|
|
33177
|
+
for (const m of rc.members ?? []) {
|
|
33178
|
+
memberIds.add(m);
|
|
33179
|
+
}
|
|
33180
|
+
}
|
|
33181
|
+
const requirementMap = new Map(
|
|
33182
|
+
(model.requirements ?? []).map((r) => [r.id, r])
|
|
33183
|
+
);
|
|
33184
|
+
const classMap = new Map(
|
|
33185
|
+
(model.requirementClasses ?? []).map((rc) => [rc.id, rc])
|
|
33186
|
+
);
|
|
33187
|
+
const dumpersRef = dumpers;
|
|
33188
|
+
const dumpClassTree = (rcId) => {
|
|
33189
|
+
const rc = classMap.get(rcId);
|
|
33190
|
+
if (!rc) {
|
|
33191
|
+
return "";
|
|
33192
|
+
}
|
|
33193
|
+
const base = dumpersRef.requirementClasses(rc);
|
|
33194
|
+
if (!rc.members || rc.members.length === 0) {
|
|
33195
|
+
return base;
|
|
33196
|
+
}
|
|
33197
|
+
const inner = rc.members.map((m) => {
|
|
33198
|
+
const body = dumpersRef.requirements(requirementMap.get(m));
|
|
33199
|
+
return body.split("\n").filter((l) => l !== "").map((l) => " " + l).join("\n");
|
|
33200
|
+
}).join("\n");
|
|
33201
|
+
return base.slice(0, base.lastIndexOf("}")) + inner + "\n}\n";
|
|
33202
|
+
};
|
|
33203
|
+
Object.keys(dumpers).forEach((field) => {
|
|
33204
|
+
if (field === "processes") {
|
|
33205
|
+
for (const p of model.processes) {
|
|
33206
|
+
if (!childIds.has(p.id)) {
|
|
33207
|
+
out += dumpProcessTree(p, processMap);
|
|
33208
|
+
}
|
|
33209
|
+
}
|
|
33210
|
+
return;
|
|
33211
|
+
}
|
|
33212
|
+
if (field === "requirements") {
|
|
33213
|
+
for (const r of model.requirements ?? []) {
|
|
33214
|
+
if (!memberIds.has(r.id)) {
|
|
33215
|
+
out += dumpersRef.requirements(r);
|
|
33216
|
+
}
|
|
33217
|
+
}
|
|
33218
|
+
return;
|
|
33219
|
+
}
|
|
33220
|
+
if (field === "requirementClasses") {
|
|
33221
|
+
for (const rc of model.requirementClasses ?? []) {
|
|
33222
|
+
out += dumpClassTree(rc.id);
|
|
33223
|
+
}
|
|
33224
|
+
return;
|
|
33225
|
+
}
|
|
33226
|
+
const items = model[field];
|
|
33227
|
+
const dumper = dumpers[field];
|
|
33228
|
+
for (const item of items) {
|
|
33229
|
+
out += dumper(item);
|
|
33230
|
+
}
|
|
33231
|
+
});
|
|
33232
|
+
return out;
|
|
33233
|
+
}
|
|
33234
|
+
|
|
33235
|
+
// src/ser-des/index.ts
|
|
33236
|
+
function load(mmelString, options = {}) {
|
|
33237
|
+
const context = parse(mmelString, PARSER_CONFIG, options);
|
|
33238
|
+
return resolve(context, RESOLVER_CONFIG);
|
|
33239
|
+
}
|
|
33240
|
+
function loadFile(filePath, options = {}) {
|
|
33241
|
+
const content = preprocessIncludes(filePath);
|
|
33242
|
+
return load(content, options);
|
|
33243
|
+
}
|
|
33244
|
+
function dump2(standard) {
|
|
33245
|
+
return dump(standard, DUMPER_CONFIG);
|
|
33246
|
+
}
|
|
33247
|
+
|
|
33248
|
+
// src/fmt.ts
|
|
33249
|
+
var ALLOWLIST = ".primmel-allowlist.prl";
|
|
33250
|
+
function walkPrl(dir, out = []) {
|
|
33251
|
+
for (const e of readdirSync4(dir).sort()) {
|
|
33252
|
+
const p = join5(dir, e);
|
|
33253
|
+
if (statSync3(p).isDirectory()) {
|
|
33254
|
+
walkPrl(p, out);
|
|
33255
|
+
} else if (e.endsWith(".prl") && e !== ALLOWLIST) {
|
|
33256
|
+
out.push(p);
|
|
33257
|
+
}
|
|
33258
|
+
}
|
|
33259
|
+
return out;
|
|
33260
|
+
}
|
|
33261
|
+
function fmtPackage(dir, check = false) {
|
|
33262
|
+
const result = { dir, files: [], written: 0 };
|
|
33263
|
+
for (const file of walkPrl(dir)) {
|
|
33264
|
+
const src = readFileSync6(file, "utf8");
|
|
33265
|
+
if (/^\s*include\s+"/m.test(src)) {
|
|
33266
|
+
result.files.push({ file, status: "skipped-includes" });
|
|
33267
|
+
continue;
|
|
33268
|
+
}
|
|
33269
|
+
let canonical2;
|
|
33270
|
+
try {
|
|
33271
|
+
const raw = dump2(loadFile(file));
|
|
33272
|
+
if (dump2(load(raw)) !== raw) {
|
|
33273
|
+
result.files.push({ file, status: "unstable" });
|
|
33274
|
+
continue;
|
|
33275
|
+
}
|
|
33276
|
+
canonical2 = /^\s*metadata\s*\{/.test(src) ? raw : raw.replace(/^metadata \{\n(?: {2}\w+ ""\n)*\}\n+/, "");
|
|
33277
|
+
} catch {
|
|
33278
|
+
result.files.push({ file, status: "unstable" });
|
|
33279
|
+
continue;
|
|
33280
|
+
}
|
|
33281
|
+
if (canonical2 === src) {
|
|
33282
|
+
result.files.push({ file, status: "unchanged" });
|
|
33283
|
+
continue;
|
|
33284
|
+
}
|
|
33285
|
+
if (!check) {
|
|
33286
|
+
writeFileSync(file, canonical2);
|
|
33287
|
+
result.written += 1;
|
|
33288
|
+
}
|
|
33289
|
+
result.files.push({ file, status: "formatted" });
|
|
33290
|
+
}
|
|
33291
|
+
return result;
|
|
33292
|
+
}
|
|
33293
|
+
|
|
30512
33294
|
// src/export/reqif.ts
|
|
30513
33295
|
var REQIF_NAMESPACE = "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd";
|
|
30514
33296
|
var REQIF_VERSION = "1.0";
|
|
@@ -31782,23 +34564,23 @@ function renderJsonLd(prefixes, triples) {
|
|
|
31782
34564
|
|
|
31783
34565
|
// src/export/retrieval.ts
|
|
31784
34566
|
import { createHash } from "node:crypto";
|
|
31785
|
-
import { readdirSync as
|
|
31786
|
-
import { join as
|
|
34567
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
34568
|
+
import { join as join7, relative } from "node:path";
|
|
31787
34569
|
|
|
31788
34570
|
// src/export/unitsdb.ts
|
|
31789
|
-
import { existsSync as existsSync6, readFileSync as
|
|
31790
|
-
import { join as
|
|
34571
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "node:fs";
|
|
34572
|
+
import { join as join6 } from "node:path";
|
|
31791
34573
|
function loadUnitsDb(dir) {
|
|
31792
34574
|
if (!dir) {
|
|
31793
34575
|
return null;
|
|
31794
34576
|
}
|
|
31795
34577
|
try {
|
|
31796
34578
|
const entries = [];
|
|
31797
|
-
const jsonPath =
|
|
34579
|
+
const jsonPath = join6(dir, "units.json");
|
|
31798
34580
|
if (!existsSync6(jsonPath)) {
|
|
31799
34581
|
return null;
|
|
31800
34582
|
}
|
|
31801
|
-
const parsed = JSON.parse(
|
|
34583
|
+
const parsed = JSON.parse(readFileSync7(jsonPath, "utf8")).units;
|
|
31802
34584
|
if (!Array.isArray(parsed)) {
|
|
31803
34585
|
return null;
|
|
31804
34586
|
}
|
|
@@ -32029,12 +34811,12 @@ function retrievalDigest(value) {
|
|
|
32029
34811
|
return createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
|
|
32030
34812
|
}
|
|
32031
34813
|
function* walkPackage(dir) {
|
|
32032
|
-
for (const entry of
|
|
34814
|
+
for (const entry of readdirSync5(dir).sort()) {
|
|
32033
34815
|
if (entry === ".DS_Store") {
|
|
32034
34816
|
continue;
|
|
32035
34817
|
}
|
|
32036
|
-
const p =
|
|
32037
|
-
if (
|
|
34818
|
+
const p = join7(dir, entry);
|
|
34819
|
+
if (statSync4(p).isDirectory()) {
|
|
32038
34820
|
yield* walkPackage(p);
|
|
32039
34821
|
} else {
|
|
32040
34822
|
yield p;
|
|
@@ -32046,7 +34828,7 @@ function packageSourceHash(dir) {
|
|
|
32046
34828
|
for (const file of walkPackage(dir)) {
|
|
32047
34829
|
h.update(relative(dir, file));
|
|
32048
34830
|
h.update("\0");
|
|
32049
|
-
h.update(createHash("sha256").update(
|
|
34831
|
+
h.update(createHash("sha256").update(readFileSync8(file)).digest());
|
|
32050
34832
|
h.update("\n");
|
|
32051
34833
|
}
|
|
32052
34834
|
return h.digest("hex");
|
|
@@ -32302,6 +35084,9 @@ function retrievalFacet(unit, pkg) {
|
|
|
32302
35084
|
facet[`app_${dim}_match`] = match;
|
|
32303
35085
|
}
|
|
32304
35086
|
}
|
|
35087
|
+
if ((unit.method_refs ?? []).length > 0) {
|
|
35088
|
+
facet.method_refs = unit.method_refs.join("|");
|
|
35089
|
+
}
|
|
32305
35090
|
return facet;
|
|
32306
35091
|
}
|
|
32307
35092
|
function resolveTextAddress(address, elementIds) {
|
|
@@ -32446,11 +35231,34 @@ function requirementUnit(r) {
|
|
|
32446
35231
|
collectClauses(r)
|
|
32447
35232
|
);
|
|
32448
35233
|
}
|
|
35234
|
+
function processUnit(pr) {
|
|
35235
|
+
const steps = pr.steps ?? [];
|
|
35236
|
+
const calls = steps.map((s) => {
|
|
35237
|
+
const st = s;
|
|
35238
|
+
const call = st.calls || st.signatureBlock?.match(/\bcalls +([\w:/.-]+)/)?.[1] || "";
|
|
35239
|
+
return call ? { id: st.id ?? "", calls: call } : null;
|
|
35240
|
+
}).filter((s) => s !== null);
|
|
35241
|
+
return assemble(
|
|
35242
|
+
{
|
|
35243
|
+
id: pr.id,
|
|
35244
|
+
kind: "process",
|
|
35245
|
+
...present(pr.name) ? { name: pr.name } : {},
|
|
35246
|
+
...present(pr.summary) ? { statement: pr.summary } : {},
|
|
35247
|
+
...calls.length > 0 ? { calls } : {}
|
|
35248
|
+
},
|
|
35249
|
+
collectClauses(pr)
|
|
35250
|
+
);
|
|
35251
|
+
}
|
|
32449
35252
|
function conformanceTestUnit(t) {
|
|
32450
35253
|
const payload = {
|
|
32451
35254
|
...present(t.kind) ? { test_kind: t.kind } : {},
|
|
32452
35255
|
...present(t.methodRef) ? { method_ref: t.methodRef } : {}
|
|
32453
35256
|
};
|
|
35257
|
+
const methodRefs = [
|
|
35258
|
+
...new Set(
|
|
35259
|
+
[t.methodRef, ...(t.requiredCompetence ?? []).map((rc) => rc.methodRef)].filter((m) => present(m)).map((m) => m)
|
|
35260
|
+
)
|
|
35261
|
+
].sort();
|
|
32454
35262
|
const decision = acceptanceDecisionOf(t.acceptance);
|
|
32455
35263
|
const criteria = testAcceptanceCriteriaOf(t);
|
|
32456
35264
|
return assemble(
|
|
@@ -32478,6 +35286,7 @@ function conformanceTestUnit(t) {
|
|
|
32478
35286
|
}))
|
|
32479
35287
|
} : {},
|
|
32480
35288
|
...presentList(t.dependencies) ? { dependencies: t.dependencies } : {},
|
|
35289
|
+
...methodRefs.length > 0 ? { method_refs: methodRefs } : {},
|
|
32481
35290
|
...Object.keys(payload).length > 0 ? { payload } : {}
|
|
32482
35291
|
},
|
|
32483
35292
|
collectClauses(t)
|
|
@@ -32909,6 +35718,9 @@ function exportStandardRetrieval(standard, options = {}) {
|
|
|
32909
35718
|
for (const t of standard.conformanceTests ?? []) {
|
|
32910
35719
|
push(conformanceTestUnit(t), t.id);
|
|
32911
35720
|
}
|
|
35721
|
+
for (const pr of standard.processes ?? []) {
|
|
35722
|
+
push(processUnit(pr), pr.id);
|
|
35723
|
+
}
|
|
32912
35724
|
for (const t of standard.terms ?? []) {
|
|
32913
35725
|
push(termUnit(t, pkg.base_urn), t.id);
|
|
32914
35726
|
}
|
|
@@ -33219,8 +36031,8 @@ function exportPackageImpact(dir) {
|
|
|
33219
36031
|
}
|
|
33220
36032
|
|
|
33221
36033
|
// src/export/cddal.ts
|
|
33222
|
-
import { readFileSync as
|
|
33223
|
-
import { basename, join as
|
|
36034
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync6 } from "node:fs";
|
|
36035
|
+
import { basename, join as join8, resolve as resolve5 } from "node:path";
|
|
33224
36036
|
var CDDAL_PROJECTION_VERSION = "primmel-cddal/1";
|
|
33225
36037
|
function escapeCddalString(s) {
|
|
33226
36038
|
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -33366,23 +36178,23 @@ function projectCddal(model, packageId, l10n = /* @__PURE__ */ new Map()) {
|
|
|
33366
36178
|
}
|
|
33367
36179
|
function exportPackageCddal(dir) {
|
|
33368
36180
|
const model = loadPackage(dir);
|
|
33369
|
-
const l10nFiles =
|
|
33370
|
-
const l10n = readL10n(l10nFiles, (p) =>
|
|
36181
|
+
const l10nFiles = readdirSync6(dir).filter((e) => /^l10n\.[^/]+\.prl$/.test(e)).map((e) => join8(dir, e));
|
|
36182
|
+
const l10n = readL10n(l10nFiles, (p) => readFileSync9(p, "utf8"));
|
|
33371
36183
|
return projectCddal(model, basename(resolve5(dir)), l10n);
|
|
33372
36184
|
}
|
|
33373
36185
|
|
|
33374
36186
|
// src/package-diff.ts
|
|
33375
|
-
import { existsSync as existsSync7, readdirSync as
|
|
33376
|
-
import { join as
|
|
36187
|
+
import { existsSync as existsSync7, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
|
|
36188
|
+
import { join as join9 } from "path";
|
|
33377
36189
|
function packageMappings(dir, standard) {
|
|
33378
36190
|
const profiles = [...standard.mapProfiles ?? []];
|
|
33379
36191
|
if (existsSync7(dir)) {
|
|
33380
|
-
for (const entry of
|
|
36192
|
+
for (const entry of readdirSync7(dir).sort()) {
|
|
33381
36193
|
if (!entry.endsWith(".prm")) {
|
|
33382
36194
|
continue;
|
|
33383
36195
|
}
|
|
33384
36196
|
profiles.push(
|
|
33385
|
-
...prmToMapProfiles(loadPrm(
|
|
36197
|
+
...prmToMapProfiles(loadPrm(readFileSync10(join9(dir, entry), "utf8")))
|
|
33386
36198
|
);
|
|
33387
36199
|
}
|
|
33388
36200
|
}
|
|
@@ -33391,17 +36203,17 @@ function packageMappings(dir, standard) {
|
|
|
33391
36203
|
}
|
|
33392
36204
|
function packageClauseTexts(dir) {
|
|
33393
36205
|
const out = /* @__PURE__ */ new Map();
|
|
33394
|
-
const prdDir =
|
|
36206
|
+
const prdDir = join9(dir, "sources-prd");
|
|
33395
36207
|
if (!existsSync7(prdDir)) {
|
|
33396
36208
|
return out;
|
|
33397
36209
|
}
|
|
33398
|
-
for (const entry of
|
|
36210
|
+
for (const entry of readdirSync7(prdDir).sort()) {
|
|
33399
36211
|
if (!entry.endsWith(".sentences.json")) {
|
|
33400
36212
|
continue;
|
|
33401
36213
|
}
|
|
33402
36214
|
let payload;
|
|
33403
36215
|
try {
|
|
33404
|
-
payload = JSON.parse(
|
|
36216
|
+
payload = JSON.parse(readFileSync10(join9(prdDir, entry), "utf8"));
|
|
33405
36217
|
} catch {
|
|
33406
36218
|
continue;
|
|
33407
36219
|
}
|
|
@@ -33454,15 +36266,15 @@ var DIFF_USAGE = "Usage: primmel diff [--json] [--exit-code] [--compare-texts] [
|
|
|
33454
36266
|
var EXPORT_USAGE = "Usage: primmel export reqif|rdf|retrieval|impact|cddal <package-dir> [--out <file>] [--format turtle|jsonld]";
|
|
33455
36267
|
function readablePackageDirProblem(target, needsManifest) {
|
|
33456
36268
|
try {
|
|
33457
|
-
if (!
|
|
36269
|
+
if (!statSync5(target).isDirectory()) {
|
|
33458
36270
|
return "not a directory";
|
|
33459
36271
|
}
|
|
33460
|
-
|
|
36272
|
+
readdirSync8(target);
|
|
33461
36273
|
} catch (e) {
|
|
33462
36274
|
const err = e;
|
|
33463
36275
|
return err.code === "ENOENT" ? "no such directory" : err.message;
|
|
33464
36276
|
}
|
|
33465
|
-
if (needsManifest && !existsSync8(
|
|
36277
|
+
if (needsManifest && !existsSync8(join10(target, "package.primmel"))) {
|
|
33466
36278
|
return "no package.primmel found";
|
|
33467
36279
|
}
|
|
33468
36280
|
return null;
|
|
@@ -33688,7 +36500,7 @@ function exportCli(args2) {
|
|
|
33688
36500
|
const out = values.get("--out");
|
|
33689
36501
|
if (out !== void 0) {
|
|
33690
36502
|
try {
|
|
33691
|
-
|
|
36503
|
+
writeFileSync2(out, document);
|
|
33692
36504
|
} catch (e) {
|
|
33693
36505
|
console.error(`cannot write ${out}: ${e.message}`);
|
|
33694
36506
|
process.exit(1);
|
|
@@ -33699,6 +36511,32 @@ function exportCli(args2) {
|
|
|
33699
36511
|
}
|
|
33700
36512
|
process.exit(0);
|
|
33701
36513
|
}
|
|
36514
|
+
function fmtCli(argv) {
|
|
36515
|
+
const check = argv.includes("--check");
|
|
36516
|
+
const rest = argv.filter((a) => a !== "--check");
|
|
36517
|
+
const dir = rest[rest.length - 1];
|
|
36518
|
+
if (!dir || !existsSync8(dir)) {
|
|
36519
|
+
console.error(`cannot read package at ${dir || "(none)"}: no such directory`);
|
|
36520
|
+
process.exit(2);
|
|
36521
|
+
}
|
|
36522
|
+
let result;
|
|
36523
|
+
try {
|
|
36524
|
+
result = fmtPackage(dir, check);
|
|
36525
|
+
} catch (e) {
|
|
36526
|
+
console.error(`cannot format package at ${dir}: ${e.message}`);
|
|
36527
|
+
process.exit(2);
|
|
36528
|
+
}
|
|
36529
|
+
for (const f of result.files) {
|
|
36530
|
+
const label = f.file.startsWith(dir + "/") ? f.file.slice(dir.length + 1) : f.file;
|
|
36531
|
+
const note = f.status === "formatted" ? check ? "would reformat" : "formatted" : f.status === "unchanged" ? "ok" : f.status === "unstable" ? "UNSTABLE \u2014 does not round-trip; left as-is" : "skipped (includes)";
|
|
36532
|
+
console.log(` ${label}: ${note}`);
|
|
36533
|
+
}
|
|
36534
|
+
const unstable = result.files.filter((f) => f.status === "unstable").length;
|
|
36535
|
+
console.log(
|
|
36536
|
+
`fmt: ${result.files.length} files, ${check ? result.files.filter((f) => f.status === "formatted").length + " would reformat" : result.written + " written"}, ${unstable} unstable`
|
|
36537
|
+
);
|
|
36538
|
+
process.exit(unstable > 0 ? 2 : check && result.files.some((f) => f.status === "formatted") ? 1 : 0);
|
|
36539
|
+
}
|
|
33702
36540
|
var args = process.argv.slice(2);
|
|
33703
36541
|
if (args[0] === "diff") {
|
|
33704
36542
|
diffCli(args.slice(1));
|
|
@@ -33706,6 +36544,12 @@ if (args[0] === "diff") {
|
|
|
33706
36544
|
checkCli(args.slice(1));
|
|
33707
36545
|
} else if (args[0] === "export") {
|
|
33708
36546
|
exportCli(args.slice(1));
|
|
36547
|
+
} else if (args[0] === "fmt") {
|
|
36548
|
+
fmtCli(args.slice(1));
|
|
33709
36549
|
} else {
|
|
33710
36550
|
checkCli(args);
|
|
33711
36551
|
}
|
|
36552
|
+
//! The Primmel expression language: the lexer, the precedence parser, and
|
|
36553
|
+
//! the AST. The machine-executable core — first-class syntax, never a
|
|
36554
|
+
//! quoted string. The identifiers resolve against the caller's scope (the
|
|
36555
|
+
//! argument bindings); the unbound names surface at parse time.
|