View mode: basic / threaded / horizontal-split · Log in · Help
March 15, 2005
Again about switch() { default } and co.
In my opinion following code:

     uint flags = ...some bit flag value...;

     uint f = DT_NOPREFIX | DT_SINGLELINE;
     switch( flags & 0xF)
     {
       case Graphics.DRAW.LEFT: f |= DT_LEFT; break;
       case Graphics.DRAW.RIGHT: f |= DT_RIGHT; break;
       case Graphics.DRAW.CENTER: f |= DT_CENTER; break;
     }
     switch( flags & 0xF0)
     {
       case Graphics.DRAW.TOP: f |= DT_TOP; break;
       case Graphics.DRAW.BOTTOM: f |= DT_BOTTOM; break;
       case Graphics.DRAW.MIDDLE: f |= DT_VCENTER; break;
     }
     ..... use of translated 'f' ....

is perfectly valid and yet logicaly clear.

But DMD/Walter does not like it for some reasons.

absence of default: break; branch being
compiled with -debug flag generates an exception in runtime (only, sic!) and
compiled with -release flag generates no exception in runtime.

This is, IMO, just unacceptable.
Either it shall not compile at all either it shall not generate an exception
(btw: in some very strange place in debugger).

And yet I don't understand intentions of forcing 'default' in 'switch'.
I am pretty sure that this was already discussed many times in the past.
Could somebody provide me a link for the discussion?
I would like to know intentions.

Andrew.
March 15, 2005
Re: Again about switch() { default } and co.
On Tue, 15 Mar 2005 13:47:57 -0800, Andrew Fedoniouk  
<news@terrainformatica.com> wrote:
> In my opinion following code:
>
>       uint flags = ...some bit flag value...;
>
>       uint f = DT_NOPREFIX | DT_SINGLELINE;
>       switch( flags & 0xF)
>       {
>         case Graphics.DRAW.LEFT: f |= DT_LEFT; break;
>         case Graphics.DRAW.RIGHT: f |= DT_RIGHT; break;
>         case Graphics.DRAW.CENTER: f |= DT_CENTER; break;
>       }
>       switch( flags & 0xF0)
>       {
>         case Graphics.DRAW.TOP: f |= DT_TOP; break;
>         case Graphics.DRAW.BOTTOM: f |= DT_BOTTOM; break;
>         case Graphics.DRAW.MIDDLE: f |= DT_VCENTER; break;
>       }
>       ..... use of translated 'f' ....
>
> is perfectly valid and yet logicaly clear.
>
> But DMD/Walter does not like it for some reasons.
>
> absence of default: break; branch being
> compiled with -debug flag generates an exception in runtime (only, sic!)  
> and
> compiled with -release flag generates no exception in runtime.
>
> This is, IMO, just unacceptable.
> Either it shall not compile at all either it shall not generate an  
> exception
> (btw: in some very strange place in debugger).
>
> And yet I don't understand intentions of forcing 'default' in 'switch'.
> I am pretty sure that this was already discussed many times in the past.
> Could somebody provide me a link for the discussion?
> I would like to know intentions.

http://www.digitalmars.com/drn-bin/wwwnews?D/19523

In short, when you write:

switch(x) {
  case 1: ..etc.. break;
  case 2: ..etc.. break;
}

Are you saying:
a. "x can only have 2 values, 1 or 2"
b. "I only want to handle x with values 1 and 2".

The compiler has no way of knowing for sure.

If (a), and x == 3 at some stage then this is clearly a bug, and asserting  
will let you know this and tell you where it is.

If (b), then you are required to state your intent explicitly, i.e.

switch(x) {
  case 1: ..etc.. break;
  case 2: ..etc.. break;
  default: break; //I don't care what other values it has
}

Of course, not everyone agrees with this reasoning. Personally, I think  
it's sound/good/valid.

Regan
March 15, 2005
Re: Again about switch() { default } and co.
On Tue, 15 Mar 2005 13:47:57 -0800, Andrew Fedoniouk wrote:

