Recent

Author Topic: how to break out early of a case ?  (Read 55417 times)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 10000
  • FPC developer.
Re: how to break out early of a case ?
« Reply #45 on: May 02, 2020, 10:54:44 pm »
Am I correct in assuming that if fall-through is not the default like in C, a break / leave statement is not necessary?
Code: Text  [Select][+][-]
  1.   when n
  2.     is 0 do
  3.       n = 1;
  4.       fall;
  5.     is 1 do
  6.       n = 2;
  7.     is 2 do
  8.       n = 3;
  9.     is 3 do
  10.       n = 4;
  11.     end;

Yeah. Since break is the default. But allowing to change the case condition and then fall through is messy IMHO. Be sure to document that very thoroughly. It will be hard to write optimizers for such case blocks (since the fallthrough and the modification of the case criterium are extra constraints to weigh in that)

munair

  • Hero Member
  • *****
  • Posts: 791
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #46 on: May 02, 2020, 11:03:43 pm »
I just changed the construct by replacing 'leave' with 'fall' and removing 'also':
Code: Text  [Select][+][-]
  1. var n: int = 0;
  2.  
  3. main do
  4.  
  5.   when n
  6.     is 0 do
  7.       n = 1;
  8.       fall;
  9.     is 1 do
  10.       n = 2;
  11.       fall;
  12.     is 2 do
  13.       n = 3;
  14.       fall;
  15.     is 3 do
  16.       n = 4;
  17.     end;
  18.  
  19.   print n;      ' 4
  20.  
  21. end;

But leaving out one 'fall' in a matching case will break the chain and exit the when-block.

But allowing to change the case condition and then fall through is messy IMHO.
I agree. That wouldn't be an option.
« Last Edit: May 03, 2020, 08:48:44 am by munair »
keep it simple

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 10000
  • FPC developer.
Re: how to break out early of a case ?
« Reply #47 on: May 02, 2020, 11:13:58 pm »
I would leave out fallthrough entirely. Not worth the effort, mostly theoretical cases only.

munair

  • Hero Member
  • *****
  • Posts: 791
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #48 on: May 02, 2020, 11:17:03 pm »
I would leave out fallthrough entirely. Not worth the effort, mostly theoretical cases only.

I actually have one routine in the compiler where it would come in handy. Generally, most of the time fall-through isn't needed, but in some cases it can prevent code duplication, or one would have to resort to loop constructs, which isn't ideal.

In any case, the current implementation works. And the explicit 'fall' statement makes the switch-block much less bug prone. Not easy to overlook anyway.
« Last Edit: May 03, 2020, 08:49:23 am by munair »
keep it simple

munair

  • Hero Member
  • *****
  • Posts: 791
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #49 on: May 02, 2020, 11:30:58 pm »
fall through _is_ the default in C, which can be a very annoying characteristic.

Misunderstanding. I meant to say that if fall-through is not the default... (I know in C it is the default).
« Last Edit: May 02, 2020, 11:50:58 pm by munair »
keep it simple

440bx

  • Hero Member
  • *****
  • Posts: 2774
Re: how to break out early of a case ?
« Reply #50 on: May 03, 2020, 12:02:05 am »
Code: Text  [Select][+][-]
  1. var n: int = 0;
  2.  
  3. main do
  4.  
  5.   when n
  6.     is 0 do
  7.       n = 1;
  8.       fall;
  9.     is 1 do
  10.       n = 2;
  11.       fall;
  12.     is 2 do
  13.       n = 3;
  14.       fall;
  15.     is 3 do
  16.       n = 4;
  17.     end;
  18.  
  19.   print n;      ' 4
  20.  
  21. end;
