coconut-develop 3.1.0.post0.dev7__tar.gz → 3.1.0.post0.dev9__tar.gz

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 (89) hide show
  1. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/DOCS.md +82 -26
  2. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/HELP.md +1 -1
  3. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/PKG-INFO +2 -2
  4. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/__coconut__/__init__.pyi +30 -24
  5. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/__coconut__.pyi +1 -1
  6. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/compiler.py +21 -16
  7. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/grammar.py +5 -1
  8. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/header.py +16 -1
  9. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/templates/header.py_template +6 -8
  10. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/constants.py +7 -2
  11. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/root.py +1 -1
  12. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/main_test.py +3 -1
  13. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/primary_2.coco +1 -0
  14. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/suite.coco +8 -4
  15. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/util.coco +26 -0
  16. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/extras.coco +5 -2
  17. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/CONTRIBUTING.md +0 -0
  18. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/FAQ.md +0 -0
  19. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/LICENSE.txt +0 -0
  20. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/MANIFEST.in +0 -0
  21. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/README.rst +0 -0
  22. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/__coconut__/__init__.py +0 -0
  23. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/__coconut__/py.typed +0 -0
  24. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/_coconut/__init__.py +0 -0
  25. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/_coconut/__init__.pyi +0 -0
  26. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/_coconut/py.typed +0 -0
  27. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/__coconut__.py +0 -0
  28. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/__init__.py +0 -0
  29. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/__init__.pyi +0 -0
  30. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/__main__.py +0 -0
  31. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/_pyparsing.py +0 -0
  32. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/api.py +0 -0
  33. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/api.pyi +0 -0
  34. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/__init__.py +0 -0
  35. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/__init__.pyi +0 -0
  36. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/cli.py +0 -0
  37. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/command.py +0 -0
  38. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/command.pyi +0 -0
  39. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/mypy.py +0 -0
  40. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/resources/zcoconut.pth +0 -0
  41. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/util.py +0 -0
  42. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/command/watch.py +0 -0
  43. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/__init__.py +0 -0
  44. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/matching.py +0 -0
  45. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/compiler/util.py +0 -0
  46. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/convenience.py +0 -0
  47. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/convenience.pyi +0 -0
  48. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/exceptions.py +0 -0
  49. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/highlighter.py +0 -0
  50. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/__init__.py +0 -0
  51. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/__main__.py +0 -0
  52. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/coconut/kernel.json +0 -0
  53. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/coconut_py/kernel.json +0 -0
  54. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/coconut_py2/kernel.json +0 -0
  55. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/coconut_py3/kernel.json +0 -0
  56. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/embed.py +0 -0
  57. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/icoconut/root.py +0 -0
  58. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/integrations.py +0 -0
  59. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/main.py +0 -0
  60. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/py.typed +0 -0
  61. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/requirements.py +0 -0
  62. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/terminal.py +0 -0
  63. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/__init__.py +0 -0
  64. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/__main__.py +0 -0
  65. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/constants_test.py +0 -0
  66. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/__init__.coco +0 -0
  67. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/__main__.coco +0 -0
  68. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/main.coco +0 -0
  69. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/primary_1.coco +0 -0
  70. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/specific.coco +0 -0
  71. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/agnostic/tutorial.coco +0 -0
  72. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/non_strict/non_strict_test.coco +0 -0
  73. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_2/py2_test.coco +0 -0
  74. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_3/py3_test.coco +0 -0
  75. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_311/py311_test.coco +0 -0
  76. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_35/py35_test.coco +0 -0
  77. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_36/py36_test.coco +0 -0
  78. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_38/py38_test.coco +0 -0
  79. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/cocotest/target_sys/target_sys_test.coco +0 -0
  80. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/importable.coco +0 -0
  81. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/runnable.coco +0 -0
  82. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/tests/src/runner.coco +0 -0
  83. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut/util.py +0 -0
  84. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/coconut_develop.egg-info/SOURCES.txt +0 -0
  85. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/conf.py +0 -0
  86. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/pyproject.toml +0 -0
  87. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/setup.cfg +0 -0
  88. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/setup.py +0 -0
  89. {coconut-develop-3.1.0.post0.dev7 → coconut-develop-3.1.0.post0.dev9}/xontrib/coconut.py +0 -0
@@ -1320,11 +1320,10 @@ data Empty() from Tree
1320
1320
  data Leaf(n) from Tree
1321
1321
  data Node(l, r) from Tree
1322
1322
 
1323
- def depth(Tree()) = 0
1324
-
1325
- addpattern def depth(Tree(n)) = 1
1326
-
1327
- addpattern def depth(Tree(l, r)) = 1 + max([depth(l), depth(r)])
1323
+ case def depth:
1324
+ match(Tree()) = 0
1325
+ match(Tree(n)) = 1
1326
+ match(Tree(l, r)) = 1 + max(depth(l), depth(r))
1328
1327
 
1329
1328
  Empty() |> depth |> print
1330
1329
  Leaf(5) |> depth |> print
@@ -1340,26 +1339,26 @@ def duplicate_first([x] + xs as l) =
1340
1339
  ```
1341
1340
  _Showcases head-tail splitting, one of the most common uses of pattern-matching, where a `+ <var>` (or `:: <var>` for any iterable) at the end of a list or tuple literal can be used to match the rest of the sequence._
1342
1341
 
1343
- ```
1344
- def sieve([head] :: tail) =
1345
- [head] :: sieve(n for n in tail if n % head)
1346
-
1347
- addpattern def sieve((||)) = []
1342
+ ```coconut
1343
+ case def sieve:
1344
+ match([head] :: tail) =
1345
+ [head] :: sieve(n for n in tail if n % head)
1346
+ match((||)) = []
1348
1347
  ```
