@rcrsr/rill 0.7.2 → 0.8.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 (71) hide show
  1. package/README.md +1 -1
  2. package/dist/ast-nodes.d.ts +635 -0
  3. package/dist/ast-nodes.d.ts.map +1 -0
  4. package/dist/ast-nodes.js +2 -0
  5. package/dist/ast-nodes.js.map +1 -0
  6. package/dist/ast-unions.d.ts +6 -0
  7. package/dist/ast-unions.d.ts.map +1 -0
  8. package/dist/ast-unions.js +6 -0
  9. package/dist/ast-unions.js.map +1 -0
  10. package/dist/error-classes.d.ts +90 -0
  11. package/dist/error-classes.d.ts.map +1 -0
  12. package/dist/error-classes.js +185 -0
  13. package/dist/error-classes.js.map +1 -0
  14. package/dist/error-registry.d.ts +93 -0
  15. package/dist/error-registry.d.ts.map +1 -0
  16. package/dist/error-registry.js +712 -0
  17. package/dist/error-registry.js.map +1 -0
  18. package/dist/generated/introspection-data.d.ts +1 -1
  19. package/dist/generated/introspection-data.d.ts.map +1 -1
  20. package/dist/generated/introspection-data.js +509 -481
  21. package/dist/generated/introspection-data.js.map +1 -1
  22. package/dist/generated/version-data.d.ts +1 -1
  23. package/dist/generated/version-data.js +3 -3
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/runtime/core/callable.d.ts +5 -5
  29. package/dist/runtime/core/callable.d.ts.map +1 -1
  30. package/dist/runtime/core/callable.js +2 -1
  31. package/dist/runtime/core/callable.js.map +1 -1
  32. package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -1
  33. package/dist/runtime/core/eval/mixins/collections.js +5 -1
  34. package/dist/runtime/core/eval/mixins/collections.js.map +1 -1
  35. package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -1
  36. package/dist/runtime/core/eval/mixins/literals.js +5 -1
  37. package/dist/runtime/core/eval/mixins/literals.js.map +1 -1
  38. package/dist/runtime/core/eval/mixins/variables.js +12 -12
  39. package/dist/runtime/core/eval/mixins/variables.js.map +1 -1
  40. package/dist/runtime/core/values.d.ts +31 -3
  41. package/dist/runtime/core/values.d.ts.map +1 -1
  42. package/dist/runtime/core/values.js +47 -1
  43. package/dist/runtime/core/values.js.map +1 -1
  44. package/dist/runtime/ext/builtins.d.ts.map +1 -1
  45. package/dist/runtime/ext/builtins.js +202 -1
  46. package/dist/runtime/ext/builtins.js.map +1 -1
  47. package/dist/runtime/ext/extensions.d.ts +39 -3
  48. package/dist/runtime/ext/extensions.d.ts.map +1 -1
  49. package/dist/runtime/ext/extensions.js +77 -12
  50. package/dist/runtime/ext/extensions.js.map +1 -1
  51. package/dist/runtime/index.d.ts +5 -5
  52. package/dist/runtime/index.d.ts.map +1 -1
  53. package/dist/runtime/index.js +2 -2
  54. package/dist/runtime/index.js.map +1 -1
  55. package/dist/source-location.d.ts +10 -0
  56. package/dist/source-location.d.ts.map +1 -0
  57. package/dist/source-location.js +5 -0
  58. package/dist/source-location.js.map +1 -0
  59. package/dist/token-types.d.ts +68 -0
  60. package/dist/token-types.d.ts.map +1 -0
  61. package/dist/token-types.js +79 -0
  62. package/dist/token-types.js.map +1 -0
  63. package/dist/types.d.ts +9 -882
  64. package/dist/types.d.ts.map +1 -1
  65. package/dist/types.js +8 -958
  66. package/dist/types.js.map +1 -1
  67. package/dist/value-types.d.ts +3 -0
  68. package/dist/value-types.d.ts.map +1 -0
  69. package/dist/value-types.js +2 -0
  70. package/dist/value-types.js.map +1 -0
  71. package/package.json +15 -2
package/dist/types.js CHANGED
@@ -2,962 +2,12 @@
2
2
  * Rill AST Types
3
3
  * Based on docs/grammar.ebnf
4
4
  */
