@mojir/lits 2.5.2 → 2.6.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.
Files changed (74) hide show
  1. package/README.md +6 -6
  2. package/dist/cli/cli.js +726 -481
  3. package/dist/cli/reference/api.d.ts +9 -7
  4. package/dist/cli/reference/index.d.ts +133 -132
  5. package/dist/cli/src/builtin/bindingNode.d.ts +5 -0
  6. package/dist/cli/src/builtin/core/assertion.d.ts +2 -0
  7. package/dist/cli/src/builtin/index.d.ts +2 -2
  8. package/dist/cli/src/builtin/interface.d.ts +1 -1
  9. package/dist/cli/src/builtin/specialExpressionTypes.d.ts +1 -1
  10. package/dist/cli/src/builtin/specialExpressions/match.d.ts +7 -0
  11. package/dist/cli/src/parser/subParsers/parseBindingTarget.d.ts +4 -2
  12. package/dist/cli/src/parser/subParsers/parseMatch.d.ts +4 -0
  13. package/dist/cli/src/parser/types.d.ts +5 -1
  14. package/dist/full.esm.js +1 -1
  15. package/dist/full.esm.js.map +1 -1
  16. package/dist/full.js +1 -1
  17. package/dist/full.js.map +1 -1
  18. package/dist/index.esm.js +1 -1
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/lits.iife.js +1 -1
  23. package/dist/lits.iife.js.map +1 -1
  24. package/dist/modules/assertion.esm.js +2 -0
  25. package/dist/modules/assertion.esm.js.map +1 -0
  26. package/dist/modules/assertion.js +2 -0
  27. package/dist/modules/assertion.js.map +1 -0
  28. package/dist/modules/reference/api.d.ts +9 -7
  29. package/dist/modules/reference/index.d.ts +133 -132
  30. package/dist/modules/src/builtin/bindingNode.d.ts +5 -0
  31. package/dist/modules/src/builtin/core/assertion.d.ts +2 -0
  32. package/dist/modules/src/builtin/index.d.ts +2 -2
  33. package/dist/modules/src/builtin/interface.d.ts +1 -1
  34. package/dist/modules/src/builtin/specialExpressionTypes.d.ts +1 -1
  35. package/dist/modules/src/builtin/specialExpressions/match.d.ts +7 -0
  36. package/dist/modules/src/full.d.ts +1 -1
  37. package/dist/modules/src/modules/{assert.d.ts → assertion.d.ts} +1 -1
  38. package/dist/modules/src/parser/subParsers/parseBindingTarget.d.ts +4 -2
  39. package/dist/modules/src/parser/subParsers/parseMatch.d.ts +4 -0
  40. package/dist/modules/src/parser/types.d.ts +5 -1
  41. package/dist/reference/api.d.ts +9 -7
  42. package/dist/reference/index.d.ts +133 -132
  43. package/dist/src/builtin/bindingNode.d.ts +5 -0
  44. package/dist/src/builtin/core/assertion.d.ts +2 -0
  45. package/dist/src/builtin/index.d.ts +2 -2
  46. package/dist/src/builtin/interface.d.ts +1 -1
  47. package/dist/src/builtin/specialExpressionTypes.d.ts +1 -1
  48. package/dist/src/builtin/specialExpressions/match.d.ts +7 -0
  49. package/dist/src/full.d.ts +1 -1
  50. package/dist/src/modules/{assert.d.ts → assertion.d.ts} +1 -1
  51. package/dist/src/parser/subParsers/parseBindingTarget.d.ts +4 -2
  52. package/dist/src/parser/subParsers/parseMatch.d.ts +4 -0
  53. package/dist/src/parser/types.d.ts +5 -1
  54. package/dist/testFramework.esm.js +1 -1
  55. package/dist/testFramework.esm.js.map +1 -1
  56. package/dist/testFramework.js +1 -1
  57. package/dist/testFramework.js.map +1 -1
  58. package/package.json +5 -5
  59. package/dist/cli/src/builtin/specialExpressions/switch.d.ts +0 -6
  60. package/dist/cli/src/parser/subParsers/parseSwitch.d.ts +0 -4
  61. package/dist/modules/assert.esm.js +0 -2
  62. package/dist/modules/assert.esm.js.map +0 -1
  63. package/dist/modules/assert.js +0 -2
  64. package/dist/modules/assert.js.map +0 -1
  65. package/dist/modules/src/builtin/specialExpressions/switch.d.ts +0 -6
  66. package/dist/modules/src/parser/subParsers/parseSwitch.d.ts +0 -4
  67. package/dist/src/builtin/specialExpressions/switch.d.ts +0 -6
  68. package/dist/src/parser/subParsers/parseSwitch.d.ts +0 -4
  69. /package/dist/cli/src/builtin/modules/{assert → assertion}/docs.d.ts +0 -0
  70. /package/dist/cli/src/builtin/modules/{assert → assertion}/index.d.ts +0 -0
  71. /package/dist/modules/src/builtin/modules/{assert → assertion}/docs.d.ts +0 -0
  72. /package/dist/modules/src/builtin/modules/{assert → assertion}/index.d.ts +0 -0
  73. /package/dist/src/builtin/modules/{assert → assertion}/docs.d.ts +0 -0
  74. /package/dist/src/builtin/modules/{assert → assertion}/index.d.ts +0 -0
package/dist/cli/cli.js CHANGED
@@ -7,7 +7,7 @@ var readline = require('node:readline');
7
7
  var os = require('node:os');
8
8
  var process$1 = require('node:process');
9
9
 
10
- var version = "2.5.2";
10
+ var version = "2.6.1";
11
11
 
12
12
  function getCodeMarker(sourceCodeInfo) {
13
13
  if (!sourceCodeInfo.position || !sourceCodeInfo.code)
@@ -98,7 +98,7 @@ const specialExpressionTypes = {
98
98
  'loop': 12,
99
99
  'object': 13,
100
100
  'recur': 14,
101
- 'switch': 15,
101
+ 'match': 15,
102
102
  'throw': 16,
103
103
  'try': 17,
104
104
  'unless': 18,
@@ -289,85 +289,6 @@ function findUnresolvedSymbolsInNode(node, contextStack, builtin, evaluateNode)
289
289
  }
290
290
  }
291
291
 
292
- function getRangeString(options) {
293
- const hasUpperAndLowerBound = (typeof options.gt === 'number' || typeof options.gte === 'number')
294
- && (typeof options.lt === 'number' || typeof options.lte === 'number');
295
- if (hasUpperAndLowerBound) {
296
- return `${typeof options.gt === 'number' ? `${options.gt} < n ` : `${options.gte} <= n `}${typeof options.lt === 'number' ? `< ${options.lt}` : `<= ${options.lte}`}`;
297
- }
298
- else if (typeof options.gt === 'number' || typeof options.gte === 'number') {
299
- return `${typeof options.gt === 'number' ? `n > ${options.gt}` : `n >= ${options.gte}`}`;
300
- }
301
- else if (typeof options.lt === 'number' || typeof options.lte === 'number') {
302
- return `${typeof options.lt === 'number' ? `n < ${options.lt}` : `n <= ${options.lte}`}`;
303
- }
304
- else {
305
- return '';
306
- }
307
- }
308
- function getSignString(options) {
309
- return options.positive
310
- ? 'positive'
311
- : options.negative
312
- ? 'negative'
313
- : options.nonNegative
314
- ? 'non negative'
315
- : options.nonPositive
316
- ? 'non positive'
317
- : options.nonZero
318
- ? 'non zero'
319
- : '';
320
- }
321
- function getNumberTypeName(options) {
322
- if (options.zero)
323
- return 'zero';
324
- const sign = getSignString(options);
325
- const numberType = options.integer ? 'integer' : 'number';
326
- const finite = options.finite ? 'finite' : '';
327
- const range = getRangeString(options);
328
- return [sign, finite, numberType, range].filter(x => !!x).join(' ');
329
- }
330
- function isNumber(value, options = {}) {
331
- if (typeof value !== 'number')
332
- return false;
333
- if (Number.isNaN(value))
334
- return false;
335
- if (options.integer && !Number.isInteger(value))
336
- return false;
337
- if (options.finite && !Number.isFinite(value))
338
- return false;
339
- if (options.zero && value !== 0)
340
- return false;
341
- if (options.nonZero && value === 0)
342
- return false;
343
- if (options.positive && value <= 0)
344
- return false;
345
- if (options.negative && value >= 0)
346
- return false;
347
- if (options.nonPositive && value > 0)
348
- return false;
349
- if (options.nonNegative && value < 0)
350
- return false;
351
- if (typeof options.gt === 'number' && value <= options.gt)
352
- return false;
353
- if (typeof options.gte === 'number' && value < options.gte)
354
- return false;
355
- if (typeof options.lt === 'number' && value >= options.lt)
356
- return false;
357
- if (typeof options.lte === 'number' && value > options.lte)
358
- return false;
359
- return true;
360
- }
361
- function assertNumber(value, sourceCodeInfo, options = {}) {
362
- if (!isNumber(value, options)) {
363
- throw new LitsError(`Expected ${getNumberTypeName(options)}, got ${valueToString(value)}.`, getSourceCodeInfo(value, sourceCodeInfo));
364
- }
365
- }
366
- function asNumber(value, sourceCodeInfo, options = {}) {
367
- assertNumber(value, sourceCodeInfo, options);
368
- return value;
369
- }
370
-
371
292
  function isNonUndefined(value) {
372
293
  return value !== undefined;
373
294
  }
@@ -474,6 +395,162 @@ function assertFunctionLike(value, sourceCodeInfo) {
474
395
  throw getAssertionError('FunctionLike', value, sourceCodeInfo);
475
396
  }
476
397
 