1349
1348
  _Showcases how to match against iterators, namely that the empty iterator case (`(||)`) must come last, otherwise that case will exhaust the whole iterator before any other pattern has a chance to match against it._
1350
1349
 
1351
- ```
1350
+ ```coconut
1352
1351
  def odd_primes(p=3) =
1353
1352
  (p,) :: filter(=> _ % p != 0, odd_primes(p + 2))
1354
1353
 
1355
1354
  def primes() =
1356
1355
  (2,) :: odd_primes()
1357
1356
 
1358
- def twin_primes(_ :: [p, (.-2) -> p] :: ps) =
1359
- [(p, p+2)] :: twin_primes([p + 2] :: ps)
1360
-
1361
- addpattern def twin_primes() = # type: ignore
1362
- twin_primes(primes())
1357
+ case def twin_primes:
1358
+ match(_ :: [p, (.-2) -> p] :: ps) =
1359
+ [(p, p+2)] :: twin_primes([p + 2] :: ps)
1360
+ match() =
1361
+ twin_primes(primes())
1363
1362
 
1364
1363
  twin_primes()$[:5] |> list |> print
1365
1364
  ```
@@ -1522,15 +1521,14 @@ data Empty()
1522
1521
  data Leaf(n)
1523
1522
  data Node(l, r)
1524
1523
 
1525
- def size(Empty()) = 0
1526
-
1527
- addpattern def size(Leaf(n)) = 1
1528
-
1529
- addpattern def size(Node(l, r)) = size(l) + size(r)
1524
+ case def size:
1525
+ match(Empty()) = 0
1526
+ match(Leaf(n)) = 1
1527
+ match(Node(l, r)) = size(l) + size(r)
1530
1528
 
1531
1529
  size(Node(Empty(), Leaf(10))) == 1
1532
1530
  ```
1533
- _Showcases the algebraic nature of `data` types when combined with pattern-matching._
1531
+ _Showcases the use of pattern-matching to deconstruct `data` types._
1534
1532
 
1535
1533
  ```coconut
1536
1534
  data vector(*pts):
@@ -2523,6 +2521,58 @@ range(5) |> last_two |> print
2523
2521
  _Can't be done without a long series of checks at the top of the function. See the compiled code for the Python syntax._
2524
2522
 
2525
2523
 
2524
+ ### `case` Functions
2525
+
2526
+ For easily defining a pattern-matching function with many different cases, Coconut provides the `case def` syntax based on Coconut's [`case`](#case) syntax. The basic syntax is
2527
+ ```
2528
+ case def <name>:
2529
+ match(<arg>, <arg>, ... [if <cond>]):
2530
+ <body>
2531
+ match(<arg>, <arg>, ... [if <cond>]):
2532
+ <body>
2533
+ ...
2534
+ ```
2535
+ where the patterns in each `match` are checked in sequence until a match is found and the body under that match is executed, or a [`MatchError`](#matcherror) is raised. Each `match(...)` statement is effectively treated as a separate pattern-matching function signature that is checked independently, as if they had each been defined separately and then combined with [`addpattern`](#addpattern).
2536
+
2537
+ Any individual body can also be defined with [assignment function syntax](#assignment-functions) such that
2538
+ ```
2539
+ case def <name>:
2540
+ match(<arg>, <arg>, ... [if <cond>]) = <body>
2541
+ ```
2542
+ is equivalent to
2543
+ ```
2544
+ case def <name>:
2545
+ match(<arg>, <arg>, ... [if <cond>]): return <body>
2546
+ ```
2547
+
2548
+ `case` function definition can also be combined with `async` functions, [`copyclosure` functions](#copyclosure-functions), and [`yield` functions](#explicit-generators). The various keywords in front of the `def` can be put in any order.
2549
+
2550
+ `case def` also allows for easily providing type annotations for pattern-matching functions. To add type annotations, inside the body of the `case def`, instead of just `match(...)` statements, include some `type(...)` statements as well, which will compile into [`typing.overload`](https://docs.python.org/3/library/typing.html#overload) declarations. The syntax is
2551
+ ```
2552
+ case def <name>[<type vars>]:
2553
+ type(<arg>: <type>, <arg>: <type>, ...) -> <type>
2554
+ type(<arg>: <type>, <arg>: <type>, ...) -> <type>
2555
+ ...
2556
+ ```
2557
+ which can be interspersed with the `match(...)` statements.
2558
+
2559
+ ##### Example
2560
+
2561
+ **Coconut:**
2562
+ ```coconut
2563
+ case def my_min[T]:
2564
+ type(x: T, y: T) -> T
2565
+ match(x, y if x <= y) = x
2566
+ match(x, y) = y
2567
+
2568
+ type(xs: T[]) -> T
2569
+ match([x]) = x
2570
+ match([x] + xs) = my_min(x, my_min(xs))
2571
+ ```
2572
+
2573
+ **Python:**
2574
+ _Can't be done without a long series of checks for each pattern-matching. See the compiled code for the Python syntax._
2575
+
2526
2576
  ### `addpattern` Functions
2527
2577
 
2528
2578
  Coconut provides the `addpattern def` syntax as a shortcut for the full
@@ -2533,10 +2583,12 @@ match def func(...):
2533
2583
  ```
