Re: About eliminating ambiguities of method call with closure argument

2020-03-29 Thread Jochen Theodorou

On 29.03.20 14:17, Paul King wrote:

Groovy's original rule was that a newline terminates a statement when it
could sensibly finish (successfully complete an expression) at that
point. So if you've opened a curly brace or bracket, for instance, the
newline would not auto-terminate an expression/statement.

The rule was later expanded with some lookahead to also merge lines when
the subsequent line couldn't be a valid statement in its own right. This
allows the following for example in Groovy 3:

def truth = maybe
   && possibly


For me the whole problem here is actually Java. People did always write
things similar to this:

"""
memberNames.stream().filter((s) -> s.startsWith("A"))
 .map(String::toUpperCase)
 .forEach(System.out::println);
"""

and IDEs like Intellij IDEA are actually forcing you into this style
quite a bit. The dot is not our problem though, it is the curly brace,
plus and minus in combination with optional return.

"""
def x = "some long text"
+ "another line"
"""

As we all know for Groovy this can mean two expression statements or one
while in

"""
def x = "some long text" +
"another line"
"""

it is very clear for the compiler that the lines belong together. So if
we make the first PLUS - example two statements we essentially "broke"
Java code.


So I was thinking we could do something intelligent with the compiler
and react differently if we have the last line or not... only that will
not solve the Spock problem at all.

So I have another alternative to suggest (besides ditching trying to be
so exact source compatible with Java), and that is:

* make plus and minus always align to the line before, essentially
disabling standalone unary plus and minus. If you want to return them,
you will have to write return.

* make Closure and block on the next line always detached from the line
before. If they are supposed to belong together, then the curly brace
has to be on the line before.


Coming back to the examples before:

```
meth
{ p ->
}
```

and

```
a | meth
{ p ->
}
```

will be two expression statements, while

```
meth { p ->
}
```

will be one.

And yes, I fully expect this to break existing code. And yes, that is
basically an inconsistent rule, since we handle +/- different from {...
though there is a difference between a syntax element like { and a
binary/unary operator

bye Jochen







Re: About eliminating ambiguities of method call with closure argument

2020-03-29 Thread Paul King
Groovy's original rule was that a newline terminates a statement when it
could sensibly finish (successfully complete an expression) at that point.
So if you've opened a curly brace or bracket, for instance, the newline
would not auto-terminate an expression/statement.

The rule was later expanded with some lookahead to also merge lines when
the subsequent line couldn't be a valid statement in its own right. This
allows the following for example in Groovy 3:

def truth = maybe
  && possibly

The string concatenation example doesn't work because of the
unaryPlus/unaryMinus operators. I'd be keen to do a GEP to see those
removed (obviously retained for numbers but no longer overridable) for
Groovy 4, then we could also support the String concatenation example and a
bunch of edge cases we currently can't support could be handled (e.g. we
currently support "def x = -0.4" but not "def y = -.4"). But that is a
separate issue in any case.

The issue at hand for GROOVY-9484 is whether we can simplify our grammar
rules and the exceptional cases that users need to remember. There are
several paths which lead to simpler rules than we have now. Some of those
would impact existing Spock code. If we put our thinking caps on we might
even be able to find alternative (even better?) solutions for Spock.

It would certainly also be good to capture the whitespace rules more
clearly in our documentation.


Paul.



On Sun, Mar 29, 2020 at 11:03 AM Remko Popma  wrote:

>
> > On Mar 29, 2020, at 0:19, Milles, Eric (TR Tech, Content & Ops) <
> eric.mil...@thomsonreuters.com> wrote:
> >
> > Is there any language that differentiates between one space and
> multiple whitespaces as a separator?  My experience with C, C++, Java,
> Groovy, etc. is that any number of whitespaces are the same in terms of
> separation between tokens.
> Not really:
>
> String accepted = "a" +
> "b" // works, gives "ab"
>
> String bad = "a"
> + "b" // compile error
>
> So, white space is significant in Groovy.
>
> >
> > In terms of parsing, you can't tell that an identifier is a method name
> -- you mention below closure follows method name -- you don't know until
> semantic analysis and possibly runtime in terms of dynamic Groovy if an
> identifier refers to a method name.
> >
> >
> > Can the user insert a semicolon to disambiguate?
> > ```
> > a | meth ; // now the parser knows this statement is over
> > { p ->
> > }
> > ```
> >
> > I don't think you are ever going to see an end to ambiguous constructs
> due to optional parentheses  and semicolons.
> >
> > -Original Message-
> > From: Daniel.Sun 
> > Sent: Friday, March 27, 2020 10:06 PM
> > To: d...@groovy.incubator.apache.org
> > Subject: About eliminating ambiguities of method call with closure
> argument
> >
> > Hi all,
> >
> >   Current groovy grammar of method call contains the following
> ambiguities, which are odd for users. For example,
> >
> > 1) method call with closure argument. That means the closure on the next
> line could be treated as argument of method `meth` ``` meth { p -> } ```
> >
> > 2) binary expression and closure expression. That means the closure is
> not an argument.
> > ```
> > a | meth
> > { p ->
> > }
> > ```
> >
> >   I propose to unify the grammar of closure arguments: when closure
> follows method name directly, it is an argument, otherwise it is just
> standalone closure. For example,
> >
> > 3) method call with closure argument
> > ```
> > meth { p ->
> > }
> > ```
> >
> > 4) variable and closure
> > ```
> > meth
> > { p ->
> > }
> > ```
> >
> >   Luckily, groovy-parser project containing source code of some
> famous groovy projects, none of which are broken because of the proposed
> change[1].
> >
> >   Here is a JIRA ticket[2] to track the proposed change, and here is
> the PR[3] to implement the change.
> >
> >   Any thoughts?
> >
> > Cheers,
> > Daniel Sun
> > [1]
> https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fdanielsun1106%2Fgroovy-parser%2Fcommits%2FGROOVY-9484data=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cbc5bd8c149104982c52b08d7d2c503df%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637209615925168880sdata=qdhNufAqJP8kpOtsz1QWwz2b06pR%2F1v5loQnNcuWWRM%3Dreserved=0
> > [2]
> https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fissues.apache.org%2Fjira%2Fbrowse%2FGROOVY-9484data=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cbc5bd8c149104982c52b08d7d2c503df%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637209615925168880sdata=Z3FyviGcsG4EtvIGiAv889dG%2F2p%2FhqClAED998%2BnT98%3Dreserved=0
> > [3]
> https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fapache%2Fgroovy%2Fpull%2F1211data=02%7C01%7Ceric.milles%40thomsonreuters.com%7Cbc5bd8c149104982c52b08d7d2c503df%7C62ccb8646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637209615925168880sdata=iXdv8OT3BMIyno8R3TlLclEB1%2BSd%2BxPlCaxhacydSqA%3Dreserved=0
> >
> >
> >
> >
> > -
> > Apache Groovy committer & PMC