D's SwitchStatement accepts statements with ridiculous semantics

Timon Gehr timon.gehr at gmx.ch
Fri Sep 29 19:56:25 UTC 2017

On 29.09.2017 17:05, Don Clugston wrote:
>> I don't see what your proposed grammar change accomplishes:
>> switch(i){
>>     for(i=8;i<10;++i){
>>         case 7:
>>             writeln(i);
>>             return;
>>         default:{}
>>     }
>> }
>> I.e., you seem to have misidentified the culprit. Whether or not to 
>> the curly braces are required by the parser has nothing to do with 
>> switch semantics.
> That case looks quite different to me.
> It's rather more obvious that the `for` statement has been skipped.
> ...

Oh, I see. (They look the same to me.)

> The problem I have with the original example is that it looks as though 
> the body of the `for` loop is the body of the switch statement.
> ...

This can be done with basically any control flow construct we have:

if(i) for(i=8;i<10;++i)
     // ...

(This relates to my point about consistency.)

>>> Can we disallow this silliness please?
>> Maybe this specific case can be disallowed during semantic (but I 
>> don't really see why it helps, it mostly just makes the language 
>> definition more complex).
> I believe it makes it simpler. You cannot avoid the reference to 
> BlockStatement.

I don't see why. For example, my compiler implementation of SwitchStm 
does not mention BlockStm.

> Note that:  "A switch statement must have a default statement."
> This is only possible only in two situations.
> 1. Silly degenerate case.
>       switch (i) default: ;
> 2. A statement which contains a BlockStatement.
> It accepts unreachable code.
>    switch (i) if ( foo() ) {} else { default: ; }
> A switch statement followed by anything other than a BlockStatement is 
> *always* wrong. Always.
> ...

Well, I have used the switch(...) with(...) idiom you mentioned in the 
original post a few times, and I'm quite confident you'd meet some 
opposition if you were to break it.

There's also this case:

     static foreach(i;0..10)
         static if(i==0) default: return f!0();
         else case i: return f!i();

and, of course, this one:

final switch(x)
     static foreach(i;0..10)
         case i: return f!i();

> We improved the switch statement a lot by disallowing implicit 
> fallthrough.

Explicit fallthrough is still allowed though.

> But it still allows other nonsense that was presumably 
> inherited from the very early days of K&R C.
> This example just struck me as exceedingly silly, and quite misleading.

Well, 'switch' does not uphold the principles of structured programming. 
It is natural that one can extract some silliness from that, and I don't 
think changing grammar rules in inconsistent ways in order to disallow 
particular silly examples is a very good way to design a language.

I think removing () and requiring {} everywhere as Go and Rust have done 
is quite good language design which eliminates many of C's grammar 
issues, but it is not the path that D has taken and it does not improve 
switch semantics.

More information about the Digitalmars-d mailing list