That looks good.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 11547
Re: how to break out early of a case ?
« Reply #51 on: May 03, 2020, 07:00:40 am »
fall through _is_ the default in C, which can be a very annoying characteristic.
I would leave out fallthrough entirely. Not worth the effort, mostly theoretical cases only.
I disagree here. We used to use that a lot in C libraries where some of the options needed preparatory setup before any option later in the switch could be executed, example: partial information need to be completed first. E.g. when a ticker was not yet in the cache, so its static information needed to be retrieved first before processing trade information.
I seem to remember I once suggested to use continue for that, so you get basically kind of a reverse syntax to C, but introducing at least the option to fall-through.
It was refused, not only as a feature, but also because it was not needed if the case labels would allow overlap anyway, shame on me  :-[ . (I was thinking about re-labeling, or case labels as true sets)
I still think that the mutual exclusiveness for case labels is a limitation rather than a feature.
Although similar solutions can be written such a feature is not only notational candy, but a clear grouping of related code. It enhances readability. {$modeswitch OverlappedCaseLabels}?
« Last Edit: May 03, 2020, 07:41:25 am by Thaddy »
Путин преступник. Россияне дезинформированы.

munair

  • Hero Member
  • *****
  • Posts: 791
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #52 on: May 03, 2020, 09:49:15 am »
Here is a practical example that could be part of a compiler to check a literal against a type. I currently use similar code but not as efficient due to the lack of fall-through functionality.

Code: Text  [Select][+][-]
  1.   // suppose type = tuint and literal = "0"
  2.  
  3.   if litype == litint do  
  4.     when val(literal)
  5.       is -128 to 0 do
  6.         when type is tint8, tint16, tint32, tint do
  7.           return true;
  8.         end;
  9.         fall;
  10.       is -32768 to 0 do
  11.         when tid is tint16, tint32, tint do
  12.           return true;
  13.         end;
  14.         fall;
  15.       is -2147483648 to 0 do
  16.         when type is tint32, tint do
  17.           return true;
  18.         end;
  19.         fall;
  20.       is 0 to 127 do
  21.         when type is tint8, tuint8, tint16, tuint16, tint32, tuint32, tint, tuint do
  22.           return true;
  23.         end;
  24.       // ..
  25.     end;
  26.   end;

Without fall-through the compiler would raise a type mismatch because it would bail-out with the first case that matches "0".
« Last Edit: May 04, 2020, 12:42:27 pm by munair »
keep it simple

BrunoK

  • Sr. Member
  • ****
  • Posts: 291
  • Retired programmer
Re: how to break out early of a case ?
« Reply #53 on: May 03, 2020, 10:11:58 pm »
How is all that code / discussion related to freepascal / object pascal ?


munair

  • Hero Member
  • *****
  • Posts: 791
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #54 on: May 04, 2020, 08:41:46 am »
How is all that code / discussion related to freepascal / object pascal ?
It has been a feature request more than once.
keep it simple

BrunoK

  • Sr. Member
  • ****
  • Posts: 291
  • Retired programmer
Re: how to break out early of a case ?
« Reply #55 on: May 04, 2020, 01:48:54 pm »
Frankly, what's the problem with :
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. var
  3.   n: integer = 0;
  4. begin
  5.   repeat
  6.     case n of
  7.       0: n := 1;
  8.       1: n := 2;
  9.       2: n := 3;
  10.       3: begin
  11.         n := 4;
  12.         break;
  13.       end;
  14.     end;
  15.   until False;
  16.   writeln(n); // 4
  17.   // or
  18.   n := 0;
  19.   if n=0 then n := 1;
  20.   if n=1 then n := 2;
  21.   if n=2 then n := 3;
  22.   if n=3 then n := 4;
  23.   writeln(n); // 4
  24.   readln;
  25. end.
« Last Edit: May 04, 2020, 02:16:05 pm by BrunoK »

Thaddy

  • Hero Member
  • *****
  • Posts: 11547
Re: how to break out early of a case ?
« Reply #56 on: May 04, 2020, 02:39:39 pm »
The first is inefficient, the second can written better with sets.
Путин преступник. Россияне дезинформированы.

BrunoK

  • Sr. Member
  • ****
  • Posts: 291
  • Retired programmer
Re: how to break out early of a case ?
« Reply #57 on: May 04, 2020, 02:50:45 pm »
The first is inefficient, the second can written better with sets.
Ok for the first, except it addresses breaking out early.

Publish working code for the second that matches the n : integer or keep out.

munair

  • Hero Member
  • *****
  • Posts: 791
  • compiler developer @SharpBASIC
    • SharpBASIC
Re: how to break out early of a case ?
« Reply #58 on: May 04, 2020, 02:55:51 pm »
Yes, like Thaddy said, a loop is inefficient. It requires a conditional jump and a full case walk-over each time, whereas a fall instruction is just one unconditional jump. In addition, a fall can be made conditional:
Code: Text  [Select][+][-]
  1. var n: int = 0;
  2.  
  3. main
  4. do
  5.   when true is 1 > n do  
  6.     when n
  7.       is 0 do
  8.         n = 1;
  9.         if n > 0 do
  10.           fall;
  11.         end;
  12.       is 1 do
  13.         n = 2;
  14.     end;
  15.   end;
  16. end;

EDIT: Indeed, sets can somewhat replace case ranges. In SharpBASIC a when/case block is meant to fulfill both IF and IN constructs.
« Last Edit: May 04, 2020, 03:28:00 pm by munair »
keep it simple

BrunoK

  • Sr. Member
  • ****
  • Posts: 291
  • Retired programmer
Re: how to break out early of a case ?
« Reply #59 on: May 04, 2020, 03:29:52 pm »
Yes, like Thaddy said, a loop is inefficient. It requires a conditional jump and a full case walk-over each time, whereas a fall instruction is just one unconditional jump. I addition, each fall can be made conditional:
Code: Text  [Select][+][-]
  1. var n: int = 0;
  2.  
  3. main
  4. do
  5.   when true is 1 > n do  
  6.     when n
  7.       is 0 do
  8.         n = 1;
  9.         if n > 0 do
  10.           fall;
  11.         end;
  12.       is 1 do
  13.         n = 2;
  14.     end;
  15.   end;
  16. end;
Please, can you comment what this bit of code is supposed to do or where documentation can be found on such instructions.

 

TinyPortal © 2005-2018