Jump to page: 1 2
Thread overview
Again about switch() { default } and co.
Mar 15, 2005
Andrew Fedoniouk
Mar 15, 2005
Regan Heath
Mar 15, 2005
Andrew Fedoniouk
Mar 15, 2005
Regan Heath
Mar 15, 2005
Derek Parnell
Mar 15, 2005
Andrew Fedoniouk
Mar 15, 2005
Derek Parnell
Mar 15, 2005
Andrew Fedoniouk
Mar 15, 2005
Regan Heath
Mar 16, 2005
Derek Parnell
The new guys
Mar 16, 2005
Ant
Mar 16, 2005
AEon
Mar 16, 2005
Sebastian Beschke
Re: The new guys (Errors)
March 15, 2005
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
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
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
> 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
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
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
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
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
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
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