Select Case operating like the C 'switch'

General FreeBASIC programming questions.
Linuxbob
Posts: 51
Joined: Sep 01, 2010 1:03
Location: Cincinnati, OH USA

Select Case operating like the C 'switch'

Postby Linuxbob » Dec 26, 2018 4:15

Question: how difficult would it be to modify Select Case to act like the C 'switch' keyword, allowing multiple selections in the same Select block? I am working on a project that would be easier to implement with a C-like implementation, but I can accomplish the task without it. Thanks in advance!
Tourist Trap
Posts: 2762
Joined: Jun 02, 2015 16:24

Re: Select Case operating like the C 'switch'

Postby Tourist Trap » Dec 26, 2018 13:26

(edit : hot wine abuse I guess.... skip this for good answer )

Have a good day!
Last edited by Tourist Trap on Dec 26, 2018 13:40, edited 1 time in total.
grindstone
Posts: 644
Joined: May 05, 2015 5:35
Location: Germany

Re: Select Case operating like the C 'switch'

Postby grindstone » Dec 26, 2018 13:31

There's no need for any modification, multiple selections are already possible:

Code: Select all

Dim As Integer x

Do
   x = Int(Rnd * 20)
   Select Case x
      Case 1,3,5,7,9,11,13,15,17,19
         Print x;" odd"
      Case 0,2,4,6,8,10,12,14,16,18,20
         Print x;" even"
   End Select
   Sleep 1000
Loop Until InKey = Chr(27)
counting_pine
Site Admin
Posts: 6170
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Select Case operating like the C 'switch'

Postby counting_pine » Dec 26, 2018 14:22

Select Case is generally a more powerful construct than switch:
- Case blocks allow not just one but a list of cases to match
- You can use variables as well as constants
- You can have ranged statements (e.g. '1 to 10', 'Is > 20')
- You can use strings or floating-point numbers, not just integers
- There is no fall-through, which of course means there are no accidental fall-through bugs

The lack of fall-through is the one thing that can make it hard to translate switch blocks.
But most fall-through cases are just when you want to handle multiple cases in the same block, which Select Case handles more clearly anyway.
In other situations, a label and Goto are required, but these tend to be much rarer.
Linuxbob
Posts: 51
Joined: Sep 01, 2010 1:03
Location: Cincinnati, OH USA

Re: Select Case operating like the C 'switch'

Postby Linuxbob » Dec 26, 2018 16:08

[quote="grindstone"]There's no need for any modification, multiple selections are already possible:

I understand that. The project I am working on requires me to do things with a CASE selection, and then perform additional tasks on a subset of the same selection. I can do it with an IF block within the CASE, but I was thinking about the possibility of capturing the subset with a fallthrough CASE immediately after the first CASE.
caseih
Posts: 1367
Joined: Feb 26, 2007 5:32

Re: Select Case operating like the C 'switch'

Postby caseih » Dec 26, 2018 16:54

The problem is you're proposing creating a new FB-like language. It certainly wouldn't be FB, and it wouldn't be able to compile FB code if select/case were changed to behave like the C switch statement.