> In my opinion following code:
> 
>       uint flags = ...some bit flag value...;
> 
>       uint f = DT_NOPREFIX | DT_SINGLELINE;
>       switch( flags & 0xF)
>       {
>         case Graphics.DRAW.LEFT: f |= DT_LEFT; break;
>         case Graphics.DRAW.RIGHT: f |= DT_RIGHT; break;
>         case Graphics.DRAW.CENTER: f |= DT_CENTER; break;
>       }
>       switch( flags & 0xF0)
>       {
>         case Graphics.DRAW.TOP: f |= DT_TOP; break;
>         case Graphics.DRAW.BOTTOM: f |= DT_BOTTOM; break;
>         case Graphics.DRAW.MIDDLE: f |= DT_VCENTER; break;
>       }
>       ..... use of translated 'f' ....
> 
> is perfectly valid and yet logicaly clear.
> 
> But DMD/Walter does not like it for some reasons.
> 
> absence of default: break; branch being
> compiled with -debug flag generates an exception in runtime (only, sic!) and
> compiled with -release flag generates no exception in runtime.
> 
> This is, IMO, just unacceptable.
> Either it shall not compile at all either it shall not generate an exception
> (btw: in some very strange place in debugger).
> 
> And yet I don't understand intentions of forcing 'default' in 'switch'.
> I am pretty sure that this was already discussed many times in the past.
> Could somebody provide me a link for the discussion?
> I would like to know intentions.

On the assumption that the vast majority of compiles results in an edition
of the application that is to undergo testing rather than being distributed
to end users, then the non -release editions attempt to help you find
'hidden' or unexpected bugs. One source of mistakes that coders have often
made is not accounting for all *possible* cases in a switch expression. And
by 'accounting for' I mean both dealing with processing the cases *and*
with telling the readers of the code that I have 'thought about
such-and-such'.

By placing the phrase "default: [statements . . .] break;" you are letting
the code readers (people and compilers) know that you have accepted
responsibility for cases not explicitly processed in the switch cases above
it.

In -release editions of your application, the assumption is that you have
completed enough testing and reviews, that for all practical
considerations, there are no mistakes in the switch code. Thus the compiler
removes (avoids inserting) code that will cause a runtime error that is not
likely to ever actually happen.

-- 
Derek Parnell
Melbourne, Australia
http://www.dsource.org/projects/build/
http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage
16/03/2005 9:20:48 AM
March 15, 2005
Re: Again about switch() { default } and co.
> Of course, not everyone agrees with this reasoning. Personally, I think 
> it's sound/good/valid.

I would agree with you if it will not compile it.
But it does - means that this construction is syntacticly valid.

I would expect either one:
1) invalid syntax - not compiled statemnt, dmd::exit(-1)
2) valid syntax - no assertion in runtime (neither debug nor release).
   warning could be generated if needed.

Andrew.



"Regan Heath" <regan@netwin.co.nz> wrote in message 
news:opsno88aew23k2f5@nrage.netwin.co.nz...
> On Tue, 15 Mar 2005 13:47:57 -0800, Andrew Fedoniouk 
> <news@terrainformatica.com> wrote:
>> In my opinion following code:
>>
>>       uint flags = ...some bit flag value...;
>>
>>       uint f = DT_NOPREFIX | DT_SINGLELINE;
>>       switch( flags & 0xF)
>>       {
>>         case Graphics.DRAW.LEFT: f |= DT_LEFT; break;
>>         case Graphics.DRAW.RIGHT: f |= DT_RIGHT; break;
>>         case Graphics.DRAW.CENTER: f |= DT_CENTER; break;
>>       }
>>       switch( flags & 0xF0)
>>       {
>>         case Graphics.DRAW.TOP: f |= DT_TOP; break;
>>         case Graphics.DRAW.BOTTOM: f |= DT_BOTTOM; break;
>>         case Graphics.DRAW.MIDDLE: f |= DT_VCENTER; break;
>>       }
>>       ..... use of translated 'f' ....
>>
>> is perfectly valid and yet logicaly clear.
>>
>> But DMD/Walter does not like it for some reasons.
>>
>> absence of default: break; branch being
>> compiled with -debug flag generates an exception in runtime (only, sic!) 
>> and
>> compiled with -release flag generates no exception in runtime.
>>
>> This is, IMO, just unacceptable.
>> Either it shall not compile at all either it shall not generate an 
>> exception
>> (btw: in some very strange place in debugger).
>>
>> And yet I don't understand intentions of forcing 'default' in 'switch'.
>> I am pretty sure that this was already discussed many times in the past.
>> Could somebody provide me a link for the discussion?
>> I would like to know intentions.
>
> http://www.digitalmars.com/drn-bin/wwwnews?D/19523
>
> In short, when you write:
>
> switch(x) {
>   case 1: ..etc.. break;
>   case 2: ..etc.. break;
> }
>
> Are you saying:
> a. "x can only have 2 values, 1 or 2"
> b. "I only want to handle x with values 1 and 2".
>
> The compiler has no way of knowing for sure.
>
> If (a), and x == 3 at some stage then this is clearly a bug, and asserting 
> will let you know this and tell you where it is.
>
> If (b), then you are required to state your intent explicitly, i.e.
>
> switch(x) {
>   case 1: ..etc.. break;
>   case 2: ..etc.. break;
>   default: break; //I don't care what other values it has
> }
>
> Of course, not everyone agrees with this reasoning. Personally, I think 
> it's sound/good/valid.
>
> Regan
March 15, 2005
Re: Again about switch() { default } and co.
Hi, Derek,

