@cavelang/canonical 0.27.14 → 0.29.1
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/Authors.md +5 -0
- package/License.md +6 -0
- package/README.md +26 -11
- package/dist/src/canonicalize.d.ts +2 -2
- package/dist/src/canonicalize.d.ts.map +1 -1
- package/dist/src/canonicalize.js +21 -6
- package/dist/src/canonicalize.js.map +1 -1
- package/dist/src/prelude.d.ts +3 -3
- package/dist/src/prelude.d.ts.map +1 -1
- package/dist/src/prelude.js +5 -3
- package/dist/src/prelude.js.map +1 -1
- package/dist/src/registry.d.ts +24 -4
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +97 -13
- package/dist/src/registry.js.map +1 -1
- package/package.json +17 -6
- package/src/canonicalize.ts +21 -7
- package/src/prelude.ts +8 -3
- package/src/registry.ts +110 -13
package/Authors.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Authors
|
|
2
|
+
|
|
3
|
+
By adding their name to this file, all listed authors confirm they have copyright over their contributions to this project and are waiving these rights, placing their work in the public domain in accordance with the CC0 1.0 Universal Public Domain Dedication.
|
|
4
|
+
|
|
5
|
+
- Mirek Rusin (Switzerland)
|
package/License.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
|
2
|
+
|
|
3
|
+
To the extent possible under law, the authors listed in [Authors.md](./Authors.md) have waived all copyright and related or neighboring rights to this software and associated documentation files (the "Software").
|
|
4
|
+
|
|
5
|
+
For more information, please see:
|
|
6
|
+
https://creativecommons.org/publicdomain/zero/1.0/
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ result.claims[0].claim.raw // 'packages/api PART-OF monorepo' — as
|
|
|
14
14
|
emit(result) // 'monorepo CONTAINS packages/api\n'
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
## Registry (spec §5.5)
|
|
17
|
+
## Registry (spec §5.5, §5.8)
|
|
18
18
|
|
|
19
19
|
Inverse pairs are declared in-band — `CONTAINS REVERSE PART-OF` is an
|
|
20
20
|
ordinary claim whose subject and object happen to be verbs. The registry is
|
|
@@ -28,6 +28,14 @@ effect for *subsequent* lines only. Rules:
|
|
|
28
28
|
`standardPrelude` CAVE text) carries the eight §5.5 pairs as the "shared
|
|
29
29
|
prelude" the spec allows.
|
|
30
30
|
|
|
31
|
+
Lifecycle declarations use `OLD RENAMED-TO NEW`. Both same-direction
|
|
32
|
+
spellings resolve to the oldest, stable storage verb, while `NEW` is exposed
|
|
33
|
+
as preferred and `OLD` as deprecated. This lets later writes use the new name
|
|
34
|
+
without rewriting rows or splitting the existing claim key and history.
|
|
35
|
+
Linear chains are supported; branches, joins, cycles, and collisions with an
|
|
36
|
+
existing verb identity are rejected. Renaming either side of a `REVERSE` pair
|
|
37
|
+
preserves direction and makes reverse reads return the preferred opposite name.
|
|
38
|
+
|
|
31
39
|
## Pipeline (spec §13.4)
|
|
32
40
|
|
|
33
41
|
`canonicalize(document, registry?)` → `{ claims, edges, registry, problems }`
|
|
@@ -43,13 +51,14 @@ effect for *subsequent* lines only. Rules:
|
|
|
43
51
|
nodes joined to the parent by role edges. `UNLESS x` normalizes to
|
|
44
52
|
role `WHEN` + negated condition. Condition shapes:
|
|
45
53
|
- bare entity → `x EXISTS` claim (negated for `NOT x`);
|
|
46
|
-
- comparison →
|
|
47
|
-
|
|
54
|
+
- comparison → a metric claim with a canonical verb: `>` → `EXCEEDS`,
|
|
55
|
+
`<` → `IS-BELOW`, `>=` → `IS-AT-LEAST`, `<=` → `IS-AT-MOST`,
|
|
56
|
+
`=` → `EQUALS`, and `!=` → `DIFFERS-FROM`;
|
|
48
57
|
- full claim → canonicalized as usual (inverse resolution applies).
|
|
49
58
|
- **Grouped claims** (§8.4): indented full triples stay independent and
|
|
50
59
|
link to their parent with the `QUALIFIES` edge role (§13.2's role list).
|
|
51
|
-
- **Declarations**: `A REVERSE B` and `X IS verb`
|
|
52
|
-
registry after the line itself is canonicalized.
|
|
60
|
+
- **Declarations**: `A REVERSE B`, `OLD RENAMED-TO NEW`, and `X IS verb`
|
|
61
|
+
claims update the registry after the line itself is canonicalized.
|
|
53
62
|
|
|
54
63
|
## Emitter
|
|
55
64
|
|
|
@@ -62,8 +71,11 @@ effect for *subsequent* lines only. Rules:
|
|
|
62
71
|
- §3.2 anatomy order: payload, `+/- delta`, `(Nσ)`, contexts, tags,
|
|
63
72
|
`@ N%` (omitted at 100%), `!`, `; comment`.
|
|
64
73
|
|
|
65
|
-
Emission
|
|
66
|
-
survive the round trip
|
|
74
|
+
Emission of a complete canonicalization result is stable:
|
|
75
|
+
`emit ∘ canonicalize ∘ emit ≡ emit`, and claim keys survive the round trip
|
|
76
|
+
(tested). Comparison rows are valid CAVE both under their qualifier edge and
|
|
77
|
+
when emitted in isolation, which keeps storage fallbacks and citations
|
|
78
|
+
parseable.
|
|
67
79
|
|
|
68
80
|
## Design decisions
|
|
69
81
|
|
|
@@ -82,9 +94,11 @@ survive the round trip (tested).
|
|
|
82
94
|
be *detected* — `PART-OF` without a declaration is just an unknown verb,
|
|
83
95
|
so the line canonicalizes forward with the inherited subject. Loading the
|
|
84
96
|
standard prelude first gives the intended reading.
|
|
85
|
-
- **Comparison
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
- **Comparison compatibility**: symbolic operators remain accepted in authored
|
|
98
|
+
`WHEN`/`UNLESS` input, and `>` retains its existing stored `EXCEEDS` verb.
|
|
99
|
+
The other five operators now store and emit the canonical verbs listed
|
|
100
|
+
above. Consumers that inspect condition-row verbs should accept those names;
|
|
101
|
+
operator input and CAVE-Q `WHERE value <op> ...` filters are unchanged.
|
|
88
102
|
- **Three-way negation XOR** for qualifier conditions: inner `NOT`,
|
|
89
103
|
qualifier-level `NOT`, and `UNLESS` each flip the condition's negation.
|
|
90
104
|
|
|
@@ -97,4 +111,5 @@ pnpm --filter @cavelang/canonical test
|
|
|
97
111
|
Covers the §5.5 inverse semantics (shared keys, negation riding the row,
|
|
98
112
|
belief series through either name), §8.3 continuation table, §8.2
|
|
99
113
|
equivalent forms, the §21 worked example including its inverse reads, and
|
|
100
|
-
emitter round-trip stability.
|
|
114
|
+
emitter round-trip stability, plus §5.8 rename chains, deprecation,
|
|
115
|
+
collision handling, stable history, and inverse composition.
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* Qualifier lines become claim nodes joined to their parent by edges
|
|
17
17
|
* (§8.1); `UNLESS x` normalizes to `WHEN` + negated condition (§8.2);
|
|
18
18
|
* grouped full claims link to their parent with the `QUALIFIES` role
|
|
19
|
-
* (§13.2). `REVERSE` and extension-verb declarations update
|
|
20
|
-
* in-band, affecting subsequent lines (§5.4, §5.5).
|
|
19
|
+
* (§13.2). `REVERSE`, `RENAMED-TO`, and extension-verb declarations update
|
|
20
|
+
* the registry in-band, affecting subsequent lines (§5.4, §5.5, §5.8).
|
|
21
21
|
*/
|
|
22
22
|
import { Claim } from '@cavelang/core';
|
|
23
23
|
import { type Ast } from '@cavelang/parser';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../../src/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAuB,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,wDAAwD;AACxD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,CAAA;AAE/D,sDAAsD;AACtD,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,yDAAyD;AACzD,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;
|
|
1
|
+
{"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../../src/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAuB,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,wDAAwD;AACxD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,CAAA;AAE/D,sDAAsD;AACtD,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,yDAAyD;AACzD,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;AA8DD,uCAAuC;AACvC,eAAO,MAAM,YAAY,GAAI,UAAU,GAAG,CAAC,QAAQ,EAAE,WAAU,QAAQ,CAAC,CAAkB,KAAG,MAsJ5F,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,WAAU,QAAQ,CAAC,CAAkB,KAAG,MAavF,CAAA"}
|
package/dist/src/canonicalize.js
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* Qualifier lines become claim nodes joined to their parent by edges
|
|
17
17
|
* (§8.1); `UNLESS x` normalizes to `WHEN` + negated condition (§8.2);
|
|
18
18
|
* grouped full claims link to their parent with the `QUALIFIES` role
|
|
19
|
-
* (§13.2). `REVERSE` and extension-verb declarations update
|
|
20
|
-
* in-band, affecting subsequent lines (§5.4, §5.5).
|
|
19
|
+
* (§13.2). `REVERSE`, `RENAMED-TO`, and extension-verb declarations update
|
|
20
|
+
* the registry in-band, affecting subsequent lines (§5.4, §5.5, §5.8).
|
|
21
21
|
*/
|
|
22
22
|
import { Claim, Entity, Value, Verb } from '@cavelang/core';
|
|
23
23
|
import { parseDocument } from '@cavelang/parser';
|
|
@@ -28,8 +28,15 @@ const roleOf = {
|
|
|
28
28
|
VIA: 'VIA',
|
|
29
29
|
BECAUSE: 'BECAUSE'
|
|
30
30
|
};
|
|
31
|
-
/**
|
|
32
|
-
const
|
|
31
|
+
/** Every qualifier operator maps to a parseable canonical verb. */
|
|
32
|
+
const comparisonVerbs = {
|
|
33
|
+
'>': 'EXCEEDS',
|
|
34
|
+
'<': 'IS-BELOW',
|
|
35
|
+
'>=': 'IS-AT-LEAST',
|
|
36
|
+
'<=': 'IS-AT-MOST',
|
|
37
|
+
'=': 'EQUALS',
|
|
38
|
+
'!=': 'DIFFERS-FROM'
|
|
39
|
+
};
|
|
33
40
|
const normalizeTerm = (term) => term.kind === 'entity' ? Claim.entity(Entity.normalize(term.text)) : term;
|
|
34
41
|
/**
|
|
35
42
|
* Term ↔ payload conversion for the §5.5 inverse swap. The parser
|
|
@@ -82,7 +89,7 @@ export const canonicalize = (document, registry = Registry.empty) => {
|
|
|
82
89
|
const buildClaim = (full, raw, line) => {
|
|
83
90
|
const writtenSubject = normalizeTerm(full.subject);
|
|
84
91
|
let subject = writtenSubject;
|
|
85
|
-
let verb = full.verb;
|
|
92
|
+
let verb = Registry.storageOf(registry, full.verb);
|
|
86
93
|
let payload = full.payload;
|
|
87
94
|
if (payload.kind === 'relation') {
|
|
88
95
|
payload = Claim.relation(normalizeTerm(payload.object));
|
|
@@ -129,6 +136,14 @@ export const canonicalize = (document, registry = Registry.empty) => {
|
|
|
129
136
|
}
|
|
130
137
|
return;
|
|
131
138
|
}
|
|
139
|
+
if (claim.verb === Verb.RENAMED_TO && claim.subject.kind === 'entity' && object.kind === 'entity') {
|
|
140
|
+
const declared = Registry.declareRename(registry, claim.subject.text, object.text);
|
|
141
|
+
registry = declared.registry;
|
|
142
|
+
if (!declared.ok) {
|
|
143
|
+
problem(line, declared.problem);
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
132
147
|
if (claim.verb === 'IS' && object.kind === 'entity' && object.text === 'verb' &&
|
|
133
148
|
claim.subject.kind === 'entity' && Verb.isVerbToken(claim.subject.text)) {
|
|
134
149
|
registry = Registry.declareVerb(registry, claim.subject.text);
|
|
@@ -153,7 +168,7 @@ export const canonicalize = (document, registry = Registry.empty) => {
|
|
|
153
168
|
case 'comparison':
|
|
154
169
|
return {
|
|
155
170
|
subject: payload.left,
|
|
156
|
-
verb:
|
|
171
|
+
verb: comparisonVerbs[payload.op],
|
|
157
172
|
negated: payload.negated !== unless,
|
|
158
173
|
payload: Claim.metric(payload.value),
|
|
159
174
|
meta: payload.meta
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../../src/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAY,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AA+BzC,MAAM,MAAM,GAAqC;IAC/C,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,SAAS;CACnB,CAAA;AAED,
|
|
1
|
+
{"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../../src/canonicalize.ts"],"names":[],"mappings":"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"}
|
package/dist/src/prelude.d.ts
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* ingesting the text first.
|
|
9
9
|
*/
|
|
10
10
|
import * as Registry from './registry.ts';
|
|
11
|
-
/** The spec §5.5 declaration block,
|
|
12
|
-
export declare const standardPrelude = "REVERSE IS verb ; declares that two verbs name the same edge read in opposite directions\nREVERSE HAS arity: 2\nEXPECTS IS verb ; a type expects its instances to carry an attribute or relation\nCONTAINS REVERSE PART-OF\nCAUSE REVERSE CAUSED-BY\nPRECEDES REVERSE FOLLOWS\nUSES REVERSE USED-BY\nNEEDS REVERSE NEEDED-BY\nENABLES REVERSE ENABLED-BY\nBLOCKS REVERSE BLOCKED-BY\nEXTENDS REVERSE EXTENDED-BY\n";
|
|
13
|
-
/** Registry with
|
|
11
|
+
/** The spec §5.5 declaration block, plus §5.8 `RENAMED-TO` and §20.1 `EXPECTS`. */
|
|
12
|
+
export declare const standardPrelude = "REVERSE IS verb ; declares that two verbs name the same edge read in opposite directions\nREVERSE HAS arity: 2\nRENAMED-TO IS verb ; deprecates a verb spelling in favor of a compatible replacement\nRENAMED-TO HAS arity: 2\nEXPECTS IS verb ; a type expects its instances to carry an attribute or relation\nCONTAINS REVERSE PART-OF\nCAUSE REVERSE CAUSED-BY\nPRECEDES REVERSE FOLLOWS\nUSES REVERSE USED-BY\nNEEDS REVERSE NEEDED-BY\nENABLES REVERSE ENABLED-BY\nBLOCKS REVERSE BLOCKED-BY\nEXTENDS REVERSE EXTENDED-BY\n";
|
|
13
|
+
/** Registry with standard inverse pairs plus `RENAMED-TO` and `EXPECTS`. */
|
|
14
14
|
export declare const standardRegistry: Registry.t;
|
|
15
15
|
//# sourceMappingURL=prelude.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prelude.d.ts","sourceRoot":"","sources":["../../src/prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,
|
|
1
|
+
{"version":3,"file":"prelude.d.ts","sourceRoot":"","sources":["../../src/prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,mFAAmF;AACnF,eAAO,MAAM,eAAe,sgBAa3B,CAAA;AAaD,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,CAOpC,CAAA"}
|
package/dist/src/prelude.js
CHANGED
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
* ingesting the text first.
|
|
9
9
|
*/
|
|
10
10
|
import * as Registry from "./registry.js";
|
|
11
|
-
/** The spec §5.5 declaration block,
|
|
11
|
+
/** The spec §5.5 declaration block, plus §5.8 `RENAMED-TO` and §20.1 `EXPECTS`. */
|
|
12
12
|
export const standardPrelude = `REVERSE IS verb ; declares that two verbs name the same edge read in opposite directions
|
|
13
13
|
REVERSE HAS arity: 2
|
|
14
|
+
RENAMED-TO IS verb ; deprecates a verb spelling in favor of a compatible replacement
|
|
15
|
+
RENAMED-TO HAS arity: 2
|
|
14
16
|
EXPECTS IS verb ; a type expects its instances to carry an attribute or relation
|
|
15
17
|
CONTAINS REVERSE PART-OF
|
|
16
18
|
CAUSE REVERSE CAUSED-BY
|
|
@@ -31,9 +33,9 @@ const standardPairs = [
|
|
|
31
33
|
['BLOCKS', 'BLOCKED-BY'],
|
|
32
34
|
['EXTENDS', 'EXTENDED-BY']
|
|
33
35
|
];
|
|
34
|
-
/** Registry with
|
|
36
|
+
/** Registry with standard inverse pairs plus `RENAMED-TO` and `EXPECTS`. */
|
|
35
37
|
export const standardRegistry = standardPairs.reduce((registry, [primary, inverse]) => {
|
|
36
38
|
const declared = Registry.declareReverse(registry, primary, inverse);
|
|
37
39
|
return declared.registry;
|
|
38
|
-
}, Registry.declareVerb(Registry.declareVerb(Registry.empty, 'REVERSE'), 'EXPECTS'));
|
|
40
|
+
}, Registry.declareVerb(Registry.declareVerb(Registry.declareVerb(Registry.empty, 'REVERSE'), 'RENAMED-TO'), 'EXPECTS'));
|
|
39
41
|
//# sourceMappingURL=prelude.js.map
|
package/dist/src/prelude.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prelude.js","sourceRoot":"","sources":["../../src/prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,
|
|
1
|
+
{"version":3,"file":"prelude.js","sourceRoot":"","sources":["../../src/prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,mFAAmF;AACnF,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;CAa9B,CAAA;AAED,MAAM,aAAa,GAAgC;IACjD,CAAC,UAAU,EAAE,SAAS,CAAC;IACvB,CAAC,OAAO,EAAE,WAAW,CAAC;IACtB,CAAC,UAAU,EAAE,SAAS,CAAC;IACvB,CAAC,MAAM,EAAE,SAAS,CAAC;IACnB,CAAC,OAAO,EAAE,WAAW,CAAC;IACtB,CAAC,SAAS,EAAE,YAAY,CAAC;IACzB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,SAAS,EAAE,aAAa,CAAC;CAC3B,CAAA;AAED,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAC3B,aAAa,CAAC,MAAM,CAAa,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE;IAChE,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACpE,OAAO,QAAQ,CAAC,QAAQ,CAAA;AAC1B,CAAC,EAAE,QAAQ,CAAC,WAAW,CACrB,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,YAAY,CAAC,EACnF,SAAS,CACV,CAAC,CAAA"}
|
package/dist/src/registry.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Verb registry (spec §5.4, §5.5).
|
|
2
|
+
* Verb registry (spec §5.4, §5.5, §5.8).
|
|
3
3
|
*
|
|
4
4
|
* Tracks in-band verb knowledge: extension verb declarations (`MIGRATES IS
|
|
5
|
-
* verb`)
|
|
6
|
-
*
|
|
7
|
-
* no reverse name.
|
|
5
|
+
* verb`), inverse pairs (`CONTAINS REVERSE PART-OF`), and lifecycle chains
|
|
6
|
+
* (`OLD RENAMED-TO NEW`). No verb is born with an inverse or alias.
|
|
8
7
|
*
|
|
9
8
|
* The registry is an immutable value; declaring returns a new registry, so
|
|
10
9
|
* the canonicalization pipeline can thread it through a document and
|
|
@@ -20,6 +19,12 @@ export type Registry = {
|
|
|
20
19
|
readonly pairs: ReadonlyMap<string, Pair>;
|
|
21
20
|
/** Extension verbs declared via `X IS verb`. */
|
|
22
21
|
readonly declared: ReadonlySet<string>;
|
|
22
|
+
/** Every lifecycle spelling → its stable, oldest storage spelling. */
|
|
23
|
+
readonly storage: ReadonlyMap<string, string>;
|
|
24
|
+
/** Stable storage spelling → the currently preferred spelling. */
|
|
25
|
+
readonly preferred: ReadonlyMap<string, string>;
|
|
26
|
+
/** Accepted `old → new` declarations, used to make replay idempotent. */
|
|
27
|
+
readonly renames: ReadonlyMap<string, string>;
|
|
23
28
|
};
|
|
24
29
|
export type t = Registry;
|
|
25
30
|
/** Registry with no declarations. */
|
|
@@ -41,6 +46,21 @@ export type Declared = {
|
|
|
41
46
|
export declare const declareReverse: (registry: Registry, a: string, b: string) => Declared;
|
|
42
47
|
/** Declares an extension verb (`X IS verb`, spec §5.4). */
|
|
43
48
|
export declare const declareVerb: (registry: Registry, verb: string) => Registry;
|
|
49
|
+
/** @returns the stable storage spelling for a lifecycle alias (spec §5.8). */
|
|
50
|
+
export declare const storageOf: (registry: Registry, verb: string) => string;
|
|
51
|
+
/** @returns the latest preferred spelling in a lifecycle chain (spec §5.8). */
|
|
52
|
+
export declare const preferredOf: (registry: Registry, verb: string) => string;
|
|
53
|
+
/** @returns whether `verb` remains accepted but has a newer preferred spelling. */
|
|
54
|
+
export declare const isDeprecated: (registry: Registry, verb: string) => boolean;
|
|
55
|
+
/** All accepted spellings for the same-direction verb, storage spelling first. */
|
|
56
|
+
export declare const spellingsOf: (registry: Registry, verb: string) => string[];
|
|
57
|
+
/**
|
|
58
|
+
* Declares `old RENAMED-TO new` (spec §5.8). The oldest spelling remains
|
|
59
|
+
* the stable storage identity, while the right side becomes preferred for
|
|
60
|
+
* authors. A chain must advance from its current preferred spelling;
|
|
61
|
+
* branches, joins, and cycles are rejected, and the first declaration wins.
|
|
62
|
+
*/
|
|
63
|
+
export declare const declareRename: (registry: Registry, old: string, replacement: string) => Declared;
|
|
44
64
|
/**
|
|
45
65
|
* @returns the canonical primary of `verb` and whether `verb` is the
|
|
46
66
|
* inverse side. An unpaired verb is its own primary.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,0FAA0F;AAC1F,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACzC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACtC,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9C,CAAA;AAED,MAAM,MAAM,CAAC,GAAG,QAAQ,CAAA;AAExB,qCAAqC;AACrC,eAAO,MAAM,KAAK,EAAE,QAMnB,CAAA;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,QA2BzE,CAAA;AAED,2DAA2D;AAC3D,eAAO,MAAM,WAAW,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,QAQ9D,CAAA;AAED,8EAA8E;AAC9E,eAAO,MAAM,SAAS,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,MACzB,CAAA;AAEpC,+EAA+E;AAC/E,eAAO,MAAM,WAAW,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,MAG9D,CAAA;AAED,mFAAmF;AACnF,eAAO,MAAM,YAAY,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,OACI,CAAA;AAEpE,kFAAkF;AAClF,eAAO,MAAM,WAAW,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,MAAM,EAQpE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,QAAQ,EAAE,KAAK,MAAM,EAAE,aAAa,MAAM,KAAG,QAkDpF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAOjG,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,SAAS,GAAG,MAQxE,CAAA;AAED,mEAAmE;AACnE,eAAO,MAAM,UAAU,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,KAAG,OACZ,CAAA;AAElD,mDAAmD;AACnD,eAAO,MAAM,QAAQ,GAAI,UAAU,QAAQ,KAAG,IAAI,EACX,CAAA"}
|
package/dist/src/registry.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Verb registry (spec §5.4, §5.5).
|
|
2
|
+
* Verb registry (spec §5.4, §5.5, §5.8).
|
|
3
3
|
*
|
|
4
4
|
* Tracks in-band verb knowledge: extension verb declarations (`MIGRATES IS
|
|
5
|
-
* verb`)
|
|
6
|
-
*
|
|
7
|
-
* no reverse name.
|
|
5
|
+
* verb`), inverse pairs (`CONTAINS REVERSE PART-OF`), and lifecycle chains
|
|
6
|
+
* (`OLD RENAMED-TO NEW`). No verb is born with an inverse or alias.
|
|
8
7
|
*
|
|
9
8
|
* The registry is an immutable value; declaring returns a new registry, so
|
|
10
9
|
* the canonicalization pipeline can thread it through a document and
|
|
@@ -14,7 +13,10 @@ import { Verb } from '@cavelang/core';
|
|
|
14
13
|
/** Registry with no declarations. */
|
|
15
14
|
export const empty = {
|
|
16
15
|
pairs: new Map(),
|
|
17
|
-
declared: new Set()
|
|
16
|
+
declared: new Set(),
|
|
17
|
+
storage: new Map(),
|
|
18
|
+
preferred: new Map(),
|
|
19
|
+
renames: new Map()
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* Declares `a REVERSE b`: `a` is primary, `b` its inverse (spec §5.5).
|
|
@@ -26,6 +28,8 @@ export const declareReverse = (registry, a, b) => {
|
|
|
26
28
|
if (!Verb.isVerbToken(a) || !Verb.isVerbToken(b)) {
|
|
27
29
|
return { ok: false, registry, problem: `REVERSE operands must be UPPERCASE verbs, got ${a} REVERSE ${b}` };
|
|
28
30
|
}
|
|
31
|
+
a = storageOf(registry, a);
|
|
32
|
+
b = storageOf(registry, b);
|
|
29
33
|
const existingA = registry.pairs.get(a);
|
|
30
34
|
const existingB = registry.pairs.get(b);
|
|
31
35
|
const existing = existingA ?? existingB;
|
|
@@ -45,25 +49,103 @@ export const declareReverse = (registry, a, b) => {
|
|
|
45
49
|
const pairs = new Map(registry.pairs);
|
|
46
50
|
pairs.set(a, pair);
|
|
47
51
|
pairs.set(b, pair);
|
|
48
|
-
return { ok: true, registry: {
|
|
52
|
+
return { ok: true, registry: { ...registry, pairs } };
|
|
49
53
|
};
|
|
50
54
|
/** Declares an extension verb (`X IS verb`, spec §5.4). */
|
|
51
55
|
export const declareVerb = (registry, verb) => {
|
|
56
|
+
verb = storageOf(registry, verb);
|
|
52
57
|
if (registry.declared.has(verb)) {
|
|
53
58
|
return registry;
|
|
54
59
|
}
|
|
55
60
|
const declared = new Set(registry.declared);
|
|
56
61
|
declared.add(verb);
|
|
57
|
-
return {
|
|
62
|
+
return { ...registry, declared };
|
|
63
|
+
};
|
|
64
|
+
/** @returns the stable storage spelling for a lifecycle alias (spec §5.8). */
|
|
65
|
+
export const storageOf = (registry, verb) => registry.storage.get(verb) ?? verb;
|
|
66
|
+
/** @returns the latest preferred spelling in a lifecycle chain (spec §5.8). */
|
|
67
|
+
export const preferredOf = (registry, verb) => {
|
|
68
|
+
const storage = storageOf(registry, verb);
|
|
69
|
+
return registry.preferred.get(storage) ?? storage;
|
|
70
|
+
};
|
|
71
|
+
/** @returns whether `verb` remains accepted but has a newer preferred spelling. */
|
|
72
|
+
export const isDeprecated = (registry, verb) => registry.storage.has(verb) && preferredOf(registry, verb) !== verb;
|
|
73
|
+
/** All accepted spellings for the same-direction verb, storage spelling first. */
|
|
74
|
+
export const spellingsOf = (registry, verb) => {
|
|
75
|
+
const storage = storageOf(registry, verb);
|
|
76
|
+
return [
|
|
77
|
+
storage,
|
|
78
|
+
...[...registry.storage.entries()]
|
|
79
|
+
.filter(([spelling, root]) => root === storage && spelling !== storage)
|
|
80
|
+
.map(([spelling]) => spelling)
|
|
81
|
+
];
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Declares `old RENAMED-TO new` (spec §5.8). The oldest spelling remains
|
|
85
|
+
* the stable storage identity, while the right side becomes preferred for
|
|
86
|
+
* authors. A chain must advance from its current preferred spelling;
|
|
87
|
+
* branches, joins, and cycles are rejected, and the first declaration wins.
|
|
88
|
+
*/
|
|
89
|
+
export const declareRename = (registry, old, replacement) => {
|
|
90
|
+
if (!Verb.isVerbToken(old) || !Verb.isVerbToken(replacement)) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
registry,
|
|
94
|
+
problem: `RENAMED-TO operands must be UPPERCASE verbs, got ${old} RENAMED-TO ${replacement}`
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (old === replacement) {
|
|
98
|
+
return { ok: false, registry, problem: `${old} cannot be RENAMED-TO itself` };
|
|
99
|
+
}
|
|
100
|
+
if (registry.renames.get(old) === replacement) {
|
|
101
|
+
return { ok: true, registry };
|
|
102
|
+
}
|
|
103
|
+
const storage = storageOf(registry, old);
|
|
104
|
+
const preferred = preferredOf(registry, old);
|
|
105
|
+
if (preferred !== old) {
|
|
106
|
+
return {
|
|
107
|
+
ok: false,
|
|
108
|
+
registry,
|
|
109
|
+
problem: `${old} was already renamed to ${preferred}; continue the chain from ${preferred}`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (registry.storage.has(replacement)) {
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
registry,
|
|
116
|
+
problem: `${replacement} already belongs to the ${storageOf(registry, replacement)} lifecycle; branches, joins, and cycles are not allowed`
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (Verb.isKnown(replacement) || registry.pairs.has(replacement) || registry.declared.has(replacement)) {
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
registry,
|
|
123
|
+
problem: `${replacement} already has an independent verb identity and cannot join the ${storage} lifecycle`
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const nextStorage = new Map(registry.storage);
|
|
127
|
+
// The original spelling is entered too, so deprecation is directly
|
|
128
|
+
// observable even for the first link in a chain.
|
|
129
|
+
nextStorage.set(old, storage);
|
|
130
|
+
nextStorage.set(replacement, storage);
|
|
131
|
+
const nextPreferred = new Map(registry.preferred);
|
|
132
|
+
nextPreferred.set(storage, replacement);
|
|
133
|
+
const renames = new Map(registry.renames);
|
|
134
|
+
renames.set(old, replacement);
|
|
135
|
+
return {
|
|
136
|
+
ok: true,
|
|
137
|
+
registry: { ...registry, storage: nextStorage, preferred: nextPreferred, renames }
|
|
138
|
+
};
|
|
58
139
|
};
|
|
59
140
|
/**
|
|
60
141
|
* @returns the canonical primary of `verb` and whether `verb` is the
|
|
61
142
|
* inverse side. An unpaired verb is its own primary.
|
|
62
143
|
*/
|
|
63
144
|
export const primaryOf = (registry, verb) => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
145
|
+
const storage = storageOf(registry, verb);
|
|
146
|
+
const pair = registry.pairs.get(storage);
|
|
147
|
+
if (pair === undefined || pair.primary === storage) {
|
|
148
|
+
return { primary: storage, isInverse: false };
|
|
67
149
|
}
|
|
68
150
|
return { primary: pair.primary, isInverse: true };
|
|
69
151
|
};
|
|
@@ -73,14 +155,16 @@ export const primaryOf = (registry, verb) => {
|
|
|
73
155
|
* (reverse reads then fall back to an un-named object-side scan, spec §5.5).
|
|
74
156
|
*/
|
|
75
157
|
export const inverseOf = (registry, verb) => {
|
|
76
|
-
const
|
|
158
|
+
const storage = storageOf(registry, verb);
|
|
159
|
+
const pair = registry.pairs.get(storage);
|
|
77
160
|
if (pair === undefined) {
|
|
78
161
|
return undefined;
|
|
79
162
|
}
|
|
80
|
-
|
|
163
|
+
const inverse = pair.primary === storage ? pair.inverse : pair.primary;
|
|
164
|
+
return preferredOf(registry, inverse);
|
|
81
165
|
};
|
|
82
166
|
/** @returns `true` if `verb` was declared as an extension verb. */
|
|
83
|
-
export const isDeclared = (registry, verb) => registry.declared.has(verb);
|
|
167
|
+
export const isDeclared = (registry, verb) => registry.declared.has(storageOf(registry, verb));
|
|
84
168
|
/** All pairs, deduplicated, in insertion order. */
|
|
85
169
|
export const allPairs = (registry) => [...new Set(registry.pairs.values())];
|
|
86
170
|
//# sourceMappingURL=registry.js.map
|
package/dist/src/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cavelang/canonical",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "CAVE canonicalization — verb
|
|
5
|
+
"description": "CAVE canonicalization — verb lifecycle and inverse registry, continuation expansion, canonical emitter.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"cave",
|
|
8
|
+
"knowledge-graph",
|
|
9
|
+
"knowledge-representation",
|
|
10
|
+
"typescript"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/mirek/cave#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/mirek/cave/issues"
|
|
15
|
+
},
|
|
6
16
|
"license": "CC0-1.0",
|
|
7
17
|
"author": "Mirek Rusin (https://github.com/mirek)",
|
|
8
18
|
"repository": {
|
|
@@ -26,18 +36,19 @@
|
|
|
26
36
|
"src",
|
|
27
37
|
"!src/**/*.test.ts",
|
|
28
38
|
"README.md",
|
|
29
|
-
"License.md"
|
|
39
|
+
"License.md",
|
|
40
|
+
"Authors.md"
|
|
30
41
|
],
|
|
31
42
|
"publishConfig": {
|
|
32
43
|
"access": "public"
|
|
33
44
|
},
|
|
34
45
|
"dependencies": {
|
|
35
|
-
"@cavelang/core": "0.
|
|
36
|
-
"@cavelang/parser": "0.
|
|
46
|
+
"@cavelang/core": "0.29.1",
|
|
47
|
+
"@cavelang/parser": "0.29.1"
|
|
37
48
|
},
|
|
38
49
|
"scripts": {
|
|
39
50
|
"build": "tsc -b",
|
|
40
|
-
"test": "node --disable-warning=ExperimentalWarning --test
|
|
51
|
+
"test": "node --disable-warning=ExperimentalWarning --test \"test/*.test.ts\"",
|
|
41
52
|
"typecheck": "tsc -b"
|
|
42
53
|
}
|
|
43
54
|
}
|
package/src/canonicalize.ts
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* Qualifier lines become claim nodes joined to their parent by edges
|
|
17
17
|
* (§8.1); `UNLESS x` normalizes to `WHEN` + negated condition (§8.2);
|
|
18
18
|
* grouped full claims link to their parent with the `QUALIFIES` role
|
|
19
|
-
* (§13.2). `REVERSE` and extension-verb declarations update
|
|
20
|
-
* in-band, affecting subsequent lines (§5.4, §5.5).
|
|
19
|
+
* (§13.2). `REVERSE`, `RENAMED-TO`, and extension-verb declarations update
|
|
20
|
+
* the registry in-band, affecting subsequent lines (§5.4, §5.5, §5.8).
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { Claim, Entity, Value, Verb } from '@cavelang/core'
|
|
@@ -60,9 +60,15 @@ const roleOf: Record<Verb.Qualifier, EdgeRole> = {
|
|
|
60
60
|
BECAUSE: 'BECAUSE'
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
/**
|
|
64
|
-
const
|
|
65
|
-
|
|
63
|
+
/** Every qualifier operator maps to a parseable canonical verb. */
|
|
64
|
+
const comparisonVerbs: Readonly<Record<Ast.ComparisonOp, string>> = {
|
|
65
|
+
'>': 'EXCEEDS',
|
|
66
|
+
'<': 'IS-BELOW',
|
|
67
|
+
'>=': 'IS-AT-LEAST',
|
|
68
|
+
'<=': 'IS-AT-MOST',
|
|
69
|
+
'=': 'EQUALS',
|
|
70
|
+
'!=': 'DIFFERS-FROM'
|
|
71
|
+
}
|
|
66
72
|
|
|
67
73
|
const normalizeTerm = (term: Claim.Term): Claim.Term =>
|
|
68
74
|
term.kind === 'entity' ? Claim.entity(Entity.normalize(term.text)) : term
|
|
@@ -123,7 +129,7 @@ export const canonicalize = (document: Ast.Document, registry: Registry.t = Regi
|
|
|
123
129
|
const buildClaim = (full: Ast.Full, raw: string, line: number): { claim: Claim.t, writtenSubject: Claim.Term } => {
|
|
124
130
|
const writtenSubject = normalizeTerm(full.subject)
|
|
125
131
|
let subject = writtenSubject
|
|
126
|
-
let verb = full.verb
|
|
132
|
+
let verb = Registry.storageOf(registry, full.verb)
|
|
127
133
|
let payload: Claim.Payload = full.payload
|
|
128
134
|
if (payload.kind === 'relation') {
|
|
129
135
|
payload = Claim.relation(normalizeTerm(payload.object))
|
|
@@ -171,6 +177,14 @@ export const canonicalize = (document: Ast.Document, registry: Registry.t = Regi
|
|
|
171
177
|
}
|
|
172
178
|
return
|
|
173
179
|
}
|
|
180
|
+
if (claim.verb === Verb.RENAMED_TO && claim.subject.kind === 'entity' && object.kind === 'entity') {
|
|
181
|
+
const declared = Registry.declareRename(registry, claim.subject.text, object.text)
|
|
182
|
+
registry = declared.registry
|
|
183
|
+
if (!declared.ok) {
|
|
184
|
+
problem(line, declared.problem)
|
|
185
|
+
}
|
|
186
|
+
return
|
|
187
|
+
}
|
|
174
188
|
if (claim.verb === 'IS' && object.kind === 'entity' && object.text === 'verb' &&
|
|
175
189
|
claim.subject.kind === 'entity' && Verb.isVerbToken(claim.subject.text)) {
|
|
176
190
|
registry = Registry.declareVerb(registry, claim.subject.text)
|
|
@@ -196,7 +210,7 @@ export const canonicalize = (document: Ast.Document, registry: Registry.t = Regi
|
|
|
196
210
|
case 'comparison':
|
|
197
211
|
return {
|
|
198
212
|
subject: payload.left,
|
|
199
|
-
verb:
|
|
213
|
+
verb: comparisonVerbs[payload.op],
|
|
200
214
|
negated: payload.negated !== unless,
|
|
201
215
|
payload: Claim.metric(payload.value),
|
|
202
216
|
meta: payload.meta
|
package/src/prelude.ts
CHANGED
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
import * as Registry from './registry.ts'
|
|
12
12
|
|
|
13
|
-
/** The spec §5.5 declaration block,
|
|
13
|
+
/** The spec §5.5 declaration block, plus §5.8 `RENAMED-TO` and §20.1 `EXPECTS`. */
|
|
14
14
|
export const standardPrelude = `REVERSE IS verb ; declares that two verbs name the same edge read in opposite directions
|
|
15
15
|
REVERSE HAS arity: 2
|
|
16
|
+
RENAMED-TO IS verb ; deprecates a verb spelling in favor of a compatible replacement
|
|
17
|
+
RENAMED-TO HAS arity: 2
|
|
16
18
|
EXPECTS IS verb ; a type expects its instances to carry an attribute or relation
|
|
17
19
|
CONTAINS REVERSE PART-OF
|
|
18
20
|
CAUSE REVERSE CAUSED-BY
|
|
@@ -35,9 +37,12 @@ const standardPairs: readonly [string, string][] = [
|
|
|
35
37
|
['EXTENDS', 'EXTENDED-BY']
|
|
36
38
|
]
|
|
37
39
|
|
|
38
|
-
/** Registry with
|
|
40
|
+
/** Registry with standard inverse pairs plus `RENAMED-TO` and `EXPECTS`. */
|
|
39
41
|
export const standardRegistry: Registry.t =
|
|
40
42
|
standardPairs.reduce<Registry.t>((registry, [primary, inverse]) => {
|
|
41
43
|
const declared = Registry.declareReverse(registry, primary, inverse)
|
|
42
44
|
return declared.registry
|
|
43
|
-
}, Registry.declareVerb(
|
|
45
|
+
}, Registry.declareVerb(
|
|
46
|
+
Registry.declareVerb(Registry.declareVerb(Registry.empty, 'REVERSE'), 'RENAMED-TO'),
|
|
47
|
+
'EXPECTS'
|
|
48
|
+
))
|
package/src/registry.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Verb registry (spec §5.4, §5.5).
|
|
2
|
+
* Verb registry (spec §5.4, §5.5, §5.8).
|
|
3
3
|
*
|
|
4
4
|
* Tracks in-band verb knowledge: extension verb declarations (`MIGRATES IS
|
|
5
|
-
* verb`)
|
|
6
|
-
*
|
|
7
|
-
* no reverse name.
|
|
5
|
+
* verb`), inverse pairs (`CONTAINS REVERSE PART-OF`), and lifecycle chains
|
|
6
|
+
* (`OLD RENAMED-TO NEW`). No verb is born with an inverse or alias.
|
|
8
7
|
*
|
|
9
8
|
* The registry is an immutable value; declaring returns a new registry, so
|
|
10
9
|
* the canonicalization pipeline can thread it through a document and
|
|
@@ -24,6 +23,12 @@ export type Registry = {
|
|
|
24
23
|
readonly pairs: ReadonlyMap<string, Pair>
|
|
25
24
|
/** Extension verbs declared via `X IS verb`. */
|
|
26
25
|
readonly declared: ReadonlySet<string>
|
|
26
|
+
/** Every lifecycle spelling → its stable, oldest storage spelling. */
|
|
27
|
+
readonly storage: ReadonlyMap<string, string>
|
|
28
|
+
/** Stable storage spelling → the currently preferred spelling. */
|
|
29
|
+
readonly preferred: ReadonlyMap<string, string>
|
|
30
|
+
/** Accepted `old → new` declarations, used to make replay idempotent. */
|
|
31
|
+
readonly renames: ReadonlyMap<string, string>
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
export type t = Registry
|
|
@@ -31,7 +36,10 @@ export type t = Registry
|
|
|
31
36
|
/** Registry with no declarations. */
|
|
32
37
|
export const empty: Registry = {
|
|
33
38
|
pairs: new Map(),
|
|
34
|
-
declared: new Set()
|
|
39
|
+
declared: new Set(),
|
|
40
|
+
storage: new Map(),
|
|
41
|
+
preferred: new Map(),
|
|
42
|
+
renames: new Map()
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
export type Declared =
|
|
@@ -48,6 +56,8 @@ export const declareReverse = (registry: Registry, a: string, b: string): Declar
|
|
|
48
56
|
if (!Verb.isVerbToken(a) || !Verb.isVerbToken(b)) {
|
|
49
57
|
return { ok: false, registry, problem: `REVERSE operands must be UPPERCASE verbs, got ${a} REVERSE ${b}` }
|
|
50
58
|
}
|
|
59
|
+
a = storageOf(registry, a)
|
|
60
|
+
b = storageOf(registry, b)
|
|
51
61
|
const existingA = registry.pairs.get(a)
|
|
52
62
|
const existingB = registry.pairs.get(b)
|
|
53
63
|
const existing = existingA ?? existingB
|
|
@@ -68,17 +78,101 @@ export const declareReverse = (registry: Registry, a: string, b: string): Declar
|
|
|
68
78
|
const pairs = new Map(registry.pairs)
|
|
69
79
|
pairs.set(a, pair)
|
|
70
80
|
pairs.set(b, pair)
|
|
71
|
-
return { ok: true, registry: {
|
|
81
|
+
return { ok: true, registry: { ...registry, pairs } }
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
/** Declares an extension verb (`X IS verb`, spec §5.4). */
|
|
75
85
|
export const declareVerb = (registry: Registry, verb: string): Registry => {
|
|
86
|
+
verb = storageOf(registry, verb)
|
|
76
87
|
if (registry.declared.has(verb)) {
|
|
77
88
|
return registry
|
|
78
89
|
}
|
|
79
90
|
const declared = new Set(registry.declared)
|
|
80
91
|
declared.add(verb)
|
|
81
|
-
return {
|
|
92
|
+
return { ...registry, declared }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** @returns the stable storage spelling for a lifecycle alias (spec §5.8). */
|
|
96
|
+
export const storageOf = (registry: Registry, verb: string): string =>
|
|
97
|
+
registry.storage.get(verb) ?? verb
|
|
98
|
+
|
|
99
|
+
/** @returns the latest preferred spelling in a lifecycle chain (spec §5.8). */
|
|
100
|
+
export const preferredOf = (registry: Registry, verb: string): string => {
|
|
101
|
+
const storage = storageOf(registry, verb)
|
|
102
|
+
return registry.preferred.get(storage) ?? storage
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** @returns whether `verb` remains accepted but has a newer preferred spelling. */
|
|
106
|
+
export const isDeprecated = (registry: Registry, verb: string): boolean =>
|
|
107
|
+
registry.storage.has(verb) && preferredOf(registry, verb) !== verb
|
|
108
|
+
|
|
109
|
+
/** All accepted spellings for the same-direction verb, storage spelling first. */
|
|
110
|
+
export const spellingsOf = (registry: Registry, verb: string): string[] => {
|
|
111
|
+
const storage = storageOf(registry, verb)
|
|
112
|
+
return [
|
|
113
|
+
storage,
|
|
114
|
+
...[...registry.storage.entries()]
|
|
115
|
+
.filter(([spelling, root]) => root === storage && spelling !== storage)
|
|
116
|
+
.map(([spelling]) => spelling)
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Declares `old RENAMED-TO new` (spec §5.8). The oldest spelling remains
|
|
122
|
+
* the stable storage identity, while the right side becomes preferred for
|
|
123
|
+
* authors. A chain must advance from its current preferred spelling;
|
|
124
|
+
* branches, joins, and cycles are rejected, and the first declaration wins.
|
|
125
|
+
*/
|
|
126
|
+
export const declareRename = (registry: Registry, old: string, replacement: string): Declared => {
|
|
127
|
+
if (!Verb.isVerbToken(old) || !Verb.isVerbToken(replacement)) {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
registry,
|
|
131
|
+
problem: `RENAMED-TO operands must be UPPERCASE verbs, got ${old} RENAMED-TO ${replacement}`
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (old === replacement) {
|
|
135
|
+
return { ok: false, registry, problem: `${old} cannot be RENAMED-TO itself` }
|
|
136
|
+
}
|
|
137
|
+
if (registry.renames.get(old) === replacement) {
|
|
138
|
+
return { ok: true, registry }
|
|
139
|
+
}
|
|
140
|
+
const storage = storageOf(registry, old)
|
|
141
|
+
const preferred = preferredOf(registry, old)
|
|
142
|
+
if (preferred !== old) {
|
|
143
|
+
return {
|
|
144
|
+
ok: false,
|
|
145
|
+
registry,
|
|
146
|
+
problem: `${old} was already renamed to ${preferred}; continue the chain from ${preferred}`
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (registry.storage.has(replacement)) {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
registry,
|
|
153
|
+
problem: `${replacement} already belongs to the ${storageOf(registry, replacement)} lifecycle; branches, joins, and cycles are not allowed`
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (Verb.isKnown(replacement) || registry.pairs.has(replacement) || registry.declared.has(replacement)) {
|
|
157
|
+
return {
|
|
158
|
+
ok: false,
|
|
159
|
+
registry,
|
|
160
|
+
problem: `${replacement} already has an independent verb identity and cannot join the ${storage} lifecycle`
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const nextStorage = new Map(registry.storage)
|
|
164
|
+
// The original spelling is entered too, so deprecation is directly
|
|
165
|
+
// observable even for the first link in a chain.
|
|
166
|
+
nextStorage.set(old, storage)
|
|
167
|
+
nextStorage.set(replacement, storage)
|
|
168
|
+
const nextPreferred = new Map(registry.preferred)
|
|
169
|
+
nextPreferred.set(storage, replacement)
|
|
170
|
+
const renames = new Map(registry.renames)
|
|
171
|
+
renames.set(old, replacement)
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
registry: { ...registry, storage: nextStorage, preferred: nextPreferred, renames }
|
|
175
|
+
}
|
|
82
176
|
}
|
|
83
177
|
|
|
84
178
|
/**
|
|
@@ -86,9 +180,10 @@ export const declareVerb = (registry: Registry, verb: string): Registry => {
|
|
|
86
180
|
* inverse side. An unpaired verb is its own primary.
|
|
87
181
|
*/
|
|
88
182
|
export const primaryOf = (registry: Registry, verb: string): { primary: string, isInverse: boolean } => {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
183
|
+
const storage = storageOf(registry, verb)
|
|
184
|
+
const pair = registry.pairs.get(storage)
|
|
185
|
+
if (pair === undefined || pair.primary === storage) {
|
|
186
|
+
return { primary: storage, isInverse: false }
|
|
92
187
|
}
|
|
93
188
|
return { primary: pair.primary, isInverse: true }
|
|
94
189
|
}
|
|
@@ -99,16 +194,18 @@ export const primaryOf = (registry: Registry, verb: string): { primary: string,
|
|
|
99
194
|
* (reverse reads then fall back to an un-named object-side scan, spec §5.5).
|
|
100
195
|
*/
|
|
101
196
|
export const inverseOf = (registry: Registry, verb: string): undefined | string => {
|
|
102
|
-
const
|
|
197
|
+
const storage = storageOf(registry, verb)
|
|
198
|
+
const pair = registry.pairs.get(storage)
|
|
103
199
|
if (pair === undefined) {
|
|
104
200
|
return undefined
|
|
105
201
|
}
|
|
106
|
-
|
|
202
|
+
const inverse = pair.primary === storage ? pair.inverse : pair.primary
|
|
203
|
+
return preferredOf(registry, inverse)
|
|
107
204
|
}
|
|
108
205
|
|
|
109
206
|
/** @returns `true` if `verb` was declared as an extension verb. */
|
|
110
207
|
export const isDeclared = (registry: Registry, verb: string): boolean =>
|
|
111
|
-
registry.declared.has(verb)
|
|
208
|
+
registry.declared.has(storageOf(registry, verb))
|
|
112
209
|
|
|
113
210
|
/** All pairs, deduplicated, in insertion order. */
|
|
114
211
|
export const allPairs = (registry: Registry): Pair[] =>
|