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