coconut-develop 3.1.0.post0.dev9__tar.gz → 3.1.0.post0.dev10__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.dev9 → coconut-develop-3.1.0.post0.dev10}/DOCS.md +8 -6
  2. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/PKG-INFO +1 -1
  3. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/compiler.py +40 -14
  4. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/grammar.py +5 -4
  5. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/root.py +1 -1
  6. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/primary_2.coco +4 -4
  7. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/suite.coco +2 -2
  8. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/util.coco +4 -4
  9. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/non_strict/non_strict_test.coco +5 -0
  10. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/extras.coco +14 -0
  11. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/CONTRIBUTING.md +0 -0
  12. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/FAQ.md +0 -0
  13. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/HELP.md +0 -0
  14. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/LICENSE.txt +0 -0
  15. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/MANIFEST.in +0 -0
  16. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/README.rst +0 -0
  17. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/__coconut__/__init__.py +0 -0
  18. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/__coconut__/__init__.pyi +0 -0
  19. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/__coconut__/py.typed +0 -0
  20. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/_coconut/__init__.py +0 -0
  21. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/_coconut/__init__.pyi +0 -0
  22. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/_coconut/py.typed +0 -0
  23. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/__coconut__.py +0 -0
  24. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/__coconut__.pyi +0 -0
  25. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/__init__.py +0 -0
  26. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/__init__.pyi +0 -0
  27. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/__main__.py +0 -0
  28. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/_pyparsing.py +0 -0
  29. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/api.py +0 -0
  30. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/api.pyi +0 -0
  31. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/__init__.py +0 -0
  32. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/__init__.pyi +0 -0
  33. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/cli.py +0 -0
  34. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/command.py +0 -0
  35. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/command.pyi +0 -0
  36. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/mypy.py +0 -0
  37. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/resources/zcoconut.pth +0 -0
  38. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/util.py +0 -0
  39. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/command/watch.py +0 -0
  40. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/__init__.py +0 -0
  41. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/header.py +0 -0
  42. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/matching.py +0 -0
  43. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/templates/header.py_template +0 -0
  44. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/compiler/util.py +0 -0
  45. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/constants.py +0 -0
  46. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/convenience.py +0 -0
  47. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/convenience.pyi +0 -0
  48. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/exceptions.py +0 -0
  49. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/highlighter.py +0 -0
  50. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/__init__.py +0 -0
  51. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/__main__.py +0 -0
  52. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/coconut/kernel.json +0 -0
  53. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/coconut_py/kernel.json +0 -0
  54. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/coconut_py2/kernel.json +0 -0
  55. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/coconut_py3/kernel.json +0 -0
  56. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/embed.py +0 -0
  57. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/icoconut/root.py +0 -0
  58. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/integrations.py +0 -0
  59. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/main.py +0 -0
  60. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/py.typed +0 -0
  61. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/requirements.py +0 -0
  62. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/terminal.py +0 -0
  63. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/__init__.py +0 -0
  64. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/__main__.py +0 -0
  65. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/constants_test.py +0 -0
  66. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/main_test.py +0 -0
  67. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/__init__.coco +0 -0
  68. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/__main__.coco +0 -0
  69. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/main.coco +0 -0
  70. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/primary_1.coco +0 -0
  71. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/specific.coco +0 -0
  72. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/agnostic/tutorial.coco +0 -0
  73. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_2/py2_test.coco +0 -0
  74. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_3/py3_test.coco +0 -0
  75. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_311/py311_test.coco +0 -0
  76. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_35/py35_test.coco +0 -0
  77. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_36/py36_test.coco +0 -0
  78. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_38/py38_test.coco +0 -0
  79. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/cocotest/target_sys/target_sys_test.coco +0 -0
  80. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/importable.coco +0 -0
  81. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/runnable.coco +0 -0
  82. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/tests/src/runner.coco +0 -0
  83. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut/util.py +0 -0
  84. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/coconut_develop.egg-info/SOURCES.txt +0 -0
  85. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/conf.py +0 -0
  86. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/pyproject.toml +0 -0
  87. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/setup.cfg +0 -0
  88. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/setup.py +0 -0
  89. {coconut-develop-3.1.0.post0.dev9 → coconut-develop-3.1.0.post0.dev10}/xontrib/coconut.py +0 -0
