@ldclabs/kip-lang 0.4.0 → 2.0.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/LICENSE +21 -0
  3. package/README.md +89 -64
  4. package/dist/ast.d.ts +511 -145
  5. package/dist/ast.d.ts.map +1 -1
  6. package/dist/diagnostics.d.ts +8 -2
  7. package/dist/diagnostics.d.ts.map +1 -1
  8. package/dist/diagnostics.js +32 -3
  9. package/dist/diagnostics.js.map +1 -1
  10. package/dist/exec-ast.d.ts +514 -149
  11. package/dist/exec-ast.d.ts.map +1 -1
  12. package/dist/exec-ast.js +8 -7
  13. package/dist/exec-ast.js.map +1 -1
  14. package/dist/formatter.d.ts.map +1 -1
  15. package/dist/formatter.js +870 -479
  16. package/dist/formatter.js.map +1 -1
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/lexer.d.ts.map +1 -1
  22. package/dist/lexer.js +12 -30
  23. package/dist/lexer.js.map +1 -1
  24. package/dist/lower.d.ts +1 -2
  25. package/dist/lower.d.ts.map +1 -1
  26. package/dist/lower.js +1287 -598
  27. package/dist/lower.js.map +1 -1
  28. package/dist/parser.d.ts.map +1 -1
  29. package/dist/parser.js +2410 -1300
  30. package/dist/parser.js.map +1 -1
  31. package/dist/semantics.d.ts +11 -7
  32. package/dist/semantics.d.ts.map +1 -1
  33. package/dist/semantics.js +295 -180
  34. package/dist/semantics.js.map +1 -1
  35. package/dist/token.d.ts +130 -40
  36. package/dist/token.d.ts.map +1 -1
  37. package/dist/token.js +264 -83
  38. package/dist/token.js.map +1 -1
  39. package/dist/version.d.ts +2 -2
  40. package/dist/version.js +2 -2
  41. package/package.json +35 -5
  42. package/src/ast.ts +914 -0
  43. package/src/budget.ts +108 -0
  44. package/src/diagnostics.ts +182 -0
  45. package/src/errors.ts +42 -0
  46. package/src/exec-ast.ts +614 -0
  47. package/src/formatter.ts +1339 -0
  48. package/src/index.ts +226 -0
  49. package/src/lexer.ts +459 -0
  50. package/src/lower.ts +2011 -0
  51. package/src/parser.ts +3506 -0
  52. package/src/semantics.ts +392 -0
  53. package/src/token.ts +408 -0
  54. package/src/version.ts +13 -0