398
+ function isString(value, options = {}) {
399
+ if (typeof value !== 'string')
400
+ return false;
401
+ if (options.nonEmpty && value.length === 0)
402
+ return false;
403
+ if (options.char && value.length !== 1)
404
+ return false;
405
+ return true;
406
+ }
407
+ function assertString(value, sourceCodeInfo, options = {}) {
408
+ if (!isString(value, options)) {
409
+ throw getAssertionError(`${options.nonEmpty ? 'non empty string' : options.char ? 'character' : 'string'}`, value, sourceCodeInfo);
410
+ }
411
+ }
412
+ function asString(value, sourceCodeInfo, options = {}) {
413
+ assertString(value, sourceCodeInfo, options);
414
+ return value;
415
+ }
416
+ function isStringOrNumber(value) {
417
+ return typeof value === 'string' || typeof value === 'number';
418
+ }
419
+ function asStringOrNumber(value, sourceCodeInfo) {
420
+ assertStringOrNumber(value, sourceCodeInfo);
421
+ return value;
422
+ }
423
+ function assertStringOrNumber(value, sourceCodeInfo) {
424
+ if (!isStringOrNumber(value))
425
+ throw getAssertionError('string or number', value, sourceCodeInfo);
426
+ }
427
+
428
+ const assertionNormalExpression = {
429
+ assert: {
430
+ evaluate: (params, sourceCodeInfo) => {
431
+ const value = params[0];
432
+ const message = params.length === 2 ? params[1] : `${value}`;
433
+ assertString(message, sourceCodeInfo);
434
+ if (!value)
435
+ throw new AssertionError(message, sourceCodeInfo);
436
+ return asAny(value, sourceCodeInfo);
437
+ },
438
+ arity: { min: 1, max: 2 },
439
+ docs: {
440
+ category: 'assertion',
441
+ description: 'If $value is falsy it throws `AssertionError` with $message. If no $message is provided, message is set to $value.',
442
+ returns: {
443
+ type: 'any',
444
+ },
445
+ args: {
446
+ value: {
447
+ type: 'any',
448
+ },
449
+ message: {
450
+ type: 'string',
451
+ },
452
+ },
453
+ variants: [
454
+ {
455
+ argumentNames: [
456
+ 'value',
457
+ ],
458
+ },
459
+ {
460
+ argumentNames: [
461
+ 'value',
462
+ 'message',
463
+ ],
464
+ },
465
+ ],
466
+ examples: [
467
+ 'try assert(0, "Expected a positive value") catch (e) e.message end',
468
+ ],
469
+ seeAlso: ['assertion.assert-truthy', 'assertion.assert-true'],
470
+ hideOperatorForm: true,
471
+ },
472
+ },
473
+ };
474
+
475
+ function getRangeString(options) {
476
+ const hasUpperAndLowerBound = (typeof options.gt === 'number' || typeof options.gte === 'number')
477
+ && (typeof options.lt === 'number' || typeof options.lte === 'number');
478
+ if (hasUpperAndLowerBound) {
479
+ return `${typeof options.gt === 'number' ? `${options.gt} < n ` : `${options.gte} <= n `}${typeof options.lt === 'number' ? `< ${options.lt}` : `<= ${options.lte}`}`;
480
+ }
481
+ else if (typeof options.gt === 'number' || typeof options.gte === 'number') {
482
+ return `${typeof options.gt === 'number' ? `n > ${options.gt}` : `n >= ${options.gte}`}`;
483
+ }
484
+ else if (typeof options.lt === 'number' || typeof options.lte === 'number') {
485
+ return `${typeof options.lt === 'number' ? `n < ${options.lt}` : `n <= ${options.lte}`}`;
486
+ }
487
+ else {
488
+ return '';
489
+ }
490
+ }
491
+ function getSignString(options) {
492
+ return options.positive
493
+ ? 'positive'
494
+ : options.negative
495
+ ? 'negative'
496
+ : options.nonNegative
497
+ ? 'non negative'
498
+ : options.nonPositive
499
+ ? 'non positive'
500
+ : options.nonZero
501
+ ? 'non zero'
502
+ : '';
503
+ }
504
+ function getNumberTypeName(options) {
505
+ if (options.zero)
506
+ return 'zero';
507
+ const sign = getSignString(options);
508
+ const numberType = options.integer ? 'integer' : 'number';
509
+ const finite = options.finite ? 'finite' : '';
510
+ const range = getRangeString(options);
511
+ return [sign, finite, numberType, range].filter(x => !!x).join(' ');
512
+ }
513
+ function isNumber(value, options = {}) {
514
+ if (typeof value !== 'number')
515
+ return false;
516
+ if (Number.isNaN(value))
517
+ return false;
518
+ if (options.integer && !Number.isInteger(value))
519
+ return false;
520
+ if (options.finite && !Number.isFinite(value))
521
+ return false;
522
+ if (options.zero && value !== 0)
523
+ return false;
524
+ if (options.nonZero && value === 0)
525
+ return false;
526
+ if (options.positive && value <= 0)
527
+ return false;
528
+ if (options.negative && value >= 0)
529
+ return false;
530
+ if (options.nonPositive && value > 0)
531
+ return false;
532
+ if (options.nonNegative && value < 0)
533
+ return false;
534
+ if (typeof options.gt === 'number' && value <= options.gt)
535
+ return false;
536
+ if (typeof options.gte === 'number' && value < options.gte)
537
+ return false;
538
+ if (typeof options.lt === 'number' && value >= options.lt)
539
+ return false;
540
+ if (typeof options.lte === 'number' && value > options.lte)
541
+ return false;
542
+ return true;
543
+ }
544
+ function assertNumber(value, sourceCodeInfo, options = {}) {
545
+ if (!isNumber(value, options)) {
546
+ throw new LitsError(`Expected ${getNumberTypeName(options)}, got ${valueToString(value)}.`, getSourceCodeInfo(value, sourceCodeInfo));
547
+ }
548
+ }
549
+ function asNumber(value, sourceCodeInfo, options = {}) {
550
+ assertNumber(value, sourceCodeInfo, options);
551
+ return value;
552
+ }
553
+
477
554
  function arityAcceptsMin(arity, nbrOfParams) {
478
555
  const { min } = arity;
479
556
  if (typeof min === 'number' && nbrOfParams < min) {
@@ -685,36 +762,6 @@ const bitwiseNormalExpression = {
685
762
  },
686
763
  };
687
764
 
688
- function isString(value, options = {}) {
689
- if (typeof value !== 'string')
690
- return false;
691
- if (options.nonEmpty && value.length === 0)
692
- return false;
693
- if (options.char && value.length !== 1)
694
- return false;
695
- return true;
696
- }
697
- function assertString(value, sourceCodeInfo, options = {}) {
698
- if (!isString(value, options)) {
699
- throw getAssertionError(`${options.nonEmpty ? 'non empty string' : options.char ? 'character' : 'string'}`, value, sourceCodeInfo);
700
- }
701
- }
702
- function asString(value, sourceCodeInfo, options = {}) {
703
- assertString(value, sourceCodeInfo, options);
704
- return value;
705
- }
706
- function isStringOrNumber(value) {
707
- return typeof value === 'string' || typeof value === 'number';
708
- }
709
- function asStringOrNumber(value, sourceCodeInfo) {
710
- assertStringOrNumber(value, sourceCodeInfo);
711
- return value;
712
- }
713
- function assertStringOrNumber(value, sourceCodeInfo) {
714
- if (!isStringOrNumber(value))
715
- throw getAssertionError('string or number', value, sourceCodeInfo);
716
- }
717
-
718
765
  function collHasKey(coll, key) {
719
766
  if (!isColl(coll))
720
767
  return false;
@@ -4379,7 +4426,7 @@ const predicatesNormalExpression = {
4379
4426
  args: { x: { type: 'any' } },
4380
4427
  variants: [{ argumentNames: ['x'] }],
4381
4428
  description: 'Returns `true` if $x is a regexp, otherwise `false`.',
4382
- seeAlso: ['regexp', 'match', 'string?', 'function?'],
4429
+ seeAlso: ['regexp', 're-match', 'string?', 'function?'],
4383
4430
  examples: [
4384
4431
  'regexp?(regexp("^start"))',
4385
4432
  'regexp?(#"^start")',
@@ -4649,11 +4696,11 @@ const regexpNormalExpression = {
4649
4696
  'regexp("albert", "ig")',
4650
4697
  '#"albert"ig',
4651
4698
  ],
4652
- seeAlso: ['-short-regexp', 'match', 'replace', 'replace-all', 'regexp?'],
4699
+ seeAlso: ['-short-regexp', 're-match', 'replace', 'replace-all', 'regexp?'],
4653
4700
  hideOperatorForm: true,
4654
4701
  },
4655
4702
  },
4656
- 'match': {
4703
+ 're-match': {
4657
4704
  evaluate: ([text, regexp], sourceCodeInfo) => {
4658
4705
  assertRegularExpression(regexp, sourceCodeInfo);
4659
4706
  if (!isString(text))
@@ -4674,16 +4721,16 @@ const regexpNormalExpression = {
4674
4721
  },
4675
4722
  variants: [{ argumentNames: ['a', 'b'] }],
4676
4723
  description: `Matches $b against regular expression $a.
4677
- If $b is a string and matches the regular expression, a \`match\`-array is returned, otherwise \`null\` is returned.`,
4724
+ If $b is a string and matches the regular expression, a \`re-match\`-array is returned, otherwise \`null\` is returned.`,
4678
4725
  seeAlso: ['regexp', 'replace', 'replace-all', '-short-regexp', 'regexp?'],
4679
4726
  examples: [
4680
- 'match(" A string", regexp("^\\\\s*(.*)$"))',
4681
- 'match(" A string", #"^\\s*(.*)$")',
4682
- 'match("My name is Albert", #"albert"i)',
4683
- 'match("My name is Ben", #"albert"i)',
4684
- 'match(null, #"albert"i)',
4685
- 'match(1, #"albert"i)',
4686
- 'match({}, #"albert"i)',
4727
+ 're-match(" A string", regexp("^\\\\s*(.*)$"))',
4728
+ 're-match(" A string", #"^\\s*(.*)$")',
4729
+ 're-match("My name is Albert", #"albert"i)',
4730
+ 're-match("My name is Ben", #"albert"i)',
4731
+ 're-match(null, #"albert"i)',
4732
+ 're-match(1, #"albert"i)',
4733
+ 're-match({}, #"albert"i)',
4687
4734
  ],
4688
4735
  },
4689
4736
  },
@@ -4706,7 +4753,7 @@ If $b is a string and matches the regular expression, a \`match\`-array is retur
4706
4753
  },
4707
4754
  variants: [{ argumentNames: ['a', 'b', 'x'] }],
4708
4755
  description: 'Returns a new string with first match of regular expression $b replaced by $x.',
4709
- seeAlso: ['replace-all', 'regexp', 'match', '-short-regexp'],
4756
+ seeAlso: ['replace-all', 'regexp', 're-match', '-short-regexp'],
4710
4757
  examples: [
4711
4758
  'replace("Duck duck", "u", "i")',
4712
4759
  'replace("Duck duck", #"u", "i")',
@@ -4736,7 +4783,7 @@ If $b is a string and matches the regular expression, a \`match\`-array is retur
4736
4783
  },
4737
4784
  variants: [{ argumentNames: ['a', 'b', 'x'] }],
4738
4785
  description: 'Returns a new string with all matches of regular expression $b replaced by $x.',
4739
- seeAlso: ['replace', 'regexp', 'match', '-short-regexp'],
4786
+ seeAlso: ['replace', 'regexp', 're-match', '-short-regexp'],
4740
4787
  examples: [
4741
4788
  'replace-all("Duck duck", "u", "i")',
4742
4789
  'replace-all("Duck duck", regexp("u"), "i")',
@@ -5328,6 +5375,7 @@ function setNormalExpressionReference(reference) {
5328
5375
  }
5329
5376
  const expressions$1 = {
5330
5377
  // Core categories
5378
+ ...assertionNormalExpression,
5331
5379
  ...bitwiseNormalExpression,
5332
5380
  ...collectionNormalExpression,
5333
5381
  ...arrayNormalExpression,
@@ -5455,121 +5503,6 @@ const condSpecialExpression = {
5455
5503
  getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].flat(), contextStack, builtin, evaluateNode),
5456
5504
  };
5457
5505
 
5458
- const docs$e = {
5459
- category: 'special-expression',
5460
- customVariants: ['switch value switch-branch switch-branch ... end'],
5461
- details: [
5462
- ['value', 'any', 'The value to test.'],
5463
- ['switch-branch', 'case test then body', 'A branch of the switch expression.'],
5464
- ['test', 'expression', 'The condition to test.'],
5465
- ['body', 'expressions', 'The expressions to evaluate if the test is truthy.'],
5466
- ],
5467
- description: 'Used for branching. `switch-branches` are tested sequentially from the top against `value`. If no branch is tested truthy, `null` is returned.',
5468
- examples: [
5469
- `
5470
- switch 1
5471
- case 1 then write!("One")
5472
- case 2 then write!("Two")
5473
- end`,
5474
- `
5475
- switch 2
5476
- case 1 then write!("One")
5477
- case 2 then write!("Two")
5478
- end`,
5479
- `
5480
- switch 3
5481
- case 1 then write!("One")
5482
- case 2 then write!("Two")
5483
- end`,
5484
- ],
5485
- };
5486
- const switchSpecialExpression = {
5487
- arity: {},
5488
- docs: docs$e,
5489
- evaluate: (node, contextStack, { evaluateNode }) => {
5490
- const [, switchValueNode, cases] = node[1];
5491
- return chain(evaluateNode(switchValueNode, contextStack), (switchValue) => {
5492
- function processCase(index) {
5493
- if (index >= cases.length)
5494
- return null;
5495
- const [test, form] = cases[index];
5496
- return chain(evaluateNode(test, contextStack), (value) => {
5497
- if (value === switchValue) {
5498
- return evaluateNode(form, contextStack);
5499
- }
5500
- return processCase(index + 1);
5501
- });
5502
- }
5503
- return processCase(0);
5504
- });
5505
- },
5506
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols([node[1][1], ...node[1][2].flat()], contextStack, builtin, evaluateNode),
5507
- };
5508
-
5509
- const docs$d = {
5510
- category: 'special-expression',
5511
- returns: {
5512
- type: 'boolean',
5513
- },
5514
- args: {
5515
- symbol: { type: 'any' },
5516
- },
5517
- variants: [
5518
- { argumentNames: ['symbol'] },
5519
- ],
5520
- description: `Returns \`true\` if \`symbol\` is defined, \`false\` otherwise.
5521
-
5522
- Built-in symbols are always considered defined. For user-defined symbols, checks if the symbol exists in the current scope.`,
5523
- examples: [
5524
- 'let x = 42; defined?(x)',
5525
- 'defined?(x)',
5526
- 'defined?(+)',
5527
- ],
5528
- };
5529
- const definedSpecialExpression = {
5530
- arity: toFixedArity(1),
5531
- docs: docs$d,
5532
- evaluate: (node, contextStack) => {
5533
- const symbolNode = node[1][1];
5534
- assertSymbolNode(symbolNode);
5535
- if (!isUserDefinedSymbolNode(symbolNode)) {
5536
- return true; // If the symbol is not a user defined symbol, it is defined. normal or special builtin
5537
- }
5538
- const lookUpResult = contextStack.lookUp(symbolNode);
5539
- return lookUpResult !== null;
5540
- },
5541
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols([node[1][1]], contextStack, builtin, evaluateNode),
5542
- };
5543
-
5544
- const docs$c = {
5545
- category: 'special-expression',
5546
- customVariants: ['do body end'],
5547
- details: [
5548
- ['body', 'expressions', 'The expressions to evaluate.'],
5549
- ],
5550
- description: 'Evaluates `body`. Resulting value is the value of the last expression.',
5551
- examples: [
5552
- `
5553
- do
5554
- let a = 1 + 2 + 3 + 4;
5555
- let b = -> $ * ( $ + 1 );
5556
- b(a)
5557
- end`,
5558
- ],
5559
- };
5560
- const doSpecialExpression = {
5561
- arity: {},
5562
- docs: docs$c,
5563
- evaluate: (node, contextStack, { evaluateNode }) => {
5564
- const newContext = {};
5565
- const newContextStack = contextStack.create(newContext);
5566
- return reduceSequential(node[1][1], (_acc, form) => evaluateNode(form, newContextStack), null);
5567
- },
5568
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5569
- return getUndefinedSymbols(node[1][1], contextStack.create({}), builtin, evaluateNode);
5570
- },
5571
- };
5572
-
5573
5506
  function isJsFunction(fn) {
5574
5507
  return typeof fn === 'object' && fn !== null && 'fn' in fn && typeof fn.fn === 'function';
5575
5508
  }
@@ -5578,6 +5511,8 @@ const bindingTargetTypes = {
5578
5511
  rest: 12,
5579
5512
  object: 13,
5580
5513
  array: 14,
5514
+ literal: 15,
5515
+ wildcard: 16,
5581
5516
  };
5582
5517
 
5583
5518
  function walkDefaults(bindingTarget, onDefault) {
@@ -5601,6 +5536,7 @@ function walkDefaults(bindingTarget, onDefault) {
5601
5536
  walkDefaults(element, onDefault);
5602
5537
  }
5603
5538
  }
5539
+ // literal and wildcard have no defaults - nothing to walk
5604
5540
  }