Possibly FB could add a switch statement separate from select, but this would simply add complexity and maintenance burden on the few people who are actively maintaining the compiler, for very little gain and very few use cases. Plus if "case" were to be reused in both a select block and a switch block, that would add quite a bit of complexity to the parser. FB is already a huge language in terms of keywords (the largest I've ever used), and the parser is already complex.

C's switch statement has always been a strange concept. Powerful, yes, and probably intended to make low-level assembler-like algorithms possible. No other language I know of except C++ has a switch statement quite like that.

In your case you'll have to just code these bits yourself, or redesign your code to operate in a different fashion that takes advantage of FB's built-in constructs. One way is simply to reconstruct what switch code by using the same low-level primitives that a C compiler would turn it into. It's a series of IF statements (each "case") that jump (goto) the appropriate body section. The body sections are all sequential, so if you don't jump out of the body, it continues on to the next body. A C "break" would be a goto that jumps to the end of the bodies' code. I bet you could even wrap that in a macro somehow to hide the gotos. Each "switch" unit would have to have its own set of labels of course.
Last edited by caseih on Dec 26, 2018 16:59, edited 1 time in total.
Linuxbob
Posts: 51
Joined: Sep 01, 2010 1:03
Location: Cincinnati, OH USA

Re: Select Case operating like the C 'switch'

Postby Linuxbob » Dec 26, 2018 16:58

caseih wrote:The problem is you're proposing creating a new FB-like language. It certainly wouldn't be FB, and it wouldn't be able to compile FB code if select/case were changed to behave like the C switch statement.

Possibly FB could add a switch statement separate from select, but this would simply add complexity and maintenance burden on the few people who are actively maintaining the compiler, for very little gain and very few use cases. Plus if "case" were to be reused in both a select block and a switch block, that would add quite a bit of complexity to the parser. FB is already a huge language in terms of keywords (the largest I've ever used), and the parser is already complex.

C's switch statement has always been a strange concept. Powerful, yes, and probably intended to make low-level assembler-like algorithms possible. No other language I know of except C++ has a switch statement quite like that.

In your case you'll have to just code these bits yourself, or redesign your code to operate in a different fashion that takes advantage of FB's built-in constructs.


Hence my original question: how difficult would it be. The answer is apparently "fairly to very."
caseih
Posts: 1367
Joined: Feb 26, 2007 5:32

Re: Select Case operating like the C 'switch'

Postby caseih » Dec 26, 2018 17:01

Yes the answer is, "not going to happen!" although that could be for reasons that aren't purely technical.
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Select Case operating like the C 'switch'

Postby dodicat » Dec 26, 2018 17:54

You could cheat a little

Code: Select all

 
#define nobreak(n)  end select: select case n
   

dim as integer x=6

select case x

case 6
    print 6
    nobreak(x)
   
case 2 to 7
    print 2;" to ";7
    nobreak(x)
 
case 9 to 14
    print 9;" to ";14
    nobreak(x)
   
case 5 to 7
    print 5;" to ";7
    nobreak(x)
   
case  12
print 12
   

end select
sleep

 
grindstone
Posts: 644
Joined: May 05, 2015 5:35
Location: Germany

Re: Select Case operating like the C 'switch'

Postby grindstone » Dec 27, 2018 8:44

caseih wrote:I bet you could even wrap that in a macro somehow to hide the gotos.
Another elegant method to avoid those GOTOs (if desired) is the "abuse" of Do...Loop:

Code: Select all

Dim As Integer x

Do
   x = Int(Rnd * 100)
   Do
      Print x;" ";
      
      If x Mod 2 = 1 Then
         Print "odd"
         Exit Do
      EndIf
      
      If x Mod 2 = 0 Then
         Print "even"
         Exit Do
      EndIf
      
   Loop Until -1 'unconditional termination
   Sleep 1000
Loop Until InKey = Chr(27)
jj2007
Posts: 1214
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Select Case operating like the C 'switch'

Postby jj2007 » Dec 27, 2018 9:04

caseih wrote:C's switch statement has always been a strange concept. Powerful, yes, and probably intended to make low-level assembler-like algorithms possible. No other language I know of except C++ has a switch statement quite like that.
Compared to assembly's Switch macro, the C/C++ version is a toothless tiger - discussed here, and spiced with some German, apologies ;-)
caseih
Posts: 1367
Joined: Feb 26, 2007 5:32

Re: Select Case operating like the C 'switch'

Postby caseih » Dec 27, 2018 15:52

I think GOTO would be much faster than abusing do/loop. And probably easier to read.

Another idiom would be to break the case body code out into their own macros (or inline functions if FB supported that), and then just use a regular select/case and call the sequences of those macros or functions in the case body. This would be fast and very easy to read. And easier to refactor.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Select Case operating like the C 'switch'

Postby sancho3 » Dec 27, 2018 23:45

@linuxbob:
It would be great to see sample code of what you want the select case to behave like switch for.
I am certain that there will be a better method.

In any case I wanted to join in the fun and here is a type that accomplishes the task, but it seems to me to be going the hard way around.

Code: Select all

'---------------------------------
Type TCase
   As Integer min
   As Integer max
   As Sub(ByVal n As integer) case_sub
   Declare function is_in_range(ByVal n As integer) As boolean   
End Type
   Function TCase.is_in_range(ByVal n As Integer) As boolean
      If n < min Then Return FALSE
      If n > max Then Return FALSE
      Return TRUE 
   End Function
'--------------------------------
Type TSwitch
   As TCase cases(Any)
   As Integer count   
   Declare Sub add_case(ByRef c As TCase)
   Declare Sub switch(ByVal n As Integer)
End Type
   Sub TSwitch.add_case(ByRef c As TCase)
      With This
         .count += 1
         ReDim Preserve .cases(1 To count)
         .cases(.count) = c
      End With
   End Sub
   Sub TSwitch.switch(ByVal n As Integer) 
      With This
         For i As Integer = 1 To .count
            If cases(i).is_in_range(n) Then
               cases(i).case_sub(n)
            EndIf
         Next
      End With
   End Sub
'----------------------------   
dim as integer x=6
Dim As TSwitch switch

Sub case_a(ByVal n As Integer)
   Print "6", n
End Sub
Sub case_b(ByVal n As Integer)
   Print "2 to 7", n
End Sub
Sub case_c(ByVal n As Integer)
   Print "9 to 14", n
End Sub
Sub case_d(ByVal n As Integer)
   Print "5 to 7", n
End Sub
Sub case_e(ByVal n As Integer)
   Print "12", n
End Sub

Dim As TCase c

c.min = 6:c.max = 6:c.case_sub = @case_a
switch.add_case(c)
c.min = 2:c.max = 7:c.case_sub = @case_b
switch.add_case(c)
c.min = 9:c.max = 14:c.case_sub = @case_c
switch.add_case(c)
c.min = 5:c.max = 7:c.case_sub = @case_d
switch.add_case(c)
c.min = 12:c.max = 12:c.case_sub = @case_e
switch.add_case(c)

switch.switch(6)
   
sleep

 
grindstone
Posts: 644
Joined: May 05, 2015 5:35
Location: Germany

Re: Select Case operating like the C 'switch'

Postby grindstone » Dec 28, 2018 8:09

caseih wrote:I think GOTO would be much faster than abusing do/loop.
An interesting question, I never wondered about that point.

In a first approximation the execution speed seems to be quite the same:

Code: Select all

Dim As Integer x,y
Dim As Double trem

Do
   trem = Timer
   x = 0
   For y = 1 To 1000000000
      Do
         x += 1
         If x > 10000 Then
            Exit Do
         EndIf
      Loop
   Next
   Print "DO   ";Timer - trem
   
   trem = Timer
   x = 0
   For y = 1 To 1000000000
repeat:
      x += 1
      If x <= 10000 Then
         GoTo repeat
      EndIf
   Next
   Print "GOTO ";Timer - trem
   Print
Loop Until InKey = Chr(27)
So I would say it's up to the programmer which way (s)he prefers.

The only thing I strongly recommend is not to jump into such a loop, for this may cause unexpected side effects.
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Select Case operating like the C 'switch'

Postby dodicat » Dec 28, 2018 11:31

With -gen gcc both are reduced to goto in the c source code before being sent to gcc.
With -gen gas there is a distinct difference between the methods once settled down.

Return to “General”

Who is online

Users browsing this forum: No registered users and 3 guests