> By placing the phrase "default: [statements . . .] break;" you are letting
> the code readers (people and compilers) know that you have accepted
> responsibility for cases not explicitly processed in the switch cases 
> above
> it.

I understand the idea but not the implementation.
Let dmd.exe  generate warnings on 'no default'. Fine
But not exceptions, please.
This implemetation ruins the meaning of  word
'debug' completely.
It is not a debug it is just different program - with
different flow (exceptions) and the like.

Andrew.


"Derek Parnell" <derek@psych.ward> wrote in message 
news:ycuvh26p74lq$.17x2pikkndxzc$.dlg@40tude.net...
> On Tue, 15 Mar 2005 13:47:57 -0800, Andrew Fedoniouk wrote:
>
>> In my opinion following code:
>>
>>       uint flags = ...some bit flag value...;
>>
>>       uint f = DT_NOPREFIX | DT_SINGLELINE;
>>       switch( flags & 0xF)
>>       {
>>         case Graphics.DRAW.LEFT: f |= DT_LEFT; break;
>>         case Graphics.DRAW.RIGHT: f |= DT_RIGHT; break;
>>         case Graphics.DRAW.CENTER: f |= DT_CENTER; break;
>>       }
>>       switch( flags & 0xF0)
>>       {
>>         case Graphics.DRAW.TOP: f |= DT_TOP; break;
>>         case Graphics.DRAW.BOTTOM: f |= DT_BOTTOM; break;
>>         case Graphics.DRAW.MIDDLE: f |= DT_VCENTER; break;
>>       }
>>       ..... use of translated 'f' ....
>>
>> is perfectly valid and yet logicaly clear.
>>
>> But DMD/Walter does not like it for some reasons.
>>
>> absence of default: break; branch being
>> compiled with -debug flag generates an exception in runtime (only, sic!) 
>> and
>> compiled with -release flag generates no exception in runtime.
>>
>> This is, IMO, just unacceptable.
>> Either it shall not compile at all either it shall not generate an 
>> exception
>> (btw: in some very strange place in debugger).
>>
>> And yet I don't understand intentions of forcing 'default' in 'switch'.
>> I am pretty sure that this was already discussed many times in the past.
>> Could somebody provide me a link for the discussion?
>> I would like to know intentions.
>
> On the assumption that the vast majority of compiles results in an edition
> of the application that is to undergo testing rather than being 
> distributed
> to end users, then the non -release editions attempt to help you find
> 'hidden' or unexpected bugs. One source of mistakes that coders have often
> made is not accounting for all *possible* cases in a switch expression. 
> And
> by 'accounting for' I mean both dealing with processing the cases *and*
> with telling the readers of the code that I have 'thought about
> such-and-such'.
>
> By placing the phrase "default: [statements . . .] break;" you are letting
> the code readers (people and compilers) know that you have accepted
> responsibility for cases not explicitly processed in the switch cases 
> above
> it.
>
> In -release editions of your application, the assumption is that you have
> completed enough testing and reviews, that for all practical
> considerations, there are no mistakes in the switch code. Thus the 
> compiler
> removes (avoids inserting) code that will cause a runtime error that is 
> not
> likely to ever actually happen.
>
> -- 
> Derek Parnell
> Melbourne, Australia
> http://www.dsource.org/projects/build/
> http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage
> 16/03/2005 9:20:48 AM
March 15, 2005
Re: Again about switch() { default } and co.
On Tue, 15 Mar 2005 14:32:14 -0800, Andrew Fedoniouk wrote:

> Hi, Derek,
> 
>> By placing the phrase "default: [statements . . .] break;" you are letting
>> the code readers (people and compilers) know that you have accepted
>> responsibility for cases not explicitly processed in the switch cases 
>> above
>> it.
> 
> I understand the idea but not the implementation.

Sorry Andrew, I knew that you understood the idea. I was just spelling it
out in case some other person reading this was not aware.

