DIP23 Counter Proposal

Timon Gehr timon.gehr at gmx.ch
Wed Feb 6 13:30:09 PST 2013


On 02/06/2013 08:09 PM, Andrei Alexandrescu wrote:
> On 2/6/13 12:41 PM, Timon Gehr wrote:
>>> If they do, in this context parens are also
>>> punctuation, not expression grouping; they don't enclose an expression,
>>> but instead define &(((...(foo)...))) as a sole syntactic unit (!).
>>>
>>
>> They are neither. They are just insignificant information thrown away by
>> the parser.
>
> Nononono. Hold them horses. We can't gloss over things like that.

We don't! What I have stated is accurate. (You can check the DMD source, 
if that helps.)

> That means in this context parens don't have the usual meaning of expression
> grouping, because what's inside is not an expression.

PrimaryExpression:
     Identifier
     ...

> They are punctuation that makes &((...(symbol)...)) one syntactic unit identical
> to &symbol.
>

Again, &((...(symbol)...)) and &symbol are both serialized 
representations of

    &
    |
  symbol

I.e. they mean the same thing.

>>> This also leads to potential confusion, seeing as &(foo) takes the
>>> address of foo, but &( true ? foo : bar ) does, in fact, take the
>>> address of whatever foo returns.
>>
>> Ah, very good point! But please note that this is 100% a ternary
>> operator issue.
>
> Not at all.

I meant 'as opposed to a paren issue'.

&( true ? foo : bar ) // <-- note the ternary operator

> What do these mean?
>
> &({ return fun; }())

That is equivalent to

&(&__dgliteral0)()

where

auto __dgliteral0(){ return fun; }


> &(fun, fun)
>

Agh, comma strikes again. It should be handled analogous to the ternary 
expression. i.e. the expression above evaluates fun and then returns the 
function pointer. The DIP now states this. (the second fun is in 
address-taken position.) This is in agreement to how lvalue positions 
propagate into comma expressions.

> The last one is really fun because the same thing may be evaluated first
> and then have its address taken. Wow. But of course it doesn't. Why?
> Because "&" and parens have special meaning for &(fun), which is my point.
>

Now you are saying that parens _do_ have a special meaning?

>>> This all makes DIP24 fail meet its own definition of success as far as I
>>> understand it, i.e. keeping "&" to mean operator and parens to mean
>>> grouping.
>>
>> 1. There is no point where the DIP calls "&" an "operator".
>
> It doesn't have to. It's everywhere else in the language.

No way. I repeat:

auto x = 5;
auto y = &5; // error!
auto z = &x; // ok!

> That's my point: new meaning of "&".
>...

Obviously your reading of my post was quite shallow.

>> 2. It succeeds in keeping parens mean grouping. (Given any of the two
>> behaviours of ternary expressions.)
>>
>> DIP24 meets its own definition of success.
>
> Of course, if moving the goalposts is an option.

It is. DIP24 is in draft stage. Moving the goalposts was not necessary 
so far though.

> My understanding was that the express purpose of DIP24 was to avoid potential confusion and avoid ascribing new meaning to "&" or parens.
> As far as I can tell it failed at both: "&" is sometimes not an operator, and parens sometimes don't encompass expressions.

"&" is never an operator and parens always encompass expressions. 
Additionally, there is a bunch of rewrite rules to get parentheses on 
function calls optional.

>>> In my opinion, it also makes DIP24 fail to improve over DIP23.
>>> ...
>>
>> In my opinion too. It conveniently also makes all other statements true,
>> as the line of reasoning crucially depends on fallaciously ascribing
>> properties of the ternary operator to the parens enclosing it.
>
> That got destroyed above.
>

No. It's just that both ternary expressions and comma expressions can 
propagate lvalue-positions, and I had forgotten about the comma 
expression as I was in a hurry.

>> (The second fallacy is ascribing the properties of rvalue vs. lvalue
>> distinction inherited from C to DIP24.)
>>
>>> DIP23 has in fact /fewer/ such problems, because it clarifies that &foo
>>> and &expr.foo are indivisible syntactic units; thus parentheses are not
>>> ascribed a special meaning by DIP23.
>>
>> That is inaccurate, and it is special enough that I do not care to fully
>> formalize the special meaning ascribed to parentheses by DIP23.
>
> DIP23 does not ascribe any special meaning to parentheses.

It does. To the point that the parser has to be changed, just in order 
to implement rewrite rules.

> That's actually part of the point and a good thing about it.
> I think there's a misunderstanding somewhere.
>

Definitely.

>> Basically it makes use of parens affect whether some position in the
>> syntax tree is treated as lvalue or rvalue position in some special cases.
>
> No, that is incorrect.
>

It is correct.

&fun   // <-- fun occurs in lvalue position
&(fun) // <-- (fun) occurs in lvalue position

You are now arguing for making the 'fun''s in "fun" and "(fun)" behave 
differently. The first should behave as if it was in address-taken 
(lvalue) position and the second should behave as if it was not (as if 
it was in rvalue position).

The rules for context dependency were intended to closely parallel those 
of lvalue position propagation in order to minimize the amount of new 
rules. If you see any other differences, please step up.

>>> If DIP25 gets approved, taking the address of ref results will be
>>> banned, and therefore that potential meaning of "&" disappears, which
>>> simplifies things.
>>
>> How? It only adds code to my front-end to make sure the case is actually
>> caught and properly reported. It does not even simplify the byte code
>> compiler. (Because it uses similar code paths for the &foo() and
>> foo()=exp cases.)
>
> I think DIP24 means more code to the front end, more special rules,

Well, you are wrong, and as far as I can tell, the speculation is 
entirely unfounded.

DIP23 is not even _implementable_ currently, because it does not even 
attempt to handle all cases that are necessary to handle. In order to do 
that, it would need to copy most of the rules of DIP24. Then, making 
&fun and &(fun) behave differently is more work than making them behave 
the same.

> more explaining,  and more confusion than DIP23.
>

I do not have any hard data on this, but &fun and &(fun) meaning 
different things is extremely confusing. Note that this is not actually 
part of DIP23 yet for non- at property functions. (It is just left 
unspecified.) I guess this is an oversight?

>>> But we'll still have to live with the reality that in
>>> the constructs "&foo" and "&expr.foo", "&" is not an operator.
>>
>> As well as in all other constructs where it is used in unary form.

Still holds.

>>> And that's okay.
>>>
>>
>> Except for the unfortunate confusion it can cause.
>
> And that DIP24 does not get rid of.

Neither does DIP23. That is not their purpose.




More information about the Digitalmars-d mailing list