groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <blackd...@gmx.org>
Subject Re: Parrot and the ++ and -- operators
Date Mon, 13 Feb 2017 18:52:21 GMT


On 12.02.2017 16:11, Mauro Zallocco wrote:
> Hi all.
>
> I tried this:
> groovy -version
> Groovy Version: 2.4.6 JVM: 1.8.0_66 Vendor: Oracle Corporation OS: Windows 7
>
> int i = 0
> ++(++(++i));
> assert i == 1
>
> However with C++, it gives 3.

It took me a while, but I think I start to get an idea why this happens.
"++i" is recognized by the compiler as it should be. But it is legal in 
Groovy to do ++1 for example. Of course we will not change the value of 
the literal 1 here. This is just to show that there is such a logic 
applying to any expression. In that sense (++i) will return a value and 
then we do ++ on that value to do it again on the result. The outer two 
cases do not involve a local variable. Or let me write this a little bit 
different:

++i is expanded to:
tmp = i.next()
i = tmp
return tmp

"++(++i)" is:
tmp = i.next()
i = tmp
return ++tmp

which is:
tmp = i.next()
i = tmp
tmp2 = tmp.next()
return tmp2

and that is because during code generation we work from inside out and 
do not return any expression.

If had this implemented in a macro manner we would probably have done 
something like this:
++i is expanded to (i = i+1)
++(++i) is expanded to ++(i=i+1) with the rule of ++ only applying to 
the local variable on the RHS we expand then to i=i+1+1.
Then of course ++(++(++i)) is i=i+1+1+1, with the compiler most probably 
shortening this to i=i+3

But as I said, we do not do it in a macro manner, instead we work with 
the result of an expression and the result of i=i.next() is the value of 
RHS, thus whatever i.next() returns. There is no chance to increase the 
value in the local variable here.

Options:
(1) do nothing and explain the difference only
(2) do allow these post- and prefix operators only on 
VariableExpressions, making the code above no longer compile
(3) do special casing
(4) combine 2 and 3 to require a VariableExpression as innermost 
expression and allow only prefix or postfix operators outside

Since (3) will include (1) to some extend my feeling here is, that this 
is no good idea at all. (1) is surely underdocumented atm. But the real 
question is if we should go with 1,2 or 4. And preferred solution is to 
go with 2. Anyone able to think of a really really good reason not to?

bye Jochen

Mime
View raw message