package/src/token.ts ADDED
@@ -0,0 +1,408 @@
1
+ export enum TokenType {
2
+ // Trivia
3
+ Whitespace = 'Whitespace',
4
+ Newline = 'Newline',
5
+ Comment = 'Comment',
6
+
7
+ // Literals
8
+ String = 'String',
9
+ Number = 'Number',
10
+ Boolean = 'Boolean',
11
+ Null = 'Null',
12
+
13
+ // Identifiers & Variables
14
+ Identifier = 'Identifier',
15
+ Variable = 'Variable', // ?foo
16
+ Parameter = 'Parameter', // :foo
17
+
18
+ // ── Keywords — KQL ────────────────────────────────────────────────
19
+ Find = 'FIND',
20
+ Where = 'WHERE',
21
+ Filter = 'FILTER',
22
+ Not = 'NOT',
23
+ Optional = 'OPTIONAL',
24
+ Union = 'UNION',
25
+ Belief = 'BELIEF',
26
+ Slot = 'SLOT',
27
+ Order = 'ORDER',
28
+ By = 'BY',
29
+ Asc = 'ASC',
30
+ Desc = 'DESC',
31
+ Limit = 'LIMIT',
32
+ Cursor = 'CURSOR',
33
+ Distinct = 'DISTINCT',
34
+ As = 'AS',
35
+ Of = 'OF',
36
+ Seq = 'SEQ',
37
+ Tx = 'TX',
38
+ Time = 'TIME',
39
+ For = 'FOR',
40
+ Epistemic = 'EPISTEMIC',
41
+
42
+ // ── Keywords — element kinds (shared KQL/KML/META) ────────────────
43
+ Concept = 'CONCEPT',
44
+ Proposition = 'PROPOSITION',
45
+ Assertion = 'ASSERTION',
46
+ Evidence = 'EVIDENCE',
47
+ Activity = 'ACTIVITY',
48
+ Structural = 'STRUCTURAL',
49
+
50
+ // ── Keywords — KML ────────────────────────────────────────────────
51
+ Mutate = 'MUTATE',
52
+ Create = 'CREATE',
53
+ Upsert = 'UPSERT',
54
+ Ensure = 'ENSURE',
55
+ Assert = 'ASSERT',
56
+ Superseding = 'SUPERSEDING',
57
+ Update = 'UPDATE',
58
+ Retract = 'RETRACT',
59
+ Supersede = 'SUPERSEDE',
60
+ Correct = 'CORRECT',
61
+ Transition = 'TRANSITION',
62
+ Set = 'SET',
63
+ Unset = 'UNSET',
64
+ Retention = 'RETENTION',
65
+ Archive = 'ARCHIVE',
66
+ Tombstone = 'TOMBSTONE',
67
+ Purge = 'PURGE',
68
+ Confirm = 'CONFIRM',
69
+ Reference = 'REFERENCE',
70
+ Policy = 'POLICY',
71
+ Merge = 'MERGE',
72
+ Into = 'INTO',
73
+ To = 'TO',
74
+ Type = 'TYPE',
75
+ Client = 'CLIENT',
76
+ Key = 'KEY',
77
+ Name = 'NAME',
78
+ Match = 'MATCH',
79
+ Fields = 'FIELDS',
80
+ Attributes = 'ATTRIBUTES',
81
+ Facet = 'FACET',
82
+ Expect = 'EXPECT',
83
+ Version = 'VERSION',
84
+ State = 'STATE',
85
+
86
+ // ── Keywords — META ───────────────────────────────────────────────
87
+ Describe = 'DESCRIBE',
88
+ List = 'LIST',
89
+ Search = 'SEARCH',
90
+ Verify = 'VERIFY',
91
+ Validate = 'VALIDATE',
92
+ Preview = 'PREVIEW',
93
+ History = 'HISTORY',
94
+ Changes = 'CHANGES',
95
+ Snapshot = 'SNAPSHOT',
96
+ Export = 'EXPORT',
97
+ Primer = 'PRIMER',
98
+ Mode = 'MODE',
99
+ Protocol = 'PROTOCOL',
100
+ Execution = 'EXECUTION',
101
+ Context = 'CONTEXT',
102
+ Capabilities = 'CAPABILITIES',
103
+ Capability = 'CAPABILITY',
104
+ Space = 'SPACE',
105
+ Spaces = 'SPACES',
106
+ Schema = 'SCHEMA',
107
+ Environment = 'ENVIRONMENT',
108
+ Package = 'PACKAGE',
109
+ Packages = 'PACKAGES',
110
+ Predicate = 'PREDICATE',
111
+ Predicates = 'PREDICATES',
112
+ Field = 'FIELD',
113
+ Facets = 'FACETS',
114
+ Types = 'TYPES',
115
+ Policies = 'POLICIES',
116
+ Compatibility = 'COMPATIBILITY',
117
+ From = 'FROM',
118
+ Error = 'ERROR',
119
+ Transaction = 'TRANSACTION',
120
+ Idempotency = 'IDEMPOTENCY',
121
+ Capsule = 'CAPSULE',
122
+ Projection = 'PROJECTION',
123
+ Trust = 'TRUST',
124
+ Access = 'ACCESS',
125
+ With = 'WITH',
126
+ Status = 'STATUS',
127
+ Cognition = 'COGNITION',
128
+ Threshold = 'THRESHOLD',
129
+ Receipt = 'RECEIPT',
130
+ Blob = 'BLOB',
131
+ Checkpoint = 'CHECKPOINT',
132
+ Kql = 'KQL',
133
+ Kml = 'KML',
134
+ Import = 'IMPORT',
135
+ Plan = 'PLAN',
136
+ Element = 'ELEMENT',
137
+ Since = 'SINCE',
138
+ After = 'AFTER',
139
+
140
+ // Operators
141
+ Eq = '==',
142
+ NotEq = '!=',
143
+ Lt = '<',
144
+ Gt = '>',
145
+ LtEq = '<=',
146
+ GtEq = '>=',
147
+ And = '&&',
148
+ Or = '||',
149
+ Bang = '!',
150
+ Minus = '-',
151
+
152
+ // Punctuation
153
+ LBrace = '{',
154
+ RBrace = '}',
155
+ LParen = '(',
156
+ RParen = ')',
157
+ LBracket = '[',
158
+ RBracket = ']',
159
+ Comma = ',',
160
+ Colon = ':',
161
+ Dot = '.',
162
+ Pipe = '|',
163
+
164
+ // Special
165
+ EOF = 'EOF',
166
+ Unknown = 'Unknown'
167
+ }
168
+
169
+ export interface Position {
170
+ /** 0-based line number */
171
+ line: number
172
+ /** 0-based column (character offset within line) */
173
+ column: number
174
+ }
175
+
176
+ export interface Range {
177
+ start: Position
178
+ end: Position
179
+ }
180
+
181
+ export interface Token {
182
+ type: TokenType
183
+ value: string
184
+ /** Byte offset in source */
185
+ offset: number
186
+ line: number
187
+ column: number
188
+ }
189
+
190
+ /**
191
+ * Every KIP 2.0 protocol keyword, keyed by its canonical uppercase spelling.
192
+ *
193
+ * KIP 2.0 keywords are ASCII case-insensitive (canonical rendering is
194
+ * uppercase), so the lexer looks names up here after upper-casing. Schema
195
+ * symbols and string values keep their own case-sensitive contracts.
196
+ */
197
+ export const KEYWORDS: ReadonlyMap<string, TokenType> = new Map([
198
+ // KQL
199
+ ['FIND', TokenType.Find],
200
+ ['WHERE', TokenType.Where],
201
+ ['FILTER', TokenType.Filter],
202
+ ['NOT', TokenType.Not],
203
+ ['OPTIONAL', TokenType.Optional],
204
+ ['UNION', TokenType.Union],
205
+ ['BELIEF', TokenType.Belief],
206
+ ['SLOT', TokenType.Slot],
207
+ ['ORDER', TokenType.Order],
208
+ ['BY', TokenType.By],
209
+ ['ASC', TokenType.Asc],
210
+ ['DESC', TokenType.Desc],
211
+ ['LIMIT', TokenType.Limit],
212
+ ['CURSOR', TokenType.Cursor],
213
+ ['DISTINCT', TokenType.Distinct],
214
+ ['AS', TokenType.As],
215
+ ['OF', TokenType.Of],
216
+ ['SEQ', TokenType.Seq],
217
+ ['TX', TokenType.Tx],
218
+ ['TIME', TokenType.Time],
219
+ ['FOR', TokenType.For],
220
+ ['EPISTEMIC', TokenType.Epistemic],
221
+
222
+ // Element kinds
223
+ ['CONCEPT', TokenType.Concept],
224
+ ['PROPOSITION', TokenType.Proposition],
225
+ ['ASSERTION', TokenType.Assertion],
226
+ ['EVIDENCE', TokenType.Evidence],
227
+ ['ACTIVITY', TokenType.Activity],
228
+ ['STRUCTURAL', TokenType.Structural],
229
+
230
+ // KML
231
+ ['MUTATE', TokenType.Mutate],
232
+ ['CREATE', TokenType.Create],
233
+ ['UPSERT', TokenType.Upsert],
234
+ ['ENSURE', TokenType.Ensure],
235
+ ['ASSERT', TokenType.Assert],
236
+ ['SUPERSEDING', TokenType.Superseding],
237
+ ['UPDATE', TokenType.Update],
238
+ ['RETRACT', TokenType.Retract],
239
+ ['SUPERSEDE', TokenType.Supersede],
240
+ ['CORRECT', TokenType.Correct],
241
+ ['TRANSITION', TokenType.Transition],
242
+ ['SET', TokenType.Set],
243
+ ['UNSET', TokenType.Unset],
244
+ ['RETENTION', TokenType.Retention],
245
+ ['ARCHIVE', TokenType.Archive],
246
+ ['TOMBSTONE', TokenType.Tombstone],
247
+ ['PURGE', TokenType.Purge],
248
+ ['CONFIRM', TokenType.Confirm],
249
+ ['REFERENCE', TokenType.Reference],
250
+ ['POLICY', TokenType.Policy],
251
+ ['MERGE', TokenType.Merge],
252
+ ['INTO', TokenType.Into],
253
+ ['TO', TokenType.To],
254
+ ['TYPE', TokenType.Type],
255
+ ['CLIENT', TokenType.Client],
256
+ ['KEY', TokenType.Key],
257
+ ['NAME', TokenType.Name],
258
+ ['MATCH', TokenType.Match],
259
+ ['FIELDS', TokenType.Fields],
260
+ ['ATTRIBUTES', TokenType.Attributes],
261
+ ['FACET', TokenType.Facet],
262
+ ['EXPECT', TokenType.Expect],
263
+ ['VERSION', TokenType.Version],
264
+ ['STATE', TokenType.State],
265
+
266
+ // META
267
+ ['DESCRIBE', TokenType.Describe],
268
+ ['LIST', TokenType.List],
269
+ ['SEARCH', TokenType.Search],
270
+ ['VERIFY', TokenType.Verify],
271
+ ['VALIDATE', TokenType.Validate],
272
+ ['PREVIEW', TokenType.Preview],
273
+ ['HISTORY', TokenType.History],
274
+ ['CHANGES', TokenType.Changes],
275
+ ['SNAPSHOT', TokenType.Snapshot],
276
+ ['EXPORT', TokenType.Export],
277
+ ['PRIMER', TokenType.Primer],
278
+ ['MODE', TokenType.Mode],
279
+ ['PROTOCOL', TokenType.Protocol],
280
+ ['EXECUTION', TokenType.Execution],
281
+ ['CONTEXT', TokenType.Context],
282
+ ['CAPABILITIES', TokenType.Capabilities],
283
+ ['CAPABILITY', TokenType.Capability],
284
+ ['SPACE', TokenType.Space],
285
+ ['SPACES', TokenType.Spaces],
286
+ ['SCHEMA', TokenType.Schema],
287
+ ['ENVIRONMENT', TokenType.Environment],
288
+ ['PACKAGE', TokenType.Package],
289
+ ['PACKAGES', TokenType.Packages],
290
+ ['PREDICATE', TokenType.Predicate],
291
+ ['PREDICATES', TokenType.Predicates],
292
+ ['FIELD', TokenType.Field],
293
+ ['FACETS', TokenType.Facets],
294
+ ['TYPES', TokenType.Types],
295
+ ['POLICIES', TokenType.Policies],
296
+ ['COMPATIBILITY', TokenType.Compatibility],
297
+ ['FROM', TokenType.From],
298
+ ['ERROR', TokenType.Error],
299
+ ['TRANSACTION', TokenType.Transaction],
300
+ ['IDEMPOTENCY', TokenType.Idempotency],
301
+ ['CAPSULE', TokenType.Capsule],
302
+ ['PROJECTION', TokenType.Projection],
303
+ ['TRUST', TokenType.Trust],
304
+ ['ACCESS', TokenType.Access],
305
+ ['WITH', TokenType.With],
306
+ ['STATUS', TokenType.Status],
307
+ ['COGNITION', TokenType.Cognition],
308
+ ['THRESHOLD', TokenType.Threshold],
309
+ ['RECEIPT', TokenType.Receipt],
310
+ ['BLOB', TokenType.Blob],
311
+ ['CHECKPOINT', TokenType.Checkpoint],
312
+ ['KQL', TokenType.Kql],
313
+ ['KML', TokenType.Kml],
314
+ ['IMPORT', TokenType.Import],
315
+ ['PLAN', TokenType.Plan],
316
+ ['ELEMENT', TokenType.Element],
317
+ ['SINCE', TokenType.Since],
318
+ ['AFTER', TokenType.After]
319
+ ])
320
+
321
+ /**
322
+ * Aggregate names legal in `aggregate_expression`.
323
+ *
324
+ * The grammar spells these as terminals, but `function_call` is an open
325
+ * `identifier, "(" ...`, so they stay lexical identifiers and the parser
326
+ * recognizes them by name. That keeps one rule for every call shape.
327
+ */
328
+ export const AGGREGATES: ReadonlySet<string> = new Set([
329
+ 'COUNT',
330
+ 'SUM',
331
+ 'AVG',
332
+ 'MIN',
333
+ 'MAX'
334
+ ])
335
+
336
+ /**
337
+ * Runtime functions KIP 2.0 registers by name.
338
+ *
339
+ * `function_call` is syntactically open so namespaced and future functions
340
+ * still parse; this set is what the semantic layer and editor tooling treat
341
+ * as known. Membership is not a parse-time gate.
342
+ */
343
+ export const FUNCTIONS: ReadonlySet<string> = new Set([
344
+ // Filter predicates
345
+ 'IN',
346
+ 'CONTAINS',
347
+ 'STARTS_WITH',
348
+ 'ENDS_WITH',
349
+ 'REGEX',
350
+ 'IS_NULL',
351
+ 'IS_NOT_NULL',
352
+ 'IS_LITERAL',
353
+ 'IS_ELEMENT',
354
+ 'IS_KIND',
355
+ 'LITERAL_TYPE',
356
+ // Deterministic update expressions
357
+ 'ADD',
358
+ 'MUL',
359
+ 'CLAMP',
360
+ 'COALESCE',
361
+ // Aggregates
362
+ ...AGGREGATES
363
+ ])
364
+
365
+ /** Reverse lookup set, built once, so membership tests are O(1). */
366
+ const KEYWORD_TYPES: ReadonlySet<TokenType> = new Set(KEYWORDS.values())
367
+
368
+ export function isKeyword(type: TokenType): boolean {
369
+ return KEYWORD_TYPES.has(type)
370
+ }
371
+
372
+ export function isFunction(name: string): boolean {
373
+ return FUNCTIONS.has(name.toUpperCase())
374
+ }
375
+
376
+ export function isAggregate(name: string): boolean {
377
+ return AGGREGATES.has(name.toUpperCase())
378
+ }
379
+
380
+ export function isLiteral(type: TokenType): boolean {
381
+ return (
382
+ type === TokenType.String ||
383
+ type === TokenType.Number ||
384
+ type === TokenType.Boolean ||
385
+ type === TokenType.Null
386
+ )
387
+ }
388
+
389
+ export function isTrivia(type: TokenType): boolean {
390
+ return (
391
+ type === TokenType.Whitespace ||
392
+ type === TokenType.Newline ||
393
+ type === TokenType.Comment
394
+ )
395
+ }
396
+
397
+ /**
398
+ * True when a token may stand where the grammar writes `identifier`.
399
+ *
400
+ * KIP 2.0 keywords are contextual, not reserved: the Spec's own examples use
401
+ * `by`, `mode`, `at`, `key`, `name`, `type` and `status` as object keys, and
402
+ * `?a.lifecycle.status` as a dot path. Rejecting a keyword in those positions
403
+ * would make the normative examples unparseable, so every keyword doubles as
404
+ * an identifier outside the position that gives it meaning.
405
+ */
406
+ export function isIdentifierLike(type: TokenType): boolean {
407
+ return type === TokenType.Identifier || isKeyword(type)
408
+ }
package/src/version.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Version of this grammar implementation.
3
+ *
4
+ * An engine stamps this into its `DESCRIBE PRIMER` output, so a grammar bump
5
+ * is visible to the agent instead of silently changing what a stored command
6
+ * means. It is a literal rather than a `package.json` read because this module
7
+ * has to load in runtimes with no filesystem; `test/lower.test.mjs` asserts the
8
+ * two stay in step.
9
+ */
10
+ export const PARSER_VERSION = '2.0.0'
11
+
12
+ /** The KIP specification revision this grammar targets. */
13
+ export const KIP_SPEC_REVISION = '2.0-draft'