@@ -543,9 +543,9 @@ a `b` c, left (captures lambda)
543
543
  all custom operators
544
544
  ?? left (short-circuits)
545
545
  ..>, <.., ..*>, <*.., n/a (captures lambda)
546
- ..**>, <**..
546
+ ..**>, <**.., etc.
547
547
  |>, <|, |*>, <*|, left (captures lambda)
548
- |**>, <**|
548
+ |**>, <**|, etc.
549
549
  ==, !=, <, >,
550
550
  <=, >=,
551
551
  in, not in,
@@ -1387,7 +1387,7 @@ match <value>:
1387
1387
  ```
1388
1388
  where `<pattern>` is any `match` pattern, `<value>` is the item to match against, `<cond>` is an optional additional check, and `<body>` is simply code that is executed if the header above it succeeds. Note the absence of an `in` in the `match` statements: that's because the `<value>` in `case <value>` is taking its place. If no `else` is present and no match succeeds, then the `case` statement is simply skipped over as with [`match` statements](#match) (though unlike [destructuring assignments](#destructuring-assignment)).
1389
1389
 
1390
- Additionally, `cases` can be used as the top-level keyword instead of `match`, and in such a `case` block `match` is allowed for each case rather than `case`. _Deprecated: Coconut also supports `case` instead of `cases` as the top-level keyword for backwards-compatibility purposes._
1390
+ _Deprecated: Additionally, `cases` or `case` can be used as the top-level keyword instead of `match`, and in such a block `match` is used for each case rather than `case`._
1391
1391
 
1392
1392
  ##### Examples
1393
1393
 
@@ -2219,7 +2219,7 @@ quad = 5 * x**2 + 3 * x + 1
2219
2219
 
2220
2220
  When passing in long variable names as keyword arguments of the same name, Coconut supports the syntax
2221
2221
  ```
2222
- f(...=long_variable_name)
2222
+ f(long_variable_name=)
2223
2223
  ```
2224
2224
  as a shorthand for
2225
2225
  ```
@@ -2228,6 +2228,8 @@ f(long_variable_name=long_variable_name)
2228
2228
 