5605
5541
  function evaluateBindingNodeValues(target, value, evaluate) {
5606
5542
  const sourceCodeInfo = target[2];
@@ -5709,14 +5645,302 @@ function getNamesFromBindingTarget(target, names) {
5709
5645
  }
5710
5646
  names[target[1][0]] = true;
5711
5647
  }
5712
- else {
5648
+ else if (target[0] === bindingTargetTypes.symbol) {
5713
5649
  if (names[target[1][0][1]]) {
5714
5650
  throw new LitsError(`Duplicate binding name: ${target[1][0]}`, target[2]);
5715
5651
  }
5716
5652
  names[target[1][0][1]] = true;
5717
5653
  }
5654
+ // literal and wildcard bind no names - skip
5655
+ }
5656
+ /**
5657
+ * Non-throwing pattern matching. Returns bindings on match, null on mismatch.
5658
+ * Used by `switch` pattern matching.
5659
+ */
5660
+ function tryMatch(target, value, evaluate) {
5661
+ const record = {};
5662
+ return chain(tryMatchRecord(target, value, evaluate, record), (matched) => {
5663
+ if (!matched)
5664
+ return null;
5665
+ return record;
5666
+ });
5667
+ }
5668
+ function tryMatchRecord(bindingTarget, value, evaluate, record) {
5669
+ // Wildcard: always matches, binds nothing
5670
+ if (bindingTarget[0] === bindingTargetTypes.wildcard) {
5671
+ return true;
5672
+ }
5673
+ // Literal: compare with deepEqual
5674
+ else if (bindingTarget[0] === bindingTargetTypes.literal) {
5675
+ const literalNode = bindingTarget[1][0];
5676
+ return chain(evaluate(literalNode), (literalValue) => {
5677
+ return deepEqual(value, literalValue);
5678
+ });
5679
+ }
5680
+ // Symbol: always matches, binds value
5681
+ else if (bindingTarget[0] === bindingTargetTypes.symbol) {
5682
+ const symbolNode = bindingTarget[1][0];
5683
+ const defaultNode = bindingTarget[1][1];
5684
+ if (value === undefined || value === null) {
5685
+ if (defaultNode) {
5686
+ return chain(evaluate(defaultNode), (defaultValue) => {
5687
+ record[symbolNode[1]] = asAny(defaultValue);
5688
+ return true;
5689
+ });
5690
+ }
5691
+ record[symbolNode[1]] = value ?? null;
5692
+ }
5693
+ else {
5694
+ record[symbolNode[1]] = asAny(value);
5695
+ }
5696
+ return true;
5697
+ }
5698
+ // Object pattern
5699
+ else if (bindingTarget[0] === bindingTargetTypes.object) {
5700
+ if (!isUnknownRecord(value))
5701
+ return false;
5702
+ const capturedKeys = new Set();
5703
+ let restElement;
5704
+ const entries = Object.entries(bindingTarget[1][0]);
5705
+ let result = true;
5706
+ for (const [key, element] of entries) {
5707
+ result = chain(result, (matched) => {
5708
+ if (!matched)
5709
+ return false;
5710
+ if (element[0] === bindingTargetTypes.rest) {
5711
+ restElement = element;
5712
+ return true;
5713
+ }
5714
+ capturedKeys.add(key);
5715
+ const existingVal = value[key];
5716
+ // For literal sub-patterns, missing key means no match
5717
+ if (existingVal === undefined && element[0] === bindingTargetTypes.literal) {
5718
+ return chain(evaluate(element[1][0]), (literalValue) => {
5719
+ return deepEqual(undefined, literalValue);
5720
+ });
5721
+ }
5722
+ const maybeVal = existingVal !== undefined
5723
+ ? existingVal
5724
+ : element[1] && element[1][1]
5725
+ ? evaluate(element[1][1])
5726
+ : null;
5727
+ return chain(maybeVal, (resolvedVal) => {
5728
+ const val = resolvedVal ?? null;
5729
+ return tryMatchRecord(element, val, evaluate, record);
5730
+ });
5731
+ });
5732
+ }
5733
+ return chain(result, (matched) => {
5734
+ if (!matched)
5735
+ return false;
5736
+ if (restElement) {
5737
+ const restValues = Object.entries(value)
5738
+ .filter(([key]) => !capturedKeys.has(key))
5739
+ .reduce((acc, [key, val]) => {
5740
+ acc[key] = asAny(val);
5741
+ return acc;
5742
+ }, {});
5743
+ record[restElement[1][0]] = restValues;
5744
+ }
5745
+ return true;
5746
+ });
5747
+ }
5748
+ // Array pattern
5749
+ else {
5750
+ const arrayTarget = bindingTarget;
5751
+ if (!Array.isArray(value))
5752
+ return false;
5753
+ const elements = arrayTarget[1][0];
5754
+ let restIndex = null;
5755
+ // Find rest element index and check length constraints
5756
+ for (let i = 0; i < elements.length; i += 1) {
5757
+ const element = elements[i];
5758
+ if (element !== null && element[0] === bindingTargetTypes.rest) {
5759
+ restIndex = i;
5760
+ break;
5761
+ }
5762
+ }
5763
+ // Without rest: array length must match exactly
5764
+ if (restIndex === null && value.length !== elements.length) {
5765
+ return false;
5766
+ }
5767
+ // With rest: array must have at least the non-rest elements
5768
+ if (restIndex !== null && value.length < restIndex) {
5769
+ return false;
5770
+ }
5771
+ let result = true;
5772
+ for (let i = 0; i < elements.length; i += 1) {
5773
+ const element = elements[i];
5774
+ if (element === null)
5775
+ continue; // skipped position
5776
+ if (element[0] === bindingTargetTypes.rest) {
5777
+ // Rest collects remaining elements
5778
+ record[element[1][0]] = value.slice(i);
5779
+ break;
5780
+ }
5781
+ const el = element;
5782
+ result = chain(result, (matched) => {
5783
+ if (!matched)
5784
+ return false;
5785
+ return tryMatchRecord(el, asAny(value[i]), evaluate, record);
5786
+ });
5787
+ }
5788
+ return result;
5789
+ }
5718
5790
  }
5719
5791
 
