diff --git a/DOCS.md b/DOCS.md index ad0f92144..81444fabd 100644 --- a/DOCS.md +++ b/DOCS.md @@ -1650,7 +1650,6 @@ Coconut supports a number of different syntactical aliases for common partial ap ```coconut .attr => operator.attrgetter("attr") .method(args) => operator.methodcaller("method", args) -obj. => getattr$(obj) func$ => ($)$(func) seq[] => operator.getitem$(seq) iter$[] => # the equivalent of seq[] for iterators diff --git a/coconut/compiler/compiler.py b/coconut/compiler/compiler.py index ea54ae5e7..7ac899ab6 100644 --- a/coconut/compiler/compiler.py +++ b/coconut/compiler/compiler.py @@ -2290,7 +2290,7 @@ def pipe_handle(self, original, loc, tokens, **kwargs): elif name == "right op partial": return partial_op_item_handle(item) elif name == "await": - raise CoconutDeferredSyntaxError("cannot pipe from await, only into await", loc) + raise CoconutDeferredSyntaxError("await in pipe must have something piped into it", loc) else: raise CoconutInternalException("invalid split pipe item", split_item) @@ -2367,7 +2367,7 @@ def pipe_handle(self, original, loc, tokens, **kwargs): else: raise CoconutInternalException("invalid pipe operator direction", direction) - def item_handle(self, loc, tokens): + def item_handle(self, original, loc, tokens): """Process trailers.""" out = tokens.pop(0) for i, trailer in enumerate(tokens): @@ -2381,6 +2381,7 @@ def item_handle(self, loc, tokens): elif trailer[0] == "[]": out = "_coconut.functools.partial(_coconut.operator.getitem, " + out + ")" elif trailer[0] == ".": + self.strict_err_or_warn("'obj.' as a shorthand for 'getattr$(obj)' is deprecated (just use the getattr partial)", original, loc) out = "_coconut.functools.partial(_coconut.getattr, " + out + ")" elif trailer[0] == "type:[]": out = "_coconut.typing.Sequence[" + out + "]" @@ -2395,7 +2396,7 @@ def item_handle(self, loc, tokens): raise CoconutDeferredSyntaxError("None-coalescing '?' must have something after it", loc) not_none_tokens = [none_coalesce_var] not_none_tokens.extend(rest_of_trailers) - not_none_expr = self.item_handle(loc, not_none_tokens) + not_none_expr = self.item_handle(original, loc, not_none_tokens) # := changes meaning inside lambdas, so we must disallow it when wrapping # user expressions in lambdas (and naive string analysis is safe here) if ":=" in not_none_expr: diff --git a/coconut/root.py b/coconut/root.py index 023acb6c4..12af06fbc 100644 --- a/coconut/root.py +++ b/coconut/root.py @@ -26,7 +26,7 @@ VERSION = "3.0.0" VERSION_NAME = None # False for release, int >= 1 for develop -DEVELOP = 24 +DEVELOP = 25 ALPHA = True # for pre releases rather than post releases # ----------------------------------------------------------------------------------------------------------------------- diff --git a/coconut/tests/src/cocotest/agnostic/primary.coco b/coconut/tests/src/cocotest/agnostic/primary.coco index ac447c664..66204d421 100644 --- a/coconut/tests/src/cocotest/agnostic/primary.coco +++ b/coconut/tests/src/cocotest/agnostic/primary.coco @@ -97,7 +97,6 @@ def primary_test() -> bool: assert isinstance(one_line_class(), one_line_class) assert (.join)("")(["1", "2", "3"]) == "123" assert "" |> .join <| ["1","2","3"] == "123" - assert "". <| "join" <| ["1","2","3"] == "123" assert 1 |> [1,2,3][] == 2 == 1 |> [1,2,3]$[] assert 1 |> "123"[] == "2" == 1 |> "123"$[] assert (| -1, 0, |) :: range(1, 5) |> list == [-1, 0, 1, 2, 3, 4] @@ -448,7 +447,6 @@ def primary_test() -> bool: assert None?[herp].derp is None # type: ignore assert None?(derp)[herp] is None # type: ignore assert None?$(herp)(derp) is None # type: ignore - assert "a b c" == (" ". ?? "not gonna happen")("join")("abc") a: int[]? = None # type: ignore assert a is None assert range(5) |> iter |> reiterable |> .[1] == 1 @@ -1583,4 +1581,5 @@ def primary_test() -> bool: assert (in)(1, [1, 2]) assert not (1 not in .)([1, 2]) assert not (in)([[]], []) + assert ("{a}" . .)("format")(a=1) == "1" return True diff --git a/coconut/tests/src/cocotest/agnostic/suite.coco b/coconut/tests/src/cocotest/agnostic/suite.coco index ba52851a5..ad31e6a53 100644 --- a/coconut/tests/src/cocotest/agnostic/suite.coco +++ b/coconut/tests/src/cocotest/agnostic/suite.coco @@ -92,7 +92,7 @@ def suite_test() -> bool: assert collatz(27) assert preop(1, 2).add() == 3 assert vector(3, 4) |> abs == 5 == vector_with_id(3, 4, 1) |> abs - assert vector(1, 2) |> ((v) -> map(v., ("x", "y"))) |> tuple == (1, 2) # type: ignore + assert vector(1, 2) |> ((v) -> map(getattr$(v), ("x", "y"))) |> tuple == (1, 2) # type: ignore assert vector(3, 1) |> vector(1, 2).transform |> ((v) -> map(v[], (0, 1))) |> tuple == (4, 3) # type: ignore assert vector(1, 2) |> vector(1, 2).__eq__ assert not vector(1, 2) |> vector(3, 4).__eq__ diff --git a/coconut/tests/src/cocotest/non_strict/non_strict_test.coco b/coconut/tests/src/cocotest/non_strict/non_strict_test.coco index 17284f1d3..099e0dad2 100644 --- a/coconut/tests/src/cocotest/non_strict/non_strict_test.coco +++ b/coconut/tests/src/cocotest/non_strict/non_strict_test.coco @@ -80,6 +80,8 @@ def non_strict_test() -> bool: assert weird_func()()(5) == 5 a_dict: TextMap[str, int] = {"a": 1} assert a_dict["a"] == 1 + assert "". <| "join" <| ["1","2","3"] == "123" + assert "a b c" == (" ". ?? "not gonna happen")("join")("abc") return True if __name__ == "__main__": diff --git a/coconut/tests/src/cocotest/target_36/py36_test.coco b/coconut/tests/src/cocotest/target_36/py36_test.coco index 6ad956bae..69b755360 100644 --- a/coconut/tests/src/cocotest/target_36/py36_test.coco +++ b/coconut/tests/src/cocotest/target_36/py36_test.coco @@ -49,6 +49,18 @@ def py36_test() -> bool: loop.run_until_complete(aiter_test()) assert l == list(range(10)) + list(range(10)) + async def arec(x) = await arec(x-1) if x else x + async def atest(): + assert ( + 10 + |> arec + |> await + |> (.+10) + |> arec + |> await + ) == 0 + loop.run_until_complete(atest()) + loop.close() return True diff --git a/coconut/tests/src/extras.coco b/coconut/tests/src/extras.coco index 533f19706..7edb48f6c 100644 --- a/coconut/tests/src/extras.coco +++ b/coconut/tests/src/extras.coco @@ -292,6 +292,7 @@ else: assert_raises(-> parse("""case x: match x: pass"""), CoconutStyleError, err_has="case x:") + assert_raises(-> parse("obj."), CoconutStyleError, err_has="getattr") setup(strict=True, target="sys") assert_raises(-> parse("await f x"), CoconutParseError, err_has='invalid use of the keyword "await"')