@primmel/primmel 1.21.12 → 1.21.14
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 +1155 -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 +83 -0
- package/dist/src/expressions/index.d.ts.map +1 -0
- package/dist/src/expressions/index.js +382 -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/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 +2791 -1925
- package/dist-cli/primmel.mjs +2931 -76
- 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,403 @@ 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", "collect"]);
|
|
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
|
+
if (tok.value === "true" || tok.value === "false") {
|
|
2699
|
+
return { type: "bool", value: tok.value === "true" };
|
|
2700
|
+
}
|
|
2701
|
+
if (tok.value === "if") {
|
|
2702
|
+
const cond = this.parseLevel(0);
|
|
2703
|
+
const thenTok = this.take();
|
|
2704
|
+
if (thenTok.kind !== "name" || thenTok.value !== "then") {
|
|
2705
|
+
throw new Error('expression: expected "then" in the conditional');
|
|
2706
|
+
}
|
|
2707
|
+
const whenTrue = this.parseLevel(0);
|
|
2708
|
+
const elseTok = this.take();
|
|
2709
|
+
if (elseTok.kind !== "name" || elseTok.value !== "else") {
|
|
2710
|
+
throw new Error('expression: expected "else" in the conditional');
|
|
2711
|
+
}
|
|
2712
|
+
const whenFalse = this.parseLevel(0);
|
|
2713
|
+
const endTok = this.take();
|
|
2714
|
+
if (endTok.kind !== "name" || endTok.value !== "endif") {
|
|
2715
|
+
throw new Error(
|
|
2716
|
+
'expression: expected "endif" to close the conditional'
|
|
2717
|
+
);
|
|
2718
|
+
}
|
|
2719
|
+
return { type: "ifelse", cond, then: whenTrue, else: whenFalse };
|
|
2720
|
+
}
|
|
2721
|
+
const segs = [tok.value];
|
|
2722
|
+
while (this.peek()?.kind === "op" && this.peek().value === ".") {
|
|
2723
|
+
this.take();
|
|
2724
|
+
const seg = this.take();
|
|
2725
|
+
if (seg.kind !== "name") {
|
|
2726
|
+
throw new Error('expression: expected a path segment after "."');
|
|
2727
|
+
}
|
|
2728
|
+
segs.push(seg.value);
|
|
2729
|
+
}
|
|
2730
|
+
const next = this.peek();
|
|
2731
|
+
if (next?.kind === "op" && next.value === "(" && !WORD_BINOPS.has(segs[0])) {
|
|
2732
|
+
this.take();
|
|
2733
|
+
const args2 = [];
|
|
2734
|
+
const closing = this.peek();
|
|
2735
|
+
if (closing?.kind === "op" && closing.value === ")") {
|
|
2736
|
+
this.take();
|
|
2737
|
+
return { type: "call", callee: segs.join("."), args: args2 };
|
|
2738
|
+
}
|
|
2739
|
+
for (; ; ) {
|
|
2740
|
+
args2.push(this.parseLevel(0));
|
|
2741
|
+
const sep = this.peek();
|
|
2742
|
+
if (sep?.kind === "op" && sep.value === ",") {
|
|
2743
|
+
this.take();
|
|
2744
|
+
continue;
|
|
2745
|
+
}
|
|
2746
|
+
break;
|
|
2747
|
+
}
|
|
2748
|
+
const close = this.take();
|
|
2749
|
+
if (close.kind !== "op" || close.value !== ")") {
|
|
2750
|
+
throw new Error("expression: expected closing parenthesis");
|
|
2751
|
+
}
|
|
2752
|
+
return { type: "call", callee: segs.join("."), args: args2 };
|
|
2753
|
+
}
|
|
2754
|
+
const arrow = this.peek();
|
|
2755
|
+
if (arrow?.kind === "op" && arrow.value === "->") {
|
|
2756
|
+
this.take();
|
|
2757
|
+
const opTok = this.take();
|
|
2758
|
+
if (opTok.kind !== "name" || !NAV_OPS.has(opTok.value)) {
|
|
2759
|
+
throw new Error(
|
|
2760
|
+
"expression: expected a collection iterator (forAll | exists | select | collect)"
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
if (this.peek()?.kind !== "op" || this.peek().value !== "(") {
|
|
2764
|
+
throw new Error("expression: expected ( after the iterator");
|
|
2765
|
+
}
|
|
2766
|
+
this.take();
|
|
2767
|
+
const varTok = this.take();
|
|
2768
|
+
if (varTok.kind !== "name") {
|
|
2769
|
+
throw new Error("expression: expected the lambda parameter");
|
|
2770
|
+
}
|
|
2771
|
+
if (this.peek()?.kind !== "op" || this.peek().value !== "|") {
|
|
2772
|
+
throw new Error("expression: expected | after the parameter");
|
|
2773
|
+
}
|
|
2774
|
+
this.take();
|
|
2775
|
+
const body = this.parseLevel(0);
|
|
2776
|
+
const close = this.take();
|
|
2777
|
+
if (close.kind !== "op" || close.value !== ")") {
|
|
2778
|
+
throw new Error("expression: expected closing parenthesis");
|
|
2779
|
+
}
|
|
2780
|
+
return {
|
|
2781
|
+
type: "nav",
|
|
2782
|
+
source: segs.join("."),
|
|
2783
|
+
op: opTok.value,
|
|
2784
|
+
var: varTok.value,
|
|
2785
|
+
body
|
|
2786
|
+
};
|
|
2787
|
+
}
|
|
2788
|
+
return { type: "name", path: segs };
|
|
2789
|
+
}
|
|
2790
|
+
throw new Error(`expression: unexpected token "${String(tok.value)}"`);
|
|
2791
|
+
}
|
|
2792
|
+
};
|
|
2793
|
+
function parseExpression(src) {
|
|
2794
|
+
return new ExprParser(lex(src)).parse();
|
|
2795
|
+
}
|
|
2796
|
+
function canonicalizeExpression(raw) {
|
|
2797
|
+
const body = raw.trim();
|
|
2798
|
+
if (body.length === 0) {
|
|
2799
|
+
throw new Error("expression: the block is empty");
|
|
2800
|
+
}
|
|
2801
|
+
return renderExpression(parseExpression(body));
|
|
2802
|
+
}
|
|
2803
|
+
function freeIdentifiers(ast) {
|
|
2804
|
+
const out = { names: [], calls: [] };
|
|
2805
|
+
const walk = (node, bound) => {
|
|
2806
|
+
switch (node.type) {
|
|
2807
|
+
case "num":
|
|
2808
|
+
return;
|
|
2809
|
+
case "str":
|
|
2810
|
+
return;
|
|
2811
|
+
case "bool":
|
|
2812
|
+
return;
|
|
2813
|
+
case "ifelse":
|
|
2814
|
+
walk(node.cond, bound);
|
|
2815
|
+
walk(node.then, bound);
|
|
2816
|
+
walk(node.else, bound);
|
|
2817
|
+
return;
|
|
2818
|
+
case "name": {
|
|
2819
|
+
if (bound.has(node.path[0].split(".")[0])) {
|
|
2820
|
+
return;
|
|
2821
|
+
}
|
|
2822
|
+
out.names.push(node.path.join("."));
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2825
|
+
case "call":
|
|
2826
|
+
out.calls.push(node.callee);
|
|
2827
|
+
for (const a of node.args) {
|
|
2828
|
+
walk(a, bound);
|
|
2829
|
+
}
|
|
2830
|
+
return;
|
|
2831
|
+
case "unop":
|
|
2832
|
+
walk(node.operand, bound);
|
|
2833
|
+
return;
|
|
2834
|
+
case "binop":
|
|
2835
|
+
walk(node.left, bound);
|
|
2836
|
+
walk(node.right, bound);
|
|
2837
|
+
return;
|
|
2838
|
+
case "nav": {
|
|
2839
|
+
const inner = new Set(bound);
|
|
2840
|
+
inner.add(node["var"]);
|
|
2841
|
+
walk({ type: "name", path: [node.source] }, bound);
|
|
2842
|
+
walk(node.body, inner);
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
};
|
|
2847
|
+
walk(ast, /* @__PURE__ */ new Set());
|
|
2848
|
+
return out;
|
|
2849
|
+
}
|
|
2850
|
+
function renderExpression(ast) {
|
|
2851
|
+
switch (ast.type) {
|
|
2852
|
+
case "num":
|
|
2853
|
+
return String(ast.value);
|
|
2854
|
+
case "str":
|
|
2855
|
+
return "'" + ast.value + "'";
|
|
2856
|
+
case "bool":
|
|
2857
|
+
return ast.value ? "true" : "false";
|
|
2858
|
+
case "ifelse":
|
|
2859
|
+
return "if " + renderExpression(ast.cond) + " then " + renderExpression(ast.then) + " else " + renderExpression(ast.else) + " endif";
|
|
2860
|
+
case "name":
|
|
2861
|
+
return ast.path.join(".");
|
|
2862
|
+
case "call":
|
|
2863
|
+
return ast.callee + "(" + ast.args.map(renderExpression).join(", ") + ")";
|
|
2864
|
+
case "unop": {
|
|
2865
|
+
const inner = renderExpression(ast.operand);
|
|
2866
|
+
return ast.op + (ast.operand.type === "binop" ? " (" + inner + ")" : " " + inner);
|
|
2867
|
+
}
|
|
2868
|
+
case "nav":
|
|
2869
|
+
return ast.source + " -> " + ast.op + "(" + ast["var"] + " | " + renderExpression(ast.body) + ")";
|
|
2870
|
+
case "binop":
|
|
2871
|
+
return renderExpression(ast.left) + " " + ast.op + " " + renderExpression(ast.right);
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
// src/ser-des/expression-carrier.ts
|
|
2876
|
+
function readExpressionCarrier(token, what) {
|
|
2877
|
+
if (token.startsWith("{")) {
|
|
2878
|
+
try {
|
|
2879
|
+
return {
|
|
2880
|
+
source: canonicalizeExpression(unwrapBlock(token)),
|
|
2881
|
+
inline: true
|
|
2882
|
+
};
|
|
2883
|
+
} catch (e) {
|
|
2884
|
+
throw new Error(
|
|
2885
|
+
`Parsing error: ${what}: ${e.message ?? String(e)}`
|
|
2886
|
+
);
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
if (token.length >= 2 && token.charAt(0) === '"') {
|
|
2890
|
+
return {
|
|
2891
|
+
source: unescapeString(token.substr(1, token.length - 2)),
|
|
2892
|
+
inline: false
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2895
|
+
return { source: token, inline: false };
|
|
2896
|
+
}
|
|
2897
|
+
function dumpExpressionBlock(keyword, source, indent) {
|
|
2898
|
+
const body = source.split("\n").map((l) => indent + " " + l).join("\n");
|
|
2899
|
+
return indent + keyword + " {\n" + body + "\n" + indent + "}\n";
|
|
2900
|
+
}
|
|
2901
|
+
function readArgsBlock(token) {
|
|
2902
|
+
const at = tokenize(token);
|
|
2903
|
+
const args2 = [];
|
|
2904
|
+
let k = 0;
|
|
2905
|
+
while (k < at.length) {
|
|
2906
|
+
const name = unescapeStringOrBare(at[k++]);
|
|
2907
|
+
if (k >= at.length) {
|
|
2908
|
+
throw new Error(`limit args: "${name}" binds to nothing`);
|
|
2909
|
+
}
|
|
2910
|
+
if (at[k] !== "<-") {
|
|
2911
|
+
throw new Error(
|
|
2912
|
+
`limit args: expected "<-" after "${name}" (name <- source)`
|
|
2913
|
+
);
|
|
2914
|
+
}
|
|
2915
|
+
k += 1;
|
|
2916
|
+
if (k >= at.length) {
|
|
2917
|
+
throw new Error(`limit args: "${name}" binds to nothing`);
|
|
2918
|
+
}
|
|
2919
|
+
args2.push({ name, source: unescapeStringOrBare(at[k++]) });
|
|
2920
|
+
}
|
|
2921
|
+
return args2;
|
|
2922
|
+
}
|
|
2923
|
+
function unescapeStringOrBare(t) {
|
|
2924
|
+
if (t.length >= 2 && t.charAt(0) === '"' && t.charAt(t.length - 1) === '"') {
|
|
2925
|
+
return unescapeString(t.substr(1, t.length - 2));
|
|
2926
|
+
}
|
|
2927
|
+
return t;
|
|
2928
|
+
}
|
|
2498
2929
|
|
|
2499
2930
|
// src/ser-des/config/quantity.ts
|
|
2500
2931
|
var NUMERIC = /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/;
|
|
@@ -2987,10 +3418,20 @@ var STEP_KINDS = /* @__PURE__ */ new Set([
|
|
|
2987
3418
|
"timer_event",
|
|
2988
3419
|
"signal_event"
|
|
2989
3420
|
]);
|
|
3421
|
+
function parseCallBindings(block) {
|
|
3422
|
+
return parseParamList(unwrapBlock(block)).map((pr) => ({
|
|
3423
|
+
param: pr.name,
|
|
3424
|
+
bind: pr.type
|
|
3425
|
+
}));
|
|
3426
|
+
}
|
|
2990
3427
|
function parseStepBody(id, kind, block) {
|
|
2991
3428
|
const step = {
|
|
2992
3429
|
id,
|
|
2993
3430
|
kind,
|
|
3431
|
+
signatureBlock: "",
|
|
3432
|
+
sigInputs: [],
|
|
3433
|
+
sigOutputs: [],
|
|
3434
|
+
completion: "",
|
|
2994
3435
|
executor: "",
|
|
2995
3436
|
role: "",
|
|
2996
3437
|
capture: "",
|
|
@@ -3260,6 +3701,112 @@ var parseProcess = function(id, data) {
|
|
|
3260
3701
|
result._relations.page = value();
|
|
3261
3702
|
} else if (keyword === "validate_provision") {
|
|
3262
3703
|
result._relations.provision = tokenizePackage(value());
|
|
3704
|
+
} else if (keyword === "step" || keyword === "binding") {
|
|
3705
|
+
const sid = stripWrapping(value());
|
|
3706
|
+
const blockTok = value();
|
|
3707
|
+
if (keyword === "step") {
|
|
3708
|
+
const raw = blockTok !== void 0 && blockTok.startsWith("{") ? unwrapBlock(blockTok) : blockTok ?? "";
|
|
3709
|
+
const st = {
|
|
3710
|
+
id: sid,
|
|
3711
|
+
kind: "action",
|
|
3712
|
+
executor: "",
|
|
3713
|
+
role: "",
|
|
3714
|
+
capture: "",
|
|
3715
|
+
reads: [],
|
|
3716
|
+
writes: [],
|
|
3717
|
+
fires: "",
|
|
3718
|
+
calls: "",
|
|
3719
|
+
callIn: [],
|
|
3720
|
+
callOut: [],
|
|
3721
|
+
wait: "",
|
|
3722
|
+
period: "",
|
|
3723
|
+
signal: "",
|
|
3724
|
+
signatureBlock: raw,
|
|
3725
|
+
sigInputs: [],
|
|
3726
|
+
sigOutputs: [],
|
|
3727
|
+
completion: "",
|
|
3728
|
+
description: ""
|
|
3729
|
+
};
|
|
3730
|
+
const tt = tokenizePackage(raw);
|
|
3731
|
+
let ti = 0;
|
|
3732
|
+
while (ti < tt.length) {
|
|
3733
|
+
const tc = tt[ti++];
|
|
3734
|
+
if (ti >= tt.length) {
|
|
3735
|
+
break;
|
|
3736
|
+
}
|
|
3737
|
+
if (tc === "inputs" || tc === "outputs") {
|
|
3738
|
+
const pairs = parseParamList(unwrapBlock(tt[ti++]));
|
|
3739
|
+
const names = pairs.map((pr) => pr.name);
|
|
3740
|
+
if (tc === "inputs") {
|
|
3741
|
+
st.sigInputs = names;
|
|
3742
|
+
} else {
|
|
3743
|
+
st.sigOutputs = names;
|
|
3744
|
+
}
|
|
3745
|
+
} else if (tc === "requires") {
|
|
3746
|
+
const ids = tokenizePackage(unwrapBlock(tt[ti++])).map(stripWrapping).filter((x) => x.length > 0);
|
|
3747
|
+
(result.stepRequires ??= []).push(...ids);
|
|
3748
|
+
} else if (tc === "completion") {
|
|
3749
|
+
if (tt[ti] === "check") {
|
|
3750
|
+
ti += 1;
|
|
3751
|
+
st.completionGate = stripWrapping(tt[ti++]);
|
|
3752
|
+
const bt = tokenizePackage(unwrapBlock(tt[ti++]));
|
|
3753
|
+
let bi = 0;
|
|
3754
|
+
while (bi < bt.length) {
|
|
3755
|
+
const bc = bt[bi++];
|
|
3756
|
+
if (bi >= bt.length) {
|
|
3757
|
+
break;
|
|
3758
|
+
}
|
|
3759
|
+
if (bc === "expression") {
|
|
3760
|
+
const c = readExpressionCarrier(
|
|
3761
|
+
bt[bi++],
|
|
3762
|
+
"step completion"
|
|
3763
|
+
);
|
|
3764
|
+
st.completion = c.source;
|
|
3765
|
+
st.completionBound = c.inline || void 0;
|
|
3766
|
+
} else {
|
|
3767
|
+
bi = skipUnknownEntry(bt, bi);
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
} else {
|
|
3771
|
+
const c = readExpressionCarrier(tt[ti++], "step completion");
|
|
3772
|
+
st.completion = c.source;
|
|
3773
|
+
st.completionBound = c.inline || void 0;
|
|
3774
|
+
}
|
|
3775
|
+
} else if (tc === "calls") {
|
|
3776
|
+
st.calls = stripWrapping(tt[ti++]);
|
|
3777
|
+
if (ti < tt.length && tt[ti] === "with") {
|
|
3778
|
+
const wt = tokenize(unwrapBlock(tt[ti++]));
|
|
3779
|
+
let wk = 0;
|
|
3780
|
+
while (wk < wt.length) {
|
|
3781
|
+
const wc = wt[wk++];
|
|
3782
|
+
if (wk >= wt.length) {
|
|
3783
|
+
break;
|
|
3784
|
+
}
|
|
3785
|
+
if (wc === "in") {
|
|
3786
|
+
st.callIn.push(...parseCallBindings(wt[wk++]));
|
|
3787
|
+
} else if (wc === "out") {
|
|
3788
|
+
st.callOut.push(...parseCallBindings(wt[wk++]));
|
|
3789
|
+
} else {
|
|
3790
|
+
unwrapBlock(wt[wk++]);
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
} else if (tc === "description") {
|
|
3795
|
+
st.description = stripWrapping(tt[ti++]);
|
|
3796
|
+
} else {
|
|
3797
|
+
ti = skipUnknownEntry(tt, ti);
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
(result.steps ??= []).push(st);
|
|
3801
|
+
} else {
|
|
3802
|
+
(result.bindings ??= []).push({
|
|
3803
|
+
id: sid,
|
|
3804
|
+
block: blockTok !== void 0 && blockTok.startsWith("{") ? unwrapBlock(blockTok) : blockTok ?? ""
|
|
3805
|
+
});
|
|
3806
|
+
}
|
|
3807
|
+
} else if (keyword === "requires") {
|
|
3808
|
+
const inner = tokenizePackage(unwrapBlock(value()));
|
|
3809
|
+
(result.stepRequires ??= []).push(...inner.map(stripWrapping));
|
|
3263
3810
|
} else if (keyword === "validate_measurement") {
|
|
3264
3811
|
result.measure = tokenizePackage(value()).map((x) => unwrapBlock(x));
|
|
3265
3812
|
} else if (keyword === "output") {
|
|
@@ -3417,6 +3964,25 @@ var resolveProcess = function(ctx, unresolved) {
|
|
|
3417
3964
|
}
|
|
3418
3965
|
return p;
|
|
3419
3966
|
};
|
|
3967
|
+
function indentBlock(block) {
|
|
3968
|
+
return block.split("\n").map((line) => line ? " " + line : line).join("\n");
|
|
3969
|
+
}
|
|
3970
|
+
function dumpProcessTree(process2, lookup, nested = false) {
|
|
3971
|
+
let out = dumpProcess(process2, { nested });
|
|
3972
|
+
if (process2.children.length > 0) {
|
|
3973
|
+
const childBlocks = [];
|
|
3974
|
+
for (const childId of process2.children) {
|
|
3975
|
+
const child = lookup.get(childId);
|
|
3976
|
+
if (child) {
|
|
3977
|
+
childBlocks.push(indentBlock(dumpProcessTree(child, lookup, true)));
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
if (childBlocks.length > 0) {
|
|
3981
|
+
out = out.replace(/\n}\n$/, "\n" + childBlocks.join("\n") + "}\n");
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
return out;
|
|
3985
|
+
}
|
|
3420
3986
|
function dumpParamList(params) {
|
|
3421
3987
|
return params.map(
|
|
3422
3988
|
(p) => p.name + (p.type ? " : " + p.type : "") + (p.initial !== void 0 ? " = " + dumpQuantityValue(p.initial) : "")
|
|
@@ -3531,6 +4097,26 @@ var dumpProcess = function(process2, ctx) {
|
|
|
3531
4097
|
if (process2.machineSteps && process2.machineSteps.length > 0) {
|
|
3532
4098
|
out += " machine_steps { " + process2.machineSteps.map(dumpBareSafe).join(" ") + " }\n";
|
|
3533
4099
|
}
|
|
4100
|
+
for (const st of process2.steps ?? []) {
|
|
4101
|
+
if (st.signatureBlock) {
|
|
4102
|
+
const lines = st.signatureBlock.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
4103
|
+
out += " step " + st.id + " {\n";
|
|
4104
|
+
for (const line of lines) {
|
|
4105
|
+
out += " " + line + "\n";
|
|
4106
|
+
}
|
|
4107
|
+
out += " }\n";
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
for (const b of process2.bindings ?? []) {
|
|
4111
|
+
out += " binding " + b.id + " {\n";
|
|
4112
|
+
for (const line of b.block.split("\n")) {
|
|
4113
|
+
out += line === "" ? "\n" : " " + line + "\n";
|
|
4114
|
+
}
|
|
4115
|
+
out += " }\n";
|
|
4116
|
+
}
|
|
4117
|
+
for (const req of process2.stepRequires ?? []) {
|
|
4118
|
+
out += " requires { " + req + " }\n";
|
|
4119
|
+
}
|
|
3534
4120
|
const inputIds = process2.inputRefs && process2.inputRefs.length > 0 ? process2.inputRefs : process2.input.map((r) => r.id);
|
|
3535
4121
|
if (inputIds.length > 0) {
|
|
3536
4122
|
out += " reference_data_registry {\n";
|
|
@@ -5270,6 +5856,11 @@ function parseColumnDefs(block) {
|
|
|
5270
5856
|
if (!name) {
|
|
5271
5857
|
break;
|
|
5272
5858
|
}
|
|
5859
|
+
if (i < t.length && t[i] === "{") {
|
|
5860
|
+
throw new Error(
|
|
5861
|
+
`Parsing error: table. Column "${name}": the old columns dialect (colN { name ... type ... }) is retired \u2014 write the canonical form: ${name === "" ? "name" : name}: type "unit"`
|
|
5862
|
+
);
|
|
5863
|
+
}
|
|
5273
5864
|
if (i < t.length && t[i] === ":") {
|
|
5274
5865
|
i++;
|
|
5275
5866
|
}
|
|
@@ -6695,6 +7286,7 @@ var parseSymbol = function(id, data) {
|
|
|
6695
7286
|
type: "number",
|
|
6696
7287
|
unit: "1",
|
|
6697
7288
|
latex: "",
|
|
7289
|
+
renders: [],
|
|
6698
7290
|
values: [],
|
|
6699
7291
|
series: null,
|
|
6700
7292
|
kind: "",
|
|
@@ -6746,6 +7338,20 @@ var parseSymbol = function(id, data) {
|
|
|
6746
7338
|
result.unit = unwrapped(value);
|
|
6747
7339
|
} else if (command === "latex") {
|
|
6748
7340
|
result.latex = unwrapped(value);
|
|
7341
|
+
} else if (command === "render") {
|
|
7342
|
+
const notation = stripWrapping(value());
|
|
7343
|
+
const text = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
7344
|
+
if (!result.renders) {
|
|
7345
|
+
result.renders = [];
|
|
7346
|
+
}
|
|
7347
|
+
if (["asciimath", "latex", "unicodemath", "mathml", "omml"].includes(
|
|
7348
|
+
notation
|
|
7349
|
+
)) {
|
|
7350
|
+
result.renders.push({ notation, text });
|
|
7351
|
+
if (notation === "latex" && !result.latex) {
|
|
7352
|
+
result.latex = text;
|
|
7353
|
+
}
|
|
7354
|
+
}
|
|
6749
7355
|
} else if (command === "values") {
|
|
6750
7356
|
const v = value();
|
|
6751
7357
|
result.values = v.startsWith("{") ? tokenizePackage(v).map(stripWrapping) : [stripWrapping(v)];
|
|
@@ -6826,6 +7432,9 @@ var dumpSymbol = function(s) {
|
|
|
6826
7432
|
if (s.latex) {
|
|
6827
7433
|
out += ' latex "' + escapeString(s.latex) + '"\n';
|
|
6828
7434
|
}
|
|
7435
|
+
for (const r of s.renders ?? []) {
|
|
7436
|
+
out += " render " + r.notation + ' "' + escapeString(r.text) + '"\n';
|
|
7437
|
+
}
|
|
6829
7438
|
if (s.values.length > 0) {
|
|
6830
7439
|
out += " values { " + s.values.map(dumpBareSafe).join(" ") + " }\n";
|
|
6831
7440
|
}
|
|
@@ -6971,6 +7580,23 @@ var parseCalculation = function(id, data) {
|
|
|
6971
7580
|
result.description = unwrapBlock(t[i++]);
|
|
6972
7581
|
} else if (command === "expression") {
|
|
6973
7582
|
result.expression = unwrapBlock(t[i++]);
|
|
7583
|
+
} else if (command === "math") {
|
|
7584
|
+
const inner = tokenizePackage(unwrapBlock(t[i++]));
|
|
7585
|
+
let notation = "";
|
|
7586
|
+
let formula = "";
|
|
7587
|
+
let j = 0;
|
|
7588
|
+
while (j < inner.length) {
|
|
7589
|
+
const k = inner[j++];
|
|
7590
|
+
if (j >= inner.length) {
|
|
7591
|
+
break;
|
|
7592
|
+
}
|
|
7593
|
+
if (k === "notation") {
|
|
7594
|
+
notation = stripWrapping(inner[j++]);
|
|
7595
|
+
} else if (k === "formula") {
|
|
7596
|
+
formula = stripWrapping(inner[j++]);
|
|
7597
|
+
}
|
|
7598
|
+
}
|
|
7599
|
+
result.math = { notation, formula };
|
|
6974
7600
|
} else if (command === "reference") {
|
|
6975
7601
|
result._relations.ref = tokenizePackage(t[i++]);
|
|
6976
7602
|
} else if (command === "ref") {
|
|
@@ -7287,6 +7913,23 @@ function parseVariant(vid, block, calcId) {
|
|
|
7287
7913
|
variant.params = tokenize(stripWrapping(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
|
|
7288
7914
|
} else if (cmd === "expression") {
|
|
7289
7915
|
variant.expression = stripWrapping(t[i++]);
|
|
7916
|
+
} else if (cmd === "math") {
|
|
7917
|
+
const inner = tokenizePackage(unwrapBlock(t[i++]));
|
|
7918
|
+
let notation = "";
|
|
7919
|
+
let formula = "";
|
|
7920
|
+
let j = 0;
|
|
7921
|
+
while (j < inner.length) {
|
|
7922
|
+
const k = inner[j++];
|
|
7923
|
+
if (j >= inner.length) {
|
|
7924
|
+
break;
|
|
7925
|
+
}
|
|
7926
|
+
if (k === "notation") {
|
|
7927
|
+
notation = stripWrapping(inner[j++]);
|
|
7928
|
+
} else if (k === "formula") {
|
|
7929
|
+
formula = stripWrapping(inner[j++]);
|
|
7930
|
+
}
|
|
7931
|
+
}
|
|
7932
|
+
variant.math = { notation, formula };
|
|
7290
7933
|
} else if (cmd === "lookup") {
|
|
7291
7934
|
variant.lookup = parseLookup(unwrapBlock(t[i++]));
|
|
7292
7935
|
} else if (cmd === "profile") {
|
|
@@ -7427,6 +8070,12 @@ var dumpCalculation = function(c) {
|
|
|
7427
8070
|
if (c.expression) {
|
|
7428
8071
|
out += ' expression "' + escapeString(c.expression) + '"\n';
|
|
7429
8072
|
}
|
|
8073
|
+
if (c.math) {
|
|
8074
|
+
out += " math {\n";
|
|
8075
|
+
out += " notation " + c.math.notation + "\n";
|
|
8076
|
+
out += ' formula "' + escapeString(c.math.formula) + '"\n';
|
|
8077
|
+
out += " }\n";
|
|
8078
|
+
}
|
|
7430
8079
|
if (c.params && c.params.length > 0) {
|
|
7431
8080
|
out += " params { " + c.params.join(" ") + " }\n";
|
|
7432
8081
|
}
|
|
@@ -8605,7 +9254,7 @@ function parseRequiredCompetence(block) {
|
|
|
8605
9254
|
const entry = {
|
|
8606
9255
|
kind: stripWrapping(t[i++]),
|
|
8607
9256
|
range: null,
|
|
8608
|
-
|
|
9257
|
+
methodRef: "",
|
|
8609
9258
|
resolution: null,
|
|
8610
9259
|
stability: null,
|
|
8611
9260
|
description: ""
|
|
@@ -8638,8 +9287,8 @@ function parseRequiredCompetence(block) {
|
|
|
8638
9287
|
}
|
|
8639
9288
|
}
|
|
8640
9289
|
entry.range = range;
|
|
8641
|
-
} else if (cc === "
|
|
8642
|
-
entry.
|
|
9290
|
+
} else if (cc === "method_ref") {
|
|
9291
|
+
entry.methodRef = stripWrapping(ct[j++]);
|
|
8643
9292
|
} else if (cc === "resolution") {
|
|
8644
9293
|
entry.resolution = readQuantity(unwrapBlock(ct[j++]));
|
|
8645
9294
|
} else if (cc === "stability") {
|
|
@@ -8682,8 +9331,8 @@ function dumpRequiredCompetence(entries) {
|
|
|
8682
9331
|
line += ' unit "' + escapeString(e.range.unit) + '" }\n';
|
|
8683
9332
|
out += line;
|
|
8684
9333
|
}
|
|
8685
|
-
if (e.
|
|
8686
|
-
out +=
|
|
9334
|
+
if (e.methodRef) {
|
|
9335
|
+
out += " method_ref " + e.methodRef + "\n";
|
|
8687
9336
|
}
|
|
8688
9337
|
out += dumpQuantity("resolution", e.resolution);
|
|
8689
9338
|
out += dumpQuantity("stability", e.stability);
|
|
@@ -8706,8 +9355,7 @@ var parseCompetenceKind = function(id, data) {
|
|
|
8706
9355
|
id,
|
|
8707
9356
|
label: "",
|
|
8708
9357
|
definition: "",
|
|
8709
|
-
source: null
|
|
8710
|
-
methodStandards: []
|
|
9358
|
+
source: null
|
|
8711
9359
|
};
|
|
8712
9360
|
const t = tokenizePackage(data);
|
|
8713
9361
|
let i = 0;
|
|
@@ -8724,14 +9372,6 @@ var parseCompetenceKind = function(id, data) {
|
|
|
8724
9372
|
result.definition = readValue(t[i++]);
|
|
8725
9373
|
} else if (keyword === "source") {
|
|
8726
9374
|
result.source = readSource(unwrapBlock(t[i++]));
|
|
8727
|
-
} else if (keyword === "method_standard") {
|
|
8728
|
-
const stdId = stripWrapping(t[i++]);
|
|
8729
|
-
if (i >= t.length) {
|
|
8730
|
-
throw new Error(
|
|
8731
|
-
`Parsing error: competence_kind. ID ${id}: Expecting title for method_standard ${stdId}`
|
|
8732
|
-
);
|
|
8733
|
-
}
|
|
8734
|
-
result.methodStandards.push({ id: stdId, title: readValue(t[i++]) });
|
|
8735
9375
|
} else if (keyword === "ref") {
|
|
8736
9376
|
const rr = parseRef(t, i, stripWrapping, unwrapBlock);
|
|
8737
9377
|
if (!foldRefIntoLegacy(result, rr.ref)) {
|
|
@@ -8762,9 +9402,6 @@ var dumpCompetenceKind = function(k) {
|
|
|
8762
9402
|
if (k.source && (k.source.doc || k.source.clause)) {
|
|
8763
9403
|
out += ' source { doc "' + escapeString(k.source.doc) + '" clause "' + escapeString(k.source.clause) + '"' + (k.source.fragment ? ' fragment "' + escapeString(k.source.fragment) + '"' : "") + " }\n";
|
|
8764
9404
|
}
|
|
8765
|
-
for (const ms of k.methodStandards) {
|
|
8766
|
-
out += " method_standard " + ms.id + ' "' + escapeString(ms.title) + '"\n';
|
|
8767
|
-
}
|
|
8768
9405
|
out += dumpCorrespondences(
|
|
8769
9406
|
k.correspondences,
|
|
8770
9407
|
" ",
|
|
@@ -8825,7 +9462,9 @@ function parseTestVariables(block) {
|
|
|
8825
9462
|
} else if (vc === "source") {
|
|
8826
9463
|
v.source = stripWrapping(vt[j++]);
|
|
8827
9464
|
} else if (vc === "derivation") {
|
|
8828
|
-
|
|
9465
|
+
const c = readExpressionCarrier(vt[j++], "test variable derivation");
|
|
9466
|
+
v.derivation = c.source;
|
|
9467
|
+
v.derivationBound = c.inline || void 0;
|
|
8829
9468
|
} else if (vc === "description") {
|
|
8830
9469
|
v.description = stripWrapping(vt[j++]);
|
|
8831
9470
|
} else if (vc === "item_type") {
|
|
@@ -8885,7 +9524,9 @@ function parsePreconditions(block) {
|
|
|
8885
9524
|
break;
|
|
8886
9525
|
}
|
|
8887
9526
|
if (pc === "check") {
|
|
8888
|
-
|
|
9527
|
+
const c = readExpressionCarrier(pt[j++], "precondition check");
|
|
9528
|
+
p.check = c.source;
|
|
9529
|
+
p.checkBound = c.inline || void 0;
|
|
8889
9530
|
} else if (pc === "description") {
|
|
8890
9531
|
p.description = stripWrapping(pt[j++]);
|
|
8891
9532
|
} else if (pc === "on_violation") {
|
|
@@ -9651,8 +10292,17 @@ var dumpConformanceTest = function(ct) {
|
|
|
9651
10292
|
if (v.source) {
|
|
9652
10293
|
line += "source " + v.source + " ";
|
|
9653
10294
|
}
|
|
10295
|
+
let derivationBlock = "";
|
|
9654
10296
|
if (v.derivation) {
|
|
9655
|
-
|
|
10297
|
+
if (v.derivationBound) {
|
|
10298
|
+
derivationBlock = dumpExpressionBlock(
|
|
10299
|
+
"derivation",
|
|
10300
|
+
v.derivation,
|
|
10301
|
+
" "
|
|
10302
|
+
);
|
|
10303
|
+
} else {
|
|
10304
|
+
line += 'derivation "' + escapeString(v.derivation) + '" ';
|
|
10305
|
+
}
|
|
9656
10306
|
}
|
|
9657
10307
|
if (v.description) {
|
|
9658
10308
|
line += 'description "' + escapeString(v.description) + '" ';
|
|
@@ -9679,7 +10329,11 @@ var dumpConformanceTest = function(ct) {
|
|
|
9679
10329
|
}
|
|
9680
10330
|
line += pv + "} ";
|
|
9681
10331
|
}
|
|
9682
|
-
|
|
10332
|
+
if (derivationBlock) {
|
|
10333
|
+
out += line + "\n" + derivationBlock + " }\n";
|
|
10334
|
+
} else {
|
|
10335
|
+
out += line + "}\n";
|
|
10336
|
+
}
|
|
9683
10337
|
}
|
|
9684
10338
|
out += " }\n";
|
|
9685
10339
|
}
|
|
@@ -9707,8 +10361,13 @@ var dumpConformanceTest = function(ct) {
|
|
|
9707
10361
|
out += " preconditions {\n";
|
|
9708
10362
|
for (const p of ct.preconditions) {
|
|
9709
10363
|
let line = " precondition " + p.id + " { ";
|
|
10364
|
+
let checkBlock = "";
|
|
9710
10365
|
if (p.check) {
|
|
9711
|
-
|
|
10366
|
+
if (p.checkBound) {
|
|
10367
|
+
checkBlock = dumpExpressionBlock("check", p.check, " ");
|
|
10368
|
+
} else {
|
|
10369
|
+
line += 'check "' + escapeString(p.check) + '" ';
|
|
10370
|
+
}
|
|
9712
10371
|
}
|
|
9713
10372
|
if (p.description) {
|
|
9714
10373
|
line += 'description "' + escapeString(p.description) + '" ';
|
|
@@ -9717,7 +10376,11 @@ var dumpConformanceTest = function(ct) {
|
|
|
9717
10376
|
if (p.onUnresolvable) {
|
|
9718
10377
|
line += "on_unresolvable " + p.onUnresolvable + " ";
|
|
9719
10378
|
}
|
|
9720
|
-
|
|
10379
|
+
if (checkBlock) {
|
|
10380
|
+
out += line + "\n" + checkBlock + " }\n";
|
|
10381
|
+
} else {
|
|
10382
|
+
out += line + "}\n";
|
|
10383
|
+
}
|
|
9721
10384
|
}
|
|
9722
10385
|
out += " }\n";
|
|
9723
10386
|
}
|
|
@@ -10082,7 +10745,9 @@ var parseVerdict = function(id, data) {
|
|
|
10082
10745
|
} else if (keyword === "behavior") {
|
|
10083
10746
|
result.behavior = value();
|
|
10084
10747
|
} else if (keyword === "derive" || keyword === "expression") {
|
|
10085
|
-
|
|
10748
|
+
const c = readExpressionCarrier(value(), "verdict derive");
|
|
10749
|
+
result.derive = c.source;
|
|
10750
|
+
result.deriveBound = c.inline || void 0;
|
|
10086
10751
|
} else if (keyword === "inputs" || keyword === "uses") {
|
|
10087
10752
|
result.inputs = readIdList3(value());
|
|
10088
10753
|
} else if (keyword === "series_reduction") {
|
|
@@ -10140,7 +10805,11 @@ var dumpVerdict = function(v) {
|
|
|
10140
10805
|
out += " }\n";
|
|
10141
10806
|
}
|
|
10142
10807
|
if (v.derive) {
|
|
10143
|
-
|
|
10808
|
+
if (v.deriveBound) {
|
|
10809
|
+
out += dumpExpressionBlock("derive", v.derive, " ");
|
|
10810
|
+
} else {
|
|
10811
|
+
out += ' derive "' + escapeString(v.derive) + '"\n';
|
|
10812
|
+
}
|
|
10144
10813
|
}
|
|
10145
10814
|
if (v.inputs.length > 0) {
|
|
10146
10815
|
out += " inputs { " + v.inputs.join(" ") + " }\n";
|
|
@@ -10743,8 +11412,15 @@ var parseConstraint = function(id, data) {
|
|
|
10743
11412
|
result.stereotype = stripWrapping(t[i++]);
|
|
10744
11413
|
} else if (keyword === "name") {
|
|
10745
11414
|
result.name = readValue2(t[i++]);
|
|
11415
|
+
} else if (keyword === "args") {
|
|
11416
|
+
if (!result.args) {
|
|
11417
|
+
result.args = [];
|
|
11418
|
+
}
|
|
11419
|
+
result.args.push(...readArgsBlock(unwrapBlock(t[i++])));
|
|
10746
11420
|
} else if (keyword === "check") {
|
|
10747
|
-
|
|
11421
|
+
const c = readExpressionCarrier(t[i++], "constraint check");
|
|
11422
|
+
result.check = c.source;
|
|
11423
|
+
result.checkBound = c.inline || void 0;
|
|
10748
11424
|
} else if (keyword === "violation_meaning") {
|
|
10749
11425
|
result.violationMeaning = readValue2(t[i++]);
|
|
10750
11426
|
} else if (keyword === "on_violation") {
|
|
@@ -10778,8 +11454,19 @@ var dumpConstraint = function(c) {
|
|
|
10778
11454
|
if (c.name) {
|
|
10779
11455
|
out += ' name "' + escapeString(c.name) + '"\n';
|
|
10780
11456
|
}
|
|
11457
|
+
if ((c.args ?? []).length > 0) {
|
|
11458
|
+
out += " args {\n";
|
|
11459
|
+
for (const a of c.args ?? []) {
|
|
11460
|
+
out += " " + a.name + " <- " + a.source + "\n";
|
|
11461
|
+
}
|
|
11462
|
+
out += " }\n";
|
|
11463
|
+
}
|
|
10781
11464
|
if (c.check) {
|
|
10782
|
-
|
|
11465
|
+
if (c.checkBound) {
|
|
11466
|
+
out += dumpExpressionBlock("check", c.check, " ");
|
|
11467
|
+
} else {
|
|
11468
|
+
out += ' check "' + escapeString(c.check) + '"\n';
|
|
11469
|
+
}
|
|
10783
11470
|
}
|
|
10784
11471
|
if (c.violationMeaning) {
|
|
10785
11472
|
out += ' violation_meaning "' + escapeString(c.violationMeaning) + '"\n';
|
|
@@ -10798,6 +11485,169 @@ var dumpConstraint = function(c) {
|
|
|
10798
11485
|
return out;
|
|
10799
11486
|
};
|
|
10800
11487
|
|
|
11488
|
+
// src/ser-des/config/uncertaintyBudget.ts
|
|
11489
|
+
var DISTRIBUTIONS = /* @__PURE__ */ new Set([
|
|
11490
|
+
"rectangular",
|
|
11491
|
+
"triangular",
|
|
11492
|
+
"normal",
|
|
11493
|
+
"ushape"
|
|
11494
|
+
]);
|
|
11495
|
+
function readComponent(block) {
|
|
11496
|
+
const c = {
|
|
11497
|
+
id: "",
|
|
11498
|
+
type: "B",
|
|
11499
|
+
series: "",
|
|
11500
|
+
distribution: "",
|
|
11501
|
+
halfWidth: "",
|
|
11502
|
+
unit: "",
|
|
11503
|
+
source: null,
|
|
11504
|
+
description: ""
|
|
11505
|
+
};
|
|
11506
|
+
const t = tokenizePackage(block);
|
|
11507
|
+
let i = 0;
|
|
11508
|
+
while (i < t.length) {
|
|
11509
|
+
const kw = t[i++];
|
|
11510
|
+
if (i >= t.length) {
|
|
11511
|
+
throw new Error(
|
|
11512
|
+
`Parsing error: uncertainty_budget component. ID ${c.id}: Expecting value for ${kw}`
|
|
11513
|
+
);
|
|
11514
|
+
}
|
|
11515
|
+
if (kw === "type") {
|
|
11516
|
+
const v = stripWrapping(t[i++]);
|
|
11517
|
+
if (v !== "A" && v !== "B") {
|
|
11518
|
+
throw new Error(
|
|
11519
|
+
`Parsing error: uncertainty_budget component. ID ${c.id}: unknown type "${v}" (A evaluates the statistics of a series; B states a distribution)`
|
|
11520
|
+
);
|
|
11521
|
+
}
|
|
11522
|
+
c.type = v;
|
|
11523
|
+
} else if (kw === "series") {
|
|
11524
|
+
c.series = stripWrapping(t[i++]);
|
|
11525
|
+
} else if (kw === "distribution") {
|
|
11526
|
+
const v = stripWrapping(t[i++]);
|
|
11527
|
+
if (!DISTRIBUTIONS.has(v)) {
|
|
11528
|
+
throw new Error(
|
|
11529
|
+
`Parsing error: uncertainty_budget component. ID ${c.id}: unknown distribution "${v}" (rectangular | triangular | normal | ushape)`
|
|
11530
|
+
);
|
|
11531
|
+
}
|
|
11532
|
+
c.distribution = v;
|
|
11533
|
+
} else if (kw === "half_width") {
|
|
11534
|
+
c.halfWidth = stripWrapping(t[i++]);
|
|
11535
|
+
} else if (kw === "unit") {
|
|
11536
|
+
c.unit = stripWrapping(t[i++]);
|
|
11537
|
+
} else if (kw === "description") {
|
|
11538
|
+
c.description = stripWrapping(t[i++]);
|
|
11539
|
+
} else if (kw === "source") {
|
|
11540
|
+
c.source = readSource(unwrapBlock(t[i++]));
|
|
11541
|
+
} else {
|
|
11542
|
+
i = skipUnknownValue(t, i, kw);
|
|
11543
|
+
}
|
|
11544
|
+
}
|
|
11545
|
+
return c;
|
|
11546
|
+
}
|
|
11547
|
+
var parseUncertaintyBudget = function(id, data) {
|
|
11548
|
+
const result = {
|
|
11549
|
+
id,
|
|
11550
|
+
target: "",
|
|
11551
|
+
coverageK: "",
|
|
11552
|
+
components: [],
|
|
11553
|
+
source: null
|
|
11554
|
+
};
|
|
11555
|
+
const t = tokenizePackage(data);
|
|
11556
|
+
let i = 0;
|
|
11557
|
+
while (i < t.length) {
|
|
11558
|
+
const kw = t[i++];
|
|
11559
|
+
if (i >= t.length) {
|
|
11560
|
+
throw new Error(
|
|
11561
|
+
`Parsing error: uncertainty_budget. ID ${id}: Expecting value for ${kw}`
|
|
11562
|
+
);
|
|
11563
|
+
}
|
|
11564
|
+
if (kw === "target") {
|
|
11565
|
+
result.target = stripWrapping(t[i++]);
|
|
11566
|
+
} else if (kw === "coverage") {
|
|
11567
|
+
const head = stripWrapping(t[i++]);
|
|
11568
|
+
if (head !== "k") {
|
|
11569
|
+
throw new Error(
|
|
11570
|
+
`Parsing error: uncertainty_budget. ID ${id}: coverage states its factor \u2014 coverage k <number>`
|
|
11571
|
+
);
|
|
11572
|
+
}
|
|
11573
|
+
result.coverageK = stripWrapping(t[i++]);
|
|
11574
|
+
} else if (kw === "component") {
|
|
11575
|
+
if (t[i].startsWith("{")) {
|
|
11576
|
+
throw new Error(
|
|
11577
|
+
`Parsing error: uncertainty_budget. ID ${id}: a component carries an id \u2014 component <id> { \u2026 }`
|
|
11578
|
+
);
|
|
11579
|
+
}
|
|
11580
|
+
const cid = stripWrapping(t[i++]);
|
|
11581
|
+
const c = readComponent(unwrapBlock(t[i++]));
|
|
11582
|
+
c.id = cid;
|
|
11583
|
+
result.components.push(c);
|
|
11584
|
+
} else if (kw === "source") {
|
|
11585
|
+
result.source = readSource(unwrapBlock(t[i++]));
|
|
11586
|
+
} else if (kw === "ref") {
|
|
11587
|
+
const rr = parseRef(t, i, stripWrapping, unwrapBlock);
|
|
11588
|
+
if (!foldRefIntoLegacy(result, rr.ref)) {
|
|
11589
|
+
(result.refs ??= []).push(rr.ref);
|
|
11590
|
+
}
|
|
11591
|
+
i = rr.next;
|
|
11592
|
+
} else if (kw === "corresponds") {
|
|
11593
|
+
const cc = parseCorresponds(t, i, stripWrapping);
|
|
11594
|
+
(result.correspondences ??= []).push(cc.corr);
|
|
11595
|
+
i = cc.next;
|
|
11596
|
+
} else {
|
|
11597
|
+
i = skipUnknownValue(t, i, kw);
|
|
11598
|
+
}
|
|
11599
|
+
}
|
|
11600
|
+
return (ctx) => {
|
|
11601
|
+
ctx.uncertaintyBudgets[id] = result;
|
|
11602
|
+
return ctx;
|
|
11603
|
+
};
|
|
11604
|
+
};
|
|
11605
|
+
var dumpUncertaintyBudget = function(b) {
|
|
11606
|
+
let out = "uncertainty_budget " + b.id + " {\n";
|
|
11607
|
+
if (b.target) {
|
|
11608
|
+
out += " target " + b.target + "\n";
|
|
11609
|
+
}
|
|
11610
|
+
if (b.coverageK) {
|
|
11611
|
+
out += " coverage k " + b.coverageK + "\n";
|
|
11612
|
+
}
|
|
11613
|
+
for (const c of b.components) {
|
|
11614
|
+
out += " component " + c.id + " {\n";
|
|
11615
|
+
out += " type " + c.type + "\n";
|
|
11616
|
+
if (c.type === "A" && c.series) {
|
|
11617
|
+
out += " series " + c.series + "\n";
|
|
11618
|
+
}
|
|
11619
|
+
if (c.type === "B") {
|
|
11620
|
+
if (c.distribution) {
|
|
11621
|
+
out += " distribution " + c.distribution + "\n";
|
|
11622
|
+
}
|
|
11623
|
+
if (c.halfWidth) {
|
|
11624
|
+
out += " half_width " + c.halfWidth + "\n";
|
|
11625
|
+
}
|
|
11626
|
+
if (c.unit) {
|
|
11627
|
+
out += ' unit "' + escapeString(c.unit) + '"\n';
|
|
11628
|
+
}
|
|
11629
|
+
}
|
|
11630
|
+
if (c.description) {
|
|
11631
|
+
out += ' description "' + escapeString(c.description) + '"\n';
|
|
11632
|
+
}
|
|
11633
|
+
if (c.source && (c.source.doc || c.source.clause)) {
|
|
11634
|
+
out += ' source { doc "' + escapeString(c.source.doc) + '" clause "' + escapeString(c.source.clause) + '"' + (c.source.fragment ? ' fragment "' + escapeString(c.source.fragment) + '"' : "") + " }\n";
|
|
11635
|
+
}
|
|
11636
|
+
out += " }\n";
|
|
11637
|
+
}
|
|
11638
|
+
if (b.source && (b.source.doc || b.source.clause)) {
|
|
11639
|
+
out += ' source { doc "' + escapeString(b.source.doc) + '" clause "' + escapeString(b.source.clause) + '"' + (b.source.fragment ? ' fragment "' + escapeString(b.source.fragment) + '"' : "") + " }\n";
|
|
11640
|
+
}
|
|
11641
|
+
out += dumpCorrespondences(
|
|
11642
|
+
b.correspondences,
|
|
11643
|
+
" ",
|
|
11644
|
+
escapeString,
|
|
11645
|
+
dumpBareSafe
|
|
11646
|
+
);
|
|
11647
|
+
out += "}\n";
|
|
11648
|
+
return out;
|
|
11649
|
+
};
|
|
11650
|
+
|
|
10801
11651
|
// src/ser-des/config/discrepancyRecord.ts
|
|
10802
11652
|
var VALID_STATUSES = ["open", "resolved"];
|
|
10803
11653
|
var parseDiscrepancyRecord = function(id, data) {
|
|
@@ -11146,8 +11996,8 @@ function readAccepts(block) {
|
|
|
11146
11996
|
}
|
|
11147
11997
|
return accepts;
|
|
11148
11998
|
}
|
|
11149
|
-
function
|
|
11150
|
-
|
|
11999
|
+
function blankLimit() {
|
|
12000
|
+
return {
|
|
11151
12001
|
expression: "",
|
|
11152
12002
|
uses: [],
|
|
11153
12003
|
modality: "",
|
|
@@ -11158,15 +12008,51 @@ function readLimit(block) {
|
|
|
11158
12008
|
acceptance: null,
|
|
11159
12009
|
sourceDiscrepancy: null
|
|
11160
12010
|
};
|
|
11161
|
-
|
|
11162
|
-
|
|
12011
|
+
}
|
|
12012
|
+
function readLimit(block) {
|
|
12013
|
+
const limit = blankLimit();
|
|
12014
|
+
readLegacyLimitFields(tokenize(block), limit, 0);
|
|
12015
|
+
return limit;
|
|
12016
|
+
}
|
|
12017
|
+
function readExpressionBlock(raw) {
|
|
12018
|
+
return canonicalizeExpression(raw);
|
|
12019
|
+
}
|
|
12020
|
+
function readLegacyLimitFields(t, limit, start) {
|
|
12021
|
+
let i = start;
|
|
11163
12022
|
while (i < t.length) {
|
|
11164
12023
|
const cmd = t[i++];
|
|
11165
12024
|
if (i >= t.length) {
|
|
11166
12025
|
break;
|
|
11167
12026
|
}
|
|
11168
|
-
if (cmd === "
|
|
11169
|
-
limit.
|
|
12027
|
+
if (cmd === "args") {
|
|
12028
|
+
if (!limit.args) {
|
|
12029
|
+
limit.args = [];
|
|
12030
|
+
}
|
|
12031
|
+
const at = tokenize(unwrapBlock(t[i++]));
|
|
12032
|
+
let k = 0;
|
|
12033
|
+
while (k < at.length) {
|
|
12034
|
+
const name = stripWrapping(at[k++]);
|
|
12035
|
+
const arrow = at[k];
|
|
12036
|
+
if (arrow !== "<-") {
|
|
12037
|
+
throw new Error(
|
|
12038
|
+
`limit args: expected "<-" after "${name}" (name <- source)`
|
|
12039
|
+
);
|
|
12040
|
+
}
|
|
12041
|
+
k += 1;
|
|
12042
|
+
if (k >= at.length) {
|
|
12043
|
+
throw new Error(`limit args: "${name}" binds to nothing`);
|
|
12044
|
+
}
|
|
12045
|
+
const source = stripWrapping(at[k++]);
|
|
12046
|
+
limit.args.push({ name, source });
|
|
12047
|
+
}
|
|
12048
|
+
} else if (cmd === "expression") {
|
|
12049
|
+
const value = t[i++];
|
|
12050
|
+
if (value.startsWith("{")) {
|
|
12051
|
+
limit.argsBound = true;
|
|
12052
|
+
limit.expression = readExpressionBlock(unwrapBlock(value));
|
|
12053
|
+
} else {
|
|
12054
|
+
limit.expression = stripWrapping(value);
|
|
12055
|
+
}
|
|
11170
12056
|
} else if (cmd === "uses") {
|
|
11171
12057
|
limit.uses = readIdList4(t[i++]);
|
|
11172
12058
|
} else if (cmd === "modality") {
|
|
@@ -11203,7 +12089,6 @@ function readLimit(block) {
|
|
|
11203
12089
|
i = skipUnknownValue(t, i, cmd);
|
|
11204
12090
|
}
|
|
11205
12091
|
}
|
|
11206
|
-
return limit;
|
|
11207
12092
|
}
|
|
11208
12093
|
function readSubjects(block) {
|
|
11209
12094
|
const out = [];
|
|
@@ -11415,6 +12300,52 @@ var parseRequirement = function(id, data) {
|
|
|
11415
12300
|
};
|
|
11416
12301
|
};
|
|
11417
12302
|
function dumpLimit(limit) {
|
|
12303
|
+
if (limit.argsBound) {
|
|
12304
|
+
let out2 = " limit {\n";
|
|
12305
|
+
if ((limit.args ?? []).length > 0) {
|
|
12306
|
+
out2 += " args {\n";
|
|
12307
|
+
for (const a of limit.args ?? []) {
|
|
12308
|
+
out2 += " " + a.name + " <- " + a.source + "\n";
|
|
12309
|
+
}
|
|
12310
|
+
out2 += " }\n";
|
|
12311
|
+
}
|
|
12312
|
+
out2 += " expression {\n";
|
|
12313
|
+
for (const line of limit.expression.split("\n")) {
|
|
12314
|
+
out2 += " " + line + "\n";
|
|
12315
|
+
}
|
|
12316
|
+
out2 += " }\n";
|
|
12317
|
+
if (limit.modality) {
|
|
12318
|
+
out2 += " modality " + limit.modality + "\n";
|
|
12319
|
+
}
|
|
12320
|
+
if (limit.relativeTo) {
|
|
12321
|
+
out2 += " relative_to " + limit.relativeTo + "\n";
|
|
12322
|
+
}
|
|
12323
|
+
if (limit.notes) {
|
|
12324
|
+
out2 += ' notes "' + escapeString(limit.notes) + '"\n';
|
|
12325
|
+
}
|
|
12326
|
+
if (limit.accepts) {
|
|
12327
|
+
const a = limit.accepts;
|
|
12328
|
+
let line = " accepts { verdict " + a.verdict;
|
|
12329
|
+
if (a.op) {
|
|
12330
|
+
line += " op " + a.op;
|
|
12331
|
+
}
|
|
12332
|
+
if (a.limit) {
|
|
12333
|
+
line += ' limit "' + escapeString(a.limit) + '"';
|
|
12334
|
+
}
|
|
12335
|
+
if (a.sourceDiscrepancy) {
|
|
12336
|
+
line += " " + dumpSourceDiscrepancy(a.sourceDiscrepancy, "");
|
|
12337
|
+
}
|
|
12338
|
+
out2 += line + " }\n";
|
|
12339
|
+
}
|
|
12340
|
+
if (limit.acceptance) {
|
|
12341
|
+
out2 += dumpAcceptance(limit.acceptance, " ") + "\n";
|
|
12342
|
+
}
|
|
12343
|
+
if (limit.sourceDiscrepancy) {
|
|
12344
|
+
out2 += dumpSourceDiscrepancy(limit.sourceDiscrepancy, " ") + "\n";
|
|
12345
|
+
}
|
|
12346
|
+
out2 += " }\n";
|
|
12347
|
+
return out2;
|
|
12348
|
+
}
|
|
11418
12349
|
let out = " limit {\n";
|
|
11419
12350
|
if (limit.expression) {
|
|
11420
12351
|
out += ' expression "' + escapeString(limit.expression) + '"\n';
|
|
@@ -11578,8 +12509,12 @@ var parseRequirementClass = function(id, data) {
|
|
|
11578
12509
|
subject: "",
|
|
11579
12510
|
guidance: "",
|
|
11580
12511
|
dependencies: [],
|
|
11581
|
-
referenceIds: []
|
|
12512
|
+
referenceIds: [],
|
|
12513
|
+
limit: null,
|
|
12514
|
+
members: []
|
|
11582
12515
|
};
|
|
12516
|
+
const nestedParsers = [];
|
|
12517
|
+
const members = [];
|
|
11583
12518
|
const t = tokenizePackage(data);
|
|
11584
12519
|
let i = 0;
|
|
11585
12520
|
while (i < t.length) {
|
|
@@ -11603,11 +12538,24 @@ var parseRequirementClass = function(id, data) {
|
|
|
11603
12538
|
result.dependencies = readIdList4(t[i++]);
|
|
11604
12539
|
} else if (cmd === "reference") {
|
|
11605
12540
|
result.referenceIds = readIdList4(t[i++]);
|
|
12541
|
+
} else if (cmd === "limit") {
|
|
12542
|
+
result.limit = readLimit(unwrapBlock(t[i++]));
|
|
12543
|
+
} else if (cmd === "requirement") {
|
|
12544
|
+
const childId = stripWrapping(t[i++]);
|
|
12545
|
+
const childBlock = t[i++];
|
|
12546
|
+
const childParse = parseRequirement(childId, unwrapBlock(childBlock));
|
|
12547
|
+
nestedParsers.push(childParse);
|
|
12548
|
+
members.push(childId);
|
|
11606
12549
|
} else {
|
|
11607
12550
|
i = skipUnknownValue(t, i, cmd);
|
|
11608
12551
|
}
|
|
11609
12552
|
}
|
|
11610
12553
|
return (ctx) => {
|
|
12554
|
+
const c = ctx;
|
|
12555
|
+
for (const parse2 of nestedParsers) {
|
|
12556
|
+
parse2(c);
|
|
12557
|
+
}
|
|
12558
|
+
result.members = members;
|
|
11611
12559
|
ctx.requirementClasses[id] = result;
|
|
11612
12560
|
return ctx;
|
|
11613
12561
|
};
|
|
@@ -11632,6 +12580,9 @@ var dumpRequirementClass = function(rc) {
|
|
|
11632
12580
|
if (rc.referenceIds.length > 0) {
|
|
11633
12581
|
out += " reference { " + rc.referenceIds.join(" ") + " }\n";
|
|
11634
12582
|
}
|
|
12583
|
+
if (rc.limit) {
|
|
12584
|
+
out += dumpLimit(rc.limit);
|
|
12585
|
+
}
|
|
11635
12586
|
out += "}\n";
|
|
11636
12587
|
return out;
|
|
11637
12588
|
};
|
|
@@ -11700,6 +12651,8 @@ var parsePackage = function(data) {
|
|
|
11700
12651
|
manifest.title = stripWrapping(t[i++]);
|
|
11701
12652
|
} else if (cmd === "version") {
|
|
11702
12653
|
manifest.version = stripWrapping(t[i++]);
|
|
12654
|
+
} else if (cmd === "language") {
|
|
12655
|
+
manifest.language = stripWrapping(t[i++]);
|
|
11703
12656
|
} else if (cmd === "editions") {
|
|
11704
12657
|
manifest.editions = readList(t[i++]);
|
|
11705
12658
|
} else if (cmd === "baseUrn" || cmd === "base_urn") {
|
|
@@ -18912,6 +19865,298 @@ var dumpPartAnnex = function(a) {
|
|
|
18912
19865
|
return out;
|
|
18913
19866
|
};
|
|
18914
19867
|
|
|
19868
|
+
// src/ser-des/config/lmlAligned.ts
|
|
19869
|
+
var MATH_NOTATIONS = ["asciimath", "latex", "unicodemath", "mathml", "omml"];
|
|
19870
|
+
var MAPPING_FORMATS = ["xml", "yaml", "json", "toml", "csv"];
|
|
19871
|
+
function splitMappingId(id) {
|
|
19872
|
+
const at = id.indexOf(":");
|
|
19873
|
+
const format = at === -1 ? "xml" : id.slice(0, at);
|
|
19874
|
+
return { format, target: at === -1 ? id : id.slice(at + 1) };
|
|
19875
|
+
}
|
|
19876
|
+
var parseWireMapping = function(id, data) {
|
|
19877
|
+
const { format, target } = splitMappingId(id);
|
|
19878
|
+
const out = {
|
|
19879
|
+
id,
|
|
19880
|
+
format,
|
|
19881
|
+
target,
|
|
19882
|
+
element: "",
|
|
19883
|
+
namespaceRef: "",
|
|
19884
|
+
content: "",
|
|
19885
|
+
mixed: false,
|
|
19886
|
+
renderNil: null,
|
|
19887
|
+
entries: [],
|
|
19888
|
+
source: null
|
|
19889
|
+
};
|
|
19890
|
+
forEachEntry(
|
|
19891
|
+
data,
|
|
19892
|
+
(command, value, peek) => {
|
|
19893
|
+
if (command === "element") {
|
|
19894
|
+
out.element = stripWrapping(value());
|
|
19895
|
+
} else if (command === "namespace") {
|
|
19896
|
+
out.namespaceRef = stripWrapping(value());
|
|
19897
|
+
} else if (command === "mixed_content") {
|
|
19898
|
+
value();
|
|
19899
|
+
out.mixed = true;
|
|
19900
|
+
} else if (command === "render_nil") {
|
|
19901
|
+
out.renderNil = stripWrapping(value()) === "true";
|
|
19902
|
+
} else if (command === "map_content") {
|
|
19903
|
+
out.content = stripWrapping(value());
|
|
19904
|
+
} else if (command === "map_element" || command === "map_attribute" || command === "map") {
|
|
19905
|
+
const wire = stripWrapping(value());
|
|
19906
|
+
const name = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
19907
|
+
const kind = command === "map_element" ? "element" : command === "map_attribute" ? "attribute" : "map";
|
|
19908
|
+
out.entries.push({ kind, wire, name, modifier: "" });
|
|
19909
|
+
} else if (command === "map_key" || command === "map_value") {
|
|
19910
|
+
const modifier = stripWrapping(value());
|
|
19911
|
+
const name = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
19912
|
+
out.entries.push({ kind: "map", wire: command, name, modifier });
|
|
19913
|
+
} else {
|
|
19914
|
+
return false;
|
|
19915
|
+
}
|
|
19916
|
+
return true;
|
|
19917
|
+
},
|
|
19918
|
+
{ construct: "mapping", id }
|
|
19919
|
+
);
|
|
19920
|
+
return (ctx) => {
|
|
19921
|
+
ctx.wireMappings[id] = out;
|
|
19922
|
+
return ctx;
|
|
19923
|
+
};
|
|
19924
|
+
};
|
|
19925
|
+
var dumpWireMapping = function(w) {
|
|
19926
|
+
const lines = [`mapping ${w.format} ${w.target} {`];
|
|
19927
|
+
if (w.element) {
|
|
19928
|
+
lines.push(` element "${escapeString(w.element)}"`);
|
|
19929
|
+
}
|
|
19930
|
+
if (w.namespaceRef) {
|
|
19931
|
+
lines.push(` namespace ${w.namespaceRef}`);
|
|
19932
|
+
}
|
|
19933
|
+
for (const e of w.entries) {
|
|
19934
|
+
if (e.kind === "map" && e.modifier) {
|
|
19935
|
+
lines.push(` ${e.wire} ${e.modifier} ${e.name}`);
|
|
19936
|
+
} else {
|
|
19937
|
+
const kw = e.kind === "element" ? "map_element" : e.kind === "attribute" ? "map_attribute" : "map";
|
|
19938
|
+
lines.push(` ${kw} "${escapeString(e.wire)}" ${e.name}`);
|
|
19939
|
+
}
|
|
19940
|
+
}
|
|
19941
|
+
if (w.content) {
|
|
19942
|
+
lines.push(` map_content ${w.content}`);
|
|
19943
|
+
}
|
|
19944
|
+
if (w.mixed) {
|
|
19945
|
+
lines.push(` mixed_content`);
|
|
19946
|
+
}
|
|
19947
|
+
if (w.renderNil !== null) {
|
|
19948
|
+
lines.push(` render_nil ${w.renderNil}`);
|
|
19949
|
+
}
|
|
19950
|
+
lines.push("}");
|
|
19951
|
+
return lines.join("\n");
|
|
19952
|
+
};
|
|
19953
|
+
var parseStringFormat = function(rawId, data) {
|
|
19954
|
+
if (!rawId.startsWith(":")) {
|
|
19955
|
+
throw new Error(
|
|
19956
|
+
`Parsing error: string_format. ID ${rawId}: the registered format name carries the colon sigil (string_format :${rawId})`
|
|
19957
|
+
);
|
|
19958
|
+
}
|
|
19959
|
+
const id = rawId.slice(1);
|
|
19960
|
+
const out = { id, artifact: "", root: "", source: null };
|
|
19961
|
+
forEachEntry(
|
|
19962
|
+
data,
|
|
19963
|
+
(command, value) => {
|
|
19964
|
+
if (command === "artifact") {
|
|
19965
|
+
out.artifact = stripWrapping(value());
|
|
19966
|
+
} else if (command === "root") {
|
|
19967
|
+
out.root = stripWrapping(value());
|
|
19968
|
+
} else {
|
|
19969
|
+
return false;
|
|
19970
|
+
}
|
|
19971
|
+
return true;
|
|
19972
|
+
},
|
|
19973
|
+
{ construct: "string_format", id }
|
|
19974
|
+
);
|
|
19975
|
+
return (ctx) => {
|
|
19976
|
+
ctx.stringFormats[id] = out;
|
|
19977
|
+
return ctx;
|
|
19978
|
+
};
|
|
19979
|
+
};
|
|
19980
|
+
var dumpStringFormat = function(f) {
|
|
19981
|
+
return [
|
|
19982
|
+
`string_format :${f.id} {`,
|
|
19983
|
+
` artifact "${escapeString(f.artifact)}"`,
|
|
19984
|
+
` root "${escapeString(f.root)}"`,
|
|
19985
|
+
"}"
|
|
19986
|
+
].join("\n");
|
|
19987
|
+
};
|
|
19988
|
+
var parseNamespace = function(id, data) {
|
|
19989
|
+
const out = {
|
|
19990
|
+
id,
|
|
19991
|
+
uri: "",
|
|
19992
|
+
prefix: "",
|
|
19993
|
+
isDefault: false,
|
|
19994
|
+
source: null
|
|
19995
|
+
};
|
|
19996
|
+
forEachEntry(
|
|
19997
|
+
data,
|
|
19998
|
+
(command, value) => {
|
|
19999
|
+
if (command === "uri") {
|
|
20000
|
+
out.uri = stripWrapping(value());
|
|
20001
|
+
} else if (command === "prefix") {
|
|
20002
|
+
out.prefix = stripWrapping(value());
|
|
20003
|
+
} else if (command === "default") {
|
|
20004
|
+
value();
|
|
20005
|
+
out.isDefault = true;
|
|
20006
|
+
} else {
|
|
20007
|
+
return false;
|
|
20008
|
+
}
|
|
20009
|
+
return true;
|
|
20010
|
+
},
|
|
20011
|
+
{ construct: "namespace", id }
|
|
20012
|
+
);
|
|
20013
|
+
return (ctx) => {
|
|
20014
|
+
ctx.namespaces[id] = out;
|
|
20015
|
+
return ctx;
|
|
20016
|
+
};
|
|
20017
|
+
};
|
|
20018
|
+
var dumpNamespace = function(d) {
|
|
20019
|
+
const lines = [`namespace ${d.id} {`, ` uri "${escapeString(d.uri)}"`];
|
|
20020
|
+
if (d.prefix) {
|
|
20021
|
+
lines.push(` prefix "${escapeString(d.prefix)}"`);
|
|
20022
|
+
}
|
|
20023
|
+
if (d.isDefault) {
|
|
20024
|
+
lines.push(` default`);
|
|
20025
|
+
}
|
|
20026
|
+
lines.push("}");
|
|
20027
|
+
return lines.join("\n");
|
|
20028
|
+
};
|
|
20029
|
+
var parseDatum = function(id, raw) {
|
|
20030
|
+
const data = raw.replace(/^\s*:\s*\S+\s*/, "");
|
|
20031
|
+
const out = {
|
|
20032
|
+
id,
|
|
20033
|
+
type: "",
|
|
20034
|
+
unit: "",
|
|
20035
|
+
quantityKind: "",
|
|
20036
|
+
origin: "declared",
|
|
20037
|
+
scope: "",
|
|
20038
|
+
renders: [],
|
|
20039
|
+
label: "",
|
|
20040
|
+
description: "",
|
|
20041
|
+
source: null
|
|
20042
|
+
};
|
|
20043
|
+
forEachEntry(
|
|
20044
|
+
data,
|
|
20045
|
+
(command, value, peek) => {
|
|
20046
|
+
if (command === "render") {
|
|
20047
|
+
const notation = stripWrapping(value());
|
|
20048
|
+
const text = peek() !== void 0 ? stripWrapping(value()) : "";
|
|
20049
|
+
if (MATH_NOTATIONS.includes(notation)) {
|
|
20050
|
+
out.renders.push({ notation, text });
|
|
20051
|
+
}
|
|
20052
|
+
} else if (command === "label") {
|
|
20053
|
+
out.label = stripWrapping(value());
|
|
20054
|
+
} else if (command === "description") {
|
|
20055
|
+
const v = value();
|
|
20056
|
+
out.description = v.startsWith("{") ? unwrapBlock(v) : stripWrapping(v);
|
|
20057
|
+
} else if (command === "unit") {
|
|
20058
|
+
out.unit = stripWrapping(value());
|
|
20059
|
+
} else if (command === "quantity_kind") {
|
|
20060
|
+
out.quantityKind = stripWrapping(value());
|
|
20061
|
+
} else if (command === "origin") {
|
|
20062
|
+
const o = stripWrapping(value());
|
|
20063
|
+
if (["declared", "design-fixed", "observed", "computed"].includes(o)) {
|
|
20064
|
+
out.origin = o;
|
|
20065
|
+
}
|
|
20066
|
+
} else if (command === "scope") {
|
|
20067
|
+
out.scope = stripWrapping(value());
|
|
20068
|
+
} else {
|
|
20069
|
+
return false;
|
|
20070
|
+
}
|
|
20071
|
+
return true;
|
|
20072
|
+
},
|
|
20073
|
+
{ construct: "datum", id }
|
|
20074
|
+
);
|
|
20075
|
+
return (ctx) => {
|
|
20076
|
+
ctx.datums[id] = out;
|
|
20077
|
+
return ctx;
|
|
20078
|
+
};
|
|
20079
|
+
};
|
|
20080
|
+
var dumpDatum = function(x) {
|
|
20081
|
+
const lines = [`datum ${x.id}${x.type ? ` : ${x.type}` : ""} {`];
|
|
20082
|
+
if (x.quantityKind) {
|
|
20083
|
+
lines.push(` quantity_kind ${x.quantityKind}`);
|
|
20084
|
+
}
|
|
20085
|
+
if (x.unit) {
|
|
20086
|
+
lines.push(` unit ${x.unit}`);
|
|
20087
|
+
}
|
|
20088
|
+
if (x.origin !== "declared") {
|
|
20089
|
+
lines.push(` origin ${x.origin}`);
|
|
20090
|
+
}
|
|
20091
|
+
if (x.scope) {
|
|
20092
|
+
lines.push(` scope ${x.scope}`);
|
|
20093
|
+
}
|
|
20094
|
+
for (const r of x.renders) {
|
|
20095
|
+
lines.push(` render ${r.notation} "${escapeString(r.text)}"`);
|
|
20096
|
+
}
|
|
20097
|
+
if (x.label) {
|
|
20098
|
+
lines.push(` label "${escapeString(x.label)}"`);
|
|
20099
|
+
}
|
|
20100
|
+
if (x.description) {
|
|
20101
|
+
lines.push(` description { ${x.description} }`);
|
|
20102
|
+
}
|
|
20103
|
+
lines.push("}");
|
|
20104
|
+
return lines.join("\n");
|
|
20105
|
+
};
|
|
20106
|
+
var parseCheck = function(id, data) {
|
|
20107
|
+
const out = {
|
|
20108
|
+
id,
|
|
20109
|
+
inputs: [],
|
|
20110
|
+
expression: "",
|
|
20111
|
+
operator: "",
|
|
20112
|
+
threshold: "",
|
|
20113
|
+
source: null
|
|
20114
|
+
};
|
|
20115
|
+
forEachEntry(
|
|
20116
|
+
data,
|
|
20117
|
+
(command, value, peek) => {
|
|
20118
|
+
if (command === "inputs") {
|
|
20119
|
+
const block = value();
|
|
20120
|
+
const inner = block.startsWith("{") ? tokenizePackage(unwrapBlock(block)) : [];
|
|
20121
|
+
out.inputs = inner.map((x) => stripWrapping(x));
|
|
20122
|
+
} else if (command === "expression") {
|
|
20123
|
+
out.expression = stripWrapping(value());
|
|
20124
|
+
} else if (command === "operator") {
|
|
20125
|
+
out.operator = stripWrapping(value());
|
|
20126
|
+
} else if (command === "threshold") {
|
|
20127
|
+
const v = value();
|
|
20128
|
+
out.threshold = v.startsWith("{") ? unwrapBlock(v) : stripWrapping(v);
|
|
20129
|
+
} else {
|
|
20130
|
+
return false;
|
|
20131
|
+
}
|
|
20132
|
+
void peek;
|
|
20133
|
+
return true;
|
|
20134
|
+
},
|
|
20135
|
+
{ construct: "check", id }
|
|
20136
|
+
);
|
|
20137
|
+
return (ctx) => {
|
|
20138
|
+
ctx.checks[id] = out;
|
|
20139
|
+
return ctx;
|
|
20140
|
+
};
|
|
20141
|
+
};
|
|
20142
|
+
var dumpCheck = function(x) {
|
|
20143
|
+
const lines = [`check ${x.id} {`];
|
|
20144
|
+
if (x.inputs.length) {
|
|
20145
|
+
lines.push(` inputs { ${x.inputs.join(" ")} }`);
|
|
20146
|
+
}
|
|
20147
|
+
if (x.expression) {
|
|
20148
|
+
lines.push(` expression "${escapeString(x.expression)}"`);
|
|
20149
|
+
}
|
|
20150
|
+
if (x.operator) {
|
|
20151
|
+
lines.push(` operator ${x.operator}`);
|
|
20152
|
+
}
|
|
20153
|
+
if (x.threshold) {
|
|
20154
|
+
lines.push(` threshold ${x.threshold}`);
|
|
20155
|
+
}
|
|
20156
|
+
lines.push("}");
|
|
20157
|
+
return lines.join("\n");
|
|
20158
|
+
};
|
|
20159
|
+
|
|
18915
20160
|
// src/ser-des/config/index.ts
|
|
18916
20161
|
function defineConstruct(def) {
|
|
18917
20162
|
return def;
|
|
@@ -19287,6 +20532,14 @@ var CONSTRUCTS = [
|
|
|
19287
20532
|
parse: parseConstraint,
|
|
19288
20533
|
dump: dumpConstraint
|
|
19289
20534
|
}),
|
|
20535
|
+
// The uncertainty budgets (register W5 — the GUM plane's language side)
|
|
20536
|
+
defineConstruct({
|
|
20537
|
+
keyword: "uncertainty_budget",
|
|
20538
|
+
field: "uncertaintyBudgets",
|
|
20539
|
+
takesID: true,
|
|
20540
|
+
parse: parseUncertaintyBudget,
|
|
20541
|
+
dump: dumpUncertaintyBudget
|
|
20542
|
+
}),
|
|
19290
20543
|
// Corpus-level source-discrepancy records (TODO.roadmap/54 — gap 13's
|
|
19291
20544
|
// corpus-level extension of the source_discrepancy facet)
|
|
19292
20545
|
defineConstruct({
|
|
@@ -19575,7 +20828,45 @@ var CONSTRUCTS = [
|
|
|
19575
20828
|
// Primmel v3.2 consumption constructs (TODO.primmel/11; MN 114 clause
|
|
19576
20829
|
// 10.6): the top-level applicability dimension (one grammar with the
|
|
19577
20830
|
// instrument's inline dimension blocks, two placements).
|
|
19578
|
-
dimensionConstruct
|
|
20831
|
+
dimensionConstruct,
|
|
20832
|
+
// ── the LML-aligned substrate (TODO.lang-gaps; Annex F) ─────────
|
|
20833
|
+
defineConstruct({
|
|
20834
|
+
keyword: "mapping",
|
|
20835
|
+
field: "wireMappings",
|
|
20836
|
+
takesID: true,
|
|
20837
|
+
takesFormat: true,
|
|
20838
|
+
parse: parseWireMapping,
|
|
20839
|
+
dump: dumpWireMapping
|
|
20840
|
+
}),
|
|
20841
|
+
defineConstruct({
|
|
20842
|
+
keyword: "string_format",
|
|
20843
|
+
field: "stringFormats",
|
|
20844
|
+
takesID: true,
|
|
20845
|
+
parse: parseStringFormat,
|
|
20846
|
+
dump: dumpStringFormat
|
|
20847
|
+
}),
|
|
20848
|
+
defineConstruct({
|
|
20849
|
+
keyword: "namespace",
|
|
20850
|
+
field: "namespaces",
|
|
20851
|
+
takesID: true,
|
|
20852
|
+
parse: parseNamespace,
|
|
20853
|
+
dump: dumpNamespace
|
|
20854
|
+
}),
|
|
20855
|
+
defineConstruct({
|
|
20856
|
+
keyword: "datum",
|
|
20857
|
+
field: "datums",
|
|
20858
|
+
takesID: true,
|
|
20859
|
+
optionalTypedId: true,
|
|
20860
|
+
parse: parseDatum,
|
|
20861
|
+
dump: dumpDatum
|
|
20862
|
+
}),
|
|
20863
|
+
defineConstruct({
|
|
20864
|
+
keyword: "check",
|
|
20865
|
+
field: "checks",
|
|
20866
|
+
takesID: true,
|
|
20867
|
+
parse: parseCheck,
|
|
20868
|
+
dump: dumpCheck
|
|
20869
|
+
})
|
|
19579
20870
|
];
|
|
19580
20871
|
function buildParserConfig(constructs) {
|
|
19581
20872
|
const out = {};
|
|
@@ -19585,6 +20876,8 @@ function buildParserConfig(constructs) {
|
|
|
19585
20876
|
}
|
|
19586
20877
|
const entry = {
|
|
19587
20878
|
takesID: c.takesID,
|
|
20879
|
+
takesFormat: c.takesFormat,
|
|
20880
|
+
optionalTypedId: c.optionalTypedId,
|
|
19588
20881
|
parse: c.parse,
|
|
19589
20882
|
field: c.field,
|
|
19590
20883
|
...c.deprecated ? { deprecated: c.deprecated } : {}
|
|
@@ -19811,6 +21104,9 @@ function loadPackageInternal(dir, options = {}, withProvenance = false) {
|
|
|
19811
21104
|
return composePackage(dir, options, manifest, withProvenance);
|
|
19812
21105
|
}
|
|
19813
21106
|
const parseOptions = withProvenance ? { ...options, withProvenance: true } : options;
|
|
21107
|
+
if (manifest?.language) {
|
|
21108
|
+
parseOptions.strict = true;
|
|
21109
|
+
}
|
|
19814
21110
|
const ctx = parse(joinChunks(chunks), PARSER_CONFIG, parseOptions);
|
|
19815
21111
|
if (manifest) {
|
|
19816
21112
|
ctx.packageManifest = manifest;
|
|
@@ -19894,6 +21190,11 @@ var MERGE_FIELDS = [
|
|
|
19894
21190
|
"calculations",
|
|
19895
21191
|
"verdicts",
|
|
19896
21192
|
"referenceMaterials",
|
|
21193
|
+
"wireMappings",
|
|
21194
|
+
"stringFormats",
|
|
21195
|
+
"namespaces",
|
|
21196
|
+
"datums",
|
|
21197
|
+
"checks",
|
|
19897
21198
|
"testPointSets",
|
|
19898
21199
|
"commonTestConditions",
|
|
19899
21200
|
"competenceKinds",
|
|
@@ -19903,6 +21204,7 @@ var MERGE_FIELDS = [
|
|
|
19903
21204
|
"schemeActivityKinds",
|
|
19904
21205
|
"schemeTypes",
|
|
19905
21206
|
"constraints",
|
|
21207
|
+
"uncertaintyBudgets",
|
|
19906
21208
|
"discrepancyRecords",
|
|
19907
21209
|
"stateMachines",
|
|
19908
21210
|
"conformanceTests",
|
|
@@ -20134,7 +21436,12 @@ function composePackage(rootDir, options, rootManifest, withProvenance = false)
|
|
|
20134
21436
|
const ctxs = /* @__PURE__ */ new Map();
|
|
20135
21437
|
const pkgChunks = /* @__PURE__ */ new Map();
|
|
20136
21438
|
for (const id of order) {
|
|
20137
|
-
const
|
|
21439
|
+
const pkgOptions = { ...parseOptions };
|
|
21440
|
+
const pkgManifest = manifests.get(id);
|
|
21441
|
+
if (pkgManifest?.language) {
|
|
21442
|
+
pkgOptions.strict = true;
|
|
21443
|
+
}
|
|
21444
|
+
const parsed = parsePackageContent(dirs.get(id), pkgOptions);
|
|
20138
21445
|
ctxs.set(id, parsed.ctx);
|
|
20139
21446
|
pkgChunks.set(id, parsed.chunks);
|
|
20140
21447
|
}
|
|
@@ -20233,7 +21540,21 @@ function composePackage(rootDir, options, rootManifest, withProvenance = false)
|
|
|
20233
21540
|
for (const id of order) {
|
|
20234
21541
|
const m = manifests.get(id);
|
|
20235
21542
|
for (const req of m.requires ?? []) {
|
|
20236
|
-
const
|
|
21543
|
+
const at = req.indexOf(":");
|
|
21544
|
+
const scoped = at > 0 ? { pkg: req.slice(0, at), token: req.slice(at + 1) } : null;
|
|
21545
|
+
let scopedProvides = null;
|
|
21546
|
+
if (scoped && !order.includes(scoped.pkg)) {
|
|
21547
|
+
try {
|
|
21548
|
+
const dir = locate(scoped.pkg);
|
|
21549
|
+
if (dir) {
|
|
21550
|
+
const rm = readPackageManifest(dir);
|
|
21551
|
+
scopedProvides = rm.provides ?? [];
|
|
21552
|
+
manifests.set(scoped.pkg, rm);
|
|
21553
|
+
}
|
|
21554
|
+
} catch {
|
|
21555
|
+
}
|
|
21556
|
+
}
|
|
21557
|
+
const satisfied = scoped ? order.includes(scoped.pkg) ? (manifests.get(scoped.pkg).provides ?? []).includes(scoped.token) : (scopedProvides ?? []).includes(scoped.token) : order.some(
|
|
20237
21558
|
(other) => other !== id && (other === req || (manifests.get(other).provides ?? []).includes(req))
|
|
20238
21559
|
);
|
|
20239
21560
|
if (!satisfied) {
|
|
@@ -22042,6 +23363,176 @@ var CHECK_RULES = [
|
|
|
22042
23363
|
"normal",
|
|
22043
23364
|
"the MMEL v2 validation parity (the rename contract \u2014 TODO.editor/41)"
|
|
22044
23365
|
),
|
|
23366
|
+
// ── the LML-aligned substrate (TODO.lang-gaps; the spec's validation
|
|
23367
|
+
// contract, language-v3 §16) ── The five constructs (mapping /
|
|
23368
|
+
// string_format / namespace / datum / check) carry their declared
|
|
23369
|
+
// data; the checker does the discipline. C163 is the release
|
|
23370
|
+
// classification contract — it runs over `primmel diff --exit-code`
|
|
23371
|
+
// (the existing diff classifier, src/model-diff.ts), so its catalog
|
|
23372
|
+
// entry documents the contract the CLI already enforces; no second
|
|
23373
|
+
// implementation lives here. C165/C166 are RESERVED for the
|
|
23374
|
+
// calculation math plane (the formula identifier bindings and the
|
|
23375
|
+
// Plurimath-conformant parse) — catalogued, not faked.
|
|
23376
|
+
R(
|
|
23377
|
+
"C158",
|
|
23378
|
+
"prose-quarantine",
|
|
23379
|
+
"base",
|
|
23380
|
+
"error",
|
|
23381
|
+
"normal",
|
|
23382
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23383
|
+
),
|
|
23384
|
+
R(
|
|
23385
|
+
"C159",
|
|
23386
|
+
"urn-only-refs",
|
|
23387
|
+
"base",
|
|
23388
|
+
"error",
|
|
23389
|
+
"normal",
|
|
23390
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23391
|
+
),
|
|
23392
|
+
R(
|
|
23393
|
+
"C160",
|
|
23394
|
+
"signature-closure",
|
|
23395
|
+
"base",
|
|
23396
|
+
"error",
|
|
23397
|
+
"normal",
|
|
23398
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23399
|
+
),
|
|
23400
|
+
R(
|
|
23401
|
+
"C161",
|
|
23402
|
+
"check-surface",
|
|
23403
|
+
"base",
|
|
23404
|
+
"error",
|
|
23405
|
+
"normal",
|
|
23406
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23407
|
+
),
|
|
23408
|
+
R(
|
|
23409
|
+
"C162",
|
|
23410
|
+
"namespace-coherence",
|
|
23411
|
+
"base",
|
|
23412
|
+
"error",
|
|
23413
|
+
"normal",
|
|
23414
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23415
|
+
),
|
|
23416
|
+
R(
|
|
23417
|
+
"C163",
|
|
23418
|
+
"change-levels",
|
|
23419
|
+
"base",
|
|
23420
|
+
"error",
|
|
23421
|
+
"normal",
|
|
23422
|
+
"the LML-aligned validation contract (language-v3 \xA716) \u2014 runs over `primmel diff --exit-code` (src/model-diff.ts, the diff classifier)"
|
|
23423
|
+
),
|
|
23424
|
+
R(
|
|
23425
|
+
"C164",
|
|
23426
|
+
"wire-mapping-coverage",
|
|
23427
|
+
"base",
|
|
23428
|
+
"error",
|
|
23429
|
+
"normal",
|
|
23430
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23431
|
+
),
|
|
23432
|
+
R(
|
|
23433
|
+
"C165",
|
|
23434
|
+
"math-symbols-declared",
|
|
23435
|
+
"quantities",
|
|
23436
|
+
"warning",
|
|
23437
|
+
"normal",
|
|
23438
|
+
"RESERVED for the calculation math plane (language-v3 \xA716) \u2014 the formula identifier bindings"
|
|
23439
|
+
),
|
|
23440
|
+
R(
|
|
23441
|
+
"C166",
|
|
23442
|
+
"math-parses",
|
|
23443
|
+
"quantities",
|
|
23444
|
+
"warning",
|
|
23445
|
+
"normal",
|
|
23446
|
+
"RESERVED for the calculation math plane (language-v3 \xA716) \u2014 the Plurimath-conformant parse (plurimath-ts)"
|
|
23447
|
+
),
|
|
23448
|
+
R(
|
|
23449
|
+
"C167",
|
|
23450
|
+
"qualified-unit-reference",
|
|
23451
|
+
"quantities",
|
|
23452
|
+
"error",
|
|
23453
|
+
"normal",
|
|
23454
|
+
"the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
|
|
23455
|
+
),
|
|
23456
|
+
R(
|
|
23457
|
+
"C168",
|
|
23458
|
+
"method-ref-resolves",
|
|
23459
|
+
"process",
|
|
23460
|
+
"error",
|
|
23461
|
+
"normal",
|
|
23462
|
+
"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"
|
|
23463
|
+
),
|
|
23464
|
+
R(
|
|
23465
|
+
"C169",
|
|
23466
|
+
"provenance-clause-resolves",
|
|
23467
|
+
"base",
|
|
23468
|
+
"error",
|
|
23469
|
+
"normal",
|
|
23470
|
+
"a provenance binding citing a shipped document lands on a real fragment or sentence of that document \u2014 nothing linked to air"
|
|
23471
|
+
),
|
|
23472
|
+
R(
|
|
23473
|
+
"C170",
|
|
23474
|
+
"edition-lineage-declared",
|
|
23475
|
+
"base",
|
|
23476
|
+
"error",
|
|
23477
|
+
"normal",
|
|
23478
|
+
"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"
|
|
23479
|
+
),
|
|
23480
|
+
R(
|
|
23481
|
+
"C171",
|
|
23482
|
+
"expression-identifiers-resolve",
|
|
23483
|
+
"base",
|
|
23484
|
+
"error",
|
|
23485
|
+
"normal",
|
|
23486
|
+
"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"
|
|
23487
|
+
),
|
|
23488
|
+
R(
|
|
23489
|
+
"C172",
|
|
23490
|
+
"requirement-algebra-resolves",
|
|
23491
|
+
"base",
|
|
23492
|
+
"error",
|
|
23493
|
+
"normal",
|
|
23494
|
+
"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"
|
|
23495
|
+
),
|
|
23496
|
+
R(
|
|
23497
|
+
"C176",
|
|
23498
|
+
"language-declared-wellformed",
|
|
23499
|
+
"base",
|
|
23500
|
+
"error",
|
|
23501
|
+
"normal",
|
|
23502
|
+
"a declared language generation is well-formed (v<major>[.<minor>]); the declaration makes the package parse strictly \u2014 unknown keywords are errors"
|
|
23503
|
+
),
|
|
23504
|
+
R(
|
|
23505
|
+
"C179",
|
|
23506
|
+
"uncertainty-budget-resolves",
|
|
23507
|
+
"base",
|
|
23508
|
+
"error",
|
|
23509
|
+
"normal",
|
|
23510
|
+
"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"
|
|
23511
|
+
),
|
|
23512
|
+
R(
|
|
23513
|
+
"C173",
|
|
23514
|
+
"step-plane-refs-resolve",
|
|
23515
|
+
"process",
|
|
23516
|
+
"error",
|
|
23517
|
+
"normal",
|
|
23518
|
+
"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"
|
|
23519
|
+
),
|
|
23520
|
+
R(
|
|
23521
|
+
"C177",
|
|
23522
|
+
"kind-coherence",
|
|
23523
|
+
"base",
|
|
23524
|
+
"error",
|
|
23525
|
+
"normal",
|
|
23526
|
+
"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"
|
|
23527
|
+
),
|
|
23528
|
+
R(
|
|
23529
|
+
"C178",
|
|
23530
|
+
"legacy-carrier-deprecated",
|
|
23531
|
+
"base",
|
|
23532
|
+
"warning",
|
|
23533
|
+
"normal",
|
|
23534
|
+
"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"
|
|
23535
|
+
),
|
|
22045
23536
|
// ── mapping (TODO.roadmap/04) ─────────────────────────────────────
|
|
22046
23537
|
R(
|
|
22047
23538
|
"C21",
|
|
@@ -23525,6 +25016,22 @@ var EMPTY = {
|
|
|
23525
25016
|
textCoverageBudgetReason: null,
|
|
23526
25017
|
entries: []
|
|
23527
25018
|
};
|
|
25019
|
+
function issueElementId(message) {
|
|
25020
|
+
const m = message.match(/^[a-z_]+ ([^:\s][^:]*):/);
|
|
25021
|
+
return m ? m[1] : "";
|
|
25022
|
+
}
|
|
25023
|
+
function entryMatches(entry, issue) {
|
|
25024
|
+
if (issue.check !== entry.rule) {
|
|
25025
|
+
return false;
|
|
25026
|
+
}
|
|
25027
|
+
if (!globMatch(entry.match, issue.message)) {
|
|
25028
|
+
return false;
|
|
25029
|
+
}
|
|
25030
|
+
if (entry.id !== void 0) {
|
|
25031
|
+
return globMatch(entry.id, issueElementId(issue.message));
|
|
25032
|
+
}
|
|
25033
|
+
return true;
|
|
25034
|
+
}
|
|
23528
25035
|
function globMatch(glob, text) {
|
|
23529
25036
|
const re = new RegExp(
|
|
23530
25037
|
"^" + glob.split("*").map(escapeRegExp).join("[\\s\\S]*") + "$"
|
|
@@ -23624,6 +25131,8 @@ function parseEntry2(block) {
|
|
|
23624
25131
|
entry.rule = value;
|
|
23625
25132
|
} else if (key === "match") {
|
|
23626
25133
|
entry.match = value;
|
|
25134
|
+
} else if (key === "id") {
|
|
25135
|
+
entry.id = value;
|
|
23627
25136
|
} else if (key === "reason") {
|
|
23628
25137
|
entry.reason = value;
|
|
23629
25138
|
} else if (key === "audit_ref") {
|
|
@@ -23642,6 +25151,13 @@ function validateEntry(entry) {
|
|
|
23642
25151
|
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)`
|
|
23643
25152
|
});
|
|
23644
25153
|
}
|
|
25154
|
+
if (entry.id !== void 0 && entry.id === "") {
|
|
25155
|
+
issues.push({
|
|
25156
|
+
check: "C56",
|
|
25157
|
+
severity: "error",
|
|
25158
|
+
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)`
|
|
25159
|
+
});
|
|
25160
|
+
}
|
|
23645
25161
|
if (!entry.match) {
|
|
23646
25162
|
issues.push({
|
|
23647
25163
|
check: "C56",
|
|
@@ -23677,7 +25193,7 @@ function applyAllowlist(issues, allowlist, activeRules) {
|
|
|
23677
25193
|
}
|
|
23678
25194
|
let matched = false;
|
|
23679
25195
|
for (const issue of out) {
|
|
23680
|
-
if (
|
|
25196
|
+
if (entryMatches(entry, issue)) {
|
|
23681
25197
|
issue.known = true;
|
|
23682
25198
|
matched = true;
|
|
23683
25199
|
}
|
|
@@ -23742,7 +25258,7 @@ function applyProviderAllowlists(issues, providers, activeRules) {
|
|
|
23742
25258
|
}
|
|
23743
25259
|
let matched = false;
|
|
23744
25260
|
for (const issue of out) {
|
|
23745
|
-
if (!issue.known &&
|
|
25261
|
+
if (!issue.known && entryMatches(entry, issue)) {
|
|
23746
25262
|
issue.known = true;
|
|
23747
25263
|
matched = true;
|
|
23748
25264
|
}
|
|
@@ -24081,6 +25597,40 @@ function computeTextCoverage(standard, manifests, config) {
|
|
|
24081
25597
|
}
|
|
24082
25598
|
const documents = [];
|
|
24083
25599
|
const matchedAllowanceSentences = /* @__PURE__ */ new Map();
|
|
25600
|
+
for (const manifest of manifests) {
|
|
25601
|
+
const urn = manifest.document.urn;
|
|
25602
|
+
const fragments = /* @__PURE__ */ new Set();
|
|
25603
|
+
const addresses = /* @__PURE__ */ new Set();
|
|
25604
|
+
for (const s of manifest.sentences) {
|
|
25605
|
+
fragments.add(s.fragment);
|
|
25606
|
+
addresses.add(s.address);
|
|
25607
|
+
}
|
|
25608
|
+
for (const b of bindings) {
|
|
25609
|
+
if (b.doc !== urn) {
|
|
25610
|
+
continue;
|
|
25611
|
+
}
|
|
25612
|
+
if (fragments.has(b.fragmentPath) || addresses.has(b.fragmentPath)) {
|
|
25613
|
+
continue;
|
|
25614
|
+
}
|
|
25615
|
+
const prefix = b.fragmentPath + ".";
|
|
25616
|
+
let resolved = false;
|
|
25617
|
+
for (const f of fragments) {
|
|
25618
|
+
if (f.startsWith(prefix) || b.fragmentPath.startsWith(f + "/")) {
|
|
25619
|
+
resolved = true;
|
|
25620
|
+
break;
|
|
25621
|
+
}
|
|
25622
|
+
}
|
|
25623
|
+
if (resolved) {
|
|
25624
|
+
continue;
|
|
25625
|
+
}
|
|
25626
|
+
const subpart = /^(table|figure|annex)-/.test(b.fragmentPath);
|
|
25627
|
+
configIssues.push({
|
|
25628
|
+
check: "C169",
|
|
25629
|
+
severity: subpart ? "warning" : "error",
|
|
25630
|
+
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)`
|
|
25631
|
+
});
|
|
25632
|
+
}
|
|
25633
|
+
}
|
|
24084
25634
|
for (const manifest of manifests) {
|
|
24085
25635
|
const urn = manifest.document.urn;
|
|
24086
25636
|
const sentences = manifest.sentences;
|
|
@@ -24479,6 +26029,7 @@ function checkPackage(dir, options = {}) {
|
|
|
24479
26029
|
issues.push(...checkDimensions(standard));
|
|
24480
26030
|
issues.push(...checkReferences(standard));
|
|
24481
26031
|
issues.push(...checkVerdictChains(standard));
|
|
26032
|
+
issues.push(...checkLmlAligned(standard));
|
|
24482
26033
|
issues.push(...checkClosedDerivations(standard));
|
|
24483
26034
|
issues.push(...checkAttestations(standard));
|
|
24484
26035
|
issues.push(...checkTypedPayloads(standard));
|
|
@@ -24563,9 +26114,12 @@ function checkPackage(dir, options = {}) {
|
|
|
24563
26114
|
};
|
|
24564
26115
|
(form.fields ?? []).forEach(checkField);
|
|
24565
26116
|
}
|
|
26117
|
+
const classIds = new Set(
|
|
26118
|
+
(standard.requirementClasses ?? []).map((rc) => rc.id)
|
|
26119
|
+
);
|
|
24566
26120
|
for (const t of standard.conformanceTests ?? []) {
|
|
24567
26121
|
for (const target of t.targets ?? []) {
|
|
24568
|
-
if (!reqIds.has(target)) {
|
|
26122
|
+
if (!reqIds.has(target) && !classIds.has(target)) {
|
|
24569
26123
|
err(
|
|
24570
26124
|
"C2",
|
|
24571
26125
|
`conformance test ${t.id}: target "${target}" is not a declared requirement`
|
|
@@ -24722,9 +26276,19 @@ function checkPackage(dir, options = {}) {
|
|
|
24722
26276
|
}
|
|
24723
26277
|
}
|
|
24724
26278
|
const covered = /* @__PURE__ */ new Set();
|
|
26279
|
+
const classMembers = /* @__PURE__ */ new Map();
|
|
26280
|
+
for (const rc of standard.requirementClasses ?? []) {
|
|
26281
|
+
classMembers.set(rc.id, rc.members ?? []);
|
|
26282
|
+
}
|
|
26283
|
+
const coverWithMembers = (id) => {
|
|
26284
|
+
covered.add(id);
|
|
26285
|
+
for (const m of classMembers.get(id) ?? []) {
|
|
26286
|
+
covered.add(m);
|
|
26287
|
+
}
|
|
26288
|
+
};
|
|
24725
26289
|
for (const t of standard.conformanceTests ?? []) {
|
|
24726
26290
|
for (const target of t.targets ?? []) {
|
|
24727
|
-
|
|
26291
|
+
coverWithMembers(target);
|
|
24728
26292
|
}
|
|
24729
26293
|
}
|
|
24730
26294
|
const provisioned = /* @__PURE__ */ new Set();
|
|
@@ -24763,6 +26327,1003 @@ function checkPackage(dir, options = {}) {
|
|
|
24763
26327
|
warn("C5", `conformance test ${t.id}: targets no requirement`);
|
|
24764
26328
|
}
|
|
24765
26329
|
}
|
|
26330
|
+
const OCL_WORDS = /* @__PURE__ */ new Set([
|
|
26331
|
+
"and",
|
|
26332
|
+
"or",
|
|
26333
|
+
"not",
|
|
26334
|
+
"xor",
|
|
26335
|
+
"implies",
|
|
26336
|
+
"if",
|
|
26337
|
+
"then",
|
|
26338
|
+
"else",
|
|
26339
|
+
"endif",
|
|
26340
|
+
"true",
|
|
26341
|
+
"false",
|
|
26342
|
+
"null",
|
|
26343
|
+
"invalid",
|
|
26344
|
+
"abs",
|
|
26345
|
+
"max",
|
|
26346
|
+
"min",
|
|
26347
|
+
"floor",
|
|
26348
|
+
"ceil",
|
|
26349
|
+
"mod",
|
|
26350
|
+
"div",
|
|
26351
|
+
"round",
|
|
26352
|
+
"sqrt",
|
|
26353
|
+
"exp",
|
|
26354
|
+
"ln",
|
|
26355
|
+
"log",
|
|
26356
|
+
"sum",
|
|
26357
|
+
"count",
|
|
26358
|
+
"exists",
|
|
26359
|
+
"forall",
|
|
26360
|
+
"oclIsUndefined",
|
|
26361
|
+
"oclIsKindOf",
|
|
26362
|
+
"oclIsTypeOf",
|
|
26363
|
+
"String",
|
|
26364
|
+
"Integer",
|
|
26365
|
+
"Real",
|
|
26366
|
+
"Boolean",
|
|
26367
|
+
"Set",
|
|
26368
|
+
"Bag",
|
|
26369
|
+
"Sequence",
|
|
26370
|
+
"Collection",
|
|
26371
|
+
// the subject-chain roots: every expression reads the dispatch
|
|
26372
|
+
// context through them — context, never air
|
|
26373
|
+
"sample",
|
|
26374
|
+
"family",
|
|
26375
|
+
"group",
|
|
26376
|
+
"model",
|
|
26377
|
+
"instrument",
|
|
26378
|
+
"specimen",
|
|
26379
|
+
"max_of",
|
|
26380
|
+
"min_of",
|
|
26381
|
+
"mean_of",
|
|
26382
|
+
"stddev_of",
|
|
26383
|
+
"count_of"
|
|
26384
|
+
]);
|
|
26385
|
+
const globalExprNames = new Set(
|
|
26386
|
+
[
|
|
26387
|
+
...(standard.symbols ?? []).map((s) => s.id),
|
|
26388
|
+
...(standard.symbols ?? []).map((s) => s.id.split("/").pop() ?? ""),
|
|
26389
|
+
...(standard.datums ?? []).map((d) => d.id),
|
|
26390
|
+
...(standard.verdicts ?? []).map((v) => v.id),
|
|
26391
|
+
// the lookup tables: a dotted helper call's OBJECT is declared here —
|
|
26392
|
+
// the method name rides the declared object
|
|
26393
|
+
...(standard.tables ?? []).map((v) => v.id),
|
|
26394
|
+
// the subject anatomy: a declared attribute is a declaration
|
|
26395
|
+
...(standard.attributeDefinitions ?? []).map((a) => a.id),
|
|
26396
|
+
...(standard.attributeDefinitions ?? []).map(
|
|
26397
|
+
(a) => a.id.split("/").pop() ?? ""
|
|
26398
|
+
),
|
|
26399
|
+
// the calculations: a derivation may call a declared calculation
|
|
26400
|
+
// (twin-cert's lookupMPE) — the callable registry
|
|
26401
|
+
...(standard.calculations ?? []).map((c) => c.id),
|
|
26402
|
+
...(standard.calculations ?? []).map((c) => c.id.split("/").pop() ?? "")
|
|
26403
|
+
].filter((x) => x !== "")
|
|
26404
|
+
);
|
|
26405
|
+
const symbolKinds = /* @__PURE__ */ new Map();
|
|
26406
|
+
for (const s of standard.symbols ?? []) {
|
|
26407
|
+
if (s.quantityKind) {
|
|
26408
|
+
symbolKinds.set(s.id, s.quantityKind);
|
|
26409
|
+
symbolKinds.set(s.id.split("/").pop() ?? "", s.quantityKind);
|
|
26410
|
+
}
|
|
26411
|
+
}
|
|
26412
|
+
const attributeKinds = /* @__PURE__ */ new Map();
|
|
26413
|
+
for (const a of standard.attributeDefinitions ?? []) {
|
|
26414
|
+
if (a.quantityKind) {
|
|
26415
|
+
attributeKinds.set(a.id, a.quantityKind);
|
|
26416
|
+
attributeKinds.set(
|
|
26417
|
+
a.id.split("/").pop() ?? "",
|
|
26418
|
+
a.quantityKind
|
|
26419
|
+
);
|
|
26420
|
+
}
|
|
26421
|
+
}
|
|
26422
|
+
const verdictKinds = /* @__PURE__ */ new Map();
|
|
26423
|
+
for (const v of standard.verdicts ?? []) {
|
|
26424
|
+
if (v.quantityKind) {
|
|
26425
|
+
verdictKinds.set(v.id, v.quantityKind);
|
|
26426
|
+
}
|
|
26427
|
+
}
|
|
26428
|
+
const tableColumnTypes = /* @__PURE__ */ new Map();
|
|
26429
|
+
for (const t of standard.tables ?? []) {
|
|
26430
|
+
const cols = /* @__PURE__ */ new Map();
|
|
26431
|
+
for (const c of t.columnDefs ?? []) {
|
|
26432
|
+
cols.set(c.name, (c.type || "").toLowerCase());
|
|
26433
|
+
}
|
|
26434
|
+
if (cols.size > 0) {
|
|
26435
|
+
tableColumnTypes.set(t.id, cols);
|
|
26436
|
+
}
|
|
26437
|
+
}
|
|
26438
|
+
const bare = (q) => q.split(":").pop() ?? q;
|
|
26439
|
+
const usesCovers = (uses, id) => uses.some((u) => {
|
|
26440
|
+
const tail = bare(u.replace(/\./g, ":"));
|
|
26441
|
+
return u === id || tail === id || u.endsWith("." + id);
|
|
26442
|
+
});
|
|
26443
|
+
const exprIds = (expr) => {
|
|
26444
|
+
const paths = expr.match(/[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*/g) ?? [];
|
|
26445
|
+
const out = [];
|
|
26446
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26447
|
+
for (const p of paths) {
|
|
26448
|
+
if (p.includes(".")) {
|
|
26449
|
+
const segs = p.split(".");
|
|
26450
|
+
if (globalExprNames.has(segs[0])) {
|
|
26451
|
+
continue;
|
|
26452
|
+
}
|
|
26453
|
+
const finalSeg = segs[segs.length - 1];
|
|
26454
|
+
if (!seen.has(p)) {
|
|
26455
|
+
seen.add(p);
|
|
26456
|
+
if (!OCL_WORDS.has(finalSeg)) {
|
|
26457
|
+
out.push(finalSeg);
|
|
26458
|
+
}
|
|
26459
|
+
}
|
|
26460
|
+
continue;
|
|
26461
|
+
}
|
|
26462
|
+
if (!OCL_WORDS.has(p) && !seen.has(p)) {
|
|
26463
|
+
seen.add(p);
|
|
26464
|
+
out.push(p);
|
|
26465
|
+
}
|
|
26466
|
+
}
|
|
26467
|
+
return out;
|
|
26468
|
+
};
|
|
26469
|
+
const unresolvedIn = (expr, scope, uses) => {
|
|
26470
|
+
const scopeSet = /* @__PURE__ */ new Set([...scope, ...globalExprNames]);
|
|
26471
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26472
|
+
const out = [];
|
|
26473
|
+
for (const id of exprIds(expr)) {
|
|
26474
|
+
if (seen.has(id)) {
|
|
26475
|
+
continue;
|
|
26476
|
+
}
|
|
26477
|
+
seen.add(id);
|
|
26478
|
+
if (OCL_WORDS.has(id) || scopeSet.has(id) || usesCovers(uses, id)) {
|
|
26479
|
+
continue;
|
|
26480
|
+
}
|
|
26481
|
+
out.push(id);
|
|
26482
|
+
}
|
|
26483
|
+
return out;
|
|
26484
|
+
};
|
|
26485
|
+
const mappedCalcIds = /* @__PURE__ */ new Set();
|
|
26486
|
+
{
|
|
26487
|
+
const mapsTo = standard.packageManifest?.mapsTo ?? [];
|
|
26488
|
+
for (const target of mapsTo) {
|
|
26489
|
+
if (!options.resolvePackage) {
|
|
26490
|
+
continue;
|
|
26491
|
+
}
|
|
26492
|
+
try {
|
|
26493
|
+
const depDir = options.resolvePackage(target);
|
|
26494
|
+
if (!depDir) {
|
|
26495
|
+
continue;
|
|
26496
|
+
}
|
|
26497
|
+
const dep = loadPackageWithIssues(depDir);
|
|
26498
|
+
for (const c of dep.standard?.calculations ?? []) {
|
|
26499
|
+
mappedCalcIds.add(c.id);
|
|
26500
|
+
mappedCalcIds.add(c.id.split("/").pop() ?? "");
|
|
26501
|
+
}
|
|
26502
|
+
} catch {
|
|
26503
|
+
}
|
|
26504
|
+
}
|
|
26505
|
+
for (const x of mappedCalcIds) {
|
|
26506
|
+
if (x !== "") {
|
|
26507
|
+
globalExprNames.add(x);
|
|
26508
|
+
}
|
|
26509
|
+
}
|
|
26510
|
+
}
|
|
26511
|
+
const INLINE_FUNCTION_WORDS = /* @__PURE__ */ new Set([
|
|
26512
|
+
"abs",
|
|
26513
|
+
"max",
|
|
26514
|
+
"min",
|
|
26515
|
+
"floor",
|
|
26516
|
+
"ceil",
|
|
26517
|
+
"round",
|
|
26518
|
+
"sqrt",
|
|
26519
|
+
"exp",
|
|
26520
|
+
"ln",
|
|
26521
|
+
"log",
|
|
26522
|
+
"mod",
|
|
26523
|
+
"sum",
|
|
26524
|
+
"count",
|
|
26525
|
+
"exists",
|
|
26526
|
+
"forall",
|
|
26527
|
+
// the series aggregations (register W4): the GUM type A vocabulary —
|
|
26528
|
+
// the statistics of a captured series; the evaluation is plurimath's
|
|
26529
|
+
"max_of",
|
|
26530
|
+
"min_of",
|
|
26531
|
+
"mean_of",
|
|
26532
|
+
"stddev_of",
|
|
26533
|
+
"count_of"
|
|
26534
|
+
]);
|
|
26535
|
+
const DECLARATION_KINDS = /* @__PURE__ */ new Set([
|
|
26536
|
+
"symbol",
|
|
26537
|
+
"table",
|
|
26538
|
+
"datum",
|
|
26539
|
+
"verdict",
|
|
26540
|
+
"attribute",
|
|
26541
|
+
"process"
|
|
26542
|
+
]);
|
|
26543
|
+
const CONTEXT_ROOTS = /* @__PURE__ */ new Set([
|
|
26544
|
+
"sample",
|
|
26545
|
+
"family",
|
|
26546
|
+
"group",
|
|
26547
|
+
"model",
|
|
26548
|
+
"instrument",
|
|
26549
|
+
"specimen"
|
|
26550
|
+
]);
|
|
26551
|
+
const checkInlineLimit = (ownerKind, ownerId, limit, memberScope) => {
|
|
26552
|
+
let ast;
|
|
26553
|
+
try {
|
|
26554
|
+
ast = parseExpression(limit.expression);
|
|
26555
|
+
} catch (e) {
|
|
26556
|
+
err(
|
|
26557
|
+
"C171",
|
|
26558
|
+
`${ownerKind} ${ownerId}: the inline limit expression does not parse \u2014 ${String(e.message ?? e)} (expression-identifiers-resolve)`
|
|
26559
|
+
);
|
|
26560
|
+
return;
|
|
26561
|
+
}
|
|
26562
|
+
const ids = freeIdentifiers(ast);
|
|
26563
|
+
const args2 = limit.args ?? [];
|
|
26564
|
+
const argNames = new Set(args2.map((a) => a.name));
|
|
26565
|
+
if (memberScope === null && args2.length === 0 && ids.names.some((n) => !n.includes("."))) {
|
|
26566
|
+
err(
|
|
26567
|
+
"C171",
|
|
26568
|
+
`${ownerKind} ${ownerId}: the inline limit declares no arguments \u2014 every identifier must bind explicitly, args { name <- <declaration> } (expression-identifiers-resolve)`
|
|
26569
|
+
);
|
|
26570
|
+
}
|
|
26571
|
+
for (const call of new Set(ids.calls)) {
|
|
26572
|
+
if (INLINE_FUNCTION_WORDS.has(call)) {
|
|
26573
|
+
continue;
|
|
26574
|
+
}
|
|
26575
|
+
if (globalExprNames.has(call)) {
|
|
26576
|
+
continue;
|
|
26577
|
+
}
|
|
26578
|
+
if (call.includes(".")) {
|
|
26579
|
+
const root = call.split(".")[0];
|
|
26580
|
+
if (argNames.has(root) || globalExprNames.has(root) || root === "self" || CONTEXT_ROOTS.has(root)) {
|
|
26581
|
+
continue;
|
|
26582
|
+
}
|
|
26583
|
+
}
|
|
26584
|
+
if (argNames.has(call)) {
|
|
26585
|
+
continue;
|
|
26586
|
+
}
|
|
26587
|
+
err(
|
|
26588
|
+
"C171",
|
|
26589
|
+
`${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)`
|
|
26590
|
+
);
|
|
26591
|
+
}
|
|
26592
|
+
for (const id of new Set(ids.names)) {
|
|
26593
|
+
const root = id.split(".")[0];
|
|
26594
|
+
if (id.includes(".") && (root === "self" || argNames.has(root) || CONTEXT_ROOTS.has(root))) {
|
|
26595
|
+
continue;
|
|
26596
|
+
}
|
|
26597
|
+
if (argNames.has(id)) {
|
|
26598
|
+
continue;
|
|
26599
|
+
}
|
|
26600
|
+
if (memberScope !== null && memberScope.has(id)) {
|
|
26601
|
+
continue;
|
|
26602
|
+
}
|
|
26603
|
+
const lawScoped = memberScope !== null;
|
|
26604
|
+
const fix = lawScoped ? "the law composes the containment only \u2014 its identifiers are the members" : "add args { " + id + " <- <declaration> } or remove it";
|
|
26605
|
+
err(
|
|
26606
|
+
lawScoped ? "C172" : "C171",
|
|
26607
|
+
`${ownerKind} ${ownerId}: the limit expression names "${id}", which no argument binds \u2014 ${fix} (${lawScoped ? "requirement-algebra-resolves" : "expression-identifiers-resolve"})`
|
|
26608
|
+
);
|
|
26609
|
+
}
|
|
26610
|
+
for (const a of args2) {
|
|
26611
|
+
if (a.source.includes(":")) {
|
|
26612
|
+
const segs = a.source.split(":");
|
|
26613
|
+
if (segs.some((s) => s.length === 0)) {
|
|
26614
|
+
err(
|
|
26615
|
+
"C171",
|
|
26616
|
+
`${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)`
|
|
26617
|
+
);
|
|
26618
|
+
continue;
|
|
26619
|
+
}
|
|
26620
|
+
if (segs.length === 2) {
|
|
26621
|
+
const [kind, id] = segs;
|
|
26622
|
+
if (kind === "process") {
|
|
26623
|
+
const segs2 = id.split(".");
|
|
26624
|
+
const proc = (standard.processes ?? []).find(
|
|
26625
|
+
(pp) => pp.id === segs2[0]
|
|
26626
|
+
);
|
|
26627
|
+
if (!proc) {
|
|
26628
|
+
err(
|
|
26629
|
+
"C171",
|
|
26630
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no declared process names \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26631
|
+
);
|
|
26632
|
+
} else if (segs2.length >= 2) {
|
|
26633
|
+
const stp = (proc.steps ?? []).find((ss) => ss.id === segs2[1]);
|
|
26634
|
+
if (!stp) {
|
|
26635
|
+
err(
|
|
26636
|
+
"C171",
|
|
26637
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 the process declares no step "${segs2[1]}" (expression-identifiers-resolve)`
|
|
26638
|
+
);
|
|
26639
|
+
} else if (segs2.length >= 3) {
|
|
26640
|
+
const io = segs2.slice(2).join(".");
|
|
26641
|
+
if (!(stp.sigInputs ?? []).includes(io) && !(stp.sigOutputs ?? []).includes(io)) {
|
|
26642
|
+
err(
|
|
26643
|
+
"C171",
|
|
26644
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 the step declares no io "${io}" (expression-identifiers-resolve)`
|
|
26645
|
+
);
|
|
26646
|
+
}
|
|
26647
|
+
}
|
|
26648
|
+
}
|
|
26649
|
+
continue;
|
|
26650
|
+
}
|
|
26651
|
+
if (kind !== "observable") {
|
|
26652
|
+
if (!DECLARATION_KINDS.has(kind)) {
|
|
26653
|
+
err(
|
|
26654
|
+
"C171",
|
|
26655
|
+
`${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)`
|
|
26656
|
+
);
|
|
26657
|
+
continue;
|
|
26658
|
+
}
|
|
26659
|
+
const idRoot = id.split(".")[0];
|
|
26660
|
+
const idTail = id.split(".").pop() ?? id;
|
|
26661
|
+
if (!globalExprNames.has(id) && !globalExprNames.has(idRoot) && !globalExprNames.has(idTail)) {
|
|
26662
|
+
err(
|
|
26663
|
+
"C171",
|
|
26664
|
+
`${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no declared ${kind} names \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26665
|
+
);
|
|
26666
|
+
}
|
|
26667
|
+
}
|
|
26668
|
+
continue;
|
|
26669
|
+
}
|
|
26670
|
+
continue;
|
|
26671
|
+
}
|
|
26672
|
+
if (a.source === "self" || a.source.startsWith("self.")) {
|
|
26673
|
+
continue;
|
|
26674
|
+
}
|
|
26675
|
+
const bare2 = (q) => q.split(":").pop() ?? q;
|
|
26676
|
+
const sourceBare = bare2(a.source.replace(/\./g, ":"));
|
|
26677
|
+
if (memberScope !== null) {
|
|
26678
|
+
if (!memberScope.has(a.source) && !memberScope.has(sourceBare)) {
|
|
26679
|
+
err(
|
|
26680
|
+
"C172",
|
|
26681
|
+
`requirement class ${ownerId}: the law binds "${a.name}" to "${a.source}", which is not a contained member (requirement-algebra-resolves)`
|
|
26682
|
+
);
|
|
26683
|
+
}
|
|
26684
|
+
continue;
|
|
26685
|
+
}
|
|
26686
|
+
if (!globalExprNames.has(a.source) && !globalExprNames.has(sourceBare) && !usesCovers(limit.uses, sourceBare)) {
|
|
26687
|
+
err(
|
|
26688
|
+
"C171",
|
|
26689
|
+
`${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)`
|
|
26690
|
+
);
|
|
26691
|
+
}
|
|
26692
|
+
}
|
|
26693
|
+
const kindLabel = (k) => k === void 0 ? "an operand of unknown kind" : k === "TEXT" ? "text" : k === null ? "a bare number" : `the "${k}" quantity`;
|
|
26694
|
+
const argKindOf = (source) => {
|
|
26695
|
+
if (source.includes(":")) {
|
|
26696
|
+
const segs = source.split(":");
|
|
26697
|
+
if (segs.length !== 2) {
|
|
26698
|
+
return void 0;
|
|
26699
|
+
}
|
|
26700
|
+
const [kind, id] = segs;
|
|
26701
|
+
if (kind === "symbol") {
|
|
26702
|
+
return symbolKinds.get(id.split(".").pop() ?? id);
|
|
26703
|
+
}
|
|
26704
|
+
if (kind === "attribute") {
|
|
26705
|
+
return attributeKinds.get(id.split(".").pop() ?? id);
|
|
26706
|
+
}
|
|
26707
|
+
if (kind === "verdict") {
|
|
26708
|
+
return verdictKinds.get(id.split(".")[0]);
|
|
26709
|
+
}
|
|
26710
|
+
if (kind === "table") {
|
|
26711
|
+
const segs2 = id.split(".");
|
|
26712
|
+
const colType = segs2.length === 2 ? tableColumnTypes.get(segs2[0])?.get(segs2[1]) : void 0;
|
|
26713
|
+
return colType === "string" ? "TEXT" : void 0;
|
|
26714
|
+
}
|
|
26715
|
+
return void 0;
|
|
26716
|
+
}
|
|
26717
|
+
if (source === "self" || source.startsWith("self.")) {
|
|
26718
|
+
return void 0;
|
|
26719
|
+
}
|
|
26720
|
+
return symbolKinds.get(source) ?? attributeKinds.get(source) ?? void 0;
|
|
26721
|
+
};
|
|
26722
|
+
const kindConflicts = /* @__PURE__ */ new Set();
|
|
26723
|
+
const kindMixErr = (node, l, r) => {
|
|
26724
|
+
const key = renderExpression(node);
|
|
26725
|
+
if (kindConflicts.has(key)) {
|
|
26726
|
+
return;
|
|
26727
|
+
}
|
|
26728
|
+
kindConflicts.add(key);
|
|
26729
|
+
err(
|
|
26730
|
+
"C177",
|
|
26731
|
+
`${ownerKind} ${ownerId}: ${kindLabel(l)} is set against ${kindLabel(r)} in "${renderExpression(node)}" \u2014 the operands must share the quantity kind (kind-coherence)`
|
|
26732
|
+
);
|
|
26733
|
+
};
|
|
26734
|
+
const kindOf = (node) => {
|
|
26735
|
+
switch (node.type) {
|
|
26736
|
+
case "num":
|
|
26737
|
+
return null;
|
|
26738
|
+
case "str":
|
|
26739
|
+
return null;
|
|
26740
|
+
case "bool":
|
|
26741
|
+
return null;
|
|
26742
|
+
case "ifelse": {
|
|
26743
|
+
kindOf(node.cond);
|
|
26744
|
+
const l = kindOf(node.then);
|
|
26745
|
+
const r = kindOf(node.else);
|
|
26746
|
+
if (l !== void 0 && r !== void 0 && l !== null && r !== null && l !== r) {
|
|
26747
|
+
kindMixErr(node, l, r);
|
|
26748
|
+
}
|
|
26749
|
+
return l !== void 0 && l !== null ? l : r;
|
|
26750
|
+
}
|
|
26751
|
+
case "name": {
|
|
26752
|
+
const root = node.path[0];
|
|
26753
|
+
if (node.path.length > 1 && (root === "self" || CONTEXT_ROOTS.has(root))) {
|
|
26754
|
+
return void 0;
|
|
26755
|
+
}
|
|
26756
|
+
const arg = args2.find((a) => a.name === root);
|
|
26757
|
+
return arg ? argKindOf(arg.source) : void 0;
|
|
26758
|
+
}
|
|
26759
|
+
case "call": {
|
|
26760
|
+
if (node.callee.includes(".")) {
|
|
26761
|
+
return void 0;
|
|
26762
|
+
}
|
|
26763
|
+
const kinded = [
|
|
26764
|
+
"abs",
|
|
26765
|
+
"max",
|
|
26766
|
+
"min",
|
|
26767
|
+
"floor",
|
|
26768
|
+
"ceil",
|
|
26769
|
+
"round",
|
|
26770
|
+
"sqrt",
|
|
26771
|
+
"exp",
|
|
26772
|
+
"ln",
|
|
26773
|
+
"log",
|
|
26774
|
+
"mod"
|
|
26775
|
+
];
|
|
26776
|
+
if (!kinded.includes(node.callee)) {
|
|
26777
|
+
return null;
|
|
26778
|
+
}
|
|
26779
|
+
let acc = void 0;
|
|
26780
|
+
for (const a of node.args) {
|
|
26781
|
+
const k = kindOf(a);
|
|
26782
|
+
if (k === void 0) {
|
|
26783
|
+
continue;
|
|
26784
|
+
}
|
|
26785
|
+
if (acc === void 0 || acc === null) {
|
|
26786
|
+
acc = k;
|
|
26787
|
+
continue;
|
|
26788
|
+
}
|
|
26789
|
+
if (k !== void 0 && k !== null && k !== acc) {
|
|
26790
|
+
kindMixErr(node, acc, k);
|
|
26791
|
+
}
|
|
26792
|
+
}
|
|
26793
|
+
return acc;
|
|
26794
|
+
}
|
|
26795
|
+
case "unop":
|
|
26796
|
+
return node.op === "not" ? null : kindOf(node.operand);
|
|
26797
|
+
case "nav":
|
|
26798
|
+
return node.op === "select" ? void 0 : node.op === "collect" ? kindOf(node.body) : null;
|
|
26799
|
+
case "binop": {
|
|
26800
|
+
if (["<=", ">=", "<", ">", "=", "!=", "\u2260"].includes(node.op)) {
|
|
26801
|
+
const l2 = kindOf(node.left);
|
|
26802
|
+
const r2 = kindOf(node.right);
|
|
26803
|
+
if (l2 !== void 0 && r2 !== void 0 && l2 !== null && r2 !== null && l2 !== r2) {
|
|
26804
|
+
kindMixErr(node, l2, r2);
|
|
26805
|
+
}
|
|
26806
|
+
return null;
|
|
26807
|
+
}
|
|
26808
|
+
if (["and", "or", "xor", "implies"].includes(node.op)) {
|
|
26809
|
+
kindOf(node.left);
|
|
26810
|
+
kindOf(node.right);
|
|
26811
|
+
return null;
|
|
26812
|
+
}
|
|
26813
|
+
const l = kindOf(node.left);
|
|
26814
|
+
const r = kindOf(node.right);
|
|
26815
|
+
if (l !== void 0 && r !== void 0 && l !== null && r !== null && l !== r) {
|
|
26816
|
+
kindMixErr(node, l, r);
|
|
26817
|
+
}
|
|
26818
|
+
return l !== void 0 && l !== null ? l : r;
|
|
26819
|
+
}
|
|
26820
|
+
}
|
|
26821
|
+
};
|
|
26822
|
+
kindOf(ast);
|
|
26823
|
+
};
|
|
26824
|
+
for (const r of standard.requirements ?? []) {
|
|
26825
|
+
if (r.limit?.argsBound) {
|
|
26826
|
+
checkInlineLimit("requirement", r.id, r.limit, null);
|
|
26827
|
+
continue;
|
|
26828
|
+
}
|
|
26829
|
+
const expr = r.limit?.expression;
|
|
26830
|
+
if (!expr) {
|
|
26831
|
+
continue;
|
|
26832
|
+
}
|
|
26833
|
+
const ocl = expr.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26834
|
+
const uses = r.limit?.uses ?? [];
|
|
26835
|
+
for (const id of unresolvedIn(ocl, [], uses)) {
|
|
26836
|
+
err(
|
|
26837
|
+
"C171",
|
|
26838
|
+
`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)`
|
|
26839
|
+
);
|
|
26840
|
+
}
|
|
26841
|
+
}
|
|
26842
|
+
const resolveInlineCarrier = (ownerKind, ownerId, what, src, scope) => {
|
|
26843
|
+
let ast;
|
|
26844
|
+
try {
|
|
26845
|
+
ast = parseExpression(src);
|
|
26846
|
+
} catch (e) {
|
|
26847
|
+
err(
|
|
26848
|
+
"C171",
|
|
26849
|
+
`${ownerKind} ${ownerId}: the ${what} does not parse \u2014 ${String(e.message ?? e)} (expression-identifiers-resolve)`
|
|
26850
|
+
);
|
|
26851
|
+
return;
|
|
26852
|
+
}
|
|
26853
|
+
const ids = freeIdentifiers(ast);
|
|
26854
|
+
for (const call of new Set(ids.calls)) {
|
|
26855
|
+
if (INLINE_FUNCTION_WORDS.has(call)) {
|
|
26856
|
+
continue;
|
|
26857
|
+
}
|
|
26858
|
+
if (call.includes(".")) {
|
|
26859
|
+
const root = call.split(".")[0];
|
|
26860
|
+
if (scope.has(root) || globalExprNames.has(root) || root === "self" || CONTEXT_ROOTS.has(root)) {
|
|
26861
|
+
continue;
|
|
26862
|
+
}
|
|
26863
|
+
}
|
|
26864
|
+
if (scope.has(call) || globalExprNames.has(call)) {
|
|
26865
|
+
continue;
|
|
26866
|
+
}
|
|
26867
|
+
err(
|
|
26868
|
+
"C171",
|
|
26869
|
+
`${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)`
|
|
26870
|
+
);
|
|
26871
|
+
}
|
|
26872
|
+
for (const id of new Set(ids.names)) {
|
|
26873
|
+
const root = id.split(".")[0];
|
|
26874
|
+
if (id.includes(".") && (scope.has(root) || root === "self" || CONTEXT_ROOTS.has(root))) {
|
|
26875
|
+
continue;
|
|
26876
|
+
}
|
|
26877
|
+
if (scope.has(id)) {
|
|
26878
|
+
continue;
|
|
26879
|
+
}
|
|
26880
|
+
if (globalExprNames.has(id) || globalExprNames.has(id.split(".").pop() ?? id)) {
|
|
26881
|
+
continue;
|
|
26882
|
+
}
|
|
26883
|
+
err(
|
|
26884
|
+
"C171",
|
|
26885
|
+
`${ownerKind} ${ownerId}: the ${what} names "${id}", which nothing in scope declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26886
|
+
);
|
|
26887
|
+
}
|
|
26888
|
+
};
|
|
26889
|
+
for (const v of standard.verdicts ?? []) {
|
|
26890
|
+
const expr = v.derive;
|
|
26891
|
+
if (!expr) {
|
|
26892
|
+
continue;
|
|
26893
|
+
}
|
|
26894
|
+
const inputs = v.inputs ?? [];
|
|
26895
|
+
if (v.deriveBound) {
|
|
26896
|
+
resolveInlineCarrier("verdict", v.id, "derive", expr, new Set(inputs));
|
|
26897
|
+
continue;
|
|
26898
|
+
}
|
|
26899
|
+
const ocl = expr.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26900
|
+
for (const id of unresolvedIn(ocl, inputs, [])) {
|
|
26901
|
+
err(
|
|
26902
|
+
"C171",
|
|
26903
|
+
`verdict ${v.id}: the derive expression names "${id}", which no input declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26904
|
+
);
|
|
26905
|
+
}
|
|
26906
|
+
}
|
|
26907
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
26908
|
+
const scope = (t.variables ?? []).map((v) => v.name);
|
|
26909
|
+
for (const v of t.variables ?? []) {
|
|
26910
|
+
if (!v.derivation) {
|
|
26911
|
+
continue;
|
|
26912
|
+
}
|
|
26913
|
+
if (v.derivationBound) {
|
|
26914
|
+
resolveInlineCarrier(
|
|
26915
|
+
"conformance test",
|
|
26916
|
+
t.id,
|
|
26917
|
+
`variable ${v.name}'s derivation`,
|
|
26918
|
+
v.derivation,
|
|
26919
|
+
new Set(scope)
|
|
26920
|
+
);
|
|
26921
|
+
continue;
|
|
26922
|
+
}
|
|
26923
|
+
const ocl = v.derivation.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
26924
|
+
for (const id of unresolvedIn(ocl, scope, [])) {
|
|
26925
|
+
err(
|
|
26926
|
+
"C171",
|
|
26927
|
+
`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)`
|
|
26928
|
+
);
|
|
26929
|
+
}
|
|
26930
|
+
}
|
|
26931
|
+
}
|
|
26932
|
+
for (const c of standard.constraints ?? []) {
|
|
26933
|
+
if (!c.checkBound || !c.check) {
|
|
26934
|
+
continue;
|
|
26935
|
+
}
|
|
26936
|
+
const cArgs = c.args ?? [];
|
|
26937
|
+
const cScope = new Set(cArgs.map((a) => a.name));
|
|
26938
|
+
for (const a of cArgs) {
|
|
26939
|
+
if (a.source.includes(":")) {
|
|
26940
|
+
const segs = a.source.split(":");
|
|
26941
|
+
if (segs.length === 2 && segs[0] !== "observable") {
|
|
26942
|
+
const [kind, id] = segs;
|
|
26943
|
+
if (!DECLARATION_KINDS.has(kind)) {
|
|
26944
|
+
err(
|
|
26945
|
+
"C171",
|
|
26946
|
+
`constraint ${c.id}: argument "${a.name}" binds to "${a.source}" \u2014 "${kind}" is not a declaration kind (expression-identifiers-resolve)`
|
|
26947
|
+
);
|
|
26948
|
+
} else {
|
|
26949
|
+
const idRoot = id.split(".")[0];
|
|
26950
|
+
const idTail = id.split(".").pop() ?? id;
|
|
26951
|
+
if (!globalExprNames.has(id) && !globalExprNames.has(idRoot) && !globalExprNames.has(idTail)) {
|
|
26952
|
+
err(
|
|
26953
|
+
"C171",
|
|
26954
|
+
`constraint ${c.id}: argument "${a.name}" binds to "${a.source}", which no declared ${kind} names \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26955
|
+
);
|
|
26956
|
+
}
|
|
26957
|
+
}
|
|
26958
|
+
}
|
|
26959
|
+
continue;
|
|
26960
|
+
}
|
|
26961
|
+
if (a.source === "self" || a.source.startsWith("self.")) {
|
|
26962
|
+
continue;
|
|
26963
|
+
}
|
|
26964
|
+
const bare2 = a.source.split(":").pop() ?? a.source;
|
|
26965
|
+
if (!globalExprNames.has(a.source) && !globalExprNames.has(bare2)) {
|
|
26966
|
+
err(
|
|
26967
|
+
"C171",
|
|
26968
|
+
`constraint ${c.id}: argument "${a.name}" binds to "${a.source}", which nothing declares \u2014 air inside the formula (expression-identifiers-resolve)`
|
|
26969
|
+
);
|
|
26970
|
+
}
|
|
26971
|
+
}
|
|
26972
|
+
resolveInlineCarrier("constraint", c.id, "check", c.check, cScope);
|
|
26973
|
+
try {
|
|
26974
|
+
const ast = parseExpression(c.check);
|
|
26975
|
+
const booleanTop = ast.type === "binop" && [
|
|
26976
|
+
"<=",
|
|
26977
|
+
">=",
|
|
26978
|
+
"<",
|
|
26979
|
+
">",
|
|
26980
|
+
"=",
|
|
26981
|
+
"!=",
|
|
26982
|
+
"\u2260",
|
|
26983
|
+
"and",
|
|
26984
|
+
"or",
|
|
26985
|
+
"xor",
|
|
26986
|
+
"implies"
|
|
26987
|
+
].includes(ast.op) || ast.type === "nav" && ["forAll", "exists"].includes(ast.op);
|
|
26988
|
+
if (!booleanTop) {
|
|
26989
|
+
err(
|
|
26990
|
+
"C84",
|
|
26991
|
+
`constraint ${c.id}: the check does not evaluate to a boolean \u2014 an invariant is one comparison or logical composition (constraint-shape)`
|
|
26992
|
+
);
|
|
26993
|
+
}
|
|
26994
|
+
} catch {
|
|
26995
|
+
}
|
|
26996
|
+
}
|
|
26997
|
+
const memberSet = /* @__PURE__ */ new Map();
|
|
26998
|
+
for (const rc of standard.requirementClasses ?? []) {
|
|
26999
|
+
memberSet.set(rc.id, new Set((rc.members ?? []).map(String)));
|
|
27000
|
+
}
|
|
27001
|
+
for (const rc of standard.requirementClasses ?? []) {
|
|
27002
|
+
const law = rc.limit?.expression;
|
|
27003
|
+
const members = memberSet.get(rc.id) ?? /* @__PURE__ */ new Set();
|
|
27004
|
+
if (!law) {
|
|
27005
|
+
continue;
|
|
27006
|
+
}
|
|
27007
|
+
if (rc.limit?.argsBound) {
|
|
27008
|
+
checkInlineLimit("requirement class", rc.id, rc.limit, members);
|
|
27009
|
+
const covered2 = /* @__PURE__ */ new Set();
|
|
27010
|
+
try {
|
|
27011
|
+
for (const n of freeIdentifiers(parseExpression(law)).names) {
|
|
27012
|
+
covered2.add(n);
|
|
27013
|
+
}
|
|
27014
|
+
} catch {
|
|
27015
|
+
}
|
|
27016
|
+
for (const a of rc.limit.args ?? []) {
|
|
27017
|
+
covered2.add(a.name);
|
|
27018
|
+
covered2.add(a.source);
|
|
27019
|
+
}
|
|
27020
|
+
for (const m of members) {
|
|
27021
|
+
if (!covered2.has(m)) {
|
|
27022
|
+
warn(
|
|
27023
|
+
"C172",
|
|
27024
|
+
`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)`
|
|
27025
|
+
);
|
|
27026
|
+
}
|
|
27027
|
+
}
|
|
27028
|
+
continue;
|
|
27029
|
+
}
|
|
27030
|
+
const ocl = law.replace(/^ocl\{/, "").replace(/\}$/, "");
|
|
27031
|
+
const ids = (ocl.match(/[A-Za-z_][A-Za-z0-9_]*/g) ?? []).filter(
|
|
27032
|
+
(x) => !OCL_WORDS.has(x)
|
|
27033
|
+
);
|
|
27034
|
+
const lawIds = /* @__PURE__ */ new Set();
|
|
27035
|
+
for (const id of ids) {
|
|
27036
|
+
lawIds.add(id);
|
|
27037
|
+
if (!members.has(id)) {
|
|
27038
|
+
err(
|
|
27039
|
+
"C172",
|
|
27040
|
+
`requirement class ${rc.id}: the law names "${id}", which is not a contained member \u2014 the algebra composes the containment only (requirement-algebra-resolves)`
|
|
27041
|
+
);
|
|
27042
|
+
}
|
|
27043
|
+
}
|
|
27044
|
+
for (const m of members) {
|
|
27045
|
+
if (!lawIds.has(m)) {
|
|
27046
|
+
warn(
|
|
27047
|
+
"C172",
|
|
27048
|
+
`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)`
|
|
27049
|
+
);
|
|
27050
|
+
}
|
|
27051
|
+
}
|
|
27052
|
+
}
|
|
27053
|
+
const DEPRECATION_GENERATION = "v3.4";
|
|
27054
|
+
const generationRank = (g) => {
|
|
27055
|
+
const m = g.match(/^v(\d+)(?:\.(\d+))?$/);
|
|
27056
|
+
if (!m) {
|
|
27057
|
+
return -1;
|
|
27058
|
+
}
|
|
27059
|
+
return Number(m[1]) * 1e3 + Number(m[2] ?? "0");
|
|
27060
|
+
};
|
|
27061
|
+
try {
|
|
27062
|
+
const mf = readPackageManifest(dir);
|
|
27063
|
+
if (mf.language !== void 0) {
|
|
27064
|
+
if (!/^v\d+(\.\d+)?$/.test(mf.language)) {
|
|
27065
|
+
err(
|
|
27066
|
+
"C176",
|
|
27067
|
+
`the declared language "${mf.language}" is not a generation (v<major>[.<minor>]) (language-declared-wellformed)`
|
|
27068
|
+
);
|
|
27069
|
+
} else if (generationRank(mf.language) >= generationRank(DEPRECATION_GENERATION)) {
|
|
27070
|
+
let legacy = 0;
|
|
27071
|
+
for (const r of standard.requirements ?? []) {
|
|
27072
|
+
if (r.limit && !r.limit.argsBound && r.limit.expression) {
|
|
27073
|
+
legacy += 1;
|
|
27074
|
+
}
|
|
27075
|
+
}
|
|
27076
|
+
for (const v of standard.verdicts ?? []) {
|
|
27077
|
+
if (v.derive && !v.deriveBound) {
|
|
27078
|
+
legacy += 1;
|
|
27079
|
+
}
|
|
27080
|
+
}
|
|
27081
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
27082
|
+
for (const v of t.variables ?? []) {
|
|
27083
|
+
if (v.derivation && !v.derivationBound) {
|
|
27084
|
+
legacy += 1;
|
|
27085
|
+
}
|
|
27086
|
+
}
|
|
27087
|
+
for (const p of t.preconditions ?? []) {
|
|
27088
|
+
if (p.check && !p.checkBound) {
|
|
27089
|
+
legacy += 1;
|
|
27090
|
+
}
|
|
27091
|
+
}
|
|
27092
|
+
}
|
|
27093
|
+
for (const c of standard.constraints ?? []) {
|
|
27094
|
+
if (c.check && !c.checkBound) {
|
|
27095
|
+
legacy += 1;
|
|
27096
|
+
}
|
|
27097
|
+
}
|
|
27098
|
+
if (legacy > 0) {
|
|
27099
|
+
warn(
|
|
27100
|
+
"C178",
|
|
27101
|
+
`${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)`
|
|
27102
|
+
);
|
|
27103
|
+
}
|
|
27104
|
+
}
|
|
27105
|
+
}
|
|
27106
|
+
} catch {
|
|
27107
|
+
}
|
|
27108
|
+
{
|
|
27109
|
+
const seriesVariables = /* @__PURE__ */ new Map();
|
|
27110
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
27111
|
+
for (const v of t.variables ?? []) {
|
|
27112
|
+
seriesVariables.set(v.name, v.series !== null);
|
|
27113
|
+
}
|
|
27114
|
+
}
|
|
27115
|
+
for (const b of standard.uncertaintyBudgets ?? []) {
|
|
27116
|
+
if (!b.target) {
|
|
27117
|
+
err(
|
|
27118
|
+
"C179",
|
|
27119
|
+
`uncertainty_budget ${b.id}: declares no target \u2014 the budget backs a declared verdict's measured quantity (uncertainty-budget-resolves)`
|
|
27120
|
+
);
|
|
27121
|
+
} else if (!(standard.verdicts ?? []).some((v) => v.id === b.target)) {
|
|
27122
|
+
err(
|
|
27123
|
+
"C179",
|
|
27124
|
+
`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)`
|
|
27125
|
+
);
|
|
27126
|
+
}
|
|
27127
|
+
if (b.components.length === 0) {
|
|
27128
|
+
warn(
|
|
27129
|
+
"C179",
|
|
27130
|
+
`uncertainty_budget ${b.id}: declares no components \u2014 an empty budget states no uncertainty (uncertainty-budget-resolves)`
|
|
27131
|
+
);
|
|
27132
|
+
}
|
|
27133
|
+
if (b.coverageK && !(Number(b.coverageK) > 0)) {
|
|
27134
|
+
err(
|
|
27135
|
+
"C179",
|
|
27136
|
+
`uncertainty_budget ${b.id}: coverage k "${b.coverageK}" is not a positive number (uncertainty-budget-resolves)`
|
|
27137
|
+
);
|
|
27138
|
+
}
|
|
27139
|
+
for (const c of b.components) {
|
|
27140
|
+
if (c.type === "A") {
|
|
27141
|
+
if (!c.series) {
|
|
27142
|
+
err(
|
|
27143
|
+
"C179",
|
|
27144
|
+
`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)`
|
|
27145
|
+
);
|
|
27146
|
+
} else if (!seriesVariables.has(c.series)) {
|
|
27147
|
+
err(
|
|
27148
|
+
"C179",
|
|
27149
|
+
`uncertainty_budget ${b.id}: component ${c.id}'s series "${c.series}" is not a declared test variable (uncertainty-budget-resolves)`
|
|
27150
|
+
);
|
|
27151
|
+
} else if (!seriesVariables.get(c.series)) {
|
|
27152
|
+
err(
|
|
27153
|
+
"C179",
|
|
27154
|
+
`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)`
|
|
27155
|
+
);
|
|
27156
|
+
}
|
|
27157
|
+
} else {
|
|
27158
|
+
if (!c.distribution) {
|
|
27159
|
+
err(
|
|
27160
|
+
"C179",
|
|
27161
|
+
`uncertainty_budget ${b.id}: component ${c.id} is Type B but states no distribution (uncertainty-budget-resolves)`
|
|
27162
|
+
);
|
|
27163
|
+
}
|
|
27164
|
+
if (!c.halfWidth) {
|
|
27165
|
+
err(
|
|
27166
|
+
"C179",
|
|
27167
|
+
`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)`
|
|
27168
|
+
);
|
|
27169
|
+
}
|
|
27170
|
+
}
|
|
27171
|
+
}
|
|
27172
|
+
}
|
|
27173
|
+
}
|
|
27174
|
+
for (const p of standard.processes ?? []) {
|
|
27175
|
+
for (const st of p.steps ?? []) {
|
|
27176
|
+
if (!st.completion) {
|
|
27177
|
+
continue;
|
|
27178
|
+
}
|
|
27179
|
+
const ios = /* @__PURE__ */ new Set([...st.sigInputs, ...st.sigOutputs]);
|
|
27180
|
+
let ids;
|
|
27181
|
+
try {
|
|
27182
|
+
ids = freeIdentifiers(
|
|
27183
|
+
parseExpression(
|
|
27184
|
+
st.completion.replace(/^ocl\{/, "").replace(/\}$/, "")
|
|
27185
|
+
)
|
|
27186
|
+
);
|
|
27187
|
+
} catch (e) {
|
|
27188
|
+
err(
|
|
27189
|
+
"C173",
|
|
27190
|
+
`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)`
|
|
27191
|
+
);
|
|
27192
|
+
continue;
|
|
27193
|
+
}
|
|
27194
|
+
for (const call of new Set(ids.calls)) {
|
|
27195
|
+
if (!INLINE_FUNCTION_WORDS.has(call)) {
|
|
27196
|
+
err(
|
|
27197
|
+
"C173",
|
|
27198
|
+
`process ${p.id}: step "${st.id}" completion calls "${call}(\u2026)", which is not in the expression function vocabulary (step-plane-refs-resolve)`
|
|
27199
|
+
);
|
|
27200
|
+
}
|
|
27201
|
+
}
|
|
27202
|
+
for (const id of new Set(ids.names)) {
|
|
27203
|
+
const root = id.split(".")[0];
|
|
27204
|
+
if (id.includes(".") && (root === "self" || CONTEXT_ROOTS.has(root))) {
|
|
27205
|
+
continue;
|
|
27206
|
+
}
|
|
27207
|
+
if (ios.has(id) || ios.has(root)) {
|
|
27208
|
+
continue;
|
|
27209
|
+
}
|
|
27210
|
+
err(
|
|
27211
|
+
"C173",
|
|
27212
|
+
`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)`
|
|
27213
|
+
);
|
|
27214
|
+
}
|
|
27215
|
+
}
|
|
27216
|
+
}
|
|
27217
|
+
try {
|
|
27218
|
+
const mf = readPackageManifest(dir);
|
|
27219
|
+
const eds = (mf.editions ?? []).map(String);
|
|
27220
|
+
if (eds.length > 1) {
|
|
27221
|
+
const map = JSON.parse(
|
|
27222
|
+
readFileSync5(join4(dir, "edition-mapping.json"), "utf8")
|
|
27223
|
+
);
|
|
27224
|
+
if (map.kind !== "primmel-edition-mapping/1") {
|
|
27225
|
+
err(
|
|
27226
|
+
"C170",
|
|
27227
|
+
`edition-mapping.json: kind "${String(map.kind)}" is not primmel-edition-mapping/1 (edition-lineage-declared)`
|
|
27228
|
+
);
|
|
27229
|
+
} else {
|
|
27230
|
+
const fromEd = map.from?.edition === void 0 ? void 0 : String(map.from.edition);
|
|
27231
|
+
const toEd = map.to?.edition === void 0 ? void 0 : String(map.to.edition);
|
|
27232
|
+
for (const [side, ed] of [
|
|
27233
|
+
["from", fromEd],
|
|
27234
|
+
["to", toEd]
|
|
27235
|
+
]) {
|
|
27236
|
+
if (!ed || !eds.includes(ed)) {
|
|
27237
|
+
err(
|
|
27238
|
+
"C170",
|
|
27239
|
+
`edition-mapping.json: the ${side} edition ${String(ed)} is not among the manifest's declared editions [${eds.join(", ")}] (edition-lineage-declared)`
|
|
27240
|
+
);
|
|
27241
|
+
}
|
|
27242
|
+
}
|
|
27243
|
+
}
|
|
27244
|
+
}
|
|
27245
|
+
} catch (e) {
|
|
27246
|
+
const code = e.code;
|
|
27247
|
+
if (code === "ENOENT") {
|
|
27248
|
+
const eds = (() => {
|
|
27249
|
+
try {
|
|
27250
|
+
return (readPackageManifest(dir).editions ?? []).map(
|
|
27251
|
+
String
|
|
27252
|
+
);
|
|
27253
|
+
} catch {
|
|
27254
|
+
return [];
|
|
27255
|
+
}
|
|
27256
|
+
})();
|
|
27257
|
+
if (eds.length > 1) {
|
|
27258
|
+
err(
|
|
27259
|
+
"C170",
|
|
27260
|
+
`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)`
|
|
27261
|
+
);
|
|
27262
|
+
}
|
|
27263
|
+
} else if (e instanceof SyntaxError) {
|
|
27264
|
+
err(
|
|
27265
|
+
"C170",
|
|
27266
|
+
`edition-mapping.json is not valid JSON: ${e.message} (edition-lineage-declared)`
|
|
27267
|
+
);
|
|
27268
|
+
}
|
|
27269
|
+
}
|
|
27270
|
+
const methodTargetIds = (s) => /* @__PURE__ */ new Set([
|
|
27271
|
+
...(s.processes ?? []).map((p) => p.id),
|
|
27272
|
+
...(s.conformanceTests ?? []).map((x) => x.id)
|
|
27273
|
+
]);
|
|
27274
|
+
const localMethodIds = methodTargetIds(standard);
|
|
27275
|
+
const scopedMethodIds = /* @__PURE__ */ new Map();
|
|
27276
|
+
const resolveCitation = (elemId, ref) => {
|
|
27277
|
+
const colon = ref.indexOf(":");
|
|
27278
|
+
if (colon <= 0) {
|
|
27279
|
+
if (!localMethodIds.has(ref)) {
|
|
27280
|
+
err(
|
|
27281
|
+
"C168",
|
|
27282
|
+
`${elemId}: the reference "${ref}" names no process or conformance test declared in this package (method-ref-resolves)`
|
|
27283
|
+
);
|
|
27284
|
+
}
|
|
27285
|
+
return;
|
|
27286
|
+
}
|
|
27287
|
+
if (!options.resolvePackage) {
|
|
27288
|
+
return;
|
|
27289
|
+
}
|
|
27290
|
+
const pkgId = ref.slice(0, colon);
|
|
27291
|
+
const localId = ref.slice(colon + 1);
|
|
27292
|
+
let ids = scopedMethodIds.get(pkgId);
|
|
27293
|
+
if (!ids) {
|
|
27294
|
+
ids = /* @__PURE__ */ new Set();
|
|
27295
|
+
try {
|
|
27296
|
+
const depDir = options.resolvePackage(pkgId);
|
|
27297
|
+
if (depDir) {
|
|
27298
|
+
const dep = loadPackageWithIssues(depDir);
|
|
27299
|
+
ids = methodTargetIds(dep.standard);
|
|
27300
|
+
}
|
|
27301
|
+
} catch {
|
|
27302
|
+
}
|
|
27303
|
+
scopedMethodIds.set(pkgId, ids);
|
|
27304
|
+
}
|
|
27305
|
+
if (!ids.has(localId)) {
|
|
27306
|
+
err(
|
|
27307
|
+
"C168",
|
|
27308
|
+
`${elemId}: the reference "${ref}" names no process or conformance test declared in package "${pkgId}" (method-ref-resolves)`
|
|
27309
|
+
);
|
|
27310
|
+
}
|
|
27311
|
+
};
|
|
27312
|
+
for (const t of standard.conformanceTests ?? []) {
|
|
27313
|
+
const ref = t.methodRef;
|
|
27314
|
+
if (ref) {
|
|
27315
|
+
resolveCitation(t.id, ref);
|
|
27316
|
+
}
|
|
27317
|
+
}
|
|
27318
|
+
for (const pr of standard.processes ?? []) {
|
|
27319
|
+
const raw = pr;
|
|
27320
|
+
for (const st of raw.steps ?? []) {
|
|
27321
|
+
const call = st.calls || st.signatureBlock?.match(/\bcalls +([\w:/.-]+)/)?.[1];
|
|
27322
|
+
if (call) {
|
|
27323
|
+
resolveCitation(`${pr.id}/step/${st.id ?? ""}`, call);
|
|
27324
|
+
}
|
|
27325
|
+
}
|
|
27326
|
+
}
|
|
24766
27327
|
const ASPECT_FAMILY = {
|
|
24767
27328
|
metadata: "is",
|
|
24768
27329
|
provenance: "is",
|
|
@@ -25650,7 +28211,7 @@ function checkPackage(dir, options = {}) {
|
|
|
25650
28211
|
`constraint ${c.id}: stereotype "${c.stereotype || "(none)"}" \u2014 a constraint is always \xABinv\xBB, the subject's declaration-level invariant (constraint-shape)`
|
|
25651
28212
|
);
|
|
25652
28213
|
}
|
|
25653
|
-
if (!OCL_CHECK.test(c.check)) {
|
|
28214
|
+
if (!c.checkBound && !OCL_CHECK.test(c.check)) {
|
|
25654
28215
|
err(
|
|
25655
28216
|
"C84",
|
|
25656
28217
|
`constraint ${c.id}: check is not one OCL boolean expression ocl{\u2026} over the subject's declared anatomy (constraint-shape)`
|
|
@@ -28745,9 +31306,9 @@ function checkPackage(dir, options = {}) {
|
|
|
28745
31306
|
if (!dataclassByEntity.has(c.id)) {
|
|
28746
31307
|
dataclassByEntity.set(c.id, c);
|
|
28747
31308
|
}
|
|
28748
|
-
const
|
|
28749
|
-
if (!dataclassByEntity.has(
|
|
28750
|
-
dataclassByEntity.set(
|
|
31309
|
+
const bare2 = c.id.includes("#") ? c.id.slice(0, c.id.indexOf("#")) : c.id;
|
|
31310
|
+
if (!dataclassByEntity.has(bare2)) {
|
|
31311
|
+
dataclassByEntity.set(bare2, c);
|
|
28751
31312
|
}
|
|
28752
31313
|
}
|
|
28753
31314
|
const whereFields = (where) => {
|
|
@@ -30345,6 +32906,101 @@ function checkVerdictChains(standard) {
|
|
|
30345
32906
|
}
|
|
30346
32907
|
return issues;
|
|
30347
32908
|
}
|
|
32909
|
+
function checkLmlAligned(standard) {
|
|
32910
|
+
const issues = [];
|
|
32911
|
+
const err = (check, message) => issues.push({ check, severity: "error", message });
|
|
32912
|
+
const warn = (check, message) => issues.push({ check, severity: "warning", message });
|
|
32913
|
+
const namespaceIds = new Set((standard.namespaces ?? []).map((n) => n.id));
|
|
32914
|
+
const dataclassIds = /* @__PURE__ */ new Set();
|
|
32915
|
+
for (const c of standard.dataclasses ?? []) {
|
|
32916
|
+
dataclassIds.add(c.id);
|
|
32917
|
+
dataclassIds.add(c.id.replace(/#data$/, ""));
|
|
32918
|
+
}
|
|
32919
|
+
const symbolIds = new Set((standard.symbols ?? []).map((s) => s.id));
|
|
32920
|
+
const datumIds = new Set((standard.datums ?? []).map((d) => d.id));
|
|
32921
|
+
const CLAUSE_CITATION = /clause-\d|§\d/i;
|
|
32922
|
+
for (const d of standard.datums ?? []) {
|
|
32923
|
+
if (!d.description) {
|
|
32924
|
+
continue;
|
|
32925
|
+
}
|
|
32926
|
+
if (CLAUSE_CITATION.test(d.description)) {
|
|
32927
|
+
err(
|
|
32928
|
+
"C158",
|
|
32929
|
+
`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)`
|
|
32930
|
+
);
|
|
32931
|
+
} else if (d.description.includes("TODO.roadmap")) {
|
|
32932
|
+
warn(
|
|
32933
|
+
"C158",
|
|
32934
|
+
`datum ${d.id}: the description carries the unfinished-prose marker TODO.roadmap (prose-quarantine)`
|
|
32935
|
+
);
|
|
32936
|
+
}
|
|
32937
|
+
}
|
|
32938
|
+
for (const w of standard.wireMappings ?? []) {
|
|
32939
|
+
if (w.namespaceRef && !namespaceIds.has(w.namespaceRef)) {
|
|
32940
|
+
err(
|
|
32941
|
+
"C159",
|
|
32942
|
+
`mapping ${w.id}: namespace "${w.namespaceRef}" names no declared namespace block (urn-only-refs)`
|
|
32943
|
+
);
|
|
32944
|
+
}
|
|
32945
|
+
}
|
|
32946
|
+
for (const c of standard.checks ?? []) {
|
|
32947
|
+
for (const inp of c.inputs ?? []) {
|
|
32948
|
+
if (!(datumIds.has(inp) || symbolIds.has(inp))) {
|
|
32949
|
+
err(
|
|
32950
|
+
"C160",
|
|
32951
|
+
`check ${c.id}: input "${inp}" resolves to no declared datum or symbol \u2014 the check consumes an undeclared name (signature-closure)`
|
|
32952
|
+
);
|
|
32953
|
+
}
|
|
32954
|
+
}
|
|
32955
|
+
}
|
|
32956
|
+
for (const d of standard.datums ?? []) {
|
|
32957
|
+
for (const r of d.renders ?? []) {
|
|
32958
|
+
if (!MATH_NOTATIONS.includes(r.notation)) {
|
|
32959
|
+
err(
|
|
32960
|
+
"C161",
|
|
32961
|
+
`datum ${d.id}: render notation "${r.notation}" is outside the closed vocabulary (${MATH_NOTATIONS.join("|")}) (check-surface)`
|
|
32962
|
+
);
|
|
32963
|
+
}
|
|
32964
|
+
}
|
|
32965
|
+
}
|
|
32966
|
+
const metaNamespace = standard.meta?.namespace ?? "";
|
|
32967
|
+
if (metaNamespace && namespaceIds.size > 0 && !namespaceIds.has(metaNamespace)) {
|
|
32968
|
+
err(
|
|
32969
|
+
"C162",
|
|
32970
|
+
`metadata namespace "${metaNamespace}" names no declared namespace block (namespace-coherence)`
|
|
32971
|
+
);
|
|
32972
|
+
}
|
|
32973
|
+
for (const w of standard.wireMappings ?? []) {
|
|
32974
|
+
if (!MAPPING_FORMATS.includes(w.format)) {
|
|
32975
|
+
err(
|
|
32976
|
+
"C164",
|
|
32977
|
+
`mapping ${w.id}: format "${w.format}" is outside the wire vocabulary (${MAPPING_FORMATS.join("|")}) (wire-mapping-coverage)`
|
|
32978
|
+
);
|
|
32979
|
+
}
|
|
32980
|
+
if (dataclassIds.size > 0 && !dataclassIds.has(w.target)) {
|
|
32981
|
+
err(
|
|
32982
|
+
"C164",
|
|
32983
|
+
`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)`
|
|
32984
|
+
);
|
|
32985
|
+
}
|
|
32986
|
+
}
|
|
32987
|
+
const QUALIFIED_REF = /^[a-z]+:[A-Za-z0-9_-]+$/;
|
|
32988
|
+
for (const d of standard.datums ?? []) {
|
|
32989
|
+
if (d.unit && !QUALIFIED_REF.test(d.unit)) {
|
|
32990
|
+
err(
|
|
32991
|
+
"C167",
|
|
32992
|
+
`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)`
|
|
32993
|
+
);
|
|
32994
|
+
}
|
|
32995
|
+
if (d.quantityKind && !QUALIFIED_REF.test(d.quantityKind)) {
|
|
32996
|
+
err(
|
|
32997
|
+
"C167",
|
|
32998
|
+
`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)`
|
|
32999
|
+
);
|
|
33000
|
+
}
|
|
33001
|
+
}
|
|
33002
|
+
return issues;
|
|
33003
|
+
}
|
|
30348
33004
|
function checkEditionLifecycle(dir, standard) {
|
|
30349
33005
|
const issues = [];
|
|
30350
33006
|
const err = (check, message) => issues.push({ check, severity: "error", message });
|
|
@@ -30546,6 +33202,143 @@ function findCycle(adj) {
|
|
|
30546
33202
|
return cycle;
|
|
30547
33203
|
}
|
|
30548
33204
|
|
|
33205
|
+
// src/fmt.ts
|
|
33206
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync3, writeFileSync } from "node:fs";
|
|
33207
|
+
import { join as join5 } from "node:path";
|
|
33208
|
+
|
|
33209
|
+
// src/ser-des/dump.ts
|
|
33210
|
+
function dump(model, dumpers) {
|
|
33211
|
+
let out = "";
|
|
33212
|
+
if (model.root !== null) {
|
|
33213
|
+
out += "root " + model.root.id + "\n\n";
|
|
33214
|
+
}
|
|
33215
|
+
out += dumpMetadata(model.meta) + "\n";
|
|
33216
|
+
const childIds = /* @__PURE__ */ new Set();
|
|
33217
|
+
for (const p of model.processes) {
|
|
33218
|
+
for (const c of p.children) {
|
|
33219
|
+
childIds.add(c);
|
|
33220
|
+
}
|
|
33221
|
+
}
|
|
33222
|
+
const processMap = new Map(model.processes.map((p) => [p.id, p]));
|
|
33223
|
+
const memberIds = /* @__PURE__ */ new Set();
|
|
33224
|
+
for (const rc of model.requirementClasses ?? []) {
|
|
33225
|
+
for (const m of rc.members ?? []) {
|
|
33226
|
+
memberIds.add(m);
|
|
33227
|
+
}
|
|
33228
|
+
}
|
|
33229
|
+
const requirementMap = new Map(
|
|
33230
|
+
(model.requirements ?? []).map((r) => [r.id, r])
|
|
33231
|
+
);
|
|
33232
|
+
const classMap = new Map(
|
|
33233
|
+
(model.requirementClasses ?? []).map((rc) => [rc.id, rc])
|
|
33234
|
+
);
|
|
33235
|
+
const dumpersRef = dumpers;
|
|
33236
|
+
const dumpClassTree = (rcId) => {
|
|
33237
|
+
const rc = classMap.get(rcId);
|
|
33238
|
+
if (!rc) {
|
|
33239
|
+
return "";
|
|
33240
|
+
}
|
|
33241
|
+
const base = dumpersRef.requirementClasses(rc);
|
|
33242
|
+
if (!rc.members || rc.members.length === 0) {
|
|
33243
|
+
return base;
|
|
33244
|
+
}
|
|
33245
|
+
const inner = rc.members.map((m) => {
|
|
33246
|
+
const body = dumpersRef.requirements(requirementMap.get(m));
|
|
33247
|
+
return body.split("\n").filter((l) => l !== "").map((l) => " " + l).join("\n");
|
|
33248
|
+
}).join("\n");
|
|
33249
|
+
return base.slice(0, base.lastIndexOf("}")) + inner + "\n}\n";
|
|
33250
|
+
};
|
|
33251
|
+
Object.keys(dumpers).forEach((field) => {
|
|
33252
|
+
if (field === "processes") {
|
|
33253
|
+
for (const p of model.processes) {
|
|
33254
|
+
if (!childIds.has(p.id)) {
|
|
33255
|
+
out += dumpProcessTree(p, processMap);
|
|
33256
|
+
}
|
|
33257
|
+
}
|
|
33258
|
+
return;
|
|
33259
|
+
}
|
|
33260
|
+
if (field === "requirements") {
|
|
33261
|
+
for (const r of model.requirements ?? []) {
|
|
33262
|
+
if (!memberIds.has(r.id)) {
|
|
33263
|
+
out += dumpersRef.requirements(r);
|
|
33264
|
+
}
|
|
33265
|
+
}
|
|
33266
|
+
return;
|
|
33267
|
+
}
|
|
33268
|
+
if (field === "requirementClasses") {
|
|
33269
|
+
for (const rc of model.requirementClasses ?? []) {
|
|
33270
|
+
out += dumpClassTree(rc.id);
|
|
33271
|
+
}
|
|
33272
|
+
return;
|
|
33273
|
+
}
|
|
33274
|
+
const items = model[field];
|
|
33275
|
+
const dumper = dumpers[field];
|
|
33276
|
+
for (const item of items) {
|
|
33277
|
+
out += dumper(item);
|
|
33278
|
+
}
|
|
33279
|
+
});
|
|
33280
|
+
return out;
|
|
33281
|
+
}
|
|
33282
|
+
|
|
33283
|
+
// src/ser-des/index.ts
|
|
33284
|
+
function load(mmelString, options = {}) {
|
|
33285
|
+
const context = parse(mmelString, PARSER_CONFIG, options);
|
|
33286
|
+
return resolve(context, RESOLVER_CONFIG);
|
|
33287
|
+
}
|
|
33288
|
+
function loadFile(filePath, options = {}) {
|
|
33289
|
+
const content = preprocessIncludes(filePath);
|
|
33290
|
+
return load(content, options);
|
|
33291
|
+
}
|
|
33292
|
+
function dump2(standard) {
|
|
33293
|
+
return dump(standard, DUMPER_CONFIG);
|
|
33294
|
+
}
|
|
33295
|
+
|
|
33296
|
+
// src/fmt.ts
|
|
33297
|
+
var ALLOWLIST = ".primmel-allowlist.prl";
|
|
33298
|
+
function walkPrl(dir, out = []) {
|
|
33299
|
+
for (const e of readdirSync4(dir).sort()) {
|
|
33300
|
+
const p = join5(dir, e);
|
|
33301
|
+
if (statSync3(p).isDirectory()) {
|
|
33302
|
+
walkPrl(p, out);
|
|
33303
|
+
} else if (e.endsWith(".prl") && e !== ALLOWLIST) {
|
|
33304
|
+
out.push(p);
|
|
33305
|
+
}
|
|
33306
|
+
}
|
|
33307
|
+
return out;
|
|
33308
|
+
}
|
|
33309
|
+
function fmtPackage(dir, check = false) {
|
|
33310
|
+
const result = { dir, files: [], written: 0 };
|
|
33311
|
+
for (const file of walkPrl(dir)) {
|
|
33312
|
+
const src = readFileSync6(file, "utf8");
|
|
33313
|
+
if (/^\s*include\s+"/m.test(src)) {
|
|
33314
|
+
result.files.push({ file, status: "skipped-includes" });
|
|
33315
|
+
continue;
|
|
33316
|
+
}
|
|
33317
|
+
let canonical2;
|
|
33318
|
+
try {
|
|
33319
|
+
const raw = dump2(loadFile(file));
|
|
33320
|
+
if (dump2(load(raw)) !== raw) {
|
|
33321
|
+
result.files.push({ file, status: "unstable" });
|
|
33322
|
+
continue;
|
|
33323
|
+
}
|
|
33324
|
+
canonical2 = /^\s*metadata\s*\{/.test(src) ? raw : raw.replace(/^metadata \{\n(?: {2}\w+ ""\n)*\}\n+/, "");
|
|
33325
|
+
} catch {
|
|
33326
|
+
result.files.push({ file, status: "unstable" });
|
|
33327
|
+
continue;
|
|
33328
|
+
}
|
|
33329
|
+
if (canonical2 === src) {
|
|
33330
|
+
result.files.push({ file, status: "unchanged" });
|
|
33331
|
+
continue;
|
|
33332
|
+
}
|
|
33333
|
+
if (!check) {
|
|
33334
|
+
writeFileSync(file, canonical2);
|
|
33335
|
+
result.written += 1;
|
|
33336
|
+
}
|
|
33337
|
+
result.files.push({ file, status: "formatted" });
|
|
33338
|
+
}
|
|
33339
|
+
return result;
|
|
33340
|
+
}
|
|
33341
|
+
|
|
30549
33342
|
// src/export/reqif.ts
|
|
30550
33343
|
var REQIF_NAMESPACE = "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd";
|
|
30551
33344
|
var REQIF_VERSION = "1.0";
|
|
@@ -31819,23 +34612,23 @@ function renderJsonLd(prefixes, triples) {
|
|
|
31819
34612
|
|
|
31820
34613
|
// src/export/retrieval.ts
|
|
31821
34614
|
import { createHash } from "node:crypto";
|
|
31822
|
-
import { readdirSync as
|
|
31823
|
-
import { join as
|
|
34615
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
34616
|
+
import { join as join7, relative } from "node:path";
|
|
31824
34617
|
|
|
31825
34618
|
// src/export/unitsdb.ts
|
|
31826
|
-
import { existsSync as existsSync6, readFileSync as
|
|
31827
|
-
import { join as
|
|
34619
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "node:fs";
|
|
34620
|
+
import { join as join6 } from "node:path";
|
|
31828
34621
|
function loadUnitsDb(dir) {
|
|
31829
34622
|
if (!dir) {
|
|
31830
34623
|
return null;
|
|
31831
34624
|
}
|
|
31832
34625
|
try {
|
|
31833
34626
|
const entries = [];
|
|
31834
|
-
const jsonPath =
|
|
34627
|
+
const jsonPath = join6(dir, "units.json");
|
|
31835
34628
|
if (!existsSync6(jsonPath)) {
|
|
31836
34629
|
return null;
|
|
31837
34630
|
}
|
|
31838
|
-
const parsed = JSON.parse(
|
|
34631
|
+
const parsed = JSON.parse(readFileSync7(jsonPath, "utf8")).units;
|
|
31839
34632
|
if (!Array.isArray(parsed)) {
|
|
31840
34633
|
return null;
|
|
31841
34634
|
}
|
|
@@ -32066,12 +34859,12 @@ function retrievalDigest(value) {
|
|
|
32066
34859
|
return createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
|
|
32067
34860
|
}
|
|
32068
34861
|
function* walkPackage(dir) {
|
|
32069
|
-
for (const entry of
|
|
34862
|
+
for (const entry of readdirSync5(dir).sort()) {
|
|
32070
34863
|
if (entry === ".DS_Store") {
|
|
32071
34864
|
continue;
|
|
32072
34865
|
}
|
|
32073
|
-
const p =
|
|
32074
|
-
if (
|
|
34866
|
+
const p = join7(dir, entry);
|
|
34867
|
+
if (statSync4(p).isDirectory()) {
|
|
32075
34868
|
yield* walkPackage(p);
|
|
32076
34869
|
} else {
|
|
32077
34870
|
yield p;
|
|
@@ -32083,7 +34876,7 @@ function packageSourceHash(dir) {
|
|
|
32083
34876
|
for (const file of walkPackage(dir)) {
|
|
32084
34877
|
h.update(relative(dir, file));
|
|
32085
34878
|
h.update("\0");
|
|
32086
|
-
h.update(createHash("sha256").update(
|
|
34879
|
+
h.update(createHash("sha256").update(readFileSync8(file)).digest());
|
|
32087
34880
|
h.update("\n");
|
|
32088
34881
|
}
|
|
32089
34882
|
return h.digest("hex");
|
|
@@ -32339,6 +35132,9 @@ function retrievalFacet(unit, pkg) {
|
|
|
32339
35132
|
facet[`app_${dim}_match`] = match;
|
|
32340
35133
|
}
|
|
32341
35134
|
}
|
|
35135
|
+
if ((unit.method_refs ?? []).length > 0) {
|
|
35136
|
+
facet.method_refs = unit.method_refs.join("|");
|
|
35137
|
+
}
|
|
32342
35138
|
return facet;
|
|
32343
35139
|
}
|
|
32344
35140
|
function resolveTextAddress(address, elementIds) {
|
|
@@ -32483,11 +35279,34 @@ function requirementUnit(r) {
|
|
|
32483
35279
|
collectClauses(r)
|
|
32484
35280
|
);
|
|
32485
35281
|
}
|
|
35282
|
+
function processUnit(pr) {
|
|
35283
|
+
const steps = pr.steps ?? [];
|
|
35284
|
+
const calls = steps.map((s) => {
|
|
35285
|
+
const st = s;
|
|
35286
|
+
const call = st.calls || st.signatureBlock?.match(/\bcalls +([\w:/.-]+)/)?.[1] || "";
|
|
35287
|
+
return call ? { id: st.id ?? "", calls: call } : null;
|
|
35288
|
+
}).filter((s) => s !== null);
|
|
35289
|
+
return assemble(
|
|
35290
|
+
{
|
|
35291
|
+
id: pr.id,
|
|
35292
|
+
kind: "process",
|
|
35293
|
+
...present(pr.name) ? { name: pr.name } : {},
|
|
35294
|
+
...present(pr.summary) ? { statement: pr.summary } : {},
|
|
35295
|
+
...calls.length > 0 ? { calls } : {}
|
|
35296
|
+
},
|
|
35297
|
+
collectClauses(pr)
|
|
35298
|
+
);
|
|
35299
|
+
}
|
|
32486
35300
|
function conformanceTestUnit(t) {
|
|
32487
35301
|
const payload = {
|
|
32488
35302
|
...present(t.kind) ? { test_kind: t.kind } : {},
|
|
32489
35303
|
...present(t.methodRef) ? { method_ref: t.methodRef } : {}
|
|
32490
35304
|
};
|
|
35305
|
+
const methodRefs = [
|
|
35306
|
+
...new Set(
|
|
35307
|
+
[t.methodRef, ...(t.requiredCompetence ?? []).map((rc) => rc.methodRef)].filter((m) => present(m)).map((m) => m)
|
|
35308
|
+
)
|
|
35309
|
+
].sort();
|
|
32491
35310
|
const decision = acceptanceDecisionOf(t.acceptance);
|
|
32492
35311
|
const criteria = testAcceptanceCriteriaOf(t);
|
|
32493
35312
|
return assemble(
|
|
@@ -32515,6 +35334,7 @@ function conformanceTestUnit(t) {
|
|
|
32515
35334
|
}))
|
|
32516
35335
|
} : {},
|
|
32517
35336
|
...presentList(t.dependencies) ? { dependencies: t.dependencies } : {},
|
|
35337
|
+
...methodRefs.length > 0 ? { method_refs: methodRefs } : {},
|
|
32518
35338
|
...Object.keys(payload).length > 0 ? { payload } : {}
|
|
32519
35339
|
},
|
|
32520
35340
|
collectClauses(t)
|
|
@@ -32946,6 +35766,9 @@ function exportStandardRetrieval(standard, options = {}) {
|
|
|
32946
35766
|
for (const t of standard.conformanceTests ?? []) {
|
|
32947
35767
|
push(conformanceTestUnit(t), t.id);
|
|
32948
35768
|
}
|
|
35769
|
+
for (const pr of standard.processes ?? []) {
|
|
35770
|
+
push(processUnit(pr), pr.id);
|
|
35771
|
+
}
|
|
32949
35772
|
for (const t of standard.terms ?? []) {
|
|
32950
35773
|
push(termUnit(t, pkg.base_urn), t.id);
|
|
32951
35774
|
}
|
|
@@ -33256,8 +36079,8 @@ function exportPackageImpact(dir) {
|
|
|
33256
36079
|
}
|
|
33257
36080
|
|
|
33258
36081
|
// src/export/cddal.ts
|
|
33259
|
-
import { readFileSync as
|
|
33260
|
-
import { basename, join as
|
|
36082
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync6 } from "node:fs";
|
|
36083
|
+
import { basename, join as join8, resolve as resolve5 } from "node:path";
|
|
33261
36084
|
var CDDAL_PROJECTION_VERSION = "primmel-cddal/1";
|
|
33262
36085
|
function escapeCddalString(s) {
|
|
33263
36086
|
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -33403,23 +36226,23 @@ function projectCddal(model, packageId, l10n = /* @__PURE__ */ new Map()) {
|
|
|
33403
36226
|
}
|
|
33404
36227
|
function exportPackageCddal(dir) {
|
|
33405
36228
|
const model = loadPackage(dir);
|
|
33406
|
-
const l10nFiles =
|
|
33407
|
-
const l10n = readL10n(l10nFiles, (p) =>
|
|
36229
|
+
const l10nFiles = readdirSync6(dir).filter((e) => /^l10n\.[^/]+\.prl$/.test(e)).map((e) => join8(dir, e));
|
|
36230
|
+
const l10n = readL10n(l10nFiles, (p) => readFileSync9(p, "utf8"));
|
|
33408
36231
|
return projectCddal(model, basename(resolve5(dir)), l10n);
|
|
33409
36232
|
}
|
|
33410
36233
|
|
|
33411
36234
|
// src/package-diff.ts
|
|
33412
|
-
import { existsSync as existsSync7, readdirSync as
|
|
33413
|
-
import { join as
|
|
36235
|
+
import { existsSync as existsSync7, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
|
|
36236
|
+
import { join as join9 } from "path";
|
|
33414
36237
|
function packageMappings(dir, standard) {
|
|
33415
36238
|
const profiles = [...standard.mapProfiles ?? []];
|
|
33416
36239
|
if (existsSync7(dir)) {
|
|
33417
|
-
for (const entry of
|
|
36240
|
+
for (const entry of readdirSync7(dir).sort()) {
|
|
33418
36241
|
if (!entry.endsWith(".prm")) {
|
|
33419
36242
|
continue;
|
|
33420
36243
|
}
|
|
33421
36244
|
profiles.push(
|
|
33422
|
-
...prmToMapProfiles(loadPrm(
|
|
36245
|
+
...prmToMapProfiles(loadPrm(readFileSync10(join9(dir, entry), "utf8")))
|
|
33423
36246
|
);
|
|
33424
36247
|
}
|
|
33425
36248
|
}
|
|
@@ -33428,17 +36251,17 @@ function packageMappings(dir, standard) {
|
|
|
33428
36251
|
}
|
|
33429
36252
|
function packageClauseTexts(dir) {
|
|
33430
36253
|
const out = /* @__PURE__ */ new Map();
|
|
33431
|
-
const prdDir =
|
|
36254
|
+
const prdDir = join9(dir, "sources-prd");
|
|
33432
36255
|
if (!existsSync7(prdDir)) {
|
|
33433
36256
|
return out;
|
|
33434
36257
|
}
|
|
33435
|
-
for (const entry of
|
|
36258
|
+
for (const entry of readdirSync7(prdDir).sort()) {
|
|
33436
36259
|
if (!entry.endsWith(".sentences.json")) {
|
|
33437
36260
|
continue;
|
|
33438
36261
|
}
|
|
33439
36262
|
let payload;
|
|
33440
36263
|
try {
|
|
33441
|
-
payload = JSON.parse(
|
|
36264
|
+
payload = JSON.parse(readFileSync10(join9(prdDir, entry), "utf8"));
|
|
33442
36265
|
} catch {
|
|
33443
36266
|
continue;
|
|
33444
36267
|
}
|
|
@@ -33491,15 +36314,15 @@ var DIFF_USAGE = "Usage: primmel diff [--json] [--exit-code] [--compare-texts] [
|
|
|
33491
36314
|
var EXPORT_USAGE = "Usage: primmel export reqif|rdf|retrieval|impact|cddal <package-dir> [--out <file>] [--format turtle|jsonld]";
|
|
33492
36315
|
function readablePackageDirProblem(target, needsManifest) {
|
|
33493
36316
|
try {
|
|
33494
|
-
if (!
|
|
36317
|
+
if (!statSync5(target).isDirectory()) {
|
|
33495
36318
|
return "not a directory";
|
|
33496
36319
|
}
|
|
33497
|
-
|
|
36320
|
+
readdirSync8(target);
|
|
33498
36321
|
} catch (e) {
|
|
33499
36322
|
const err = e;
|
|
33500
36323
|
return err.code === "ENOENT" ? "no such directory" : err.message;
|
|
33501
36324
|
}
|
|
33502
|
-
if (needsManifest && !existsSync8(
|
|
36325
|
+
if (needsManifest && !existsSync8(join10(target, "package.primmel"))) {
|
|
33503
36326
|
return "no package.primmel found";
|
|
33504
36327
|
}
|
|
33505
36328
|
return null;
|
|
@@ -33725,7 +36548,7 @@ function exportCli(args2) {
|
|
|
33725
36548
|
const out = values.get("--out");
|
|
33726
36549
|
if (out !== void 0) {
|
|
33727
36550
|
try {
|
|
33728
|
-
|
|
36551
|
+
writeFileSync2(out, document);
|
|
33729
36552
|
} catch (e) {
|
|
33730
36553
|
console.error(`cannot write ${out}: ${e.message}`);
|
|
33731
36554
|
process.exit(1);
|
|
@@ -33736,6 +36559,32 @@ function exportCli(args2) {
|
|
|
33736
36559
|
}
|
|
33737
36560
|
process.exit(0);
|
|
33738
36561
|
}
|
|
36562
|
+
function fmtCli(argv) {
|
|
36563
|
+
const check = argv.includes("--check");
|
|
36564
|
+
const rest = argv.filter((a) => a !== "--check");
|
|
36565
|
+
const dir = rest[rest.length - 1];
|
|
36566
|
+
if (!dir || !existsSync8(dir)) {
|
|
36567
|
+
console.error(`cannot read package at ${dir || "(none)"}: no such directory`);
|
|
36568
|
+
process.exit(2);
|
|
36569
|
+
}
|
|
36570
|
+
let result;
|
|
36571
|
+
try {
|
|
36572
|
+
result = fmtPackage(dir, check);
|
|
36573
|
+
} catch (e) {
|
|
36574
|
+
console.error(`cannot format package at ${dir}: ${e.message}`);
|
|
36575
|
+
process.exit(2);
|
|
36576
|
+
}
|
|
36577
|
+
for (const f of result.files) {
|
|
36578
|
+
const label = f.file.startsWith(dir + "/") ? f.file.slice(dir.length + 1) : f.file;
|
|
36579
|
+
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)";
|
|
36580
|
+
console.log(` ${label}: ${note}`);
|
|
36581
|
+
}
|
|
36582
|
+
const unstable = result.files.filter((f) => f.status === "unstable").length;
|
|
36583
|
+
console.log(
|
|
36584
|
+
`fmt: ${result.files.length} files, ${check ? result.files.filter((f) => f.status === "formatted").length + " would reformat" : result.written + " written"}, ${unstable} unstable`
|
|
36585
|
+
);
|
|
36586
|
+
process.exit(unstable > 0 ? 2 : check && result.files.some((f) => f.status === "formatted") ? 1 : 0);
|
|
36587
|
+
}
|
|
33739
36588
|
var args = process.argv.slice(2);
|
|
33740
36589
|
if (args[0] === "diff") {
|
|
33741
36590
|
diffCli(args.slice(1));
|
|
@@ -33743,6 +36592,12 @@ if (args[0] === "diff") {
|
|
|
33743
36592
|
checkCli(args.slice(1));
|
|
33744
36593
|
} else if (args[0] === "export") {
|
|
33745
36594
|
exportCli(args.slice(1));
|
|
36595
|
+
} else if (args[0] === "fmt") {
|
|
36596
|
+
fmtCli(args.slice(1));
|
|
33746
36597
|
} else {
|
|
33747
36598
|
checkCli(args);
|
|
33748
36599
|
}
|
|
36600
|
+
//! The Primmel expression language: the lexer, the precedence parser, and
|
|
36601
|
+
//! the AST. The machine-executable core — first-class syntax, never a
|
|
36602
|
+
//! quoted string. The identifiers resolve against the caller's scope (the
|
|
36603
|
+
//! argument bindings); the unbound names surface at parse time.
|