2534
2584
  syntax using the [`addpattern`](#addpattern) decorator.
2535
2585
 
2536
- Additionally, `addpattern def` will act just like a normal [`match def`](#pattern-matching-functions) if the function has not previously been defined, allowing for `addpattern def` to be used for each case rather than requiring `match def` for the first case and `addpattern def` for future cases.
2537
-
2538
2586
  If you want to put a decorator on an `addpattern def` function, make sure to put it on the _last_ pattern function.
2539
2587
 
2588
+ For complex multi-pattern functions, it is generally recommended to use [`case def`](#case-functions) over `addpattern def` in most situations.
2589
+
2590
+ _Deprecated: `addpattern def` will act just like a normal [`match def`](#pattern-matching-functions) if the function has not previously been defined. This will show a [`CoconutWarning`](#coconutwarning) and is not recommended._
2591
+
2540
2592
  ##### Example
2541
2593
 
2542
2594
  **Coconut:**
@@ -2954,7 +3006,7 @@ depth: 1
2954
3006
  Takes one argument that is a [pattern-matching function](#pattern-matching-functions), and returns a decorator that adds the patterns in the existing function to the new function being decorated, where the existing patterns are checked first, then the new. `addpattern` also supports a shortcut syntax where the new patterns can be passed in directly.
2955
3007
 
2956
3008
  Roughly equivalent to:
2957
- ```
3009
+ ```coconut_python
2958
3010
  def _pattern_adder(base_func, add_func):
2959
3011
  def add_pattern_func(*args, **kwargs):
2960
3012
  try:
@@ -2992,7 +3044,7 @@ print_type() # appears to work
2992
3044
  print_type(1) # TypeError: print_type() takes 0 positional arguments but 1 was given
2993
3045
  ```
2994
3046
 
2995
- This can be fixed by using either the `match` or `addpattern` keyword. For example:
3047
+ This can be fixed by using either the `match` keyword. For example:
2996
3048
  ```coconut
2997
3049
  match def print_type():
2998
3050
  print("Received no arguments.")
@@ -3343,6 +3395,10 @@ Additionally, if you are using [view patterns](#match), you might need to raise
3343
3395
 
3344
3396
  In some cases where there are multiple Coconut packages installed at the same time, there may be multiple `MatchError`s defined in different packages. Coconut can perform some magic under the hood to make sure that all these `MatchError`s will seamlessly interoperate, but only if all such packages are compiled in [`--package` mode rather than `--standalone` mode](#compilation-modes).
3345
3397
 
3398
+ ### `CoconutWarning`
3399
+
3400
+ `CoconutWarning` is the [`Warning`](https://docs.python.org/3/library/exceptions.html#Warning) subclass used for all runtime Coconut warnings; see [`warnings`](https://docs.python.org/3/library/warnings.html).
3401
+
3346
3402
 
3347
3403
  ### Generic Built-In Functions
3348
3404
 
@@ -379,7 +379,7 @@ def factorial(n):
379
379
  ```
380
380
 
381
381
  By making use of the [Coconut `addpattern` syntax](./DOCS.md#addpattern), we can take that from three indentation levels down to one. Take a look:
382
- ```
382
+ ```coconut
383
383
  def factorial(0) = 1
384
384
 
385
385
  addpattern def factorial(int() as n if n > 0) =
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: coconut-develop
3
- Version: 3.1.0.post0.dev7
3
+ Version: 3.1.0.post0.dev9
4
4
  Summary: Simple, elegant, Pythonic functional programming.
5
5
  Home-page: http://coconut-lang.org
6
6
  Author: Evan Hubinger
@@ -89,7 +89,7 @@ Description: |logo| Coconut
89
89
  __ Sponsor_
90
90
  .. _Sponsor: https://opencollective.com/coconut#sponsor
91
91
 
92
- Keywords: functional,programming,language,compiler,pattern,pattern-matching,algebraic,data type,data types,lambda,lambdas,lazy,evaluation,lazy list,lazy lists,tail,recursion,call,recursive,recursive_iterator,infix,function,composition,compose,partial,application,currying,curry,pipeline,pipe,unicode,operator,operators,frozenset,literal,syntax,destructuring,assignment,fold,datamaker,prepattern,iterator,generator,none,coalesce,coalescing,statement,lru_cache,memoization,backport,typing,embed,PEP 622,overrides,islice,itertools,functools,TYPE_CHECKING,Expected,breakpoint,help,reduce,takewhile,dropwhile,tee,count,makedata,consume,process_map,thread_map,addpattern,recursive_generator,fmap,starmap,reiterable,scan,groupsof,memoize,zip_longest,override,flatten,ident,call,safe_call,flip,const,lift,lift_apart,all_equal,collectby,mapreduce,multi_enumerate,cartesian_product,multiset,cycle,windowsof,and_then,and_then_await,async_map,py_chr,py_dict,py_hex,py_input,py_int,py_map,py_object,py_oct,py_open,py_print,py_range,py_str,py_super,py_zip,py_filter,py_reversed,py_enumerate,py_raw_input,py_xrange,py_repr,py_breakpoint,py_min,py_max,_namedtuple_of,reveal_type,reveal_locals,MatchError,__fmap__,__iter_getitem__,data,match,case,cases,where,addpattern,then,operator,type,copyclosure,λ
92
+ Keywords: functional,programming,language,compiler,pattern,pattern-matching,algebraic,data type,data types,lambda,lambdas,lazy,evaluation,lazy list,lazy lists,tail,recursion,call,recursive,recursive_iterator,infix,function,composition,compose,partial,application,currying,curry,pipeline,pipe,unicode,operator,operators,frozenset,literal,syntax,destructuring,assignment,fold,datamaker,prepattern,iterator,generator,none,coalesce,coalescing,statement,lru_cache,memoization,backport,typing,embed,PEP 622,overrides,islice,itertools,functools,TYPE_CHECKING,Expected,breakpoint,help,reduce,takewhile,dropwhile,tee,count,makedata,consume,process_map,thread_map,addpattern,recursive_generator,fmap,starmap,reiterable,scan,groupsof,memoize,zip_longest,override,flatten,ident,call,safe_call,flip,const,lift,lift_apart,all_equal,collectby,mapreduce,multi_enumerate,cartesian_product,multiset,cycle,windowsof,and_then,and_then_await,async_map,py_chr,py_dict,py_hex,py_input,py_int,py_map,py_object,py_oct,py_open,py_print,py_range,py_str,py_super,py_zip,py_filter,py_reversed,py_enumerate,py_raw_input,py_xrange,py_repr,py_breakpoint,py_min,py_max,_namedtuple_of,reveal_type,reveal_locals,MatchError,CoconutWarning,__fmap__,__iter_getitem__,data,match,case,cases,where,addpattern,then,operator,type,copyclosure,λ
93
93
  Platform: UNKNOWN
94
94
  Classifier: Development Status :: 5 - Production/Stable
95
95
  Classifier: License :: OSI Approved :: Apache Software License
@@ -239,6 +239,11 @@ def scan(
239
239
  _coconut_scan = scan
240
240
 
241
241
 
242
+ class CoconutWarning(Warning):
243
+ pass
244
+ _coconut_CoconutWarning = CoconutWarning
245
+
246
+
242
247
  class MatchError(Exception):
243
248
  """Pattern-matching error. Has attributes .pattern, .value, and .message."""
244
249
  pattern: _t.Optional[_t.Text]
@@ -279,30 +284,30 @@ def call(
279
284
  _y: _U,
280
285
  _z: _V,
281
286
  ) -> _W: ...
282
- # @_t.overload
283
- # def call(
284
- # _func: _t.Callable[_t.Concatenate[_T, _P], _U],
285
- # _x: _T,
286
- # *args: _t.Any,
287
- # **kwargs: _t.Any,
288
- # ) -> _U: ...
289
- # @_t.overload
290
- # def call(
291
- # _func: _t.Callable[_t.Concatenate[_T, _U, _P], _V],
292
- # _x: _T,
293
- # _y: _U,
294
- # *args: _t.Any,
295
- # **kwargs: _t.Any,
296
- # ) -> _V: ...
297
- # @_t.overload
298
- # def call(
299
- # _func: _t.Callable[_t.Concatenate[_T, _U, _V, _P], _W],
300
- # _x: _T,
301
- # _y: _U,
302
- # _z: _V,
303
- # *args: _t.Any,
304
- # **kwargs: _t.Any,
305
- # ) -> _W: ...
287
+ @_t.overload
288
+ def call(
289
+ _func: _t.Callable[_t.Concatenate[_T, _P], _U],
290
+ _x: _T,
291
+ *args: _t.Any,
292
+ **kwargs: _t.Any,
293
+ ) -> _U: ...
294
+ @_t.overload
295
+ def call(
296
+ _func: _t.Callable[_t.Concatenate[_T, _U, _P], _V],
297
+ _x: _T,
298
+ _y: _U,
299
+ *args: _t.Any,
300
+ **kwargs: _t.Any,
301
+ ) -> _V: ...
302
+ @_t.overload
303
+ def call(
304
+ _func: _t.Callable[_t.Concatenate[_T, _U, _V, _P], _W],
305
+ _x: _T,
306
+ _y: _U,
307
+ _z: _V,
308
+ *args: _t.Any,
309
+ **kwargs: _t.Any,
310
+ ) -> _W: ...
306
311
  @_t.overload
307
312
  def call(
308
313
  _func: _t.Callable[..., _T],
@@ -316,6 +321,7 @@ def call(
316
321
  """
317
322
  ...
318
323
 
324
+ # call = _coconut.operator.call
319
325
  _coconut_tail_call = call
320
326
  of = _deprecated("use call instead")(call)
321
327
 
@@ -1,2 +1,2 @@
1
1
  from __coconut__ import *
2
- from __coconut__ import _coconut_tail_call, _coconut_tco, _coconut_call_set_names, _coconut_handle_cls_kwargs, _coconut_handle_cls_stargs, _namedtuple_of, _coconut, _coconut_Expected, _coconut_MatchError, _coconut_SupportsAdd, _coconut_SupportsMinus, _coconut_SupportsMul, _coconut_SupportsPow, _coconut_SupportsTruediv, _coconut_SupportsFloordiv, _coconut_SupportsMod, _coconut_SupportsAnd, _coconut_SupportsXor, _coconut_SupportsOr, _coconut_SupportsLshift, _coconut_SupportsRshift, _coconut_SupportsMatmul, _coconut_SupportsInv, _coconut_Expected, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_complex_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_arr_concat_op, _coconut_mk_anon_namedtuple, _coconut_matmul, _coconut_py_str, _coconut_flatten, _coconut_multiset, _coconut_back_none_pipe, _coconut_back_none_star_pipe, _coconut_back_none_dubstar_pipe, _coconut_forward_none_compose, _coconut_back_none_compose, _coconut_forward_none_star_compose, _coconut_back_none_star_compose, _coconut_forward_none_dubstar_compose, _coconut_back_none_dubstar_compose, _coconut_call_or_coefficient, _coconut_in, _coconut_not_in, _coconut_attritemgetter, _coconut_if_op
2
+ from __coconut__ import _coconut_tail_call, _coconut_tco, _coconut_call_set_names, _coconut_handle_cls_kwargs, _coconut_handle_cls_stargs, _namedtuple_of, _coconut, _coconut_Expected, _coconut_MatchError, _coconut_SupportsAdd, _coconut_SupportsMinus, _coconut_SupportsMul, _coconut_SupportsPow, _coconut_SupportsTruediv, _coconut_SupportsFloordiv, _coconut_SupportsMod, _coconut_SupportsAnd, _coconut_SupportsXor, _coconut_SupportsOr, _coconut_SupportsLshift, _coconut_SupportsRshift, _coconut_SupportsMatmul, _coconut_SupportsInv, _coconut_Expected, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_complex_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_arr_concat_op, _coconut_mk_anon_namedtuple, _coconut_matmul, _coconut_py_str, _coconut_flatten, _coconut_multiset, _coconut_back_none_pipe, _coconut_back_none_star_pipe, _coconut_back_none_dubstar_pipe, _coconut_forward_none_compose, _coconut_back_none_compose, _coconut_forward_none_star_compose, _coconut_back_none_star_compose, _coconut_forward_none_dubstar_compose, _coconut_back_none_dubstar_compose, _coconut_call_or_coefficient, _coconut_in, _coconut_not_in, _coconut_attritemgetter, _coconut_if_op, _coconut_CoconutWarning
@@ -2390,6 +2390,7 @@ else:
2390
2390
  try:
2391
2391
  {addpattern_decorator} = _coconut_addpattern({func_name}) {type_ignore}
2392
2392
  except _coconut.NameError:
2393
+ _coconut.warnings.warn("Deprecated use of 'addpattern def {func_name}' with no prior 'match def {func_name}'", _coconut_CoconutWarning)
2393
2394
  {addpattern_decorator} = lambda f: f
2394
2395
  """,
2395
2396
  add_newline=True,
@@ -2557,33 +2558,25 @@ def {mock_var}({mock_paramdef}):
2557
2558
  # handle typed case def functions (must happen before decorators are cleared out)
2558
2559
  type_code = None
2559
2560
  if typed_case_def:
2561
+ internal_assert(len(all_type_defs) not in (0, 2), "invalid typed case def all_type_defs", all_type_defs)
2560
2562
  if undotted_name is not None:
2561
2563
  all_type_defs = [
2562
2564
  "def " + def_name + assert_remove_prefix(type_def, "def " + func_name)
2563
2565
  for type_def in all_type_defs
2564
2566
  ]
2565
- type_code = (
2566
- self.deferred_code_proc(type_param_code)
2567
- + "\n".join(
2568
- ("@_coconut.typing.overload\n" if len(all_type_defs) > 1 else "")
2567
+ type_def_lines = []
2568
+ for i, type_def in enumerate(all_type_defs):
2569
+ type_def_lines.append(
2570
+ ("@_coconut.typing.overload\n" if i < len(all_type_defs) - 1 else "")
2569
2571
  + decorators
2570
2572
  + self.deferred_code_proc(type_def)
2571
- for type_def in all_type_defs
2572
- )
2573
- )
2574
- if len(all_type_defs) > 1:
2575
- type_code += "\n" + decorators + handle_indentation("""
2576
- def {def_name}(*_coconut_args, **_coconut_kwargs):
2577
- return {any_type_ellipsis}
2578
- """).format(
2579
- def_name=def_name,
2580
- any_type_ellipsis=self.any_type_ellipsis(),
2581
2573
  )
2582
2574
  if undotted_name is not None:
2583
- type_code += "\n{func_name} = {def_name}".format(
2575
+ type_def_lines.append("{func_name} = {def_name}".format(
2584
2576
  func_name=func_name,
2585
2577
  def_name=def_name,
2586
- )
2578
+ ))
2579
+ type_code = self.deferred_code_proc(type_param_code) + "\n".join(type_def_lines)
2587
2580
 
2588
2581
  # handle dotted function definition
2589
2582
  if undotted_name is not None:
@@ -3919,11 +3912,13 @@ if not {check_var}:
3919
3912
  typed_params, typed_ret = case_toks
3920
3913
  all_type_defs.append(handle_indentation("""
3921
3914
  def {name}{typed_params}{typed_ret}
3915
+ {docstring}
3922
3916
  return {ellipsis}
3923
3917
  """).format(
3924
3918
  name=name,
3925
3919
  typed_params=typed_params,
3926
3920
  typed_ret=typed_ret,
3921
+ docstring=docstring if docstring is not None else "",
3927
3922
  ellipsis=self.any_type_ellipsis(),
3928
3923
  ))
3929
3924
  else:
@@ -3931,6 +3926,16 @@ def {name}{typed_params}{typed_ret}
3931
3926
 
3932
3927
  if type_param_code and not all_type_defs:
3933
3928
  raise CoconutDeferredSyntaxError("type parameters in case def but no type declaration cases", loc)
3929
+ if len(all_type_defs) > 1:
3930
+ all_type_defs.append(handle_indentation("""
3931
+ def {name}(*_coconut_args, **_coconut_kwargs):
3932
+ {docstring}
3933
+ return {ellipsis}
3934
+ """).format(
3935
+ name=name,
3936
+ docstring=docstring if docstring is not None else "",
3937
+ ellipsis=self.any_type_ellipsis(),
3938
+ ))
3934
3939
 
3935
3940
  func_code = handle_indentation("""
3936
3941
  def {name}({match_func_paramdef}):
@@ -2256,6 +2256,7 @@ class Grammar(object):
2256
2256
  op_tfpdef = unsafe_typedef_default | condense(setname + Optional(default))
2257
2257
  op_funcdef_arg = setname | condense(lparen.suppress() + op_tfpdef + rparen.suppress())
2258
2258
  op_funcdef_name = unsafe_backtick.suppress() + funcname_typeparams + unsafe_backtick.suppress()
2259
+ op_funcdef_name_tokens = unsafe_backtick.suppress() + funcname_typeparams_tokens + unsafe_backtick.suppress()
2259
2260
  op_funcdef = attach(
2260
2261
  Group(Optional(op_funcdef_arg))
2261
2262
  + op_funcdef_name
@@ -2359,7 +2360,10 @@ class Grammar(object):
2359
2360
  base_case_funcdef = Forward()
2360
2361
  base_case_funcdef_ref = (
2361
2362
  keyword("def").suppress()
2362
- + Group(funcname_typeparams_tokens)
2363
+ + Group(
2364
+ funcname_typeparams_tokens
2365
+ | op_funcdef_name_tokens
2366
+ )
2363
2367
  + colon.suppress()
2364
2368
  - newline.suppress()
2365
2369
  - indent.suppress()
@@ -641,7 +641,7 @@ for _coconut_varname in dir(MatchError):
641
641
  # (extra_format_dict is to keep indentation levels matching)
642
642
  extra_format_dict = dict(
643
643
  # when anything is added to this list it must also be added to *both* __coconut__ stub files
644
- underscore_imports="{tco_comma}{call_set_names_comma}{handle_cls_args_comma}_namedtuple_of, _coconut, _coconut_Expected, _coconut_MatchError, _coconut_SupportsAdd, _coconut_SupportsMinus, _coconut_SupportsMul, _coconut_SupportsPow, _coconut_SupportsTruediv, _coconut_SupportsFloordiv, _coconut_SupportsMod, _coconut_SupportsAnd, _coconut_SupportsXor, _coconut_SupportsOr, _coconut_SupportsLshift, _coconut_SupportsRshift, _coconut_SupportsMatmul, _coconut_SupportsInv, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_complex_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_arr_concat_op, _coconut_mk_anon_namedtuple, _coconut_matmul, _coconut_py_str, _coconut_flatten, _coconut_multiset, _coconut_back_none_pipe, _coconut_back_none_star_pipe, _coconut_back_none_dubstar_pipe, _coconut_forward_none_compose, _coconut_back_none_compose, _coconut_forward_none_star_compose, _coconut_back_none_star_compose, _coconut_forward_none_dubstar_compose, _coconut_back_none_dubstar_compose, _coconut_call_or_coefficient, _coconut_in, _coconut_not_in, _coconut_attritemgetter, _coconut_if_op".format(**format_dict),
644
+ underscore_imports="{tco_comma}{call_set_names_comma}{handle_cls_args_comma}_namedtuple_of, _coconut, _coconut_Expected, _coconut_MatchError, _coconut_SupportsAdd, _coconut_SupportsMinus, _coconut_SupportsMul, _coconut_SupportsPow, _coconut_SupportsTruediv, _coconut_SupportsFloordiv, _coconut_SupportsMod, _coconut_SupportsAnd, _coconut_SupportsXor, _coconut_SupportsOr, _coconut_SupportsLshift, _coconut_SupportsRshift, _coconut_SupportsMatmul, _coconut_SupportsInv, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_complex_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_arr_concat_op, _coconut_mk_anon_namedtuple, _coconut_matmul, _coconut_py_str, _coconut_flatten, _coconut_multiset, _coconut_back_none_pipe, _coconut_back_none_star_pipe, _coconut_back_none_dubstar_pipe, _coconut_forward_none_compose, _coconut_back_none_compose, _coconut_forward_none_star_compose, _coconut_back_none_star_compose, _coconut_forward_none_dubstar_compose, _coconut_back_none_dubstar_compose, _coconut_call_or_coefficient, _coconut_in, _coconut_not_in, _coconut_attritemgetter, _coconut_if_op, _coconut_CoconutWarning".format(**format_dict),
645
645
  import_typing=pycondition(
646
646
  (3, 5),
647
647
  if_ge='''
@@ -865,6 +865,21 @@ def async_map(*args, **kwargs):
865
865
  "{_coconut_}zip".format(**format_dict): "zip",
866
866
  },
867
867
  ),
868
+ def_call=pycondition(
869
+ (3, 11),
870
+ if_ge=r'''
871
+ call = _coconut.operator.call
872
+ ''',
873
+ if_lt=r'''
874
+ def call(_coconut_f{comma_slash}, *args, **kwargs):
875
+ """Function application operator function.
876
+
877
+ Equivalent to:
878
+ def call(f, /, *args, **kwargs) = f(*args, **kwargs).
879
+ """
880
+ return _coconut_f(*args, **kwargs)
881
+ '''.format(**format_dict),
882
+ ),
868
883
  )
869
884
  format_dict.update(extra_format_dict)
870
885
 
@@ -136,6 +136,10 @@ def _coconut_xarray_to_numpy(obj):
136
136
  return obj.to_dataframe().to_numpy()
137
137
  else:
138
138
  return obj.to_numpy()
139
+ class CoconutWarning(Warning{comma_object}):
140
+ """Exception class used for all Coconut warnings."""
141
+ __slots__ = ()
142
+ _coconut_CoconutWarning = CoconutWarning
139
143
  class MatchError(_coconut_baseclass, Exception):
140
144
  """Pattern-matching error. Has attributes .pattern, .value, and .message."""{COMMENT.no_slots_to_allow_setattr_below}
141
145
  max_val_repr_len = 500
@@ -1439,7 +1443,7 @@ def addpattern(base_func, *add_funcs, **kwargs):
1439
1443
  """
1440
1444
  allow_any_func = kwargs.pop("allow_any_func", False)
1441
1445
  if not allow_any_func and not _coconut.getattr(base_func, "_coconut_is_match", False):
1442
- _coconut.warnings.warn("Possible misuse of addpattern with non-pattern-matching function " + _coconut.repr(base_func) + " (pass allow_any_func=True to dismiss)", stacklevel=2)
1446
+ _coconut.warnings.warn("Possible misuse of addpattern with non-pattern-matching function " + _coconut.repr(base_func) + " (pass allow_any_func=True to dismiss)", _coconut_CoconutWarning, 2)
1443
1447
  if kwargs:
1444
1448
  raise _coconut.TypeError("addpattern() got unexpected keyword arguments " + _coconut.repr(kwargs))
1445
1449
  if add_funcs:
@@ -1709,13 +1713,7 @@ def ident(x, **kwargs):
1709
1713
  if side_effect is not None:
1710
1714
  side_effect(x)
1711
1715
  return x
1712
- def call(_coconut_f{comma_slash}, *args, **kwargs):
1713
- """Function application operator function.
1714
-
1715
- Equivalent to:
1716
- def call(f, /, *args, **kwargs) = f(*args, **kwargs).
1717
- """
1718
- return _coconut_f(*args, **kwargs)
1716
+ {def_call}
1719
1717
  def safe_call(_coconut_f{comma_slash}, *args, **kwargs):
1720
1718
  """safe_call is a version of call that catches any Exceptions and
1721
1719
  returns an Expected containing either the result or the error.
@@ -287,10 +287,10 @@ match_set_name_var = reserved_prefix + "_match_set_name"
287
287
  openindent = "\u204b" # reverse pilcrow
288
288
  closeindent = "\xb6" # pilcrow
289
289
  strwrapper = "\u25b6" # black right-pointing triangle
290
- errwrapper = "\u24d8" # circled letter i
291
290
  early_passthrough_wrapper = "\u2038" # caret
292
291
  lnwrapper = "\u2021" # double dagger
293
292
  unwrapper = "\u23f9" # stop square
293
+ errwrapper = "\u24d8" # circled letter i
294
294
  tempsep = "\u22ee" # vertical ellipsis
295
295
  funcwrapper = "def:"
296
296
 
@@ -309,12 +309,16 @@ str_chars = "'\"" # string open/close chars
309
309
  # together should include all the constants defined above
310
310
  delimiter_symbols = tuple(open_chars + close_chars + str_chars) + (
311
311
  strwrapper,
312
- errwrapper,
313
312
  early_passthrough_wrapper,
314
313
  unwrapper,
314
+ "`",
315
+ ":",
316
+ ",",
317
+ ";",
315
318
  ) + indchars + comment_chars
316
319
  reserved_compiler_symbols = delimiter_symbols + (
317
320
  reserved_prefix,
321
+ errwrapper,
318
322
  tempsep,
319
323
  funcwrapper,
320
324
  )
@@ -835,6 +839,7 @@ must_use_specific_target_builtins = (
835
839
 
836
840
  coconut_exceptions = (
837
841
  "MatchError",
842
+ "CoconutWarning",
838
843
  )
839
844
 
840
845
  highlight_builtins = coconut_specific_builtins + interp_only_builtins + python_builtins
@@ -26,7 +26,7 @@ import sys as _coconut_sys
26
26
  VERSION = "3.1.0"
27
27
  VERSION_NAME = None
28
28
  # False for release, int >= 1 for develop
29
- DEVELOP = 7
29
+ DEVELOP = 9
30
30
  ALPHA = False # for pre releases rather than post releases
31
31
 
32
32
  assert DEVELOP is False or DEVELOP >= 1, "DEVELOP must be False or an int >= 1"
@@ -174,8 +174,10 @@ ignore_last_lines_with = (
174
174
  "DeprecationWarning: The distutils package is deprecated",
175
175
  "from distutils.version import LooseVersion",
176
176
  ": SyntaxWarning: 'int' object is not ",
177
+ ": CoconutWarning: Deprecated use of ",
177
178
  " assert_raises(",
178
179
  "Populating initial parsing cache",
180
+ "_coconut.warnings.warn(",
179
181
  )
180
182
 
181
183
  kernel_installation_msg = (
@@ -681,7 +683,7 @@ def run(
681
683
  assert use_run_arg + run_directory < 2
682
684
 
683
685
  if manage_cache and "--no-cache" not in args:
684
- args += ["--no-cache"]
686
+ args = ["--no-cache"] + args
685
687
 
686
688
  if agnostic_target is None:
687
689
  agnostic_args = args
@@ -458,6 +458,7 @@ def primary_test_2() -> bool:
458
458
  assert min((), default=10) == 10 == max((), default=10)
459
459
  assert py_min(3, 4) == 3 == py_max(2, 3)
460
460
  assert len(zip()) == 0 == len(zip_longest()) # type: ignore
461
+ assert CoconutWarning `issubclass` Warning
461
462
 
462
463
  with process_map.multiple_sequential_calls(): # type: ignore
463
464
  assert map((+), range(3), range(4)$[:-1], strict=True) |> list == [0, 2, 4] == process_map((+), range(3), range(4)$[:-1], strict=True) |> list # type: ignore
@@ -10,6 +10,7 @@ from .util import operator CONST
10
10
  from .util import operator “
11
11
  from .util import operator ”
12
12
  from .util import operator !
13
+ from .util import operator <>
13
14
 
14
15
  operator lol
15
16
  operator ++
@@ -152,9 +153,11 @@ def suite_test() -> bool:
152
153
  assert -4 == neg_square_u(2) ≠ 4 ∩ 0 ≤ neg_square_u(0) ≤ 0
153
154
  assert is_null(null1())
154
155
  assert is_null(null2())
155
- assert empty() |> depth_1 == 0 == empty() |> depth_2
156
- assert leaf(5) |> depth_1 == 1 == leaf(5) |> depth_2
157
- assert node(leaf(2), node(empty(), leaf(3))) |> depth_1 == 3 == node(leaf(2), node(empty(), leaf(3))) |> depth_2
156
+ for depth in (depth_1, depth_2, depth_3):
157
+ assert empty() |> depth == 0 # type: ignore
158
+ assert leaf(5) |> depth == 1 # type: ignore
159
+ assert node(leaf(2), node(empty(), leaf(3))) |> depth == 3 # type: ignore
160
+ assert size(node(empty(), leaf(10))) == 1 == size_(node(empty(), leaf(10)))
158
161
  assert maybes(5, square, plus1) == 26
159
162
  assert maybes(None, square, plus1) is None
160
163
  assert square <| 2 == 4
@@ -870,7 +873,7 @@ forward 2""") == 900
870
873
  assert split1_comma(",") == ("", "")
871
874
  assert split1_comma("abcd") == ("abcd", "")
872
875
  assert primes()$[:5] |> tuple == (2, 3, 5, 7, 11)
873
- assert twin_primes()$[:5] |> list == [(3, 5), (5, 7), (11, 13), (17, 19), (29, 31)]
876
+ assert twin_primes()$[:5] |> list == [(3, 5), (5, 7), (11, 13), (17, 19), (29, 31)] == twin_primes_()$[:5] |> list
874
877
  assert stored_default(2) == [2, 1] == stored_default_cls()(2)
875
878
  assert stored_default(2) == [2, 1, 2, 1] == stored_default_cls()(2)
876
879
  if sys.version_info >= (3,): # naive namespace classes don't work on py2
@@ -1088,6 +1091,7 @@ forward 2""") == 900
1088
1091
  assert [1, 2, 3] |> reduce_with_init$(+) == 6 == (1, 2, 3) |> iter |> reduce_with_init$((+), init=0)
1089
1092
  assert min(1, 2) == 1 == my_min(1, 2)
1090
1093
  assert min([1, 2]) == 1 == my_min([1, 2])
1094
+ assert 3 <> 4
1091
1095
 
1092
1096
  with process_map.multiple_sequential_calls(): # type: ignore
1093
1097
  assert process_map(tuple <.. (|>)$(to_sort), qsorts) |> list == [to_sort |> sorted |> tuple] * len(qsorts)
@@ -245,6 +245,12 @@ addpattern def (float(x))! = 0.0 if x else 1.0 # type: ignore
245
245
  addpattern def x! if x = False # type: ignore
246
246
  addpattern def x! = True # type: ignore
247
247
 
248
+ operator <>
249
+ case def <>:
250
+ match(x, y if x < y) = True
251
+ match(x, y if x > y) = True
252
+ match(x, y) = False
253
+
248
254
  # Type aliases:
249
255
  if sys.version_info >= (3, 5) or TYPE_CHECKING:
250
256
  type list_or_tuple = list | tuple
@@ -787,6 +793,20 @@ def depth_2(t):
787
793
  match tree(l=l, r=r) in t:
788
794
  return 1 + max([depth_2(l), depth_2(r)])
789
795
 
796
+ case def depth_3:
797
+ match(tree()) = 0
798
+ match(tree(n=n)) = 1
799
+ match(tree(l=l, r=r)) = 1 + max(depth_3(l), depth_3(r))
800
+
801
+ def size(empty()) = 0
802
+ addpattern def size(leaf(n)) = 1 # type: ignore
803
+ addpattern def size(node(l, r)) = size(l) + size(r) # type: ignore
804
+
805
+ case def size_:
806
+ match(empty()) = 0
807
+ match(leaf(n)) = 1
808
+ match(node(l, r)) = size_(l) + size_(r)
809
+
790
810
  class Tree
791
811
  data Node(*children) from Tree
792
812
  data Leaf(elem) from Tree
@@ -1940,6 +1960,12 @@ def twin_primes(_ :: [p, (.-2) -> p] :: ps) =
1940
1960
  addpattern def twin_primes() = # type: ignore
1941
1961
  twin_primes(primes())
1942
1962
 
1963
+ case def twin_primes_:
1964
+ match(_ :: [p, (.-2) -> p] :: ps) =
1965
+ [(p, p+2)] :: twin_primes_([p + 2] :: ps)
1966
+ match() =
1967
+ twin_primes_(primes())
1968
+
1943
1969
 
1944
1970
  # class matching
1945
1971
  class HasElems:
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import sys
2
3
  from collections.abc import Sequence
3
4
 
4
5
  os.environ["COCONUT_USE_COLOR"] = "False"
@@ -14,6 +15,7 @@ from coconut.constants import (
14
15
  PYPY,
15
16
  ) # type: ignore
16
17
  from coconut._pyparsing import USE_COMPUTATION_GRAPH # type: ignore
18
+ from coconut.terminal import logger
17
19
  from coconut.exceptions import (
18
20
  CoconutSyntaxError,
19
21
  CoconutStyleError,
@@ -325,7 +327,8 @@ def g(x) = x
325
327
  return True
326
328
 
327
329
 
328
- def test_convenience() -> bool:
330
+ def test_api() -> bool:
331
+ assert not logger.enable_colors(sys.stdout)
329
332
  if IPY:
330
333
  import coconut.highlighter # noqa # type: ignore
331
334
 
@@ -733,7 +736,7 @@ def test_extras() -> bool:
733
736
  print(".") # newline bc we print stuff after this
734
737
  assert test_setup_none() is True # ...
735
738
  print(".") # ditto
736
- assert test_convenience() is True # ....
739
+ assert test_api() is True # ....
737
740
  # everything after here uses incremental parsing, so it must come last
738
741
  print(".", end="")
739
742
  assert test_incremental() is True # .....