5792
+ const docs$e = {
5793
+ category: 'special-expression',
5794
+ customVariants: ['match value match-branch match-branch ... end'],
5795
+ details: [
5796
+ ['value', 'any', 'The value to match against patterns.'],
5797
+ ['match-branch', 'case pattern [when guard] then body', 'A branch of the match expression.'],
5798
+ ['pattern', 'pattern', 'A pattern to match: literal, variable, array destructuring, object destructuring, or wildcard (_).'],
5799
+ ['guard', 'expression', 'An optional guard expression that must be truthy for the match to succeed.'],
5800
+ ['body', 'expressions', 'The expressions to evaluate if the pattern matches.'],
5801
+ ],
5802
+ description: 'Pattern matching expression. Matches `value` against each `pattern` sequentially. If a pattern matches (and the optional `when` guard is truthy), the corresponding `body` is evaluated and its result returned. Bound variables from the pattern are available in the guard and body. If no pattern matches, `null` is returned.',
5803
+ examples: [
5804
+ `
5805
+ match 1
5806
+ case 1 then "One"
5807
+ case 2 then "Two"
5808
+ end`,
5809
+ `
5810
+ match [1, 2, 3]
5811
+ case [x] then "one element"
5812
+ case [x, y] then "two elements"
5813
+ case [x, ...xs] then "first: " ++ str(x) ++ " rest: " ++ str(xs)
5814
+ end`,
5815
+ `
5816
+ match { type: "click", x: 10, y: 20 }
5817
+ case { type: "click", x, y } then "Click at " ++ str(x) ++ ", " ++ str(y)
5818
+ case { type: "keydown", key } then "Key: " ++ key
5819
+ case _ then "unknown event"
5820
+ end`,
5821
+ `
5822
+ match { role: "admin", name: "Alice" }
5823
+ case { role: "admin", name } then "Admin: " ++ name
5824
+ case { role, name } when role == "user" then "User: " ++ name
5825
+ case _ then "Unknown role"
5826
+ end`,
5827
+ ],
5828
+ };
5829
+ const matchSpecialExpression = {
5830
+ arity: {},
5831
+ docs: docs$e,
5832
+ evaluate: (node, contextStack, { evaluateNode }) => {
5833
+ const [, matchValueNode, cases] = node[1];
5834
+ return chain(evaluateNode(matchValueNode, contextStack), (matchValue) => {
5835
+ function processCase(index) {
5836
+ if (index >= cases.length)
5837
+ return null;
5838
+ const [pattern, body, guard] = cases[index];
5839
+ return chain(tryMatch(pattern, matchValue, n => evaluateNode(n, contextStack)), (bindings) => {
5840
+ if (bindings === null)
5841
+ return processCase(index + 1);
5842
+ // Pattern matched - create context with bound variables
5843
+ const context = {};
5844
+ for (const [name, value] of Object.entries(bindings)) {
5845
+ context[name] = { value };
5846
+ }
5847
+ const newContextStack = contextStack.create(context);
5848
+ // Check guard if present
5849
+ if (guard) {
5850
+ return chain(evaluateNode(guard, newContextStack), (guardResult) => {
5851
+ if (!guardResult)
5852
+ return processCase(index + 1);
5853
+ return evaluateNode(body, newContextStack);
5854
+ });
5855
+ }
5856
+ return evaluateNode(body, newContextStack);
5857
+ });
5858
+ }
5859
+ return processCase(0);
5860
+ });
5861
+ },
5862
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5863
+ const result = new Set();
5864
+ // The match value expression
5865
+ getUndefinedSymbols([node[1][1]], contextStack, builtin, evaluateNode).forEach(s => result.add(s));
5866
+ // Each case
5867
+ for (const [pattern, body, guard] of node[1][2]) {
5868
+ const newContext = {};
5869
+ Object.assign(newContext, getAllBindingTargetNames(pattern));
5870
+ const caseContextStack = contextStack.create(newContext);
5871
+ if (guard) {
5872
+ getUndefinedSymbols([guard], caseContextStack, builtin, evaluateNode).forEach(s => result.add(s));
5873
+ }
5874
+ getUndefinedSymbols([body], caseContextStack, builtin, evaluateNode).forEach(s => result.add(s));
5875
+ }
5876
+ return result;
5877
+ },
5878
+ };
5879
+
5880
+ const docs$d = {
5881
+ category: 'special-expression',
5882
+ returns: {
5883
+ type: 'boolean',
5884
+ },
5885
+ args: {
5886
+ symbol: { type: 'any' },
5887
+ },
5888
+ variants: [
5889
+ { argumentNames: ['symbol'] },
5890
+ ],
5891
+ description: `Returns \`true\` if \`symbol\` is defined, \`false\` otherwise.
5892
+
5893
+ Built-in symbols are always considered defined. For user-defined symbols, checks if the symbol exists in the current scope.`,
5894
+ examples: [
5895
+ 'let x = 42; defined?(x)',
5896
+ 'defined?(x)',
5897
+ 'defined?(+)',
5898
+ ],
5899
+ };
5900
+ const definedSpecialExpression = {
5901
+ arity: toFixedArity(1),
5902
+ docs: docs$d,
5903
+ evaluate: (node, contextStack) => {
5904
+ const symbolNode = node[1][1];
5905
+ assertSymbolNode(symbolNode);
5906
+ if (!isUserDefinedSymbolNode(symbolNode)) {
5907
+ return true; // If the symbol is not a user defined symbol, it is defined. normal or special builtin
5908
+ }
5909
+ const lookUpResult = contextStack.lookUp(symbolNode);
5910
+ return lookUpResult !== null;
5911
+ },
5912
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols([node[1][1]], contextStack, builtin, evaluateNode),
5913
+ };
5914
+
5915
+ const docs$c = {
5916
+ category: 'special-expression',
5917
+ customVariants: ['do body end'],
5918
+ details: [
5919
+ ['body', 'expressions', 'The expressions to evaluate.'],
5920
+ ],
5921
+ description: 'Evaluates `body`. Resulting value is the value of the last expression.',
5922
+ examples: [
5923
+ `
5924
+ do
5925
+ let a = 1 + 2 + 3 + 4;
5926
+ let b = -> $ * ( $ + 1 );
5927
+ b(a)
5928
+ end`,
5929
+ ],
5930
+ };
5931
+ const doSpecialExpression = {
5932
+ arity: {},
5933
+ docs: docs$c,
5934
+ evaluate: (node, contextStack, { evaluateNode }) => {
5935
+ const newContext = {};
5936
+ const newContextStack = contextStack.create(newContext);
5937
+ return reduceSequential(node[1][1], (_acc, form) => evaluateNode(form, newContextStack), null);
5938
+ },
5939
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5940
+ return getUndefinedSymbols(node[1][1], contextStack.create({}), builtin, evaluateNode);
5941
+ },
5942
+ };
5943
+
5720
5944
  const lambdaSpecialExpression = {
5721
5945
  arity: {},
5722
5946
  evaluate: (node, contextStack, { builtin, getUndefinedSymbols, evaluateNode }) => {
@@ -6693,7 +6917,7 @@ const specialExpressions = [
6693
6917
  loopSpecialExpression,
6694
6918
  objectSpecialExpression,
6695
6919
  recurSpecialExpression,
6696
- switchSpecialExpression,
6920
+ matchSpecialExpression,
6697
6921
  throwSpecialExpression,
6698
6922
  trySpecialExpression,
6699
6923
  unlessSpecialExpression,
@@ -7924,6 +8148,12 @@ function assertOperatorToken(token, operatorName) {
7924
8148
  function isWhitespaceToken(token) {
7925
8149
  return token?.[0] === 'Whitespace';
7926
8150
  }
8151
+ function isNumberToken(token) {
8152
+ return token?.[0] === 'Number';
8153
+ }
8154
+ function isBasePrefixedNumberToken(token) {
8155
+ return token?.[0] === 'BasePrefixedNumber';
8156
+ }
7927
8157
  function isLParenToken(token) {
7928
8158
  return token?.[0] === 'LParen';
7929
8159
  }
@@ -8491,8 +8721,48 @@ function parseSymbol(ctx) {
8491
8721
  }
8492
8722
  }
8493
8723
 
8494
- function parseBindingTarget(ctx, { requireDefaultValue, noRest } = {}) {
8724
+ function parseNumber(ctx) {
8725
+ const token = ctx.peek();
8726
+ ctx.advance();
8727
+ const value = token[1];
8728
+ const negative = value[0] === '-';
8729
+ const numberString = (negative ? value.substring(1) : value).replace(/_/g, '');
8730
+ return withSourceCodeInfo([NodeTypes.Number, negative ? -Number(numberString) : Number(numberString)], token[2]);
8731
+ }
8732
+
8733
+ function parseBindingTarget(ctx, { requireDefaultValue, noRest, allowLiteralPatterns } = {}) {
8495
8734
  const firstToken = ctx.tryPeek();
8735
+ // Wildcard _ (only in pattern matching context)
8736
+ if (allowLiteralPatterns && isReservedSymbolToken(firstToken, '_')) {
8737
+ ctx.advance();
8738
+ return withSourceCodeInfo([bindingTargetTypes.wildcard, []], firstToken[2]);
8739
+ }
8740
+ // Literal patterns: number, string, true, false, null (only in pattern matching context)
8741
+ if (allowLiteralPatterns && isLiteralToken(firstToken)) {
8742
+ if (isNumberToken(firstToken) || isBasePrefixedNumberToken(firstToken)) {
8743
+ const node = parseNumber(ctx);
8744
+ return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
8745
+ }
8746
+ if (isStringToken(firstToken)) {
8747
+ const node = parseString(ctx, firstToken);
8748
+ return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
8749
+ }
8750
+ if (isReservedSymbolToken(firstToken, 'true')) {
8751
+ ctx.advance();
8752
+ const node = withSourceCodeInfo([NodeTypes.ReservedSymbol, 'true'], firstToken[2]);
8753
+ return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
8754
+ }
8755
+ if (isReservedSymbolToken(firstToken, 'false')) {
8756
+ ctx.advance();
8757
+ const node = withSourceCodeInfo([NodeTypes.ReservedSymbol, 'false'], firstToken[2]);
8758
+ return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
8759
+ }
8760
+ if (isReservedSymbolToken(firstToken, 'null')) {
8761
+ ctx.advance();
8762
+ const node = withSourceCodeInfo([NodeTypes.ReservedSymbol, 'null'], firstToken[2]);
8763
+ return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
8764
+ }
8765
+ }
8496
8766
  // Symbol
8497
8767
  if (isSymbolToken(firstToken)) {
8498
8768
  const symbol = parseSymbol(ctx);
@@ -8533,7 +8803,7 @@ function parseBindingTarget(ctx, { requireDefaultValue, noRest } = {}) {
8533
8803
  token = ctx.peek();
8534
8804
  continue;
8535
8805
  }
8536
- const target = parseBindingTarget(ctx);
8806
+ const target = parseBindingTarget(ctx, { allowLiteralPatterns });
8537
8807
  if (target[0] === bindingTargetTypes.rest) {
8538
8808
  rest = true;
8539
8809
  }
@@ -8597,10 +8867,18 @@ function parseBindingTarget(ctx, { requireDefaultValue, noRest } = {}) {
8597
8867
  else if (isOperatorToken(token, ':')) {
8598
8868
  ctx.advance();
8599
8869
  token = ctx.peek();
8600
- if (!isLBraceToken(token) && !isLBracketToken(token)) {
8601
- throw new LitsError('Expected object or array', token[2]);
8870
+ if (allowLiteralPatterns) {
8871
+ // In pattern matching context, allow literals, nested objects/arrays, and variable bindings after ':'
8872
+ if (!isLBraceToken(token) && !isLBracketToken(token) && !isLiteralToken(token)) {
8873
+ throw new LitsError('Expected literal, object or array pattern', token[2]);
8874
+ }
8602
8875
  }
8603
- elements[keyName] = parseBindingTarget(ctx);
8876
+ else {
8877
+ if (!isLBraceToken(token) && !isLBracketToken(token)) {
8878
+ throw new LitsError('Expected object or array', token[2]);
8879
+ }
8880
+ }
8881
+ elements[keyName] = parseBindingTarget(ctx, { allowLiteralPatterns });
8604
8882
  }
8605
8883
  if (!isRBraceToken(ctx.peek())) {
8606
8884
  assertOperatorToken(ctx.peek(), ',');
@@ -8625,6 +8903,14 @@ function parseOptionalDefaulValue(ctx) {
8625
8903
  }
8626
8904
  return undefined;
8627
8905
  }
8906
+ function isLiteralToken(token) {
8907
+ return isNumberToken(token)
8908
+ || isBasePrefixedNumberToken(token)
8909
+ || isStringToken(token)
8910
+ || isReservedSymbolToken(token, 'true')
8911
+ || isReservedSymbolToken(token, 'false')
8912
+ || isReservedSymbolToken(token, 'null');
8913
+ }
8628
8914
 
8629
8915
  function parseLet(ctx, token) {
8630
8916
  ctx.advance();
@@ -9050,15 +9336,6 @@ function parseFunctionCall(ctx, symbol) {
9050
9336
  }
9051
9337
  }
9052
9338
 
9053
- function parseNumber(ctx) {
9054
- const token = ctx.peek();
9055
- ctx.advance();
9056
- const value = token[1];
9057
- const negative = value[0] === '-';
9058
- const numberString = (negative ? value.substring(1) : value).replace(/_/g, '');
9059
- return withSourceCodeInfo([NodeTypes.Number, negative ? -Number(numberString) : Number(numberString)], token[2]);
9060
- }
9061
-
9062
9339
  function parseObject(ctx) {
9063
9340
  const firstToken = asLBraceToken(ctx.tryPeek());
9064
9341
  ctx.advance();
@@ -9209,25 +9486,32 @@ function createAccessorNode(left, right, sourceCodeInfo) {
9209
9486
  return withSourceCodeInfo([NodeTypes.NormalExpression, [[NodeTypes.NormalBuiltinSymbol, normalExpressionTypes.get], [left, right]]], sourceCodeInfo);
9210
9487
  }
9211
9488
 
9212
- function parseSwitch(ctx, token) {
9489
+ function parseMatch(ctx, token) {
9213
9490
  ctx.advance();
9214
9491
  const valueExpression = ctx.parseExpression();
9215
9492
  const params = [];
9216
9493
  while (!ctx.isAtEnd() && !isReservedSymbolToken(ctx.tryPeek(), 'end')) {
9217
9494
  assertReservedSymbolToken(ctx.tryPeek(), 'case');
9218
9495
  ctx.advance();
9219
- const caseExpression = ctx.parseExpression();
9496
+ // Parse pattern instead of expression
9497
+ const pattern = parseBindingTarget(ctx, { allowLiteralPatterns: true });
9498
+ // Check for optional guard: `when <expression>`
9499
+ let guard;
9500
+ if (isReservedSymbolToken(ctx.tryPeek(), 'when')) {
9501
+ ctx.advance();
9502
+ guard = ctx.parseExpression();
9503
+ }
9220
9504
  assertReservedSymbolToken(ctx.tryPeek(), 'then');
9221
9505
  ctx.advance();
9222
9506
  const thenExpression = parseImplicitBlock(ctx, ['case', 'end']);
9223
- params.push([caseExpression, thenExpression]);
9507
+ params.push([pattern, thenExpression, guard]);
9224
9508
  if (isReservedSymbolToken(ctx.tryPeek(), 'end')) {
9225
9509
  break;
9226
9510
  }
9227
9511
  }
9228
9512
  assertReservedSymbolToken(ctx.tryPeek(), 'end');
9229
9513
  ctx.advance();
9230
- return withSourceCodeInfo([NodeTypes.SpecialExpression, [specialExpressionTypes.switch, valueExpression, params]], token[2]);
9514
+ return withSourceCodeInfo([NodeTypes.SpecialExpression, [specialExpressionTypes.match, valueExpression, params]], token[2]);
9231
9515
  }
9232
9516
 
9233
9517
  function parseTry(ctx, token) {
@@ -9265,8 +9549,8 @@ function parseExpression(ctx, precedence = 0) {
9265
9549
  case 'cond':
9266
9550
  left = parseCond(ctx, token);
9267
9551
  break;
9268
- case 'switch':
9269
- left = parseSwitch(ctx, token);
9552
+ case 'match':
9553
+ left = parseMatch(ctx, token);
9270
9554
  break;
9271
9555
  case 'for':
9272
9556
  case 'doseq':
@@ -9555,41 +9839,8 @@ class Lits {
9555
9839
  }
9556
9840
 
9557
9841
  const moduleDocs$6 = {
9558
- 'assert': {
9559
- category: 'assert',
9560
- description: 'If $value is falsy it throws `AssertionError` with $message. If no $message is provided, message is set to $value.',
9561
- returns: {
9562
- type: 'any',
9563
- },
9564
- args: {
9565
- value: {
9566
- type: 'any',
9567
- },
9568
- message: {
9569
- type: 'string',
9570
- },
9571
- },
9572
- variants: [
9573
- {
9574
- argumentNames: [
9575
- 'value',
9576
- ],
9577
- },
9578
- {
9579
- argumentNames: [
9580
- 'value',
9581
- 'message',
9582
- ],
9583
- },
9584
- ],
9585
- examples: [
9586
- 'let { assert } = import(assert);\ntry assert(0, "Expected a positive value") catch (e) e.message end',
9587
- ],
9588
- seeAlso: ['assert.assert-truthy', 'assert.assert-true'],
9589
- hideOperatorForm: true,
9590
- },
9591
9842
  'assert!=': {
9592
- category: 'assert',
9843
+ category: 'assertion',
9593
9844
  description: 'If $a is the same as $b it throws `AssertionError`.',
9594
9845
  returns: {
9595
9846
  type: 'null',
@@ -9621,16 +9872,16 @@ const moduleDocs$6 = {
9621
9872
  },
9622
9873
  ],
9623
9874
  examples: [
9624
- 'let { assert!= } = import(assert);\ntry assert!=(0, 0, "Expected different values") catch (e) e.message end',
9625
- 'let { assert!= } = import(assert);\ntry assert!=(0, 0) catch (e) e.message end',
9626
- 'let { assert!= } = import(assert);\ntry 0 assert!= 0 catch (e) e.message end',
9627
- 'let { assert!= } = import(assert);\ntry assert!=(0, 1) catch (e) e.message end',
9875
+ 'let { assert!= } = import(assertion);\ntry assert!=(0, 0, "Expected different values") catch (e) e.message end',
9876
+ 'let { assert!= } = import(assertion);\ntry assert!=(0, 0) catch (e) e.message end',
9877
+ 'let { assert!= } = import(assertion);\ntry 0 assert!= 0 catch (e) e.message end',
9878
+ 'let { assert!= } = import(assertion);\ntry assert!=(0, 1) catch (e) e.message end',
9628
9879
  ],
9629
- seeAlso: ['assert.assert='],
9880
+ seeAlso: ['assertion.assert='],
9630
9881
  hideOperatorForm: true,
9631
9882
  },
9632
9883
  'assert=': {
9633
- category: 'assert',
9884
+ category: 'assertion',
9634
9885
  description: 'If $a is not structural equal to $b it throws `AssertionError`.',
9635
9886
  returns: {
9636
9887
  type: 'null',
@@ -9662,15 +9913,15 @@ const moduleDocs$6 = {
9662
9913
  },
9663
9914
  ],
9664
9915
  examples: [
9665
- 'let { assert= } = import(assert);\ntry assert=({ "a": 1 }, { "a": 2 }, "Expected equal values") catch (e) e.message end',
9666
- 'let { assert= } = import(assert);\ntry assert=({ "a": 1 }, { "a": 2 }) catch (e) e.message end',
9667
- 'let { assert= } = import(assert);\ntry assert=({ "a": 1 }, { "a": 1 }) catch (e) e.message end',
9916
+ 'let { assert= } = import(assertion);\ntry assert=({ "a": 1 }, { "a": 2 }, "Expected equal values") catch (e) e.message end',
9917
+ 'let { assert= } = import(assertion);\ntry assert=({ "a": 1 }, { "a": 2 }) catch (e) e.message end',
9918
+ 'let { assert= } = import(assertion);\ntry assert=({ "a": 1 }, { "a": 1 }) catch (e) e.message end',
9668
9919
  ],
9669
- seeAlso: ['assert.assert!='],
9920
+ seeAlso: ['assertion.assert!='],
9670
9921
  hideOperatorForm: true,
9671
9922
  },
9672
9923
  'assert-gt': {
9673
- category: 'assert',
9924
+ category: 'assertion',
9674
9925
  description: 'If $a is not greater than $b it throws `AssertionError`.',
9675
9926
  returns: {
9676
9927
  type: 'null',
@@ -9702,15 +9953,15 @@ const moduleDocs$6 = {
9702
9953
  },
9703
9954
  ],
9704
9955
  examples: [
9705
- 'let { assert-gt } = import(assert);\ntry assert-gt(0, 1, "Expected greater value") catch (e) e.message end',
9706
- 'let { assert-gt } = import(assert);\ntry assert-gt(0, 0) catch (e) e.message end',
9707
- 'let { assert-gt } = import(assert);\ntry assert-gt(1, 0) catch (e) e.message end',
9956
+ 'let { assert-gt } = import(assertion);\ntry assert-gt(0, 1, "Expected greater value") catch (e) e.message end',
9957
+ 'let { assert-gt } = import(assertion);\ntry assert-gt(0, 0) catch (e) e.message end',
9958
+ 'let { assert-gt } = import(assertion);\ntry assert-gt(1, 0) catch (e) e.message end',
9708
9959
  ],
9709
- seeAlso: ['assert.assert-lt', 'assert.assert-gte', 'assert.assert-lte'],
9960
+ seeAlso: ['assertion.assert-lt', 'assertion.assert-gte', 'assertion.assert-lte'],
9710
9961
  hideOperatorForm: true,
9711
9962
  },
9712
9963
  'assert-lt': {
9713
- category: 'assert',
9964
+ category: 'assertion',
9714
9965
  description: 'If $a is not less than $b it throws `AssertionError`.',
9715
9966
  returns: {
9716
9967
  type: 'null',
@@ -9742,15 +9993,15 @@ const moduleDocs$6 = {
9742
9993
  },
9743
9994
  ],
9744
9995
  examples: [
9745
- 'let { assert-lt } = import(assert);\ntry assert-lt(1, 0, "Expected smaller value value") catch (e) e.message end',
9746
- 'let { assert-lt } = import(assert);\ntry assert-lt(1, 1) catch (e) e.message end',
9747
- 'let { assert-lt } = import(assert);\ntry assert-lt(0, 1) catch (e) e.message end',
9996
+ 'let { assert-lt } = import(assertion);\ntry assert-lt(1, 0, "Expected smaller value value") catch (e) e.message end',
9997
+ 'let { assert-lt } = import(assertion);\ntry assert-lt(1, 1) catch (e) e.message end',
9998
+ 'let { assert-lt } = import(assertion);\ntry assert-lt(0, 1) catch (e) e.message end',
9748
9999
  ],
9749
- seeAlso: ['assert.assert-gt', 'assert.assert-lte', 'assert.assert-gte'],
10000
+ seeAlso: ['assertion.assert-gt', 'assertion.assert-lte', 'assertion.assert-gte'],
9750
10001
  hideOperatorForm: true,
9751
10002
  },
9752
10003
  'assert-gte': {
9753
- category: 'assert',
10004
+ category: 'assertion',
9754
10005
  description: 'If $a is less than $b it throws `AssertionError`.',
9755
10006
  returns: {
9756
10007
  type: 'null',
@@ -9782,15 +10033,15 @@ const moduleDocs$6 = {
9782
10033
  },
9783
10034
  ],
9784
10035
  examples: [
9785
- 'let { assert-gte } = import(assert);\ntry assert-gte(0, 1, "Expected greater value") catch (e) e.message end',
9786
- 'let { assert-gte } = import(assert);\ntry assert-gte(0, 1) catch (e) e.message end',
9787
- 'let { assert-gte } = import(assert);\ntry assert-gte(1, 1) catch (e) e.message end',
10036
+ 'let { assert-gte } = import(assertion);\ntry assert-gte(0, 1, "Expected greater value") catch (e) e.message end',
10037
+ 'let { assert-gte } = import(assertion);\ntry assert-gte(0, 1) catch (e) e.message end',
10038
+ 'let { assert-gte } = import(assertion);\ntry assert-gte(1, 1) catch (e) e.message end',
9788
10039
  ],
9789
- seeAlso: ['assert.assert-lte', 'assert.assert-gt', 'assert.assert-lt'],
10040
+ seeAlso: ['assertion.assert-lte', 'assertion.assert-gt', 'assertion.assert-lt'],
9790
10041
  hideOperatorForm: true,
9791
10042
  },
9792
10043
  'assert-lte': {
9793
- category: 'assert',
10044
+ category: 'assertion',
9794
10045
  description: 'If $a is grater than $b it throws `AssertionError`.',
9795
10046
  returns: {
9796
10047
  type: 'null',
@@ -9822,15 +10073,15 @@ const moduleDocs$6 = {
9822
10073
  },
9823
10074
  ],
9824
10075
  examples: [
9825
- 'let { assert-lte } = import(assert);\ntry assert-lte(1, 0, "Expected smaller value value") catch (e) e.message end',
9826
- 'let { assert-lte } = import(assert);\ntry assert-lte(1, 0) catch (e) e.message end',
9827
- 'let { assert-lte } = import(assert);\ntry assert-lte(1, 1) catch (e) e.message end',
10076
+ 'let { assert-lte } = import(assertion);\ntry assert-lte(1, 0, "Expected smaller value value") catch (e) e.message end',
10077
+ 'let { assert-lte } = import(assertion);\ntry assert-lte(1, 0) catch (e) e.message end',
10078
+ 'let { assert-lte } = import(assertion);\ntry assert-lte(1, 1) catch (e) e.message end',
9828
10079
  ],
9829
- seeAlso: ['assert.assert-gte', 'assert.assert-lt', 'assert.assert-gt'],
10080
+ seeAlso: ['assertion.assert-gte', 'assertion.assert-lt', 'assertion.assert-gt'],
9830
10081
  hideOperatorForm: true,
9831
10082
  },
9832
10083
  'assert-true': {
9833
- category: 'assert',
10084
+ category: 'assertion',
9834
10085
  description: 'If $value is not `true` it throws `AssertionError`.',
9835
10086
  returns: {
9836
10087
  type: 'null',
@@ -9857,15 +10108,15 @@ const moduleDocs$6 = {
9857
10108
  },
9858
10109
  ],
9859
10110
  examples: [
9860
- 'let { assert-true } = import(assert);\ntry assert-true(false, "Expected true") catch (e) e.message end',
9861
- 'let { assert-true } = import(assert);\ntry assert-true(false) catch (e) e.message end',
9862
- 'let { assert-true } = import(assert);\ntry assert-true(true) catch (e) e.message end',
10111
+ 'let { assert-true } = import(assertion);\ntry assert-true(false, "Expected true") catch (e) e.message end',
10112
+ 'let { assert-true } = import(assertion);\ntry assert-true(false) catch (e) e.message end',
10113
+ 'let { assert-true } = import(assertion);\ntry assert-true(true) catch (e) e.message end',
9863
10114
  ],
9864
- seeAlso: ['assert.assert-false', 'assert.assert-truthy', 'assert.assert-falsy', 'assert.assert', 'assert.assert-boolean'],
10115
+ seeAlso: ['assertion.assert-false', 'assertion.assert-truthy', 'assertion.assert-falsy', 'assert', 'assertion.assert-boolean'],
9865
10116
  hideOperatorForm: true,
9866
10117
  },
9867
10118
  'assert-false': {
9868
- category: 'assert',
10119
+ category: 'assertion',
9869
10120
  description: 'If $value is not `false` it throws `AssertionError`.',
9870
10121
  returns: {
9871
10122
  type: 'null',
@@ -9892,15 +10143,15 @@ const moduleDocs$6 = {
9892
10143
  },
9893
10144
  ],
9894
10145
  examples: [
9895
- 'let { assert-false } = import(assert);\ntry assert-false(true, "Expected false") catch (e) e.message end',
9896
- 'let { assert-false } = import(assert);\ntry assert-false(true) catch (e) e.message end',
9897
- 'let { assert-false } = import(assert);\ntry assert-false(false) catch (e) e.message end',
10146
+ 'let { assert-false } = import(assertion);\ntry assert-false(true, "Expected false") catch (e) e.message end',
10147
+ 'let { assert-false } = import(assertion);\ntry assert-false(true) catch (e) e.message end',
10148
+ 'let { assert-false } = import(assertion);\ntry assert-false(false) catch (e) e.message end',
9898
10149
  ],
9899
- seeAlso: ['assert.assert-true', 'assert.assert-falsy', 'assert.assert-truthy', 'assert.assert-boolean'],
10150
+ seeAlso: ['assertion.assert-true', 'assertion.assert-falsy', 'assertion.assert-truthy', 'assertion.assert-boolean'],
9900
10151
  hideOperatorForm: true,
9901
10152
  },
9902
10153
  'assert-truthy': {
9903
- category: 'assert',
10154
+ category: 'assertion',
9904
10155
  description: 'If $value is not `truthy` it throws `AssertionError`.',
9905
10156
  returns: {
9906
10157
  type: 'null',
@@ -9927,22 +10178,22 @@ const moduleDocs$6 = {
9927
10178
  },
9928
10179
  ],
9929
10180
  examples: [
9930
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(false, "Expected truthy") catch (e) e.message end',
9931
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(false) catch (e) e.message end',
9932
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(0) catch (e) e.message end',
9933
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(null) catch (e) e.message end',
9934
- 'let { assert-truthy } = import(assert);\ntry assert-truthy("") catch (e) e.message end',
9935
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(true) catch (e) e.message end',
9936
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(1) catch (e) e.message end',
9937
- 'let { assert-truthy } = import(assert);\ntry assert-truthy("x") catch (e) e.message end',
9938
- 'let { assert-truthy } = import(assert);\ntry assert-truthy([]) catch (e) e.message end',
9939
- 'let { assert-truthy } = import(assert);\ntry assert-truthy(nd) catch (e) e.message end',
10181
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(false, "Expected truthy") catch (e) e.message end',
10182
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(false) catch (e) e.message end',
10183
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(0) catch (e) e.message end',
10184
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(null) catch (e) e.message end',
10185
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy("") catch (e) e.message end',
10186
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(true) catch (e) e.message end',
10187
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(1) catch (e) e.message end',
10188
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy("x") catch (e) e.message end',
10189
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy([]) catch (e) e.message end',
10190
+ 'let { assert-truthy } = import(assertion);\ntry assert-truthy(nd) catch (e) e.message end',
9940
10191
  ],
9941
- seeAlso: ['assert.assert-falsy', 'assert.assert-true', 'assert.assert-false', 'assert.assert', 'assert.assert-null'],
10192
+ seeAlso: ['assertion.assert-falsy', 'assertion.assert-true', 'assertion.assert-false', 'assert', 'assertion.assert-null'],
9942
10193
  hideOperatorForm: true,
9943
10194
  },
9944
10195
  'assert-falsy': {
9945
- category: 'assert',
10196
+ category: 'assertion',
9946
10197
  description: 'If $value is not `falsy` it throws `AssertionError`.',
9947
10198
  returns: {
9948
10199
  type: 'null',
@@ -9969,21 +10220,21 @@ const moduleDocs$6 = {
9969
10220
  },
9970
10221
  ],
9971
10222
  examples: [
9972
- 'let { assert-falsy } = import(assert);\ntry assert-falsy(true, "Expected falsy") catch (e) e.message end',
9973
- 'let { assert-falsy } = import(assert);\ntry assert-falsy("x") catch (e) e.message end',
9974
- 'let { assert-falsy } = import(assert);\ntry assert-falsy([]) catch (e) e.message end',
9975
- 'let { assert-falsy } = import(assert);\ntry assert-falsy(nd) catch (e) e.message end',
9976
- 'let { assert-falsy } = import(assert);\ntry assert-falsy(1) catch (e) e.message end',
9977
- 'let { assert-falsy } = import(assert);\ntry assert-falsy(false) catch (e) e.message end',
9978
- 'let { assert-falsy } = import(assert);\ntry assert-falsy(0) catch (e) e.message end',
9979
- 'let { assert-falsy } = import(assert);\ntry assert-falsy(null) catch (e) e.message end',
9980
- 'let { assert-falsy } = import(assert);\ntry assert-falsy("") catch (e) e.message end',
10223
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy(true, "Expected falsy") catch (e) e.message end',
10224
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy("x") catch (e) e.message end',
10225
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy([]) catch (e) e.message end',
10226
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy(nd) catch (e) e.message end',
10227
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy(1) catch (e) e.message end',
10228
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy(false) catch (e) e.message end',
10229
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy(0) catch (e) e.message end',
10230
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy(null) catch (e) e.message end',
10231
+ 'let { assert-falsy } = import(assertion);\ntry assert-falsy("") catch (e) e.message end',
9981
10232
  ],
9982
- seeAlso: ['assert.assert-truthy', 'assert.assert-false', 'assert.assert-true', 'assert.assert-null'],
10233
+ seeAlso: ['assertion.assert-truthy', 'assertion.assert-false', 'assertion.assert-true', 'assertion.assert-null'],
9983
10234
  hideOperatorForm: true,
9984
10235
  },
9985
10236
  'assert-null': {
9986
- category: 'assert',
10237
+ category: 'assertion',
9987
10238
  description: 'If $value is not `null` it throws `AssertionError`.',
9988
10239
  returns: {
9989
10240
  type: 'null',
@@ -10010,21 +10261,21 @@ const moduleDocs$6 = {
10010
10261
  },
10011
10262
  ],
10012
10263
  examples: [
10013
- 'let { assert-null } = import(assert);\ntry assert-null(null) catch (e) e.message end',
10014
- 'let { assert-null } = import(assert);\ntry assert-null(true, "Expected null") catch (e) e.message end',
10015
- 'let { assert-null } = import(assert);\ntry assert-null("x") catch (e) e.message end',
10016
- 'let { assert-null } = import(assert);\ntry assert-null([]) catch (e) e.message end',
10017
- 'let { assert-null } = import(assert);\ntry assert-null(nd) catch (e) e.message end',
10018
- 'let { assert-null } = import(assert);\ntry assert-null(1) catch (e) e.message end',
10019
- 'let { assert-null } = import(assert);\ntry assert-null(false) catch (e) e.message end',
10020
- 'let { assert-null } = import(assert);\ntry assert-null(0) catch (e) e.message end',
10021
- 'let { assert-null } = import(assert);\ntry assert-null("") catch (e) e.message end',
10264
+ 'let { assert-null } = import(assertion);\ntry assert-null(null) catch (e) e.message end',
10265
+ 'let { assert-null } = import(assertion);\ntry assert-null(true, "Expected null") catch (e) e.message end',
10266
+ 'let { assert-null } = import(assertion);\ntry assert-null("x") catch (e) e.message end',
10267
+ 'let { assert-null } = import(assertion);\ntry assert-null([]) catch (e) e.message end',
10268
+ 'let { assert-null } = import(assertion);\ntry assert-null(nd) catch (e) e.message end',
10269
+ 'let { assert-null } = import(assertion);\ntry assert-null(1) catch (e) e.message end',
10270
+ 'let { assert-null } = import(assertion);\ntry assert-null(false) catch (e) e.message end',
10271
+ 'let { assert-null } = import(assertion);\ntry assert-null(0) catch (e) e.message end',
10272
+ 'let { assert-null } = import(assertion);\ntry assert-null("") catch (e) e.message end',
10022
10273
  ],
10023
- seeAlso: ['assert.assert-truthy', 'assert.assert-falsy'],
10274
+ seeAlso: ['assertion.assert-truthy', 'assertion.assert-falsy'],
10024
10275
  hideOperatorForm: true,
10025
10276
  },
10026
10277
  'assert-throws': {
10027
- category: 'assert',
10278
+ category: 'assertion',
10028
10279
  description: 'If $fun does not throw, it throws `AssertionError`.',
10029
10280
  returns: {
10030
10281
  type: 'null',
@@ -10051,14 +10302,14 @@ const moduleDocs$6 = {
10051
10302
  },
10052
10303
  ],
10053
10304
  examples: [
10054
- 'let { assert-throws } = import(assert);\nassert-throws(-> throw("Error"))',
10055
- 'let { assert-throws } = import(assert);\ntry assert-throws(-> identity("Error")) catch (e) e.message end',
10305
+ 'let { assert-throws } = import(assertion);\nassert-throws(-> throw("Error"))',
10306
+ 'let { assert-throws } = import(assertion);\ntry assert-throws(-> identity("Error")) catch (e) e.message end',
10056
10307
  ],
10057
- seeAlso: ['assert.assert-throws-error', 'assert.assert-not-throws'],
10308
+ seeAlso: ['assertion.assert-throws-error', 'assertion.assert-not-throws'],
10058
10309
  hideOperatorForm: true,
10059
10310
  },
10060
10311
  'assert-throws-error': {
10061
- category: 'assert',
10312
+ category: 'assertion',
10062
10313
  description: 'If $fun does not throw $error-message, it throws `AssertionError`.',
10063
10314
  returns: {
10064
10315
  type: 'null',
@@ -10090,14 +10341,14 @@ const moduleDocs$6 = {
10090
10341
  },
10091
10342
  ],
10092
10343
  examples: [
10093
- 'let { assert-throws-error } = import(assert);\ntry assert-throws-error(-> throw("Error"), "Error") catch (e) e.message end',
10094
- 'let { assert-throws-error } = import(assert);\ntry assert-throws-error(-> identity("Error"), "Error") catch (e) e.message end',
10344
+ 'let { assert-throws-error } = import(assertion);\ntry assert-throws-error(-> throw("Error"), "Error") catch (e) e.message end',
10345
+ 'let { assert-throws-error } = import(assertion);\ntry assert-throws-error(-> identity("Error"), "Error") catch (e) e.message end',
10095
10346
  ],
10096
- seeAlso: ['assert.assert-throws', 'assert.assert-not-throws'],
10347
+ seeAlso: ['assertion.assert-throws', 'assertion.assert-not-throws'],
10097
10348
  hideOperatorForm: true,
10098
10349
  },
10099
10350
  'assert-not-throws': {
10100
- category: 'assert',
10351
+ category: 'assertion',
10101
10352
  description: 'If $fun throws, it throws `AssertionError`.',
10102
10353
  returns: {
10103
10354
  type: 'null',
@@ -10124,14 +10375,14 @@ const moduleDocs$6 = {
10124
10375
  },
10125
10376
  ],
10126
10377
  examples: [
10127
- 'let { assert-not-throws } = import(assert);\ntry assert-not-throws(-> identity("Error")) catch (e) e.message end',
10128
- 'let { assert-not-throws } = import(assert);\ntry assert-not-throws(-> throw("Error")) catch (e) e.message end',
10378
+ 'let { assert-not-throws } = import(assertion);\ntry assert-not-throws(-> identity("Error")) catch (e) e.message end',
10379
+ 'let { assert-not-throws } = import(assertion);\ntry assert-not-throws(-> throw("Error")) catch (e) e.message end',
10129
10380
  ],
10130
- seeAlso: ['assert.assert-throws', 'assert.assert-throws-error'],
10381
+ seeAlso: ['assertion.assert-throws', 'assertion.assert-throws-error'],
10131
10382
  hideOperatorForm: true,
10132
10383
  },
10133
10384
  'assert-array': {
10134
- category: 'assert',
10385
+ category: 'assertion',
10135
10386
  description: 'If $value is not an `array` it throws `AssertionError`.',
10136
10387
  returns: {
10137
10388
  type: 'null',
@@ -10158,15 +10409,15 @@ const moduleDocs$6 = {
10158
10409
  },
10159
10410
  ],
10160
10411
  examples: [
10161
- 'let { assert-array } = import(assert);\ntry assert-array([1, 2, 3]) catch (e) e.message end',
10162
- 'let { assert-array } = import(assert);\ntry assert-array("string") catch (e) e.message end',
10163
- 'let { assert-array } = import(assert);\ntry assert-array(42, "Expected an array") catch (e) e.message end',
10412
+ 'let { assert-array } = import(assertion);\ntry assert-array([1, 2, 3]) catch (e) e.message end',
10413
+ 'let { assert-array } = import(assertion);\ntry assert-array("string") catch (e) e.message end',
10414
+ 'let { assert-array } = import(assertion);\ntry assert-array(42, "Expected an array") catch (e) e.message end',
10164
10415
  ],
10165
- seeAlso: ['assert.assert-object', 'assert.assert-collection', 'assert.assert-sequence'],
10416
+ seeAlso: ['assertion.assert-object', 'assertion.assert-collection', 'assertion.assert-sequence'],
10166
10417
  hideOperatorForm: true,
10167
10418
  },
10168
10419
  'assert-boolean': {
10169
- category: 'assert',
10420
+ category: 'assertion',
10170
10421
  description: 'If $value is not a `boolean` it throws `AssertionError`.',
10171
10422
  returns: {
10172
10423
  type: 'null',
@@ -10193,15 +10444,15 @@ const moduleDocs$6 = {
10193
10444
  },
10194
10445
  ],
10195
10446
  examples: [
10196
- 'let { assert-boolean } = import(assert);\ntry assert-boolean(true) catch (e) e.message end',
10197
- 'let { assert-boolean } = import(assert);\ntry assert-boolean(false) catch (e) e.message end',
10198
- 'let { assert-boolean } = import(assert);\ntry assert-boolean(1, "Expected a boolean") catch (e) e.message end',
10447
+ 'let { assert-boolean } = import(assertion);\ntry assert-boolean(true) catch (e) e.message end',
10448
+ 'let { assert-boolean } = import(assertion);\ntry assert-boolean(false) catch (e) e.message end',
10449
+ 'let { assert-boolean } = import(assertion);\ntry assert-boolean(1, "Expected a boolean") catch (e) e.message end',
10199
10450
  ],
10200
- seeAlso: ['assert.assert-true', 'assert.assert-false', 'assert.assert-number', 'assert.assert-string'],
10451
+ seeAlso: ['assertion.assert-true', 'assertion.assert-false', 'assertion.assert-number', 'assertion.assert-string'],
10201
10452
  hideOperatorForm: true,
10202
10453
  },
10203
10454
  'assert-collection': {
10204
- category: 'assert',
10455
+ category: 'assertion',
10205
10456
  description: 'If $value is not a `collection` (array, object, or string) it throws `AssertionError`.',
10206
10457
  returns: {
10207
10458
  type: 'null',
@@ -10228,16 +10479,16 @@ const moduleDocs$6 = {
10228
10479
  },
10229
10480
  ],
10230
10481
  examples: [
10231
- 'let { assert-collection } = import(assert);\ntry assert-collection([1, 2]) catch (e) e.message end',
10232
- 'let { assert-collection } = import(assert);\ntry assert-collection({ a: 1 }) catch (e) e.message end',
10233
- 'let { assert-collection } = import(assert);\ntry assert-collection("hello") catch (e) e.message end',
10234
- 'let { assert-collection } = import(assert);\ntry assert-collection(42, "Expected a collection") catch (e) e.message end',
10482
+ 'let { assert-collection } = import(assertion);\ntry assert-collection([1, 2]) catch (e) e.message end',
10483
+ 'let { assert-collection } = import(assertion);\ntry assert-collection({ a: 1 }) catch (e) e.message end',
10484
+ 'let { assert-collection } = import(assertion);\ntry assert-collection("hello") catch (e) e.message end',
10485
+ 'let { assert-collection } = import(assertion);\ntry assert-collection(42, "Expected a collection") catch (e) e.message end',
10235
10486
  ],
10236
- seeAlso: ['assert.assert-sequence', 'assert.assert-array', 'assert.assert-object'],
10487
+ seeAlso: ['assertion.assert-sequence', 'assertion.assert-array', 'assertion.assert-object'],
10237
10488
  hideOperatorForm: true,
10238
10489
  },
10239
10490
  'assert-function': {
10240
- category: 'assert',
10491
+ category: 'assertion',
10241
10492
  description: 'If $value is not a `function` it throws `AssertionError`.',
10242
10493
  returns: {
10243
10494
  type: 'null',
@@ -10264,14 +10515,14 @@ const moduleDocs$6 = {
10264
10515
  },
10265
10516
  ],
10266
10517
  examples: [
10267
- 'let { assert-function } = import(assert);\ntry assert-function(-> $ + 1) catch (e) e.message end',
10268
- 'let { assert-function } = import(assert);\ntry assert-function(42, "Expected a function") catch (e) e.message end',
10518
+ 'let { assert-function } = import(assertion);\ntry assert-function(-> $ + 1) catch (e) e.message end',
10519
+ 'let { assert-function } = import(assertion);\ntry assert-function(42, "Expected a function") catch (e) e.message end',
10269
10520
  ],
10270
- seeAlso: ['assert.assert-number', 'assert.assert-string'],
10521
+ seeAlso: ['assertion.assert-number', 'assertion.assert-string'],
10271
10522
  hideOperatorForm: true,
10272
10523
  },
10273
10524
  'assert-grid': {
10274
- category: 'assert',
10525
+ category: 'assertion',
10275
10526
  description: 'If $value is not a `grid` it throws `AssertionError`.',
10276
10527
  returns: {
10277
10528
  type: 'null',
@@ -10298,14 +10549,14 @@ const moduleDocs$6 = {
10298
10549
  },
10299
10550
  ],
10300
10551
  examples: [
10301
- 'let { assert-grid } = import(assert);\ntry assert-grid([[1, 2], [3, 4]]) catch (e) e.message end',
10302
- 'let { assert-grid } = import(assert);\ntry assert-grid([1, 2], "Expected a grid") catch (e) e.message end',
10552
+ 'let { assert-grid } = import(assertion);\ntry assert-grid([[1, 2], [3, 4]]) catch (e) e.message end',
10553
+ 'let { assert-grid } = import(assertion);\ntry assert-grid([1, 2], "Expected a grid") catch (e) e.message end',
10303
10554
  ],
10304
- seeAlso: ['assert.assert-matrix', 'assert.assert-vector'],
10555
+ seeAlso: ['assertion.assert-matrix', 'assertion.assert-vector'],
10305
10556
  hideOperatorForm: true,
10306
10557
  },
10307
10558
  'assert-integer': {
10308
- category: 'assert',
10559
+ category: 'assertion',
10309
10560
  description: 'If $value is not an `integer` it throws `AssertionError`.',
10310
10561
  returns: {
10311
10562
  type: 'null',
@@ -10332,14 +10583,14 @@ const moduleDocs$6 = {
10332
10583
  },
10333
10584
  ],
10334
10585
  examples: [
10335
- 'let { assert-integer } = import(assert);\ntry assert-integer(42) catch (e) e.message end',
10336
- 'let { assert-integer } = import(assert);\ntry assert-integer(3.14, "Expected an integer") catch (e) e.message end',
10586
+ 'let { assert-integer } = import(assertion);\ntry assert-integer(42) catch (e) e.message end',
10587
+ 'let { assert-integer } = import(assertion);\ntry assert-integer(3.14, "Expected an integer") catch (e) e.message end',
10337
10588
  ],
10338
- seeAlso: ['assert.assert-number'],
10589
+ seeAlso: ['assertion.assert-number'],
10339
10590
  hideOperatorForm: true,
10340
10591
  },
10341
10592
  'assert-matrix': {
10342
- category: 'assert',
10593
+ category: 'assertion',
10343
10594
  description: 'If $value is not a `matrix` it throws `AssertionError`.',
10344
10595
  returns: {
10345
10596
  type: 'null',
@@ -10366,14 +10617,14 @@ const moduleDocs$6 = {
10366
10617
  },
10367
10618
  ],
10368
10619
  examples: [
10369
- 'let { assert-matrix } = import(assert);\ntry assert-matrix([[1, 2], [3, 4]]) catch (e) e.message end',
10370
- 'let { assert-matrix } = import(assert);\ntry assert-matrix([1, 2], "Expected a matrix") catch (e) e.message end',
10620
+ 'let { assert-matrix } = import(assertion);\ntry assert-matrix([[1, 2], [3, 4]]) catch (e) e.message end',
10621
+ 'let { assert-matrix } = import(assertion);\ntry assert-matrix([1, 2], "Expected a matrix") catch (e) e.message end',
10371
10622
  ],
10372
- seeAlso: ['assert.assert-vector', 'assert.assert-grid'],
10623
+ seeAlso: ['assertion.assert-vector', 'assertion.assert-grid'],
10373
10624
  hideOperatorForm: true,
10374
10625
  },
10375
10626
  'assert-number': {
10376
- category: 'assert',
10627
+ category: 'assertion',
10377
10628
  description: 'If $value is not a `number` it throws `AssertionError`.',
10378
10629
  returns: {
10379
10630
  type: 'null',
@@ -10400,14 +10651,14 @@ const moduleDocs$6 = {
10400
10651
  },
10401
10652
  ],
10402
10653
  examples: [
10403
- 'let { assert-number } = import(assert);\ntry assert-number(42) catch (e) e.message end',
10404
- 'let { assert-number } = import(assert);\ntry assert-number("hello", "Expected a number") catch (e) e.message end',
10654
+ 'let { assert-number } = import(assertion);\ntry assert-number(42) catch (e) e.message end',
10655
+ 'let { assert-number } = import(assertion);\ntry assert-number("hello", "Expected a number") catch (e) e.message end',
10405
10656
  ],
10406
- seeAlso: ['assert.assert-integer', 'assert.assert-boolean', 'assert.assert-string', 'assert.assert-function'],
10657
+ seeAlso: ['assertion.assert-integer', 'assertion.assert-boolean', 'assertion.assert-string', 'assertion.assert-function'],
10407
10658
  hideOperatorForm: true,
10408
10659
  },
10409
10660
  'assert-object': {
10410
- category: 'assert',
10661
+ category: 'assertion',
10411
10662
  description: 'If $value is not an `object` it throws `AssertionError`.',
10412
10663
  returns: {
10413
10664
  type: 'null',
@@ -10434,14 +10685,14 @@ const moduleDocs$6 = {
10434
10685
  },
10435
10686
  ],
10436
10687
  examples: [
10437
- 'let { assert-object } = import(assert);\ntry assert-object({ a: 1 }) catch (e) e.message end',
10438
- 'let { assert-object } = import(assert);\ntry assert-object([1, 2], "Expected an object") catch (e) e.message end',
10688
+ 'let { assert-object } = import(assertion);\ntry assert-object({ a: 1 }) catch (e) e.message end',
10689
+ 'let { assert-object } = import(assertion);\ntry assert-object([1, 2], "Expected an object") catch (e) e.message end',
10439
10690
  ],
10440
- seeAlso: ['assert.assert-array', 'assert.assert-collection'],
10691
+ seeAlso: ['assertion.assert-array', 'assertion.assert-collection'],
10441
10692
  hideOperatorForm: true,
10442
10693
  },
10443
10694
  'assert-regexp': {
10444
- category: 'assert',
10695
+ category: 'assertion',
10445
10696
  description: 'If $value is not a `regexp` it throws `AssertionError`.',
10446
10697
  returns: {
10447
10698
  type: 'null',
@@ -10468,14 +10719,14 @@ const moduleDocs$6 = {
10468
10719
  },
10469
10720
  ],
10470
10721
  examples: [
10471
- 'let { assert-regexp } = import(assert);\ntry assert-regexp(#"^start") catch (e) e.message end',
10472
- 'let { assert-regexp } = import(assert);\ntry assert-regexp("hello", "Expected a regexp") catch (e) e.message end',
10722
+ 'let { assert-regexp } = import(assertion);\ntry assert-regexp(#"^start") catch (e) e.message end',
10723
+ 'let { assert-regexp } = import(assertion);\ntry assert-regexp("hello", "Expected a regexp") catch (e) e.message end',
10473
10724
  ],
10474
- seeAlso: ['assert.assert-string'],
10725
+ seeAlso: ['assertion.assert-string'],
10475
10726
  hideOperatorForm: true,
10476
10727
  },
10477
10728
  'assert-sequence': {
10478
- category: 'assert',
10729
+ category: 'assertion',
10479
10730
  description: 'If $value is not a `sequence` (array or string) it throws `AssertionError`.',
10480
10731
  returns: {
10481
10732
  type: 'null',
@@ -10502,15 +10753,15 @@ const moduleDocs$6 = {
10502
10753
  },
10503
10754
  ],
10504
10755
  examples: [
10505
- 'let { assert-sequence } = import(assert);\ntry assert-sequence([1, 2]) catch (e) e.message end',
10506
- 'let { assert-sequence } = import(assert);\ntry assert-sequence("hello") catch (e) e.message end',
10507
- 'let { assert-sequence } = import(assert);\ntry assert-sequence({ a: 1 }, "Expected a sequence") catch (e) e.message end',
10756
+ 'let { assert-sequence } = import(assertion);\ntry assert-sequence([1, 2]) catch (e) e.message end',
10757
+ 'let { assert-sequence } = import(assertion);\ntry assert-sequence("hello") catch (e) e.message end',
10758
+ 'let { assert-sequence } = import(assertion);\ntry assert-sequence({ a: 1 }, "Expected a sequence") catch (e) e.message end',
10508
10759
  ],
10509
- seeAlso: ['assert.assert-collection', 'assert.assert-array'],
10760
+ seeAlso: ['assertion.assert-collection', 'assertion.assert-array'],
10510
10761
  hideOperatorForm: true,
10511
10762
  },
10512
10763
  'assert-string': {
10513
- category: 'assert',
10764
+ category: 'assertion',
10514
10765
  description: 'If $value is not a `string` it throws `AssertionError`.',
10515
10766
  returns: {
10516
10767
  type: 'null',
@@ -10537,14 +10788,14 @@ const moduleDocs$6 = {
10537
10788
  },
10538
10789
  ],
10539
10790
  examples: [
10540
- 'let { assert-string } = import(assert);\ntry assert-string("hello") catch (e) e.message end',
10541
- 'let { assert-string } = import(assert);\ntry assert-string(42, "Expected a string") catch (e) e.message end',
10791
+ 'let { assert-string } = import(assertion);\ntry assert-string("hello") catch (e) e.message end',
10792
+ 'let { assert-string } = import(assertion);\ntry assert-string(42, "Expected a string") catch (e) e.message end',
10542
10793
  ],
10543
- seeAlso: ['assert.assert-number', 'assert.assert-boolean', 'assert.assert-regexp', 'assert.assert-function'],
10794
+ seeAlso: ['assertion.assert-number', 'assertion.assert-boolean', 'assertion.assert-regexp', 'assertion.assert-function'],
10544
10795
  hideOperatorForm: true,
10545
10796
  },
10546
10797
  'assert-vector': {
10547
- category: 'assert',
10798
+ category: 'assertion',
10548
10799
  description: 'If $value is not a `vector` it throws `AssertionError`.',
10549
10800
  returns: {
10550
10801
  type: 'null',
@@ -10571,26 +10822,15 @@ const moduleDocs$6 = {
10571
10822
  },
10572
10823
  ],
10573
10824
  examples: [
10574
- 'let { assert-vector } = import(assert);\ntry assert-vector([1, 2, 3]) catch (e) e.message end',
10575
- 'let { assert-vector } = import(assert);\ntry assert-vector(["a", "b"], "Expected a vector") catch (e) e.message end',
10825
+ 'let { assert-vector } = import(assertion);\ntry assert-vector([1, 2, 3]) catch (e) e.message end',
10826
+ 'let { assert-vector } = import(assertion);\ntry assert-vector(["a", "b"], "Expected a vector") catch (e) e.message end',
10576
10827
  ],
10577
- seeAlso: ['assert.assert-matrix', 'assert.assert-grid'],
10828
+ seeAlso: ['assertion.assert-matrix', 'assertion.assert-grid'],
10578
10829
  hideOperatorForm: true,
10579
10830
  },
10580
10831
  };
10581
10832
 
10582
10833
  const assertNormalExpression = {
10583
- 'assert': {
10584
- evaluate: (params, sourceCodeInfo) => {
10585
- const value = params[0];
10586
- const message = params.length === 2 ? params[1] : `${value}`;
10587
- assertString(message, sourceCodeInfo);
10588
- if (!value)
10589
- throw new AssertionError(message, sourceCodeInfo);
10590
- return asAny(value, sourceCodeInfo);
10591
- },
10592
- arity: { min: 1, max: 2 },
10593
- },
10594
10834
  'assert=': {
10595
10835
  evaluate: ([first, second, message], sourceCodeInfo) => {
10596
10836
  if (message !== undefined) {
@@ -10968,7 +11208,7 @@ for (const [key, docs] of Object.entries(moduleDocs$6)) {
10968
11208
  assertNormalExpression[key].docs = docs;
10969
11209
  }
10970
11210
  const assertModule = {
10971
- name: 'assert',
11211
+ name: 'assertion',
10972
11212
  functions: assertNormalExpression,
10973
11213
  };
10974
11214
 
@@ -32733,7 +32973,7 @@ const shorthand = {
32733
32973
  '#"^\\s*(.*)$"',
32734
32974
  '#"albert"ig',
32735
32975
  ],
32736
- seeAlso: ['regexp', 'match', 'replace', 'replace-all'],
32976
+ seeAlso: ['regexp', 're-match', 'replace', 'replace-all'],
32737
32977
  },
32738
32978
  '-short-fn': {
32739
32979
  shorthand: true,
@@ -32799,6 +33039,7 @@ function moduledDocsToReference(moduleName, expressions) {
32799
33039
  return result;
32800
33040
  }
32801
33041
  // Derive all core category references from co-located docs
33042
+ const assertionRef = docsToReference(assertionNormalExpression);
32802
33043
  const bitwiseReference = docsToReference(bitwiseNormalExpression);
32803
33044
  const arrayRef = docsToReference(arrayNormalExpression);
32804
33045
  const collectionRef = docsToReference(collectionNormalExpression);
@@ -32856,6 +33097,7 @@ function isFunctionReference(ref) {
32856
33097
  }
32857
33098
  const normalExpressionReference = {
32858
33099
  // Core categories — all derived from co-located docs
33100
+ ...assertionRef,
32859
33101
  ...bitwiseReference,
32860
33102
  ...collectionRef,
32861
33103
  ...arrayRef,
@@ -33570,7 +33812,7 @@ const api = {
33570
33812
  ],
33571
33813
  regularExpression: [
33572
33814
  'regexp',
33573
- 'match',
33815
+ 're-match',
33574
33816
  'replace',
33575
33817
  'replace-all',
33576
33818
  ],
@@ -33616,35 +33858,37 @@ const api = {
33616
33858
  'bitwise.bit-set',
33617
33859
  'bitwise.bit-test',
33618
33860
  ],
33619
- assert: [
33620
- 'assert.assert',
33621
- 'assert.assert=',
33622
- 'assert.assert!=',
33623
- 'assert.assert-gt',
33624
- 'assert.assert-lt',
33625
- 'assert.assert-gte',
33626
- 'assert.assert-lte',
33627
- 'assert.assert-true',
33628
- 'assert.assert-false',
33629
- 'assert.assert-truthy',
33630
- 'assert.assert-falsy',
33631
- 'assert.assert-null',
33632
- 'assert.assert-throws',
33633
- 'assert.assert-throws-error',
33634
- 'assert.assert-not-throws',
33635
- 'assert.assert-array',
33636
- 'assert.assert-boolean',
33637
- 'assert.assert-collection',
33638
- 'assert.assert-function',
33639
- 'assert.assert-grid',
33640
- 'assert.assert-integer',
33641
- 'assert.assert-matrix',
33642
- 'assert.assert-number',
33643
- 'assert.assert-object',
33644
- 'assert.assert-regexp',
33645
- 'assert.assert-sequence',
33646
- 'assert.assert-string',
33647
- 'assert.assert-vector',
33861
+ assertion: [
33862
+ 'assert',
33863
+ ],
33864
+ assertionUtils: [
33865
+ 'assertion.assert=',
33866
+ 'assertion.assert!=',
33867
+ 'assertion.assert-gt',
33868
+ 'assertion.assert-lt',
33869
+ 'assertion.assert-gte',
33870
+ 'assertion.assert-lte',
33871
+ 'assertion.assert-true',
33872
+ 'assertion.assert-false',
33873
+ 'assertion.assert-truthy',
33874
+ 'assertion.assert-falsy',
33875
+ 'assertion.assert-null',
33876
+ 'assertion.assert-throws',
33877
+ 'assertion.assert-throws-error',
33878
+ 'assertion.assert-not-throws',
33879
+ 'assertion.assert-array',
33880
+ 'assertion.assert-boolean',
33881
+ 'assertion.assert-collection',
33882
+ 'assertion.assert-function',
33883
+ 'assertion.assert-grid',
33884
+ 'assertion.assert-integer',
33885
+ 'assertion.assert-matrix',
33886
+ 'assertion.assert-number',
33887
+ 'assertion.assert-object',
33888
+ 'assertion.assert-regexp',
33889
+ 'assertion.assert-sequence',
33890
+ 'assertion.assert-string',
33891
+ 'assertion.assert-vector',
33648
33892
  ],
33649
33893
  grid: [
33650
33894
  'grid.cell-every?',
@@ -34475,6 +34719,7 @@ const coreApiFunctionNames = [
34475
34719
  ...api.string,
34476
34720
  ...api.bitwise,
34477
34721
  ...api.vector,
34722
+ ...api.assertion,
34478
34723
  ];
34479
34724
  // Core API names (core functions + shorthand + datatype)
34480
34725
  const coreApiNames = [