But as for the warnings, I believe that Walter has made the decision that
people need to opt-in for warnings. I suspect that Walter is not trying to
encourage the 'warning' concept but has (grudgingly?) allowed people who
want them to explicitly choose to have them. So if one doesn't turn on
warnings, then the consequence is that you get a run time error. True,
*which* run time error depends on whether you have compiled with -release
or not. 

The -debug switch is very misunderstood, IMO. It does not cause DMD to
insert debugging code, but it enables you to include hand-crafted debugging
code into your application. DMD inserts its own variety of debugging code
if you do not compile with -release.

-- 
Derek Parnell
Melbourne, Australia
http://www.dsource.org/projects/build/
http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage
16/03/2005 9:42:36 AM
March 15, 2005
Re: Again about switch() { default } and co.
On Tue, 15 Mar 2005 14:24:10 -0800, Andrew Fedoniouk  
<news@terrainformatica.com> wrote:
>> Of course, not everyone agrees with this reasoning. Personally, I think
>> it's sound/good/valid.
>
> I would agree with you if it will not compile it.
> But it does - means that this construction is syntacticly valid.

Correct. And technically it *is* "syntactically" valid. But, It might also  
be a bug.

The compiler cannot know for certain at compile time, because it cannot  
know all the possible values the variable 'x' can take eg.

switch(x) {
  case 1:
  case 2:
}

can 'x' be '3'?

So, it *might* be a bug, it might not.

> I would expect either one:
> 1) invalid syntax - not compiled statemnt, dmd::exit(-1)

Technically, the syntax isn't invalid. However, I know what you mean... It  
could produce an error for every switch with a missing default  
statement.That would force you to specify one, but, unless you're well  
versed on this subject and the code involved there can be problems, eg:

1) default: break;
2) default: assert(0); break
3) default: ..code you forgot.. break;

You should add #1 if it's reachable but no code is required.
You should add #2 if it's (supposedly) unreachable.
You should add #3 if it's a genuine bug/mistake, i.e. you forgot to code  
the case.

The problem arises that if you're in a hurry, or otherwise not thinking  
clearly, or this error is in someone else's code and you just want to get  
it to build, you may add #1 when you should add #2 or #3, in this case  
you're delaying the detection of a bug, it will manifest later in the code.

> 2) valid syntax - no assertion in runtime (neither debug nor release).
>     warning could be generated if needed.

D does not have warnings.. until recently.. perhaps this is a candidate  
for a warning, though last time that was suggested Walter did not think  
so, but then, last time there were no other warnings.

Regan


> "Regan Heath" <regan@netwin.co.nz> wrote in message
> news:opsno88aew23k2f5@nrage.netwin.co.nz...
>> On Tue, 15 Mar 2005 13:47:57 -0800, Andrew Fedoniouk
>> <news@terrainformatica.com> wrote:
>>> In my opinion following code:
>>>
>>>       uint flags = ...some bit flag value...;
>>>
>>>       uint f = DT_NOPREFIX | DT_SINGLELINE;
>>>       switch( flags & 0xF)
>>>       {
>>>         case Graphics.DRAW.LEFT: f |= DT_LEFT; break;
>>>         case Graphics.DRAW.RIGHT: f |= DT_RIGHT; break;
>>>         case Graphics.DRAW.CENTER: f |= DT_CENTER; break;
>>>       }
>>>       switch( flags & 0xF0)
>>>       {
>>>         case Graphics.DRAW.TOP: f |= DT_TOP; break;
>>>         case Graphics.DRAW.BOTTOM: f |= DT_BOTTOM; break;
>>>         case Graphics.DRAW.MIDDLE: f |= DT_VCENTER; break;
>>>       }
>>>       ..... use of translated 'f' ....
>>>
>>> is perfectly valid and yet logicaly clear.
>>>
>>> But DMD/Walter does not like it for some reasons.
>>>
>>> absence of default: break; branch being
>>> compiled with -debug flag generates an exception in runtime (only,  
>>> sic!)
>>> and
>>> compiled with -release flag generates no exception in runtime.
>>>
>>> This is, IMO, just unacceptable.
>>> Either it shall not compile at all either it shall not generate an
>>> exception
>>> (btw: in some very strange place in debugger).
>>>
>>> And yet I don't understand intentions of forcing 'default' in 'switch'.
>>> I am pretty sure that this was already discussed many times in the  
>>> past.
>>> Could somebody provide me a link for the discussion?
>>> I would like to know intentions.
>>
>> http://www.digitalmars.com/drn-bin/wwwnews?D/19523
>>
>> In short, when you write:
>>
>> switch(x) {
>>   case 1: ..etc.. break;
>>   case 2: ..etc.. break;
>> }
>>
>> Are you saying:
>> a. "x can only have 2 values, 1 or 2"
>> b. "I only want to handle x with values 1 and 2".
>>
>> The compiler has no way of knowing for sure.
>>
>> If (a), and x == 3 at some stage then this is clearly a bug, and  
>> asserting
>> will let you know this and tell you where it is.
>>
>> If (b), then you are required to state your intent explicitly, i.e.
>>
>> switch(x) {
>>   case 1: ..etc.. break;
>>   case 2: ..etc.. break;
>>   default: break; //I don't care what other values it has
>> }
>>
>> Of course, not everyone agrees with this reasoning. Personally, I think
>> it's sound/good/valid.
>>
>> Regan
>
>
March 15, 2005
Re: Again about switch() { default } and co.
Thanks Derek,