2229
2229
  Such syntax is also supported in [partial application](#partial-application) and [anonymous `namedtuple`s](#anonymous-namedtuples).
2230
2230
 
2231
+ _Deprecated: Coconut also supports `f(...=long_variable_name)` as an alternative shorthand syntax._
2232
+
2231
2233
  ##### Example
2232
2234
 
2233
2235
  **Coconut:**
@@ -2235,8 +2237,8 @@ Such syntax is also supported in [partial application](#partial-application) and
2235
2237
  really_long_variable_name_1 = get_1()
2236
2238
  really_long_variable_name_2 = get_2()
2237
2239
  main_func(
2238
- ...=really_long_variable_name_1,
2239
- ...=really_long_variable_name_2,
2240
+ really_long_variable_name_1=,
2241
+ really_long_variable_name_2=,
2240
2242
  )
2241
2243
  ```
2242
2244
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: coconut-develop
3
- Version: 3.1.0.post0.dev9
3
+ Version: 3.1.0.post0.dev10
4
4
  Summary: Simple, elegant, Pythonic functional programming.
5
5
  Home-page: http://coconut-lang.org
6
6
  Author: Evan Hubinger
@@ -539,6 +539,7 @@ class Compiler(Grammar, pickleable_obj):
539
539
  self.add_code_before_replacements = {}
540
540
  self.add_code_before_ignore_names = {}
541
541
  self.remaining_original = None
542
+ self.shown_warnings = set()
542
543
 
543
544
  @contextmanager
544
545
  def inner_environment(self, ln=None):
@@ -556,6 +557,7 @@ class Compiler(Grammar, pickleable_obj):
556
557
  kept_lines, self.kept_lines = self.kept_lines, []
557
558
  num_lines, self.num_lines = self.num_lines, 0
558
559
  remaining_original, self.remaining_original = self.remaining_original, None
560
+ shown_warnings, self.shown_warnings = self.shown_warnings, set()
559
561
  try:
560
562
  with ComputationNode.using_overrides():
561
563
  yield
@@ -571,6 +573,7 @@ class Compiler(Grammar, pickleable_obj):
571
573
  self.kept_lines = kept_lines
572
574
  self.num_lines = num_lines
573
575
  self.remaining_original = remaining_original
576
+ self.shown_warnings = shown_warnings
574
577
 
575
578
  @contextmanager
576
579
  def disable_checks(self):
@@ -937,11 +940,14 @@ class Compiler(Grammar, pickleable_obj):
937
940
  if self.strict:
938
941
  raise self.make_err(CoconutStyleError, *args, **kwargs)
939
942
 
940
- def syntax_warning(self, *args, **kwargs):
943
+ def syntax_warning(self, message, original, loc, **kwargs):
941
944
  """Show a CoconutSyntaxWarning. Usage:
942
945
  self.syntax_warning(message, original, loc)
943
946
  """
944
- logger.warn_err(self.make_err(CoconutSyntaxWarning, *args, **kwargs))
947
+ key = (message, loc)
948
+ if key not in self.shown_warnings:
949
+ logger.warn_err(self.make_err(CoconutSyntaxWarning, message, original, loc, **kwargs))
950
+ self.shown_warnings.add(key)
945
951
 
946
952
  def strict_err_or_warn(self, *args, **kwargs):
947
953
  """Raises an error if in strict mode, otherwise raises a warning. Usage:
@@ -2390,7 +2396,7 @@ else:
2390
2396
  try:
2391
2397
  {addpattern_decorator} = _coconut_addpattern({func_name}) {type_ignore}
2392
2398
  except _coconut.NameError:
2393
- _coconut.warnings.warn("Deprecated use of 'addpattern def {func_name}' with no prior 'match def {func_name}'", _coconut_CoconutWarning)
2399
+ _coconut.warnings.warn("Deprecated use of 'addpattern def {func_name}' with no pre-existing '{func_name}' function (use 'match def {func_name}' for the first definition or switch to 'case def' syntax)", _coconut_CoconutWarning)
2394
2400
  {addpattern_decorator} = lambda f: f
2395
2401
  """,
2396
2402
  add_newline=True,
@@ -2779,7 +2785,7 @@ else:
2779
2785
  # HANDLERS:
2780
2786
  # -----------------------------------------------------------------------------------------------------------------------
2781
2787
 
2782
- def split_function_call(self, tokens, loc):
2788
+ def split_function_call(self, original, loc, tokens):
2783
2789
  """Split into positional arguments and keyword arguments."""
2784
2790
  pos_args = []
2785
2791
  star_args = []
@@ -2802,7 +2808,10 @@ else:
2802
2808
  star_args.append(argstr)
2803
2809
  elif arg[0] == "**":
2804
2810
  dubstar_args.append(argstr)
2811
+ elif arg[1] == "=":
2812
+ kwd_args.append(arg[0] + "=" + arg[0])
2805
2813
  elif arg[0] == "...":
2814
+ self.strict_err_or_warn("'...={name}' shorthand is deprecated, use '{name}=' shorthand instead".format(name=arg[1]), original, loc)
2806
2815
  kwd_args.append(arg[1] + "=" + arg[1])
2807
2816
  else:
2808
2817
  kwd_args.append(argstr)
@@ -2818,9 +2827,9 @@ else:
2818
2827
 
2819
2828
  return pos_args, star_args, kwd_args, dubstar_args
2820
2829
 
2821
- def function_call_handle(self, loc, tokens):
2830
+ def function_call_handle(self, original, loc, tokens):
2822
2831
  """Enforce properly ordered function parameters."""
2823
- return "(" + join_args(*self.split_function_call(tokens, loc)) + ")"
2832
+ return "(" + join_args(*self.split_function_call(original, loc, tokens)) + ")"
2824
2833
 
2825
2834
  def pipe_item_split(self, original, loc, tokens):
2826
2835
  """Process a pipe item, which could be a partial, an attribute access, a method call, or an expression.
@@ -2841,7 +2850,7 @@ else:
2841
2850
  return "expr", tokens
2842
2851
  elif "partial" in tokens:
2843
2852
  func, args = tokens
2844
- pos_args, star_args, kwd_args, dubstar_args = self.split_function_call(args, loc)
2853
+ pos_args, star_args, kwd_args, dubstar_args = self.split_function_call(original, loc, args)
2845
2854
  return "partial", (func, join_args(pos_args, star_args), join_args(kwd_args, dubstar_args))
2846
2855
  elif "attrgetter" in tokens:
2847
2856
  name, args = attrgetter_atom_split(tokens)
@@ -3061,7 +3070,7 @@ else:
3061
3070
  elif trailer[0] == "$[":
3062
3071
  out = "_coconut_iter_getitem(" + out + ", " + trailer[1] + ")"
3063
3072
  elif trailer[0] == "$(?":
3064
- pos_args, star_args, base_kwd_args, dubstar_args = self.split_function_call(trailer[1], loc)
3073
+ pos_args, star_args, base_kwd_args, dubstar_args = self.split_function_call(original, loc, trailer[1])
3065
3074
 
3066
3075
  has_question_mark = False
3067
3076
  needs_complex_partial = False
@@ -3232,7 +3241,7 @@ while True:
3232
3241
  # handle classlist
3233
3242
  base_classes = []
3234
3243
  if classlist_toks:
3235
- pos_args, star_args, kwd_args, dubstar_args = self.split_function_call(classlist_toks, loc)
3244
+ pos_args, star_args, kwd_args, dubstar_args = self.split_function_call(original, loc, classlist_toks)
3236
3245
 
3237
3246
  # check for just inheriting from object
3238
3247
  if (
@@ -3566,7 +3575,7 @@ def __hash__(self):
3566
3575
 
3567
3576
  return "".join(out)
3568
3577
 
3569
- def anon_namedtuple_handle(self, tokens):
3578
+ def anon_namedtuple_handle(self, original, loc, tokens):
3570
3579
  """Handle anonymous named tuples."""
3571
3580
  names = []
3572
3581
  types = {}
@@ -3579,7 +3588,10 @@ def __hash__(self):
3579
3588
  types[i] = typedef
3580
3589
  else:
3581
3590
  raise CoconutInternalException("invalid anonymous named item", tok)
3582
- if name == "...":
3591
+ if item == "=":
3592
+ item = name
3593
+ elif name == "...":
3594
+ self.strict_err_or_warn("'...={item}' shorthand is deprecated, use '{item}=' shorthand instead".format(item=item), original, loc)
3583
3595
  name = item
3584
3596
  names.append(name)
3585
3597
  items.append(item)
@@ -3924,8 +3936,11 @@ def {name}{typed_params}{typed_ret}
3924
3936
  else:
3925
3937
  raise CoconutInternalException("invalid case_funcdef case_toks", case_toks)
3926
3938
 
3939
+ if not all_case_code:
3940
+ raise CoconutDeferredSyntaxError("case def with no match cases", loc)
3927
3941
  if type_param_code and not all_type_defs:
3928
- raise CoconutDeferredSyntaxError("type parameters in case def but no type declaration cases", loc)
3942
+ raise CoconutDeferredSyntaxError("type parameters in case def but no type cases", loc)
3943
+
3929
3944
  if len(all_type_defs) > 1:
3930
3945
  all_type_defs.append(handle_indentation("""
3931
3946
  def {name}(*_coconut_args, **_coconut_kwargs):
@@ -4267,9 +4282,20 @@ __annotations__["{name}"] = {annotation}
4267
4282
  else:
4268
4283
  raise CoconutInternalException("invalid case tokens", tokens)
4269
4284
 
4270
- self.internal_assert(block_kwd in ("cases", "case", "match"), original, loc, "invalid case statement keyword", block_kwd)
4271
4285
  if block_kwd == "case":
4272
- self.strict_err_or_warn("deprecated case keyword at top level in case ...: match ...: block (use Python 3.10 match ...: case ...: syntax instead)", original, loc)
4286
+ self.strict_err_or_warn(
4287
+ "deprecated case keyword at top level in case ...: match ...: block (use Python 3.10 match ...: case ...: syntax instead)",
4288
+ original,
4289
+ loc,
4290
+ )
4291
+ elif block_kwd == "cases":
4292
+ self.syntax_warning(
4293
+ "deprecated cases keyword at top level in cases ...: match ...: block (use Python 3.10 match ...: case ...: syntax instead)",
4294
+ original,
4295
+ loc,
4296
+ )
4297
+ else:
4298
+ self.internal_assert(block_kwd == "match", original, loc, "invalid case statement keyword", block_kwd)
4273
4299
 
4274
4300
  check_var = self.get_temp_var("case_match_check", loc)
4275
4301
  match_var = self.get_temp_var("case_match_to", loc)
@@ -1249,11 +1249,12 @@ class Grammar(object):
1249
1249
 
1250
1250
  call_item = (
1251
1251
  unsafe_name + default
1252
- # ellipsis must come before namedexpr_test
1253
- | ellipsis_tokens + equals.suppress() + refname
1254
- | namedexpr_test
1255
1252
  | star + test
1256
1253
  | dubstar + test
1254
+ | refname + equals # new long name ellision syntax
1255
+ | ellipsis_tokens + equals.suppress() + refname # old long name ellision syntax
1256
+ # must come at end
1257
+ | namedexpr_test
1257
1258
  )
1258
1259
  function_call_tokens = lparen.suppress() + (
1259
1260
  # everything here must end with rparen
@@ -1303,7 +1304,7 @@ class Grammar(object):
1303
1304
  maybe_typedef = Optional(colon.suppress() + typedef_test)
1304
1305
  anon_namedtuple_ref = tokenlist(
1305
1306
  Group(
1306
- unsafe_name + maybe_typedef + equals.suppress() + test
1307
+ unsafe_name + maybe_typedef + (equals.suppress() + test | equals)
1307
1308
  | ellipsis_tokens + maybe_typedef + equals.suppress() + refname
1308
1309
  ),
1309
1310
  comma,
@@ -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 = 9
29
+ DEVELOP = 10
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"
@@ -313,10 +313,10 @@ def primary_test_2() -> bool:
313
313
  f.is_f = True # type: ignore
314
314
  assert (f ..*> (+)).is_f # type: ignore
315
315
  really_long_var = 10
316
- assert (...=really_long_var) == (10,)
317
- assert (...=really_long_var, abc="abc") == (10, "abc")
318
- assert (abc="abc", ...=really_long_var) == ("abc", 10)
319
- assert (...=really_long_var).really_long_var == 10 # type: ignore
316
+ assert (really_long_var=) == (10,)
317
+ assert (really_long_var=, abc="abc") == (10, "abc")
318
+ assert (abc="abc", really_long_var=) == ("abc", 10)
319
+ assert (really_long_var=).really_long_var == 10 # type: ignore
320
320
  n = [0]
321
321
  assert n[0] == 0
322
322
  assert_raises(-> m{{1:2,2:3}}, TypeError)
@@ -1055,8 +1055,8 @@ forward 2""") == 900
1055
1055
  assert InitAndIter(range(3)) |> fmap$((.+1), fallback_to_init=True) == InitAndIter(range(1, 4))
1056
1056
  assert_raises(-> InitAndIter(range(3)) |> fmap$(.+1), TypeError)
1057
1057
  really_long_var = 10
1058
- assert ret_args_kwargs(...=really_long_var) == ((), {"really_long_var": 10}) == ret_args_kwargs$(...=really_long_var)()
1059
- assert ret_args_kwargs(123, ...=really_long_var, abc="abc") == ((123,), {"really_long_var": 10, "abc": "abc"}) == ret_args_kwargs$(123, ...=really_long_var, abc="abc")()
1058
+ assert ret_args_kwargs(really_long_var=) == ((), {"really_long_var": 10}) == ret_args_kwargs$(really_long_var=)()
1059
+ assert ret_args_kwargs(123, really_long_var=, abc="abc") == ((123,), {"really_long_var": 10, "abc": "abc"}) == ret_args_kwargs$(123, really_long_var=, abc="abc")()
1060
1060
  assert "Coconut version of typing" in typing.__doc__
1061
1061
  numlist: NumList = [1, 2.3, 5]
1062
1062
  assert hasloc([[1, 2]]).loc[0][1] == 2 == hasloc([[1, 2]]) |> .loc[0][1]
@@ -240,7 +240,7 @@ operator ”
240
240
  (“) = (”) = (,) ..> map$(str) ..> "".join
241
241
 
242
242
  operator !
243
- addpattern def (int(x))! = 0 if x else 1 # type: ignore
243
+ match def (int(x))! = 0 if x else 1 # type: ignore
244
244
  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
@@ -664,7 +664,7 @@ match def fact(n) = fact(n, 1)
664
664
  match addpattern def fact(0, acc) = acc # type: ignore
665
665
  addpattern match def fact(n, acc) = fact(n-1, acc*n) # type: ignore
666
666
 
667
- addpattern def factorial(0, acc=1) = acc
667
+ match def factorial(0, acc=1) = acc
668
668
  addpattern def factorial(int() as n, acc=1 if n > 0) = # type: ignore
669
669
  """this is a docstring"""
670
670
  factorial(n-1, acc*n)
@@ -954,12 +954,12 @@ class MySubExc(MyExc):
954
954
 
955
955
  class test_super_A:
956
956
  @classmethod
957
- addpattern def method(cls, {'somekey': str()}) = True
957
+ match def method(cls, {'somekey': str()}) = True
958
958
 
959
959
 
960
960
  class test_super_B(test_super_A):
961
961
  @classmethod
962
- addpattern def method(cls, {'someotherkey': int(), **rest}) =
962
+ match def method(cls, {'someotherkey': int(), **rest}) =
963
963
  super().method(rest)
964
964
 
965
965
 
@@ -93,6 +93,11 @@ def non_strict_test() -> bool:
93
93
  @recursive_iterator
94
94
  def fib() = (1, 1) :: map((+), fib(), fib()$[1:])
95
95
  assert fib()$[:5] |> list == [1, 1, 2, 3, 5]
96
+ addpattern def args_or_kwargs(*args) = args
97
+ addpattern def args_or_kwargs(**kwargs) = kwargs # type: ignore
98
+ assert args_or_kwargs(1, 2) == (1, 2)
99
+ very_long_name = 10
100
+ assert args_or_kwargs(short_name=5, very_long_name=) == {"short_name": 5, "very_long_name": 10}
96
101
  return True
97
102
 
98
103
  if __name__ == "__main__":
@@ -185,6 +185,15 @@ parsing failed for format string expression: 1+ (line 2)
185
185
  ^
186
186
  """.strip())
187
187
 
188
+ assert_raises(-> parse("""
189
+ case def f[T]:
190
+ match(x) = x
191
+ """.strip()), CoconutSyntaxError)
192
+ assert_raises(-> parse("""
193
+ case def f[T]:
194
+ type(x: T) -> T
195
+ """.strip()), CoconutSyntaxError)
196
+
188
197
  assert_raises(-> parse("(|*?>)"), CoconutSyntaxError, err_has="'|?*>'")
189
198
  assert_raises(-> parse("(|**?>)"), CoconutSyntaxError, err_has="'|?**>'")
190
199
  assert_raises(-> parse("(<?*|)"), CoconutSyntaxError, err_has="'<*?|'")
@@ -478,6 +487,11 @@ type Num = int | float""".strip())
478
487
  # Compiled Coconut: -----------------------------------------------------------
479
488
 
480
489
  type L[T] = list[T]""".strip())
490
+ assert parse("def f[T](x) = x").strip().endswith("""
491
+ # Compiled Coconut: -----------------------------------------------------------
492
+
493
+ def f[T](x):
494
+ return x""".strip())
481
495
 
482
496
  setup(line_numbers=False, minify=True)
483
497
  assert parse("123 # derp", "lenient") == "123# derp"