September 16, 2003
"Ian Woollard" <Ian_member@pathlink.com> ha scritto nel messaggio news:bk5nri$14cm$1@digitaldaemon.com...
> [...] The default behaviour is really unsafe. I would
> suggest a 'nobreak' statement for cases where you really do want the code
to
> fall through; otherwise  the compiler probably should fail to compile
(possibly
> switcheable off with a compiler option.)

I vote for that too.

And BTW, Walter, while we're on the subject... how about multiple-value case labels, a la VB?

switch (x)
{
case 0:
    ...
case 1, 3, 5:
    ...
case 2, 4, 6 to 10:  // or 6..10 as in Pascal, or [6, 10] or whatever
    ...
case is < 1:  // see comments on this one below
    ...
case 11, 13 to 15, is > 16:  // All together now!
    ...
default:  // no, I'm not proposing a "case else" :)
}

While all other forms are simply short for writing more labels, the "is" form really requires the switch to be compiled as it was a series of if's, with the difference that part of the if expression has already been evaluated. The syntax would be "is <relational operator> <expression>"

If the switched-on expression is an object, overloaded operators might be used (provided it's not already so); in this case, "case is <obj_reference_or_null>" would compare pointers instead of checking object equality. Note that I'm following the "is" operator proposal here...

OK, just daydreaming maybe... I suppose that optimizing such a thing would be rather hard... anyway I tried...

Ric


September 16, 2003
>>[...] The default behaviour is really unsafe. I would
>>suggest a 'nobreak' statement for cases where you really do want the code
>>to
>>fall through; otherwise  the compiler probably should fail to compile
>>(possibly
>>switcheable off with a compiler option.)
> 
> I vote for that too.

I'd like to see a nobreak statement, but I absolutely hate to see a compiler option that basically changes the language. If a D program is valid then it should always be valid. And if it is not then the compiler shouldn't accept it, no matter what switches you pass.

Otherwise we will end up with two different types of D programs (the auto-fall-through and the nobreak-required one) that are not source compatible. Stuff like that should be avoided from the very beginning, so there should be a definite decision on wether nobreak is required or not.


> And BTW, Walter, while we're on the subject... how about multiple-value case
> labels, a la VB?

I think that is a nice idea. And it would also make the nobreak requirement less of a hassle, since most fall through cases are really multi-value cases (i.e. the same code body for all cases).

> switch (x)
> {
> case 0:
>     ...
> case 1, 3, 5:
>     ...
> case 2, 4, 6 to 10:  // or 6..10 as in Pascal, or [6, 10] or whatever
>     ...
> case is < 1:  // see comments on this one below
>     ...

Is the last 'case' consistent with the proposed use of the "is" operator as a replacement for ===? Wouldn't this mean that if x is an object, then the pointer would be compared with 1?

> If the switched-on expression is an object, overloaded operators might be
> used (provided it's not already so); in this case, "case is
> <obj_reference_or_null>" would compare pointers instead of checking object
> equality. Note that I'm following the "is" operator proposal here...

One thing to consider is that case statements involving objects and overloaded operators make it impossible for the compiler to check wether they are non-overlapping. E.g.

class X;

X c1;
X c2;
X c3;

switch(somevalue)
{
case < c1: ...
	break;
case [c2..c3]: ...
	break;
}

How should the compiler check wether there isn't a value v < c1 that is also >=c2 and <=c3?

Now that I think more about it, I think retrofitting switch to become as powerful as if is probably not a good idea at all. Lets face it, the switch statement is really only an optimization to help the compiler generate efficient code. If switch was as powerful as if, then there would be no additional optimization possibilities and the whole statement would be pretty useless. [Oh the irony ;)].

Hauke


September 16, 2003
I recall that there are good reasons for not having compile-time options that change the semantics of the code. If my memory is not failing me, Walter said somewhere that he has a rather strong opinion about this.

Generally I think the same, but I'd allow the following border case:

- Default behavior of switch statement is to break.
- Keyword "fallthrough" is required to, well, fall through.
- A compiler-switch "-require-explicit-break-or-fallthrough" that will
  require explicit "break;" or "fallthrough;". The purpose of this
  switch is to make porting C apps easier.

That way you could write native D apps without writing the tedious break
statement. After all, as Philippe said, the behavior in 9 out of
10 cases is to break. The superfluous breaks just clutter up the code.

If you'd need to port C apps, just use the option -require-explicit-break-or-fallthrough and insert "fallthrough" where there is no break. After the code compiles, you can remove the option and works correctly. There will be a couple of redundant break statements but they won't hurt anyone.

-Antti

In article <bk615t$22md$1@digitaldaemon.com>, John Boucher wrote:
> Hmmm, a compiler switch to say whether or not it is required... kinda starting to border on being a pragma, isn't it?
> 
> In article <bk5pk9$1a54$1@digitaldaemon.com>, Ian Woollard says...
>>
>>In article <bk5o47$15o3$1@digitaldaemon.com>, Charles Sanders says...
>>>I like the idea of a nobreak statement ( this has been a popular topic) , I
>>>think the reason for keeping this is backward compatibility ( on a user
>>>level ).
>>
>>Provided the nobreak statement is optional (just a nasty compiler warning if left out), or mandatory but the compiler has a flag to make it ignore it's omission (but still warn- my colleagues ARE out to get me :-) ), then backward compatibility is, in practice, a non issue.
>>
>>>Charles
> 
> 
September 16, 2003
In article <bk6n5l$11j6$1@digitaldaemon.com>, Hauke Duden wrote:
> Now that I think more about it, I think retrofitting switch to become as powerful as if is probably not a good idea at all. Lets face it, the switch statement is really only an optimization to help the compiler generate efficient code. If switch was as powerful as if, then there would be no additional optimization possibilities and the whole statement would be pretty useless. [Oh the irony ;)].

Of course, you *could* make the switch statement a generalization of the old one without losing optimizations.

Just define switch so that

switch (<expr>)
{
case <c11>, <c12>:
    <statement1>
case <c2>:
    <statement2>
...
default:
    <statementn>
}

is be semantically equivalent to (ignoring fallthroughs for a moment, they'd have to be implemented with gotos or sth like that)

typeof <expr> tmp = <expr>;

if ((tmp == <c11>) || (tmp == <c12>))
{
    <statement1>
}
else if (tmp == <c2>)
{
    <statement2>
}
else
{
    <statementn>
}

The compiler will in this case have to recognize the "old-style" switch statements (where all cases are constant and maybe not overlapping), which should be trivial, and perform the usual optimizations on them. More complex statements (where some case is non-constant) are implemented as an if-elseif-etc-else statement.

-Antti
September 16, 2003
Please not that the suggested syntax leaves both 'break' and 'nobreak' redundant.

erik

In article <bk6fbt$8n2$1@digitaldaemon.com>, Riccardo De Agostini says...
>
>"Ian Woollard" <Ian_member@pathlink.com> ha scritto nel messaggio news:bk5nri$14cm$1@digitaldaemon.com...
>> [...] The default behaviour is really unsafe. I would
>> suggest a 'nobreak' statement for cases where you really do want the code
>to
>> fall through; otherwise  the compiler probably should fail to compile
>(possibly
>> switcheable off with a compiler option.)
>
>I vote for that too.
>
>And BTW, Walter, while we're on the subject... how about multiple-value case labels, a la VB?
>
>switch (x)
>{
>case 0:
>    ...
>case 1, 3, 5:
>    ...
>case 2, 4, 6 to 10:  // or 6..10 as in Pascal, or [6, 10] or whatever
>    ...
>case is < 1:  // see comments on this one below
>    ...
>case 11, 13 to 15, is > 16:  // All together now!
>    ...
>default:  // no, I'm not proposing a "case else" :)
>}
>
>While all other forms are simply short for writing more labels, the "is" form really requires the switch to be compiled as it was a series of if's, with the difference that part of the if expression has already been evaluated. The syntax would be "is <relational operator> <expression>"
>
>If the switched-on expression is an object, overloaded operators might be used (provided it's not already so); in this case, "case is <obj_reference_or_null>" would compare pointers instead of checking object equality. Note that I'm following the "is" operator proposal here...
>
>OK, just daydreaming maybe... I suppose that optimizing such a thing would be rather hard... anyway I tried...
>
>Ric
>
>


September 16, 2003
Antti Sykäri wrote:
> Of course, you *could* make the switch statement a generalization of the
> old one without losing optimizations.

<snip>

> The compiler will in this case have to recognize the "old-style" switch
> statements (where all cases are constant and maybe not overlapping),
> which should be trivial, and perform the usual optimizations on them.
> More complex statements (where some case is non-constant) are
> implemented as an if-elseif-etc-else statement.

I don't know. To me this seems to be a feature that complicates the the language (and the compiler) with not much of a real benefit. If you need if-capabilities, why not use if? You might need a temporary variable to store the "switch value", but that is really the only downside I see.

Upsides of leaving the switch-case statement simple are:

- less complicated compiler
- no need to invent new syntax to express <,>,<=, is-in-interval [a..b], ]a..b], [a..b[, ]a..b[ etc.
- You can instantly be certain that you are looking at "flat" code (i.e. code where no operator overloads and stuff like that are involved) when you see a switch statement.

I still think a multi-case statement would be nice, though. It would only be syntactic sugar for multiple cases with a fallthrough, of course, but this is something that would probably actually be useful in everyday programming. Especially if "nobreak" is required to fall through to the next case statement.


Hauke

September 16, 2003
"Riccardo De Agostini" <riccardo.de.agostini@email.it> ha scritto nel messaggio news:bk6fbt$8n2$1@digitaldaemon.com...
> I vote for that too.

Except for the compiler option, I meant. Let D be D.

Ric


September 16, 2003
"Hauke Duden" <H.NS.Duden@gmx.net> ha scritto nel messaggio news:bk6n5l$11j6$1@digitaldaemon.com...
> Is the last 'case' consistent with the proposed use of the "is" operator as a replacement for ===? Wouldn't this mean that if x is an object, then the pointer would be compared with 1?

Nice and right objection. I blind-copied it from VB. "is" might as well be omitted altogether.

> One thing to consider is that case statements involving objects and overloaded operators make it impossible for the compiler to check wether they are non-overlapping.

I think the first matching case should apply.

> Now that I think more about it, I think retrofitting switch to become as powerful as if is probably not a good idea at all. Lets face it, the switch statement is really only an optimization to help the compiler generate efficient code. If switch was as powerful as if, then there would be no additional optimization possibilities and the whole statement would be pretty useless. [Oh the irony ;)].

The switch statement is a logical construct; the fact that it *can* be optimized, e.g. using jump tables, pertains to the compiler's internals. I don't think that such extreme optimizations are needed any longer on today's machines, or at least they could be sacrificed (at least partially; DMD _is_ an optimizing compiler, it does not optimize only switch statements...) if the advantages in code readability and maintainability are found to be more important than the loss in pure speed.

Besides, when the switch expression is really an expression (as opposed to a single variable) it is computed once, which doesn't happen with chained if's...

Ric


September 16, 2003
"Antti Sykäri" <jsykari@gamma.hut.fi> ha scritto nel messaggio news:slrnbmdvgs.jlv.jsykari@pulu.hut.fi...
> The compiler will in this case have to recognize the "old-style" switch statements (where all cases are constant and maybe not overlapping), which should be trivial, and perform the usual optimizations on them. More complex statements (where some case is non-constant) are implemented as an if-elseif-etc-else statement.

Great! Now I'm curious about Walter's opinion, he's the compiler guy after all...

Ric


September 16, 2003
"Erik Baklund" <Erik_member@pathlink.com> ha scritto nel messaggio news:bk6vgp$1rn2$1@digitaldaemon.com...
> Please not that the suggested syntax leaves both 'break' and 'nobreak' redundant.

Of course: break should be implied. Thanks for pointing that out.

Ric