"...DMD inserts its own variety of debugging code
if you do not compile with -release..."

See, you are using "debugging code"
But in fact it should be just debugging information, right?

If I *explicitly* say
debug {
  something
}
it is a code. But what does compiler in -debug should not be a 'code'.

"nondestructive test" should not introduce sideffects
(exceptions)
Runtime warnings are fine - as much as you wish - they help a lot.
But not exceptions from under the hood which you did not programed
and not expect neither in debug nor in release.

Andrew.



"Derek Parnell" <derek@psych.ward> wrote in message 
news:81ie2v5f7n06.ylqpa53ohfhz$.dlg@40tude.net...
> On Tue, 15 Mar 2005 14:32:14 -0800, Andrew Fedoniouk wrote:
>
>> Hi, Derek,
>>
>>> By placing the phrase "default: [statements . . .] break;" you are 
>>> letting
>>> the code readers (people and compilers) know that you have accepted
>>> responsibility for cases not explicitly processed in the switch cases
>>> above
>>> it.
>>
>> I understand the idea but not the implementation.
>
> Sorry Andrew, I knew that you understood the idea. I was just spelling it
> out in case some other person reading this was not aware.
>
> But as for the warnings, I believe that Walter has made the decision that
> people need to opt-in for warnings. I suspect that Walter is not trying to
> encourage the 'warning' concept but has (grudgingly?) allowed people who
> want them to explicitly choose to have them. So if one doesn't turn on
> warnings, then the consequence is that you get a run time error. True,
> *which* run time error depends on whether you have compiled with -release
> or not.
>
> The -debug switch is very misunderstood, IMO. It does not cause DMD to
> insert debugging code, but it enables you to include hand-crafted 
> debugging
> code into your application. DMD inserts its own variety of debugging code
> if you do not compile with -release.
>
> -- 
> Derek Parnell
> Melbourne, Australia
> http://www.dsource.org/projects/build/
> http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage
> 16/03/2005 9:42:36 AM
March 15, 2005
Re: Again about switch() { default } and co.
On Tue, 15 Mar 2005 15:02:54 -0800, Andrew Fedoniouk  
<news@terrainformatica.com> wrote:
> Thanks Derek,
>
> "...DMD inserts its own variety of debugging code
> if you do not compile with -release..."
>
> See, you are using "debugging code"
> But in fact it should be just debugging information, right?

Well.. it's not "D code", it's "machine code" which is added.

Regan
March 16, 2005
Re: Again about switch() { default } and co.
On Tue, 15 Mar 2005 15:02:54 -0800, Andrew Fedoniouk wrote:

> Thanks Derek,
> 
> "...DMD inserts its own variety of debugging code
> if you do not compile with -release..."
> 
> See, you are using "debugging code"
> But in fact it should be just debugging information, right?
> 
> If I *explicitly* say
> debug {
>    something
> }
> it is a code. But what does compiler in -debug should not be a 'code'.
> 
> "nondestructive test" should not introduce sideffects
> (exceptions)
> Runtime warnings are fine - as much as you wish - they help a lot.
> But not exceptions from under the hood which you did not programed
> and not expect neither in debug nor in release.

Hmmmm... could be just a terminology issue, but when I talked about DMD
inserting code, I was talking about it inserting machine code instructions
into the object file it creates. And the machine code is not derived from
any D source code you wrote.

-- 
Derek
Melbourne, Australia
16/03/2005 11:56:37 AM
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home