@ldclabs/kip-lang 2.0.2 → 2.2.0
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/CHANGELOG.md +69 -0
- package/README.md +4 -4
- package/dist/ast.d.ts +75 -58
- package/dist/ast.d.ts.map +1 -1
- package/dist/exec-ast.d.ts +51 -50
- package/dist/exec-ast.d.ts.map +1 -1
- package/dist/formatter.d.ts.map +1 -1
- package/dist/formatter.js +62 -121
- package/dist/formatter.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +112 -97
- package/dist/lower.js.map +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +146 -224
- package/dist/parser.js.map +1 -1
- package/dist/semantics.js +66 -35
- package/dist/semantics.js.map +1 -1
- package/dist/token.d.ts +4 -11
- package/dist/token.d.ts.map +1 -1
- package/dist/token.js +8 -22
- package/dist/token.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/src/ast.ts +73 -70
- package/src/exec-ast.ts +53 -42
- package/src/formatter.ts +61 -139
- package/src/index.ts +7 -13
- package/src/lower.ts +134 -106
- package/src/parser.ts +161 -250
- package/src/semantics.ts +63 -37
- package/src/token.ts +8 -22
- package/src/version.ts +1 -1
package/dist/parser.js
CHANGED
|
@@ -63,13 +63,8 @@ class Parser {
|
|
|
63
63
|
case TokenType.Ensure:
|
|
64
64
|
case TokenType.Assert:
|
|
65
65
|
case TokenType.Update:
|
|
66
|
-
case TokenType.Retract:
|
|
67
|
-
case TokenType.Supersede:
|
|
68
|
-
case TokenType.Correct:
|
|
69
66
|
case TokenType.Transition:
|
|
70
67
|
case TokenType.Set:
|
|
71
|
-
case TokenType.Archive:
|
|
72
|
-
case TokenType.Tombstone:
|
|
73
68
|
case TokenType.Purge:
|
|
74
69
|
case TokenType.Merge:
|
|
75
70
|
return this.parseMutationClause();
|
|
@@ -90,8 +85,6 @@ class Parser {
|
|
|
90
85
|
return this.parseHistoryStatement();
|
|
91
86
|
case TokenType.Changes:
|
|
92
87
|
return this.parseChangesStatement();
|
|
93
|
-
case TokenType.Snapshot:
|
|
94
|
-
return this.parseSnapshotStatement();
|
|
95
88
|
case TokenType.Export:
|
|
96
89
|
return this.parseExportCapsuleStatement();
|
|
97
90
|
default:
|
|
@@ -113,20 +106,10 @@ class Parser {
|
|
|
113
106
|
return this.parseAssertStatement();
|
|
114
107
|
case TokenType.Update:
|
|
115
108
|
return this.parseUpdateStatement();
|
|
116
|
-
case TokenType.Retract:
|
|
117
|
-
return this.parseRetractAssertion();
|
|
118
|
-
case TokenType.Supersede:
|
|
119
|
-
return this.parseSupersedeAssertion();
|
|
120
|
-
case TokenType.Correct:
|
|
121
|
-
return this.parseCorrectEvidence();
|
|
122
109
|
case TokenType.Transition:
|
|
123
|
-
return this.
|
|
110
|
+
return this.parseTransitionStatement();
|
|
124
111
|
case TokenType.Set:
|
|
125
112
|
return this.parseSetRetention();
|
|
126
|
-
case TokenType.Archive:
|
|
127
|
-
return this.parseArchiveStatement();
|
|
128
|
-
case TokenType.Tombstone:
|
|
129
|
-
return this.parseTombstoneStatement();
|
|
130
113
|
case TokenType.Purge:
|
|
131
114
|
return this.parsePurgeStatement();
|
|
132
115
|
case TokenType.Merge:
|
|
@@ -225,24 +208,15 @@ class Parser {
|
|
|
225
208
|
const start = this.currentPos();
|
|
226
209
|
const first = this.expect(TokenType.As);
|
|
227
210
|
this.expectSecondWord(TokenType.Of, first);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
basis = 'TX';
|
|
234
|
-
}
|
|
235
|
-
else if (this.match(TokenType.Time)) {
|
|
236
|
-
basis = 'TIME';
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
this.error(`Expected SEQ, TX or TIME after AS OF but got '${this.current().value}'`, this.current());
|
|
240
|
-
basis = 'SEQ';
|
|
211
|
+
// Cognitive time is a sequence coordinate. A transaction id or an instant
|
|
212
|
+
// is resolved to one first (DESCRIBE TRANSACTION / DESCRIBE SNAPSHOT AT
|
|
213
|
+
// TIME), so the read names the sequence it actually ran against.
|
|
214
|
+
if (!this.match(TokenType.Seq)) {
|
|
215
|
+
this.error(`Expected SEQ after AS OF but got '${this.current().value}'`, this.current());
|
|
241
216
|
}
|
|
242
217
|
const value = this.parseScalarValue();
|
|
243
218
|
return {
|
|
244
219
|
kind: 'AsOfClause',
|
|
245
|
-
basis,
|
|
246
220
|
value,
|
|
247
221
|
range: { start, end: this.endPos() }
|
|
248
222
|
};
|
|
@@ -992,6 +966,7 @@ class Parser {
|
|
|
992
966
|
handle,
|
|
993
967
|
setFacets: [],
|
|
994
968
|
unsetFacets: [],
|
|
969
|
+
expectVersions: [],
|
|
995
970
|
range: { start, end: start },
|
|
996
971
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
997
972
|
};
|
|
@@ -1006,10 +981,6 @@ class Parser {
|
|
|
1006
981
|
this.rejectRepeat(stmt.match, 'MATCH', tok);
|
|
1007
982
|
stmt.match = this.parseMatchClause();
|
|
1008
983
|
break;
|
|
1009
|
-
case TokenType.Expect:
|
|
1010
|
-
this.rejectRepeat(stmt.expectVersion, 'EXPECT VERSION', tok);
|
|
1011
|
-
stmt.expectVersion = this.parseExpectVersionClause();
|
|
1012
|
-
break;
|
|
1013
984
|
case TokenType.Set: {
|
|
1014
985
|
const clause = this.parseSetClause();
|
|
1015
986
|
if (clause.kind === 'SetFieldsClause') {
|
|
@@ -1055,6 +1026,9 @@ class Parser {
|
|
|
1055
1026
|
break;
|
|
1056
1027
|
}
|
|
1057
1028
|
this.expect(TokenType.RBrace);
|
|
1029
|
+
// Preconditions trail the body, in the one tail order every mutation
|
|
1030
|
+
// shares: [WHERE] [LIMIT] {EXPECT VERSION} (Spec §52.8).
|
|
1031
|
+
stmt.expectVersions = this.parseExpectVersions();
|
|
1058
1032
|
stmt.range = { start, end: this.endPos() };
|
|
1059
1033
|
return stmt;
|
|
1060
1034
|
}
|
|
@@ -1068,14 +1042,12 @@ class Parser {
|
|
|
1068
1042
|
: undefined;
|
|
1069
1043
|
this.dialect = 'raw';
|
|
1070
1044
|
const tuple = this.parsePropositionTuple();
|
|
1071
|
-
const
|
|
1072
|
-
? this.parseExpectVersionClause()
|
|
1073
|
-
: undefined;
|
|
1045
|
+
const expectVersions = this.parseExpectVersions();
|
|
1074
1046
|
return {
|
|
1075
1047
|
kind: 'EnsurePropositionStatement',
|
|
1076
1048
|
handle,
|
|
1077
1049
|
tuple,
|
|
1078
|
-
|
|
1050
|
+
expectVersions,
|
|
1079
1051
|
range: { start, end: this.endPos() },
|
|
1080
1052
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1081
1053
|
};
|
|
@@ -1314,22 +1286,47 @@ class Parser {
|
|
|
1314
1286
|
const expect = this.expect(TokenType.Expect);
|
|
1315
1287
|
this.expectSecondWord(TokenType.Version, expect);
|
|
1316
1288
|
const value = this.parseScalarValue();
|
|
1289
|
+
// `OF <plane>` guards one plane's own version instead of the element's
|
|
1290
|
+
// (Spec §35.1): a verdict guarded on ATTRIBUTES is not spoiled by a
|
|
1291
|
+
// metabolism sweep that touched a Facet.
|
|
1292
|
+
let plane;
|
|
1293
|
+
if (this.match(TokenType.Of)) {
|
|
1294
|
+
const tok = this.current();
|
|
1295
|
+
switch (tok.type) {
|
|
1296
|
+
case TokenType.Attributes:
|
|
1297
|
+
this.advance();
|
|
1298
|
+
plane = { kind: 'ATTRIBUTES' };
|
|
1299
|
+
break;
|
|
1300
|
+
case TokenType.Structural:
|
|
1301
|
+
this.advance();
|
|
1302
|
+
plane = { kind: 'STRUCTURAL' };
|
|
1303
|
+
break;
|
|
1304
|
+
case TokenType.Retention:
|
|
1305
|
+
this.advance();
|
|
1306
|
+
plane = { kind: 'RETENTION' };
|
|
1307
|
+
break;
|
|
1308
|
+
case TokenType.Facet:
|
|
1309
|
+
this.advance();
|
|
1310
|
+
plane = { kind: 'FACET', facet: this.parseSchemaSymbol() };
|
|
1311
|
+
break;
|
|
1312
|
+
default:
|
|
1313
|
+
this.error(`Expected ATTRIBUTES, STRUCTURAL, RETENTION or FACET after OF but got '${tok.value}'`, tok);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1317
1316
|
return {
|
|
1318
1317
|
kind: 'ExpectVersionClause',
|
|
1319
1318
|
value,
|
|
1319
|
+
plane,
|
|
1320
1320
|
range: { start, end: this.endPos() }
|
|
1321
1321
|
};
|
|
1322
1322
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
const
|
|
1326
|
-
this.
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
value,
|
|
1331
|
-
range: { start, end: this.endPos() }
|
|
1332
|
-
};
|
|
1323
|
+
/** `{ expect_version_clause }` — the trailing precondition list. */
|
|
1324
|
+
parseExpectVersions() {
|
|
1325
|
+
const clauses = [];
|
|
1326
|
+
while (this.check(TokenType.Expect)) {
|
|
1327
|
+
clauses.push(this.parseExpectVersionClause());
|
|
1328
|
+
}
|
|
1329
|
+
return clauses;
|
|
1333
1330
|
}
|
|
1334
1331
|
// ────────────────────────────────────────────────────────────────────
|
|
1335
1332
|
// KML — UPDATE
|
|
@@ -1339,9 +1336,6 @@ class Parser {
|
|
|
1339
1336
|
const start = this.currentPos();
|
|
1340
1337
|
this.expectKeywordWithSpace(TokenType.Update);
|
|
1341
1338
|
const target = this.parseTargetRef();
|
|
1342
|
-
const expectVersion = this.check(TokenType.Expect)
|
|
1343
|
-
? this.parseExpectVersionClause()
|
|
1344
|
-
: undefined;
|
|
1345
1339
|
const actions = [];
|
|
1346
1340
|
for (;;) {
|
|
1347
1341
|
if (this.check(TokenType.Set)) {
|
|
@@ -1363,9 +1357,9 @@ class Parser {
|
|
|
1363
1357
|
this.error('UPDATE requires at least one SET or UNSET action', this.current());
|
|
1364
1358
|
}
|
|
1365
1359
|
// WHERE binds a ?variable target; a direct :id / "id" target already names
|
|
1366
|
-
// the element and may omit it, exactly as
|
|
1367
|
-
// SET RETENTION
|
|
1368
|
-
//
|
|
1360
|
+
// the element and may omit it, exactly as TRANSITION / PURGE /
|
|
1361
|
+
// SET RETENTION do (Spec §58). Whether a bare ?variable is bound is
|
|
1362
|
+
// semantic — inside MUTATE it may be a local handle.
|
|
1369
1363
|
let where;
|
|
1370
1364
|
if (this.check(TokenType.Where)) {
|
|
1371
1365
|
this.expectKeywordWithSpace(TokenType.Where);
|
|
@@ -1373,96 +1367,35 @@ class Parser {
|
|
|
1373
1367
|
where = this.parseWhereClause();
|
|
1374
1368
|
}
|
|
1375
1369
|
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1370
|
+
const expectVersions = this.parseExpectVersions();
|
|
1376
1371
|
return {
|
|
1377
1372
|
kind: 'UpdateStatement',
|
|
1378
1373
|
target,
|
|
1379
|
-
expectVersion,
|
|
1380
1374
|
actions,
|
|
1381
1375
|
where,
|
|
1382
1376
|
limit,
|
|
1377
|
+
expectVersions,
|
|
1383
1378
|
range: { start, end: this.endPos() },
|
|
1384
1379
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1385
1380
|
};
|
|
1386
1381
|
}
|
|
1387
1382
|
// ────────────────────────────────────────────────────────────────────
|
|
1388
|
-
// KML — lifecycle
|
|
1383
|
+
// KML — TRANSITION (the one lifecycle statement, Spec §52.5)
|
|
1389
1384
|
// ────────────────────────────────────────────────────────────────────
|
|
1390
|
-
|
|
1385
|
+
parseTransitionStatement() {
|
|
1391
1386
|
const leadingComments = this.collectLeadingComments();
|
|
1392
1387
|
const start = this.currentPos();
|
|
1393
|
-
|
|
1394
|
-
this.expectSecondWord(TokenType.Assertion, retract);
|
|
1395
|
-
const target = this.parseTargetRef();
|
|
1396
|
-
let where;
|
|
1397
|
-
if (this.check(TokenType.Where)) {
|
|
1398
|
-
this.expectKeywordWithSpace(TokenType.Where);
|
|
1399
|
-
this.dialect = 'raw';
|
|
1400
|
-
where = this.parseWhereClause();
|
|
1401
|
-
}
|
|
1402
|
-
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1403
|
-
const expectState = this.check(TokenType.Expect)
|
|
1404
|
-
? this.parseExpectStateClause()
|
|
1405
|
-
: undefined;
|
|
1406
|
-
return {
|
|
1407
|
-
kind: 'RetractAssertionStatement',
|
|
1408
|
-
target,
|
|
1409
|
-
where,
|
|
1410
|
-
limit,
|
|
1411
|
-
expectState,
|
|
1412
|
-
range: { start, end: this.endPos() },
|
|
1413
|
-
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1414
|
-
};
|
|
1415
|
-
}
|
|
1416
|
-
parseSupersedeAssertion() {
|
|
1417
|
-
const leadingComments = this.collectLeadingComments();
|
|
1418
|
-
const start = this.currentPos();
|
|
1419
|
-
const supersede = this.expectKeywordWithSpace(TokenType.Supersede);
|
|
1420
|
-
this.expectSecondWord(TokenType.Assertion, supersede);
|
|
1421
|
-
const target = this.parseTargetRef();
|
|
1422
|
-
this.expect(TokenType.By);
|
|
1423
|
-
const by = this.parseTargetRef();
|
|
1424
|
-
const expectState = this.check(TokenType.Expect)
|
|
1425
|
-
? this.parseExpectStateClause()
|
|
1426
|
-
: undefined;
|
|
1427
|
-
return {
|
|
1428
|
-
kind: 'SupersedeAssertionStatement',
|
|
1429
|
-
target,
|
|
1430
|
-
by,
|
|
1431
|
-
expectState,
|
|
1432
|
-
range: { start, end: this.endPos() },
|
|
1433
|
-
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1434
|
-
};
|
|
1435
|
-
}
|
|
1436
|
-
parseCorrectEvidence() {
|
|
1437
|
-
const leadingComments = this.collectLeadingComments();
|
|
1438
|
-
const start = this.currentPos();
|
|
1439
|
-
const correct = this.expectKeywordWithSpace(TokenType.Correct);
|
|
1440
|
-
this.expectSecondWord(TokenType.Evidence, correct);
|
|
1441
|
-
const target = this.parseTargetRef();
|
|
1442
|
-
this.expect(TokenType.By);
|
|
1443
|
-
const by = this.parseTargetRef();
|
|
1444
|
-
const expectState = this.check(TokenType.Expect)
|
|
1445
|
-
? this.parseExpectStateClause()
|
|
1446
|
-
: undefined;
|
|
1447
|
-
return {
|
|
1448
|
-
kind: 'CorrectEvidenceStatement',
|
|
1449
|
-
target,
|
|
1450
|
-
by,
|
|
1451
|
-
expectState,
|
|
1452
|
-
range: { start, end: this.endPos() },
|
|
1453
|
-
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1454
|
-
};
|
|
1455
|
-
}
|
|
1456
|
-
parseTransitionActivity() {
|
|
1457
|
-
const leadingComments = this.collectLeadingComments();
|
|
1458
|
-
const start = this.currentPos();
|
|
1459
|
-
const transition = this.expectKeywordWithSpace(TokenType.Transition);
|
|
1460
|
-
this.expectSecondWord(TokenType.Activity, transition);
|
|
1388
|
+
this.expectKeywordWithSpace(TokenType.Transition);
|
|
1461
1389
|
const target = this.parseTargetRef();
|
|
1462
1390
|
this.expect(TokenType.To);
|
|
1463
1391
|
const to = this.parseScalarValue();
|
|
1464
|
-
//
|
|
1465
|
-
|
|
1392
|
+
// `BY` names the replacing element for "superseded" / "corrected".
|
|
1393
|
+
let by;
|
|
1394
|
+
if (this.match(TokenType.By)) {
|
|
1395
|
+
by = this.parseTargetRef();
|
|
1396
|
+
}
|
|
1397
|
+
// A pending Activity finalizes terminal fields and topology in the same
|
|
1398
|
+
// statement that moves it (Spec §17.5, §52.5).
|
|
1466
1399
|
const finalize = [];
|
|
1467
1400
|
while (this.check(TokenType.Set)) {
|
|
1468
1401
|
const clause = this.parseSetClause();
|
|
@@ -1470,19 +1403,27 @@ class Parser {
|
|
|
1470
1403
|
finalize.push(clause);
|
|
1471
1404
|
}
|
|
1472
1405
|
else {
|
|
1473
|
-
this.error('TRANSITION
|
|
1406
|
+
this.error('TRANSITION accepts only SET FIELDS and SET STRUCTURAL', this.current());
|
|
1474
1407
|
break;
|
|
1475
1408
|
}
|
|
1476
1409
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1410
|
+
let where;
|
|
1411
|
+
if (this.check(TokenType.Where)) {
|
|
1412
|
+
this.expectKeywordWithSpace(TokenType.Where);
|
|
1413
|
+
this.dialect = 'raw';
|
|
1414
|
+
where = this.parseWhereClause();
|
|
1415
|
+
}
|
|
1416
|
+
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1417
|
+
const expectVersions = this.parseExpectVersions();
|
|
1480
1418
|
return {
|
|
1481
|
-
kind: '
|
|
1419
|
+
kind: 'TransitionStatement',
|
|
1482
1420
|
target,
|
|
1483
1421
|
to,
|
|
1422
|
+
by,
|
|
1484
1423
|
finalize,
|
|
1485
|
-
|
|
1424
|
+
where,
|
|
1425
|
+
limit,
|
|
1426
|
+
expectVersions,
|
|
1486
1427
|
range: { start, end: this.endPos() },
|
|
1487
1428
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1488
1429
|
};
|
|
@@ -1504,73 +1445,25 @@ class Parser {
|
|
|
1504
1445
|
where = this.parseWhereClause();
|
|
1505
1446
|
}
|
|
1506
1447
|
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1507
|
-
const
|
|
1508
|
-
? this.parseExpectVersionClause()
|
|
1509
|
-
: undefined;
|
|
1448
|
+
const expectVersions = this.parseExpectVersions();
|
|
1510
1449
|
return {
|
|
1511
1450
|
kind: 'SetRetentionStatement',
|
|
1512
1451
|
target,
|
|
1513
1452
|
assignments,
|
|
1514
1453
|
where,
|
|
1515
1454
|
limit,
|
|
1516
|
-
|
|
1455
|
+
expectVersions,
|
|
1517
1456
|
range: { start, end: this.endPos() },
|
|
1518
1457
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1519
1458
|
};
|
|
1520
1459
|
}
|
|
1521
|
-
parseArchiveStatement() {
|
|
1522
|
-
const { start, target, where, limit, expectState, leadingComments } = this.parseRemovalBody(TokenType.Archive);
|
|
1523
|
-
return {
|
|
1524
|
-
kind: 'ArchiveStatement',
|
|
1525
|
-
target,
|
|
1526
|
-
where,
|
|
1527
|
-
limit,
|
|
1528
|
-
expectState,
|
|
1529
|
-
range: { start, end: this.endPos() },
|
|
1530
|
-
leadingComments
|
|
1531
|
-
};
|
|
1532
|
-
}
|
|
1533
|
-
parseTombstoneStatement() {
|
|
1534
|
-
const { start, target, where, limit, expectState, leadingComments } = this.parseRemovalBody(TokenType.Tombstone);
|
|
1535
|
-
return {
|
|
1536
|
-
kind: 'TombstoneStatement',
|
|
1537
|
-
target,
|
|
1538
|
-
where,
|
|
1539
|
-
limit,
|
|
1540
|
-
expectState,
|
|
1541
|
-
range: { start, end: this.endPos() },
|
|
1542
|
-
leadingComments
|
|
1543
|
-
};
|
|
1544
|
-
}
|
|
1545
|
-
/** ARCHIVE and TOMBSTONE share one shape; PURGE adds its confirmation. */
|
|
1546
|
-
parseRemovalBody(keyword) {
|
|
1547
|
-
const comments = this.collectLeadingComments();
|
|
1548
|
-
const start = this.currentPos();
|
|
1549
|
-
this.expectKeywordWithSpace(keyword);
|
|
1550
|
-
const target = this.parseTargetRef();
|
|
1551
|
-
let where;
|
|
1552
|
-
if (this.check(TokenType.Where)) {
|
|
1553
|
-
this.expectKeywordWithSpace(TokenType.Where);
|
|
1554
|
-
this.dialect = 'raw';
|
|
1555
|
-
where = this.parseWhereClause();
|
|
1556
|
-
}
|
|
1557
|
-
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1558
|
-
const expectState = this.check(TokenType.Expect)
|
|
1559
|
-
? this.parseExpectStateClause()
|
|
1560
|
-
: undefined;
|
|
1561
|
-
return {
|
|
1562
|
-
start,
|
|
1563
|
-
target,
|
|
1564
|
-
where,
|
|
1565
|
-
limit,
|
|
1566
|
-
expectState,
|
|
1567
|
-
leadingComments: comments.length ? comments : undefined
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
1460
|
parsePurgeStatement() {
|
|
1571
1461
|
const leadingComments = this.collectLeadingComments();
|
|
1572
1462
|
const start = this.currentPos();
|
|
1573
|
-
this.expectKeywordWithSpace(TokenType.Purge);
|
|
1463
|
+
const purge = this.expectKeywordWithSpace(TokenType.Purge);
|
|
1464
|
+
if (this.check(TokenType.Payload)) {
|
|
1465
|
+
return this.parsePurgePayloadTail(start, purge, leadingComments);
|
|
1466
|
+
}
|
|
1574
1467
|
const target = this.parseTargetRef();
|
|
1575
1468
|
let where;
|
|
1576
1469
|
if (this.check(TokenType.Where)) {
|
|
@@ -1579,6 +1472,7 @@ class Parser {
|
|
|
1579
1472
|
where = this.parseWhereClause();
|
|
1580
1473
|
}
|
|
1581
1474
|
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1475
|
+
const expectVersions = this.parseExpectVersions();
|
|
1582
1476
|
let referencePolicy;
|
|
1583
1477
|
if (this.check(TokenType.Reference)) {
|
|
1584
1478
|
const reference = this.expect(TokenType.Reference);
|
|
@@ -1599,12 +1493,46 @@ class Parser {
|
|
|
1599
1493
|
target,
|
|
1600
1494
|
where,
|
|
1601
1495
|
limit,
|
|
1496
|
+
expectVersions,
|
|
1602
1497
|
referencePolicy,
|
|
1603
1498
|
confirm,
|
|
1604
1499
|
range: { start, end: this.endPos() },
|
|
1605
1500
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1606
1501
|
};
|
|
1607
1502
|
}
|
|
1503
|
+
/**
|
|
1504
|
+
* `PURGE PAYLOAD` erases Evidence bytes while the element survives
|
|
1505
|
+
* (Spec §60.6), so there is no REFERENCE POLICY clause; the confirmation
|
|
1506
|
+
* literal is the same as element purge.
|
|
1507
|
+
*/
|
|
1508
|
+
parsePurgePayloadTail(start, purge, leadingComments) {
|
|
1509
|
+
this.expectSecondWord(TokenType.Payload, purge);
|
|
1510
|
+
const target = this.parseTargetRef();
|
|
1511
|
+
let where;
|
|
1512
|
+
if (this.check(TokenType.Where)) {
|
|
1513
|
+
this.expectKeywordWithSpace(TokenType.Where);
|
|
1514
|
+
this.dialect = 'raw';
|
|
1515
|
+
where = this.parseWhereClause();
|
|
1516
|
+
}
|
|
1517
|
+
const limit = this.check(TokenType.Limit) ? this.parseLimitClause() : undefined;
|
|
1518
|
+
const expectVersions = this.parseExpectVersions();
|
|
1519
|
+
this.expect(TokenType.Confirm);
|
|
1520
|
+
const confirmTok = this.current();
|
|
1521
|
+
const confirm = this.parseStringLiteral();
|
|
1522
|
+
if (confirm.parsed !== 'PURGE') {
|
|
1523
|
+
this.error(`PURGE PAYLOAD must be confirmed with the exact literal "PURGE", got ${confirmTok.value}`, confirmTok);
|
|
1524
|
+
}
|
|
1525
|
+
return {
|
|
1526
|
+
kind: 'PurgePayloadStatement',
|
|
1527
|
+
target,
|
|
1528
|
+
where,
|
|
1529
|
+
limit,
|
|
1530
|
+
expectVersions,
|
|
1531
|
+
confirm,
|
|
1532
|
+
range: { start, end: this.endPos() },
|
|
1533
|
+
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
1608
1536
|
parseMergeConcept() {
|
|
1609
1537
|
const leadingComments = this.collectLeadingComments();
|
|
1610
1538
|
const start = this.currentPos();
|
|
@@ -1619,15 +1547,13 @@ class Parser {
|
|
|
1619
1547
|
this.dialect = 'raw';
|
|
1620
1548
|
where = this.parseWhereClause();
|
|
1621
1549
|
}
|
|
1622
|
-
const
|
|
1623
|
-
? this.parseExpectVersionClause()
|
|
1624
|
-
: undefined;
|
|
1550
|
+
const expectVersions = this.parseExpectVersions();
|
|
1625
1551
|
return {
|
|
1626
1552
|
kind: 'MergeConceptStatement',
|
|
1627
1553
|
source,
|
|
1628
1554
|
into,
|
|
1629
1555
|
where,
|
|
1630
|
-
|
|
1556
|
+
expectVersions,
|
|
1631
1557
|
range: { start, end: this.endPos() },
|
|
1632
1558
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
1633
1559
|
};
|
|
@@ -1658,11 +1584,6 @@ class Parser {
|
|
|
1658
1584
|
case TokenType.Protocol:
|
|
1659
1585
|
this.expectSecondWord(TokenType.Protocol, describe);
|
|
1660
1586
|
return stmt('PROTOCOL');
|
|
1661
|
-
case TokenType.Execution: {
|
|
1662
|
-
const exec = this.expectSecondWord(TokenType.Execution, describe);
|
|
1663
|
-
this.expectSecondWord(TokenType.Context, exec);
|
|
1664
|
-
return stmt('EXECUTION_CONTEXT');
|
|
1665
|
-
}
|
|
1666
1587
|
case TokenType.Capabilities:
|
|
1667
1588
|
this.expectSecondWord(TokenType.Capabilities, describe);
|
|
1668
1589
|
return stmt('CAPABILITIES');
|
|
@@ -1719,8 +1640,19 @@ class Parser {
|
|
|
1719
1640
|
}
|
|
1720
1641
|
case TokenType.Snapshot: {
|
|
1721
1642
|
this.expectSecondWord(TokenType.Snapshot, describe);
|
|
1722
|
-
|
|
1723
|
-
|
|
1643
|
+
// A snapshot is addressed by sequence, or resolved from an instant:
|
|
1644
|
+
// the one place wall-clock time enters cognitive-time addressing.
|
|
1645
|
+
let asOf;
|
|
1646
|
+
let atTime;
|
|
1647
|
+
if (this.check(TokenType.As)) {
|
|
1648
|
+
asOf = this.parseAsOfClause();
|
|
1649
|
+
}
|
|
1650
|
+
else if (this.check(TokenType.At)) {
|
|
1651
|
+
const at = this.expect(TokenType.At);
|
|
1652
|
+
this.expectSecondWord(TokenType.Time, at);
|
|
1653
|
+
atTime = this.parseScalarValue();
|
|
1654
|
+
}
|
|
1655
|
+
return stmt('SNAPSHOT', { asOf, atTime });
|
|
1724
1656
|
}
|
|
1725
1657
|
case TokenType.Capsule:
|
|
1726
1658
|
this.expectSecondWord(TokenType.Capsule, describe);
|
|
@@ -1731,11 +1663,6 @@ class Parser {
|
|
|
1731
1663
|
const value = this.isMetaValueStart() ? this.parseScalarValue() : undefined;
|
|
1732
1664
|
return stmt('EPISTEMIC_POLICY', { value });
|
|
1733
1665
|
}
|
|
1734
|
-
case TokenType.Projection: {
|
|
1735
|
-
const projection = this.expectSecondWord(TokenType.Projection, describe);
|
|
1736
|
-
this.expectSecondWord(TokenType.Capability, projection);
|
|
1737
|
-
return stmt('PROJECTION_CAPABILITY');
|
|
1738
|
-
}
|
|
1739
1666
|
case TokenType.Trust: {
|
|
1740
1667
|
this.expectSecondWord(TokenType.Trust, describe);
|
|
1741
1668
|
const value = this.isMetaValueStart() ? this.parseScalarValue() : undefined;
|
|
@@ -1763,6 +1690,8 @@ class Parser {
|
|
|
1763
1690
|
const tok = this.current();
|
|
1764
1691
|
let target;
|
|
1765
1692
|
let status;
|
|
1693
|
+
let element;
|
|
1694
|
+
let depth;
|
|
1766
1695
|
switch (tok.type) {
|
|
1767
1696
|
case TokenType.Spaces:
|
|
1768
1697
|
this.expectSecondWord(TokenType.Spaces, list);
|
|
@@ -1800,6 +1729,15 @@ class Parser {
|
|
|
1800
1729
|
target = 'EPISTEMIC_POLICIES';
|
|
1801
1730
|
break;
|
|
1802
1731
|
}
|
|
1732
|
+
case TokenType.Dependents:
|
|
1733
|
+
// Bounded reverse provenance closure (Spec §63.5): the operand is
|
|
1734
|
+
// required, the DEPTH bound is optional and defaults engine-side to 1.
|
|
1735
|
+
this.expectSecondWord(TokenType.Dependents, list);
|
|
1736
|
+
target = 'DEPENDENTS';
|
|
1737
|
+
element = this.parseScalarValue();
|
|
1738
|
+
if (this.match(TokenType.Depth))
|
|
1739
|
+
depth = this.parseScalarValue();
|
|
1740
|
+
break;
|
|
1803
1741
|
default:
|
|
1804
1742
|
this.error(`Unknown LIST target '${tok.value}'`, tok);
|
|
1805
1743
|
throw new ParseAbort();
|
|
@@ -1812,6 +1750,8 @@ class Parser {
|
|
|
1812
1750
|
kind: 'ListStatement',
|
|
1813
1751
|
target,
|
|
1814
1752
|
status,
|
|
1753
|
+
element,
|
|
1754
|
+
depth,
|
|
1815
1755
|
limit,
|
|
1816
1756
|
cursor,
|
|
1817
1757
|
range: { start, end: this.endPos() },
|
|
@@ -2030,7 +1970,7 @@ class Parser {
|
|
|
2030
1970
|
throw new ParseAbort();
|
|
2031
1971
|
}
|
|
2032
1972
|
// ────────────────────────────────────────────────────────────────────
|
|
2033
|
-
// META — HISTORY / CHANGES
|
|
1973
|
+
// META — HISTORY / CHANGES
|
|
2034
1974
|
// ────────────────────────────────────────────────────────────────────
|
|
2035
1975
|
parseHistoryStatement() {
|
|
2036
1976
|
const leadingComments = this.collectLeadingComments();
|
|
@@ -2109,18 +2049,6 @@ class Parser {
|
|
|
2109
2049
|
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
2110
2050
|
};
|
|
2111
2051
|
}
|
|
2112
|
-
parseSnapshotStatement() {
|
|
2113
|
-
const leadingComments = this.collectLeadingComments();
|
|
2114
|
-
const start = this.currentPos();
|
|
2115
|
-
this.expect(TokenType.Snapshot);
|
|
2116
|
-
const asOf = this.check(TokenType.As) ? this.parseAsOfClause() : undefined;
|
|
2117
|
-
return {
|
|
2118
|
-
kind: 'SnapshotStatement',
|
|
2119
|
-
asOf,
|
|
2120
|
-
range: { start, end: this.endPos() },
|
|
2121
|
-
leadingComments: leadingComments.length ? leadingComments : undefined
|
|
2122
|
-
};
|
|
2123
|
-
}
|
|
2124
2052
|
// ────────────────────────────────────────────────────────────────────
|
|
2125
2053
|
// META — EXPORT CAPSULE
|
|
2126
2054
|
// ────────────────────────────────────────────────────────────────────
|
|
@@ -2949,13 +2877,8 @@ class Parser {
|
|
|
2949
2877
|
TokenType.Ensure,
|
|
2950
2878
|
TokenType.Assert,
|
|
2951
2879
|
TokenType.Update,
|
|
2952
|
-
TokenType.Retract,
|
|
2953
|
-
TokenType.Supersede,
|
|
2954
|
-
TokenType.Correct,
|
|
2955
2880
|
TokenType.Transition,
|
|
2956
2881
|
TokenType.Set,
|
|
2957
|
-
TokenType.Archive,
|
|
2958
|
-
TokenType.Tombstone,
|
|
2959
2882
|
TokenType.Purge,
|
|
2960
2883
|
TokenType.Merge,
|
|
2961
2884
|
TokenType.Describe,
|
|
@@ -2966,7 +2889,6 @@ class Parser {
|
|
|
2966
2889
|
TokenType.Preview,
|
|
2967
2890
|
TokenType.History,
|
|
2968
2891
|
TokenType.Changes,
|
|
2969
|
-
TokenType.Snapshot,
|
|
2970
2892
|
TokenType.Export,
|
|
2971
2893
|
TokenType.EOF
|
|
2972
2894
|
]);
|