5
- import { VERSION } from './generated/version-data.js';
6
- class ErrorRegistryImpl {
7
- byId;
8
- constructor(definitions) {
9
- const idMap = new Map();
10
- for (const def of definitions) {
11
- idMap.set(def.errorId, def);
12
- }
13
- this.byId = idMap;
14
- }
15
- get(errorId) {
16
- return this.byId.get(errorId);
17
- }
18
- has(errorId) {
19
- return this.byId.has(errorId);
20
- }
21
- get size() {
22
- return this.byId.size;
23
- }
24
- entries() {
25
- return this.byId.entries();
26
- }
27
- }
28
- /** All error definitions indexed by error ID */
29
- const ERROR_DEFINITIONS = [
30
- // Lexer Errors (RILL-L0xx)
31
- {
32
- errorId: 'RILL-L001',
33
- category: 'lexer',
34
- description: 'Unterminated string literal',
35
- messageTemplate: 'Unterminated string literal at {location}',
36
- cause: 'String opened with quote but never closed before end of line or file.',
37
- resolution: 'Add closing quote to complete the string, or use multiline strings with triple quotes (""") for multi-line content.',
38
- examples: [
39
- {
40
- description: 'Missing closing quote on single line',
41
- code: '"hello',
42
- },
43
- {
44
- description: 'Newline inside single-quoted string',
45
- code: '"hello\nworld"',
46
- },
47
- ],
48
- },
49
- {
50
- errorId: 'RILL-L002',
51
- category: 'lexer',
52
- description: 'Invalid character',
53
- messageTemplate: 'Invalid character {char} at {location}',
54
- cause: 'Character not recognized by the lexer (not part of Rill syntax).',
55
- resolution: 'Remove or replace the invalid character. Common causes: unicode characters in identifiers, unsupported operators, or copy-paste artifacts.',
56
- examples: [
57
- {
58
- description: 'Unicode character in code',
59
- code: '$x → "value" # → is not valid, use ->',
60
- },
61
- {
62
- description: 'Backtick instead of quote',
63
- code: '`hello` # Use "hello" instead',
64
- },
65
- ],
66
- },
67
- {
68
- errorId: 'RILL-L003',
69
- category: 'lexer',
70
- description: 'Invalid number format',
71
- messageTemplate: 'Invalid number format: {value}',
72
- cause: 'Number contains invalid characters, multiple decimal points, or unsupported notation.',
73
- resolution: 'Use valid number format: integers (123), decimals (1.5), or scientific notation (1e5). No underscores, trailing dots, or multiple decimals allowed.',
74
- examples: [
75
- {
76
- description: 'Multiple decimal points',
77
- code: '1.2.3',
78
- },
79
- {
80
- description: 'Trailing decimal point',
81
- code: '123.',
82
- },
83
- {
84
- description: 'Leading zeros (octal notation not supported)',
85
- code: '0123',
86
- },
87
- ],
88
- },
89
- {
90
- errorId: 'RILL-L004',
91
- category: 'lexer',
92
- description: 'Unterminated multiline string',
93
- messageTemplate: 'Unterminated multiline string starting at {location}',
94
- cause: 'Multiline string opened with triple quotes (""") but never closed.',
95
- resolution: 'Add closing triple quotes (""") to complete the multiline string.',
96
- examples: [
97
- {
98
- description: 'Missing closing triple quotes',
99
- code: '"""hello\nworld',
100
- },
101
- {
102
- description: 'Only two closing quotes instead of three',
103
- code: '"""content""',
104
- },
105
- ],
106
- },
107
- {
108
- errorId: 'RILL-L005',
109
- category: 'lexer',
110
- description: 'Invalid escape sequence',
111
- messageTemplate: 'Invalid escape sequence {sequence} at {location}',
112
- cause: 'Backslash followed by unsupported character in string literal.',
113
- resolution: 'Use valid escape sequences: \\n (newline), \\t (tab), \\\\ (backslash), \\" (quote), \\{ (brace). For literal backslash, use \\\\.',
114
- examples: [
115
- {
116
- description: 'Invalid escape character',
117
- code: '"hello\\xworld" # \\x not supported',
118
- },
119
- {
120
- description: 'Incomplete escape at end',
121
- code: '"path\\',
122
- },
123
- ],
124
- },
125
- // Parse Errors (RILL-P0xx)
126
- {
127
- errorId: 'RILL-P001',
128
- category: 'parse',
129
- description: 'Unexpected token',
130
- messageTemplate: 'Unexpected token {token}, expected {expected}',
131
- cause: 'Token appears in invalid position according to grammar rules.',
132
- resolution: 'Check syntax at the indicated position. Common causes: missing operators, mismatched delimiters, or keywords in wrong context.',
133
- examples: [
134
- {
135
- description: 'Missing pipe operator between expressions',
136
- code: '"hello" "world" # Missing -> between',
137
- },
138
- {
139
- description: 'Statement starting with operator',
140
- code: '-> "value" # Missing left side',
141
- },
142
- {
143
- description: 'Unexpected closing brace',
144
- code: '{ "value" }} # Extra closing brace',
145
- },
146
- ],
147
- },
148
- {
149
- errorId: 'RILL-P002',
150
- category: 'parse',
151
- description: 'Unexpected end of input',
152
- messageTemplate: 'Unexpected end of input, expected {expected}',
153
- cause: 'File or block ended while parser expected more tokens (incomplete expression or statement).',
154
- resolution: 'Complete the incomplete construct. Common causes: unclosed blocks, incomplete pipe chains, or missing expression after operator.',
155
- examples: [
156
- {
157
- description: 'Unclosed block',
158
- code: '{ "value"',
159
- },
160
- {
161
- description: 'Pipe with no target',
162
- code: '"hello" ->',
163
- },
164
- {
165
- description: 'Incomplete conditional',
166
- code: '?($x > 0) "yes" # Missing else branch',
167
- },
168
- ],
169
- },
170
- {
171
- errorId: 'RILL-P003',
172
- category: 'parse',
173
- description: 'Invalid type annotation',
174
- messageTemplate: 'Invalid type annotation: {type}',
175
- cause: 'Type name not recognized. Rill supports: string, number, bool, closure, list, dict, tuple.',
176
- resolution: 'Use valid type name from supported set. Check spelling and casing (types are lowercase).',
177
- examples: [
178
- {
179
- description: 'Uppercase type name',
180
- code: '$x => String # Use "string" not "String"',
181
- },
182
- {
183
- description: 'Invalid type name',
184
- code: '$x => int # Use "number" for all numeric types',
185
- },
186
- {
187
- description: 'Generic type syntax not supported',
188
- code: '$x => list<string> # Use "list" only',
189
- },
190
- ],
191
- },
192
- {
193
- errorId: 'RILL-P004',
194
- category: 'parse',
195
- description: 'Invalid expression',
196
- messageTemplate: 'Invalid expression: {details}',
197
- cause: 'Expression structure violates grammar rules or contains unsupported constructs.',
198
- resolution: 'Check expression syntax. Common causes: invalid operator combinations, malformed literals, or unsupported language features.',
199
- examples: [
200
- {
201
- description: 'Double operators',
202
- code: '$x + + $y',
203
- },
204
- {
205
- description: 'Assignment operator (not supported)',
206
- code: '$x = 5 # Use "5 => $x" instead',
207
- },
208
- ],
209
- },
210
- {
211
- errorId: 'RILL-P005',
212
- category: 'parse',
213
- description: 'Missing delimiter',
214
- messageTemplate: 'Missing {delimiter}, found {found}',
215
- cause: 'Expected closing delimiter (parenthesis, bracket, brace) not found.',
216
- resolution: 'Add the missing delimiter. Check for proper nesting and matching pairs.',
217
- examples: [
218
- {
219
- description: 'Missing closing parenthesis',
220
- code: 'func($a, $b',
221
- },
222
- {
223
- description: 'Missing closing bracket in tuple',
224
- code: '[1, 2, 3',
225
- },
226
- {
227
- description: 'Mismatched delimiters',
228
- code: '{ "value"] # Opened with { but closed with ]',
229
- },
230
- ],
231
- },
232
- {
233
- errorId: 'RILL-P006',
234
- category: 'parse',
235
- description: 'Deprecated capture arrow syntax',
236
- messageTemplate: 'The capture arrow syntax changed from :> to =>',
237
- cause: 'Code uses old capture arrow syntax (:>) instead of current syntax (=>).',
238
- resolution: 'Replace :> with => for all variable captures. This change was made in version 0.4.0.',
239
- examples: [
240
- {
241
- description: 'Old capture syntax',
242
- code: '"value" :> $x # Change to "value" => $x',
243
- },
244
- {
245
- description: 'Old typed capture',
246
- code: '5 :> $x:number # Change to 5 => $x:number',
247
- },
248
- ],
249
- },
250
- // Runtime Errors (RILL-R0xx)
251
- {
252
- errorId: 'RILL-R001',
253
- category: 'runtime',
254
- description: 'Parameter type mismatch',
255
- messageTemplate: 'Function {function} expects parameter {param} (position {position}) to be {expected}, got {actual}',
256
- cause: 'Argument passed to function does not match declared parameter type.',
257
- resolution: 'Pass value of correct type, or convert the value before passing. Check function signature for expected types.',
258
- examples: [
259
- {
260
- description: 'String passed to number parameter',
261
- code: '|x: number| $x * 2\n"5" -> $()',
262
- },
263
- {
264
- description: 'Number passed to string method',
265
- code: '123 -> .split(",") # split expects string',
266
- },
267
- ],
268
- },
269
- {
270
- errorId: 'RILL-R002',
271
- category: 'runtime',
272
- description: 'Operator type mismatch',
273
- messageTemplate: 'Operator {operator} cannot be applied to {leftType} and {rightType}',
274
- cause: 'Binary operator applied to incompatible types. Rill does not perform implicit type coercion.',
275
- resolution: 'Ensure both operands are compatible types. Convert values explicitly if needed using type-specific methods.',
276
- examples: [
277
- {
278
- description: 'Adding string and number',
279
- code: '"5" + 1 # Error: no implicit coercion',
280
- },
281
- {
282
- description: 'Comparing different types',
283
- code: '"10" == 10 # Always false, no coercion',
284
- },
285
- {
286
- description: 'Arithmetic on non-numbers',
287
- code: '"hello" * 2',
288
- },
289
- ],
290
- },
291
- {
292
- errorId: 'RILL-R003',
293
- category: 'runtime',
294
- description: 'Method receiver type mismatch',
295
- messageTemplate: 'Method {method} cannot be called on {type}',
296
- cause: 'Method called on value of wrong type. String methods require strings, list methods require lists, etc.',
297
- resolution: 'Call method on correct type, or convert value before calling. Check method documentation for receiver type.',
298
- examples: [
299
- {
300
- description: 'String method on number',
301
- code: '123 -> .upper() # upper() is string method',
302
- },
303
- {
304
- description: 'List method on string',
305
- code: '"hello" -> .first() # first() is list method',
306
- },
307
- ],
308
- },
309
- {
310
- errorId: 'RILL-R004',
311
- category: 'runtime',
312
- description: 'Type conversion failure',
313
- messageTemplate: 'Cannot convert {value} to {targetType}',
314
- cause: 'Value cannot be converted to target type (invalid format or incompatible types).',
315
- resolution: 'Ensure value has valid format for target type. For string-to-number: check numeric format. For parse operations: validate input structure.',
316
- examples: [
317
- {
318
- description: 'Invalid number string',
319
- code: '"abc" -> .num() # Not a valid number',
320
- },
321
- {
322
- description: 'Cannot serialize closure',
323
- code: 'fn() => "test" end -> json()',
324
- },
325
- ],
326
- },
327
- {
328
- errorId: 'RILL-R005',
329
- category: 'runtime',
330
- description: 'Undefined variable',
331
- messageTemplate: 'Variable {name} is not defined',
332
- cause: 'Variable referenced before assignment, or variable name misspelled.',
333
- resolution: 'Assign value to variable before use (value => $var), or check spelling. Variables must be captured before reference.',
334
- examples: [
335
- {
336
- description: 'Variable used before assignment',
337
- code: '$count + 1 # $count never assigned',
338
- },
339
- {
340
- description: 'Typo in variable name',
341
- code: '"hi" => $mesage\n$message # Typo: mesage vs message',
342
- },
343
- {
344
- description: 'Variable out of scope',
345
- code: '{ "local" => $x }\n$x # $x only exists inside block',
346
- },
347
- ],
348
- },
349
- {
350
- errorId: 'RILL-R006',
351
- category: 'runtime',
352
- description: 'Undefined function',
353
- messageTemplate: 'Function {name} is not defined',
354
- cause: 'Function name not found in runtime context (not a built-in or host-provided function).',
355
- resolution: 'Check function name spelling, ensure function is provided by host application, or verify module imports.',
356
- examples: [
357
- {
358
- description: 'Misspelled function name',
359
- code: 'leng("hello") # Should be length()',
360
- },
361
- {
362
- description: 'Missing host function',
363
- code: 'app::fetch($url) # Host must provide app::fetch',
364
- },
365
- ],
366
- },
367
- {
368
- errorId: 'RILL-R007',
369
- category: 'runtime',
370
- description: 'Undefined method',
371
- messageTemplate: 'Method {method} is not defined on {type}',
372
- cause: 'Method name not supported for the given type, or method name misspelled.',
373
- resolution: 'Check method documentation for the type. Verify method name spelling and that it exists for this type.',
374
- examples: [
375
- {
376
- description: 'Method not available on type',
377
- code: '123 -> .trim() # trim() only on strings',
378
- },
379
- {
380
- description: 'Misspelled method name',
381
- code: '"hello" -> .upcase() # Should be .upper()',
382
- },
383
- ],
384
- },
385
- {
386
- errorId: 'RILL-R008',
387
- category: 'runtime',
388
- description: 'Undefined annotation',
389
- messageTemplate: 'Annotation {key} is not defined',
390
- cause: 'Annotation key accessed but not set on statement or parameter.',
391
- resolution: 'Set annotation before accessing (^(key: value)), or check annotation key spelling.',
392
- examples: [
393
- {
394
- description: 'Accessing undefined annotation',
395
- code: '$stmt.^timeout # No ^(timeout: ...) set',
396
- },
397
- ],
398
- },
399
- {
400
- errorId: 'RILL-R009',
401
- category: 'runtime',
402
- description: 'Property not found',
403
- messageTemplate: 'Property {property} not found on {type}',
404
- cause: 'Dict key or tuple index does not exist in the value.',
405
- resolution: 'Check property name spelling, verify the property exists, or use null-coalescing (??) to provide default. For safe access, use .? operator.',
406
- examples: [
407
- {
408
- description: 'Missing dict key',
409
- code: '[name: "x"] -> .age # age key not in dict',
410
- },
411
- {
412
- description: 'Index out of bounds',
413
- code: '[1, 2, 3] -> [5] # Only 3 elements (0-2)',
414
- },
415
- {
416
- description: 'Safe alternative',
417
- code: '[name: "x"] -> .age ?? 0 # Returns 0 if missing',
418
- },
419
- ],
420
- },
421
- {
422
- errorId: 'RILL-R010',
423
- category: 'runtime',
424
- description: 'Iteration limit exceeded',
425
- messageTemplate: 'Iteration limit of {limit} exceeded',
426
- cause: 'Loop or collection operation exceeded configured iteration limit (prevents infinite loops).',
427
- resolution: 'Reduce data size, adjust iteration limit via RuntimeOptions, or check for infinite loop conditions.',
428
- examples: [
429
- {
430
- description: 'Infinite loop without termination',
431
- code: '(true) @ { "looping" } # Never terminates',
432
- },
433
- {
434
- description: 'Large collection with default limit',
435
- code: 'range(0, 1000000) -> each |x| $x # May exceed default limit',
436
- },
437
- ],
438
- },
439
- {
440
- errorId: 'RILL-R011',
441
- category: 'runtime',
442
- description: 'Invalid regex pattern',
443
- messageTemplate: 'Invalid regex pattern: {pattern}',
444
- cause: 'Regular expression pattern has invalid syntax or unsupported features.',
445
- resolution: 'Fix regex syntax errors. Check for unescaped special characters, unclosed groups, or invalid quantifiers.',
446
- examples: [
447
- {
448
- description: 'Unclosed group',
449
- code: '"test" -> .match("(abc") # Missing closing )',
450
- },
451
- {
452
- description: 'Invalid quantifier',
453
- code: '"test" -> .match("a{,5}") # Empty min in range',
454
- },
455
- ],
456
- },
457
- {
458
- errorId: 'RILL-R012',
459
- category: 'runtime',
460
- description: 'Operation timeout',
461
- messageTemplate: 'Operation timed out after {timeout}ms',
462
- cause: 'Function execution exceeded configured timeout duration.',
463
- resolution: 'Increase timeout via RuntimeOptions, optimize slow operations, or add ^(timeout: ms) annotation to specific calls.',
464
- examples: [
465
- {
466
- description: 'Slow host function',
467
- code: 'app::slow_api() # Times out if exceeds limit',
468
- },
469
- {
470
- description: 'Setting higher timeout',
471
- code: '^(timeout: 30000) app::slow_api() # 30 seconds',
472
- },
473
- ],
474
- },
475
- {
476
- errorId: 'RILL-R013',
477
- category: 'runtime',
478
- description: 'Execution aborted',
479
- messageTemplate: 'Execution aborted by signal',
480
- cause: 'Host application cancelled execution via AbortSignal.',
481
- resolution: 'This is intentional cancellation, not an error. If unexpected, check host abort signal logic.',
482
- examples: [
483
- {
484
- description: 'User cancellation in UI',
485
- code: '# Long-running script cancelled by user',
486
- },
487
- ],
488
- },
489
- {
490
- errorId: 'RILL-R014',
491
- category: 'runtime',
492
- description: 'Auto-exception triggered',
493
- messageTemplate: 'Auto-exception triggered: pattern {pattern} matched',
494
- cause: 'Value matched auto-exception pattern (configured to halt on specific error patterns in output).',
495
- resolution: 'Handle error condition that produced the matched pattern, or adjust auto-exception configuration.',
496
- examples: [
497
- {
498
- description: 'API error response',
499
- code: '# API returned "ERROR:" prefix, auto-exception configured to catch this',
500
- },
501
- ],
502
- },
503
- {
504
- errorId: 'RILL-R015',
505
- category: 'runtime',
506
- description: 'Assertion failed',
507
- messageTemplate: 'Assertion failed: {condition}',
508
- cause: 'Assertion statement evaluated to false.',
509
- resolution: 'Fix the condition causing assertion failure, or remove/adjust assertion if condition is incorrect.',
510
- examples: [
511
- {
512
- description: 'Basic assertion',
513
- code: 'assert $count > 0 # Fails if $count <= 0',
514
- },
515
- {
516
- description: 'Assertion with message',
517
- code: 'assert $age >= 18 "Must be adult"',
518
- },
519
- ],
520
- },
521
- {
522
- errorId: 'RILL-R016',
523
- category: 'runtime',
524
- description: 'Error statement executed',
525
- messageTemplate: 'Error raised: {message}',
526
- cause: 'Error statement executed explicitly in code.',
527
- resolution: 'This is intentional error raising. Fix the condition that triggers the error statement, or handle the error case differently.',
528
- examples: [
529
- {
530
- description: 'Explicit error',
531
- code: 'error "Invalid configuration"',
532
- },
533
- {
534
- description: 'Conditional error',
535
- code: '($status == "failed") ? { error "Process failed" } ! "ok"',
536
- },
537
- ],
538
- },
539
- // Check Errors (RILL-C0xx)
540
- {
541
- errorId: 'RILL-C001',
542
- category: 'check',
543
- description: 'File not found',
544
- messageTemplate: 'File not found: {path}',
545
- cause: 'Specified file path does not exist in filesystem.',
546
- resolution: 'Verify file path is correct, check file exists, or create the file if it should exist.',
547
- examples: [
548
- {
549
- description: 'Nonexistent file',
550
- code: 'rill-check missing.rill',
551
- },
552
- {
553
- description: 'Wrong file extension',
554
- code: 'rill-check script.txt # Should be script.rill',
555
- },
556
- ],
557
- },
558
- {
559
- errorId: 'RILL-C002',
560
- category: 'check',
561
- description: 'File unreadable',
562
- messageTemplate: 'File unreadable: {path}',
563
- cause: 'File exists but cannot be read (permission denied or IO error).',
564
- resolution: 'Check file permissions, ensure read access, or verify file is not locked by another process.',
565
- examples: [
566
- {
567
- description: 'Permission denied',
568
- code: 'rill-check protected.rill # File exists but no read permission',
569
- },
570
- ],
571
- },
572
- {
573
- errorId: 'RILL-C003',
574
- category: 'check',
575
- description: 'Invalid configuration',
576
- messageTemplate: 'Invalid configuration: {details}',
577
- cause: 'Configuration file or options contain invalid values or structure.',
578
- resolution: 'Fix configuration syntax, ensure all required fields are present, and values are of correct type.',
579
- examples: [
580
- {
581
- description: 'Invalid JSON in config',
582
- code: '# .rillrc.json contains malformed JSON',
583
- },
584
- {
585
- description: 'Unknown config option',
586
- code: '# Config contains unsupported option key',
587
- },
588
- ],
589
- },
590
- {
591
- errorId: 'RILL-C004',
592
- category: 'check',
593
- description: 'Fix collision detected',
594
- messageTemplate: 'Fix collision detected for {location}',
595
- cause: 'Multiple auto-fix rules attempt to modify the same source location.',
596
- resolution: 'Apply fixes one at a time, or disable conflicting lint rules. Some fixes may need manual resolution.',
597
- examples: [
598
- {
599
- description: 'Overlapping fix ranges',
600
- code: '# Two rules try to fix same code section',
601
- },
602
- ],
603
- },
604
- ];
605
- /**
606
- * Global error registry instance.
607
- * Read-only singleton initialized at module load.
608
- */
609
- export const ERROR_REGISTRY = new ErrorRegistryImpl(ERROR_DEFINITIONS);
610
- // ============================================================
611
- // TEMPLATE RENDERING
612
- // ============================================================
613
- /**
614
- * Renders a message template by replacing placeholders with context values.
615
- *
616
- * Placeholder format: {varName}
617
- * Missing context values render as empty string.
618
- * Non-string values are coerced via String().
619
- * Invalid templates (unclosed braces) return template unchanged.
620
- *
621
- * @param template - Template string with {placeholder} syntax
622
- * @param context - Key-value pairs for placeholder replacement
623
- * @returns Rendered message with placeholders replaced
624
- *
625
- * @example
626
- * renderMessage("Expected {expected}, got {actual}", {expected: "string", actual: "number"})
627
- * // Returns: "Expected string, got number"
628
- *
629
- * @example
630
- * renderMessage("Hello {name}", {})
631
- * // Returns: "Hello "
632
- */
633
- export function renderMessage(template, context) {
634
- let result = '';
635
- let i = 0;
636
- while (i < template.length) {
637
- const char = template[i];
638
- if (char === '{') {
639
- // Check if this is the start of a placeholder
640
- const nextChar = template[i + 1];
641
- if (nextChar !== '{') {
642
- // Find the closing brace
643
- let j = i + 1;
644
- while (j < template.length && template[j] !== '}') {
645
- j++;
646
- }
647
- // Check if we found a closing brace
648
- if (j >= template.length) {
649
- // Unclosed brace - return template unchanged
650
- return template;
651
- }
652
- // Extract placeholder name and render value
653
- const placeholderName = template.slice(i + 1, j);
654
- const value = context[placeholderName];
655
- // Render value: missing = empty string, non-string coerced via String()
656
- if (value === undefined) {
657
- result += '';
658
- }
659
- else {
660
- try {
661
- result += String(value);
662
- }
663
- catch {
664
- // String() coercion failed - use default toString behavior
665
- result += Object.prototype.toString.call(value);
666
- }
667
- }
668
- // Move past closing brace. Each character is visited once (O(n) performance).
669
- i = j + 1;
670
- continue;
671
- }
672
- }
673
- // Regular character - append to result
674
- result += char;
675
- i++;
676
- }
677
- return result;
678
- }
679
- /**
680
- * Generates documentation URL for an error ID.
681
- *
682
- * Format: https://github.com/rcrsr/rill/blob/v{version}/docs/ref-errors.md#{errorId}
683
- * Error ID is lowercased in anchor.
684
- *
685
- * @param errorId - Error identifier (format: RILL-{category}{3-digit}, e.g., RILL-R001)
686
- * @param version - Semver version (format: X.Y.Z)
687
- * @returns Documentation URL, or empty string if inputs are invalid
688
- *
689
- * @example
690
- * getHelpUrl("RILL-R001", "0.4.1")
691
- * // Returns: "https://github.com/rcrsr/rill/blob/v0.4.1/docs/ref-errors.md#rill-r001"
692
- *
693
- * @example
694
- * getHelpUrl("invalid", "0.4.1")
695
- * // Returns: ""
696
- */
697
- export function getHelpUrl(errorId, version) {
698
- // Validate errorId format: RILL-{category}{3-digit}
699
- // Category is single letter (L=lexer, P=parse, R=runtime, C=check)
700
- const errorIdPattern = /^RILL-[LPRC]\d{3}$/;
701
- if (!errorIdPattern.test(errorId)) {
702
- return '';
703
- }
704
- // Validate version format: X.Y.Z (semver)
705
- const versionPattern = /^\d+\.\d+\.\d+$/;
706
- if (!versionPattern.test(version)) {
707
- return '';
708
- }
709
- // Build URL with lowercased errorId in anchor
710
- const anchor = errorId.toLowerCase();
711
- return `https://github.com/rcrsr/rill/blob/v${version}/docs/ref-errors.md#${anchor}`;
712
- }
713
- // ============================================================
714
- // ERROR FACTORY
715
- // ============================================================
716
- /**
717
- * Factory function for creating errors from registry.
718
- *
719
- * Looks up error definition from registry, renders message template with context,
720
- * and creates RillError with structured metadata.
721
- *
722
- * @param errorId - Error identifier (format: RILL-{category}{3-digit})
723
- * @param context - Key-value pairs for template placeholder replacement
724
- * @param location - Source location where error occurred (optional)
725
- * @returns RillError instance with rendered message
726
- * @throws TypeError if errorId is not found in registry
727
- *
728
- * @example
729
- * createError("RILL-R005", { name: "foo" }, location)
730
- * // Creates RuntimeError: "Variable foo is not defined at 1:5"
731
- *
732
- * @example
733
- * createError("RILL-X999", {})
734
- * // Throws: TypeError("Unknown error ID: RILL-X999")
735
- */
736
- export function createError(errorId, context, location) {
737
- // Lookup error definition from registry (O(1))
738
- const definition = ERROR_REGISTRY.get(errorId);
739
- // EC-9: Unknown errorId -> Throws TypeError
740
- if (!definition) {
741
- throw new TypeError(`Unknown error ID: ${errorId}`);
742
- }
743
- // Render message from template + context (O(n) where n = template length)
744
- // EC-10: Context value fails String() coercion -> Uses fallback "[object Object]"
745
- // This is handled inside renderMessage via try-catch
746
- const message = renderMessage(definition.messageTemplate, context);
747
- // EC-11: Malformed location (missing line/column) -> Error created without location metadata
748
- // We accept the location as-is; if it's malformed, the error won't have proper location data
749
- // This is acceptable per spec - the error is still created, just without complete location info
750
- // Compute helpUrl from errorId using VERSION constant
751
- const helpUrl = getHelpUrl(errorId, VERSION);
752
- // Create RillError with errorId, helpUrl, and rendered message
753
- return new RillError({
754
- errorId,
755
- helpUrl: helpUrl || undefined, // Convert empty string to undefined
756
- message,
757
- location,
758
- context,
759
- });
760
- }
761
- /**
762
- * Base error class for all Rill errors.
763
- * Provides structured data for host applications to format as needed.
764
- */
765
- export class RillError extends Error {
766
- errorId;
767
- helpUrl;
768
- location;
769
- context;
770
- constructor(data) {
771
- // EC-3: Missing errorId
772
- if (!data.errorId) {
773
- throw new TypeError('errorId is required');
774
- }
775
- // EC-4: Unknown errorId
776
- if (!ERROR_REGISTRY.has(data.errorId)) {
777
- throw new TypeError(`Unknown error ID: ${data.errorId}`);
778
- }
779
- const locationStr = data.location
780
- ? ` at ${data.location.line}:${data.location.column}`
781
- : '';
782
- super(`${data.message}${locationStr}`);
783
- this.name = 'RillError';
784
- this.errorId = data.errorId;
785
- this.helpUrl = data.helpUrl;
786
- this.location = data.location;
787
- this.context = data.context;
788
- }
789
- /** Get structured error data for custom formatting */
790
- toData() {
791
- return {
792
- errorId: this.errorId,
793
- helpUrl: this.helpUrl,
794
- message: this.message.replace(/ at \d+:\d+$/, ''), // Strip location suffix
795
- location: this.location,
796
- context: this.context,
797
- };
798
- }
799
- /** Format error for display (can be overridden by host) */
800
- format(formatter) {
801
- if (formatter)
802
- return formatter(this.toData());
803
- return this.message;
804
- }
805
- }
806
- /** Parse-time errors */
807
- export class ParseError extends RillError {
808
- constructor(errorId, message, location, context) {
809
- // EC-7: Unknown errorId
810
- const definition = ERROR_REGISTRY.get(errorId);
811
- if (!definition) {
812
- throw new TypeError(`Unknown error ID: ${errorId}`);
813
- }
814
- // EC-8: Wrong category
815
- if (definition.category !== 'parse') {
816
- throw new TypeError(`Expected parse error ID, got: ${errorId}`);
817
- }
818
- const helpUrl = getHelpUrl(errorId, VERSION);
819
- super({
820
- errorId,
821
- helpUrl: helpUrl || undefined,
822
- message,
823
- location,
824
- context,
825
- });
826
- this.name = 'ParseError';
827
- }
828
- }
829
- /** Runtime execution errors */
830
- export class RuntimeError extends RillError {
831
- constructor(errorId, message, location, context) {
832
- // Validate errorId exists in registry
833
- const definition = ERROR_REGISTRY.get(errorId);
834
- if (!definition) {
835
- throw new TypeError(`Unknown error ID: ${errorId}`);
836
- }
837
- // Validate errorId is a runtime error
838
- if (definition.category !== 'runtime') {
839
- throw new TypeError(`Expected runtime error ID, got: ${errorId}`);
840
- }
841
- const helpUrl = getHelpUrl(errorId, VERSION);
842
- super({
843
- errorId,
844
- helpUrl: helpUrl || undefined,
845
- message,
846
- location,
847
- context,
848
- });
849
- this.name = 'RuntimeError';
850
- }
851
- /** Create from an AST node */
852
- static fromNode(errorId, message, node, context) {
853
- return new RuntimeError(errorId, message, node?.span.start, context);
854
- }
855
- }
856
- /** Timeout errors */
857
- export class TimeoutError extends RuntimeError {
858
- functionName;
859
- timeoutMs;
860
- constructor(functionName, timeoutMs, location) {
861
- super('RILL-R012', `Function '${functionName}' timed out after ${timeoutMs}ms`, location, { functionName, timeoutMs });
862
- this.name = 'TimeoutError';
863
- this.functionName = functionName;
864
- this.timeoutMs = timeoutMs;
865
- }
866
- }
867
- /** Auto-exception errors (when $_ matches a pattern) */
868
- export class AutoExceptionError extends RuntimeError {
869
- pattern;
870
- matchedValue;
871
- constructor(pattern, matchedValue, location) {
872
- super('RILL-R014', `Auto-exception triggered: pattern '${pattern}' matched`, location, { pattern, matchedValue });
873
- this.name = 'AutoExceptionError';
874
- this.pattern = pattern;
875
- this.matchedValue = matchedValue;
876
- }
877
- }
878
- /** Abort errors (when execution is cancelled via AbortSignal) */
879
- export class AbortError extends RuntimeError {
880
- constructor(location) {
881
- super('RILL-R013', 'Execution aborted', location, {});
882
- this.name = 'AbortError';
883
- }
884
- }
885
- // ============================================================
886
- // TOKEN TYPES
887
- // ============================================================
888
- export const TOKEN_TYPES = {
889
- // Literals
890
- STRING: 'STRING',
891
- NUMBER: 'NUMBER',
892
- TRUE: 'TRUE',
893
- FALSE: 'FALSE',
894
- // Identifiers
895
- IDENTIFIER: 'IDENTIFIER',
896
- // Variables
897
- DOLLAR: 'DOLLAR', // $
898
- PIPE_VAR: 'PIPE_VAR', // $ (lone dollar sign)
899
- // Operators
900
- ARROW: 'ARROW', // ->
901
- CAPTURE_ARROW: 'CAPTURE_ARROW', // =>
902
- DOT: 'DOT', // .
903
- QUESTION: 'QUESTION', // ?
904
- AT: 'AT', // @
905
- CARET: 'CARET', // ^ (annotation prefix)
906
- COLON: 'COLON', // :
907
- DOUBLE_COLON: 'DOUBLE_COLON', // :: (namespace separator)
908
- COMMA: 'COMMA', // ,
909
- // Boolean operators
910
- BANG: 'BANG', // !
911
- AND: 'AND', // &&
912
- OR: 'OR', // ||
913
- // Null-coalescing and existence
914
- NULLISH_COALESCE: 'NULLISH_COALESCE', // ??
915
- DOT_QUESTION: 'DOT_QUESTION', // .?
916
- AMPERSAND: 'AMPERSAND', // &
917
- // Assignment
918
- ASSIGN: 'ASSIGN', // =
919
- // Comparison operators
920
- EQ: 'EQ', // ==
921
- NE: 'NE', // !=
922
- LT: 'LT', // <
923
- GT: 'GT', // >
924
- LE: 'LE', // <=
925
- GE: 'GE', // >=
926
- // Extraction operators
927
- STAR_LT: 'STAR_LT', // *< (destructure)
928
- SLASH_LT: 'SLASH_LT', // /< (slice)
929
- UNDERSCORE: 'UNDERSCORE', // _ (skip in destructure)
930
- // Spread operator
931
- ELLIPSIS: 'ELLIPSIS', // ... (list spread)
932
- // Arithmetic operators
933
- PIPE_BAR: 'PIPE_BAR', // |
934
- PLUS: 'PLUS', // +
935
- MINUS: 'MINUS', // -
936
- STAR: 'STAR', // *
937
- SLASH: 'SLASH', // /
938
- PERCENT: 'PERCENT', // %
939
- // Delimiters
940
- LPAREN: 'LPAREN', // (
941
- RPAREN: 'RPAREN', // )
942
- LBRACE: 'LBRACE', // {
943
- RBRACE: 'RBRACE', // }
944
- LBRACKET: 'LBRACKET', // [
945
- RBRACKET: 'RBRACKET', // ]
946
- // Keywords
947
- BREAK: 'BREAK',
948
- RETURN: 'RETURN',
949
- PASS: 'PASS',
950
- ASSERT: 'ASSERT',
951
- ERROR: 'ERROR',
952
- EACH: 'EACH',
953
- MAP: 'MAP',
954
- FOLD: 'FOLD',
955
- FILTER: 'FILTER',
956
- // Frontmatter
957
- FRONTMATTER_DELIM: 'FRONTMATTER_DELIM', // ---
958
- // Special
959
- NEWLINE: 'NEWLINE',
960
- COMMENT: 'COMMENT',
961
- EOF: 'EOF',
962
- };
5
+ // Re-export all public symbols from sub-modules
6
+ export * from './source-location.js';
7
+ export * from './error-registry.js';
8
+ export * from './value-types.js';
9
+ export * from './token-types.js';
10
+ export * from './ast-nodes.js';
11
+ export * from './ast-unions.js';
12
+ export * from './error-classes.js';
963
13
  //# sourceMappingURL=types.js.map