Topic: Extending the switch statement


Author: robert@alkymi.unit.no (Robert Schmidt)
Date: Tue, 10 Aug 93 13:20:31 GMT
Raw View
In article <1993Aug6.154137@ra.alcbel.be>, jvsb@ra.alcbel.be (Johan Vanslembrouck) writes:
|>
|> This extension does not break existing code; the switch with one
|> selector
|> is a special case of the multi-selector switch.
|>

It does break existing (though rare) code, or will at best confuse the
compiler.  Your example was:

 switch (z_state, z_control_code)
                ^^^^^^^^^^^^^^^^^^^^^^^
The above is perfectly legal already, and evaluates to z_control_code.
Another separation operator is required.

 {
   case e_statc_idle, e_cntlc_open_disp :
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I'm not sure if the same applies here.  The case values must be constants,
not expressions in the current definitions, so this looks usable.

   case e_statc_idle, e_cntlc_open_dyn :
  statements
  break;
   case e_statc_idle, e_cntlc_open_mod :
  statements
  break;
   case e_statc_disp, e_cntlc_open_dyn :
  statements
  break;
   case *,  e_cntlc_user_abort:
              ^^^
This looks terrible. * is both multiplication and dereferencing, and you
want it to extend it to work as a wildcard?

  statements
  break;
   default:
  statements
 }



--
Robert Schmidt - robert@alkymi.unit.no - Buuud@IRC
Ztiff Zox Softwear: fast/tiny utilities, games/graphics programming on
                    the DOS platform (C/C++ & asm).  Suggestions welcome!

Everything I write is my opinion only - go make up your own!




Author: warwick@cs.uq.oz.au (Warwick Allison)
Date: 10 Aug 93 23:48:22 GMT
Raw View
The "multiple arguments" and "anything with ==" propositions are the same:


        switch ({1,2}) {
                case {1,2}:
                        printf("1,2\n");
        break;  case {2,1}:
                        printf("2,1\n");
        }

--
Warwick
  _-_|\      warwick@cs.uq.oz.au            /
 /     * <-- Computer Science Department,  /
 \_.-._/     University of Queensland,    /         How now, Tao cow?
      v      Brisbane, Australia.        /




Author: jvsb@ra.alcbel.be (Johan Vanslembrouck)
Date: 11 Aug 93 07:16:57 GMT
Raw View
I agree with the observation made by Allison Warwick in article
<14834@uqcspe.cs.uq.oz.au> that the "multiple argument switch"
proposed in <1993Aug6.154137@ra.alcbel.be> can be simulated
(except for the wildcard) by structuring the arguments first into a struct
or a class on which the == operator has been defined,
assuming of course that C++ supports such classes as the argument type
of the switch statement
(see article <1993Aug4.135526.27658@mnemosyne.cs.du.edu>).

This solution is satisfactory to me; I always prefer semantic extensions
over syntactic ones.
So, let's get this extended switch into the language.

-----------------------------------------------------------------------
Johan Vanslembrouck - SE99                 Tel    : +32 3 2407739
Alcatel Bell Telephone                     Telex  : 72128 Bella B
Francis Wellesplein  1                     Fax    : +32 3 2409932
B-2018 Antwerp                             e-mail : jvsb@ra.alcbel.be
Belgium
-----------------------------------------------------------------------




Author: ajacobs@nyx.cs.du.edu (Andrew Jacobs)
Date: Thu, 12 Aug 93 19:10:59 GMT
Raw View
tob@world.std.com (Tom O Breton) writes:
>That's tougher than you think. How do you make a not-built-in type act
>like a literal constant?

You are right.  What I had in mind originally, was (using the CString
class from MFC):

   switch(i) {
      case "AAA": statement; break;
   }

where a compiler could construct objects for all of the comparitors.
I still agree that it would be even more usefull to include comparisons
to non-constants.

It was suggested to extend the switch statment to allow multiple values.
It was then pointed out that if the above were allowed, this could be
simulated.  It was also pointed out that the comma syntax following the
switch could break existing code, while the comma syntax following the
case would not (as expressions are not allowed).  So my next suggestions
is to allow ranges in the cases - using a similar comma syntax.
This would be interchangeable with case's with single values (ie. the
current syntax).  The expressions would have to be >= to the first
value, and <= to the second value.  For example:

   switch(i) {
      case 5,7: do_stuff_for_5_6_and_7; break;
   }

This proposal is also independant of my first  (ie. either one could
be accepted without the other).  I believe that this would also
not break any code.  More comments...?
--
                                  *     *
 - Andy Jacobs                       *
                                  \_____/




Author: tjm@netcom.com (Thomas J. Merritt)
Date: Thu, 12 Aug 1993 21:37:09 GMT
Raw View
In article <1993Aug12.191059.23187@mnemosyne.cs.du.edu> ajacobs@nyx.cs.du.edu (Andrew Jacobs) writes:
|tob@world.std.com (Tom O Breton) writes:
|>That's tougher than you think. How do you make a not-built-in type act
|>like a literal constant?
|
|You are right.  What I had in mind originally, was (using the CString
|class from MFC):
|
|   switch(i) {
|      case "AAA": statement; break;
|   }
|
|where a compiler could construct objects for all of the comparitors.

Unfortunately, the general case would require the compiler to execute
the CString constructor at runtime for each of the case labels and the
possiblity would then exist for more than one case label to compare
equal at runtime.  A semantic would have to be developed for how to handle
this.

|I still agree that it would be even more usefull to include comparisons
|to non-constants.

They are really indistinguishable from the compiler perspective.

|It was suggested to extend the switch statment to allow multiple values.
|It was then pointed out that if the above were allowed, this could be
|simulated.  It was also pointed out that the comma syntax following the
|switch could break existing code, while the comma syntax following the
|case would not (as expressions are not allowed).  So my next suggestions
|is to allow ranges in the cases - using a similar comma syntax.
|This would be interchangeable with case's with single values (ie. the
|current syntax).  The expressions would have to be >= to the first
|value, and <= to the second value.  For example:
|
|   switch(i) {
|      case 5,7: do_stuff_for_5_6_and_7; break;
|   }

This already exists in GCC with different syntax.

    switch (i) {
 case 5...7: do_stuff_for_5_6_and_7; break;
    }

|This proposal is also independant of my first  (ie. either one could
|be accepted without the other).  I believe that this would also
|not break any code.  More comments...?

The constant expressions in the case label do allow comma's and so this could
possibly break existing code.

-------------------------------------------------------------------------------
Thomas J. Merritt    |      Code Generation      |    PO Box 192746
tjm@netcom.com       |           Technology      |    San Francisco, CA  94119
-------------------------------------------------------------------------------




Author: dak@messua.informatik.rwth-aachen.de (David Kastrup)
Date: 13 Aug 1993 05:45:46 GMT
Raw View
tjm@netcom.com (Thomas J. Merritt) writes:

>|case would not (as expressions are not allowed).  So my next suggestions
>|is to allow ranges in the cases - using a similar comma syntax.
>|This would be interchangeable with case's with single values (ie. the
>|current syntax).  The expressions would have to be >= to the first
>|value, and <= to the second value.  For example:
>|
>|   switch(i) {
>|      case 5,7: do_stuff_for_5_6_and_7; break;
>|   }
I consider this dead beat ugly. To use a comma for a range is both
unintuitive, and comma has a meaning entirely different already in
C++, although not in that surrounds.

>This already exists in GCC with different syntax.

>    switch (i) {
> case 5...7: do_stuff_for_5_6_and_7; break;
>    }

>|This proposal is also independant of my first  (ie. either one could
>|be accepted without the other).  I believe that this would also
>|not break any code.  More comments...?

>The constant expressions in the case label do allow comma's and so this could
>possibly break existing code.
Constant expressions are not allowed to contain commas. Why should they?
They make only sense if the first part has a side effect, and constant
expressions should not have these. And don't tell me you write code like
static int x = 2/0, 5;
in order to trigger an exception before starting main, then reassign
a nice value.
--
 David Kastrup        dak@pool.informatik.rwth-aachen.de
 Tel: +49-241-72419 Fax: +49-241-79502
 Goethestr. 20, D-52064 Aachen




Author: klamer@mi.el.utwente.nl (Klamer Schutte)
Date: Fri, 13 Aug 1993 07:39:19 GMT
Raw View
In <1993Aug12.191059.23187@mnemosyne.cs.du.edu> ajacobs@nyx.cs.du.edu (Andrew Jacobs) writes:

]This would be interchangeable with case's with single values (ie. the
]current syntax).  The expressions would have to be >= to the first
]value, and <= to the second value.  For example:

]   switch(i) {
]      case 5,7: do_stuff_for_5_6_and_7; break;
]   }

When comparing this solution to other ways of specifying ranges
I associate this method to 5 or 7, and not the range from 5 to 7.

Better will be 5...7, with perhaps an or-operator as well. But that already
exists, as we can specify several case ...: labels before the statement.

Klamer
--
Klamer Schutte       Tel: +31-53-892778   Fax: +31-53-340045
Dept. of Electrical Engineering  --  University of Twente, The Netherlands
preferred: klamer@mi.el.utwente.nl              SMTP: klamer@[130.89.33.3]




Author: ajacobs@nyx.cs.du.edu (Andrew Jacobs)
Date: Thu, 5 Aug 93 15:43:46 GMT
Raw View
tjm@netcom.com (Thomas J. Merritt) writes:
>|Is there any interest (other than myself) in extending the switch
>|statement in C++ to include any class that defines an operator==().

>It sounds great and has been asked for over the years.  The only problem is
>what are the semantics for the following code.  Are the semantics clear?
>    void foo(int s, int x, int y) {
> switch (s) {
> case x:

The case you bring is very clear.  It would not be allowed (with only my
above perposal).  I did not suggest extending the switch statement to allow
comparisons with variables - only to expand the types supported by the
switch statement.  Although I have no problem with the additional extention,
and even think it would be worthwile, I just wanted to make it clear that
it was not what I was proposing with this thread, and that I consider them
two independant extentions.
--
                                  *     *
 - Andy Jacobs                       *
                                  \_____/




Author: tob@world.std.com (Tom O Breton)
Date: Thu, 5 Aug 1993 17:56:33 GMT
Raw View
Andy:

> I did not suggest extending the switch statement to allow comparisons
> with variables - only to expand the types supported by the switch
> statement.

That's tougher than you think. How do you make a not-built-in type act
like a literal constant?

Even if you construct it in place, EG:

mystruct
{ YorN          operator==(int) const;
  inline        mystruct(int,int) {...};
  ....
};

foo(int z)
{ switch(z)
  { case  mystruct(10,35):
    ....
  }
}

many compilers will not understand that it's a literal constant,(*) even
if the CTOR is inline and makes no calls to out-of-line functions.

And if the CTOR is NOT inline or calls something not inline, then
there's no way you can test for duplicate cases at compile-time.

Furthermore, you'd need to restrict the syntax, otherwise

//...
  switch(z)
  { case  mystruct  &reference  = mystruct(10,35):
    ....
  }
  reference.lets_CHANGE_it();
}



(*) I want to single out Borland for this. I am saddled with an
atrocious compiler by them, called Turbo C++  1.01. If you look through
the assembly language output, you will find it has NO idea when it can
"look through" a CTOR. With optimizations on, it will happily generate
more than a dozen lines of excess code for initializations that can be
done in 1 or 2 lines!

In their defense, I will point out that unlike many of their other bugs,
this behavior is legal. It's just stupid, that's all.

        Tom

--
The Tom spreads its huge, scaly wings and soars into the sky...
(tob@world.std.com, TomBreton@delphi.com)




Author: tjm@netcom.com (Thomas J. Merritt)
Date: Thu, 5 Aug 1993 18:04:38 GMT
Raw View
In article <1993Aug5.154346.12072@mnemosyne.cs.du.edu> ajacobs@nyx.cs.du.edu (Andrew Jacobs) writes:
|tjm@netcom.com (Thomas J. Merritt) writes:
|>|Is there any interest (other than myself) in extending the switch
|>|statement in C++ to include any class that defines an operator==().
|
|>It sounds great and has been asked for over the years.  The only problem is
|>what are the semantics for the following code.  Are the semantics clear?
|>    void foo(int s, int x, int y) {
|> switch (s) {
|> case x:
|
|The case you bring is very clear.  It would not be allowed (with only my
|above perposal).  I did not suggest extending the switch statement to allow
|comparisons with variables - only to expand the types supported by the
|switch statement.  Although I have no problem with the additional extention,
|and even think it would be worthwile, I just wanted to make it clear that
|it was not what I was proposing with this thread, and that I consider them
|two independant extentions.

Unfortunately, your extension is equivelent to supporting arbitrary expressions
in switch case clauses.  The reason being, that constants are only defined for
the builtin types.  Any other type would require an arbitrary expression to
produce the constant at runtime.

-------------------------------------------------------------------------------
Thomas J. Merritt    |      Code Generation      |    PO Box 192746
tjm@netcom.com       |           Technology      |    San Francisco, CA  94119
-------------------------------------------------------------------------------




Author: dag@control.lth.se (Dag Bruck)
Date: 5 Aug 93 18:39:36 GMT
Raw View
In <comp.std.c++> ajacobs@nyx.cs.du.edu (Andrew Jacobs) writes:
>Is there any interest (other than myself) in extending the switch
>statement in C++ to include any class that defines an operator==().
>This would even include int's which were not possible in straight C.

I don't understand what you're saying.  The last sentence looks like
you're saying that you can't "switch" on an int in straight C.

 int i = ....;
 switch (i) {
 case 1:
  /* .... */
  break;
 }

What's the problem?

  -- Dag




Author: jvsb@ra.alcbel.be (Johan Vanslembrouck)
Date: 6 Aug 93 13:41:37 GMT
Raw View
In article <1993Aug4.135526.27658@mnemosyne.cs.du.edu>
ajacobs@nyx.cs.du.edu (Andrew Jacobs) writes:
|Is there any interest (other than myself) in extending the switch
|statement in C++ to include any class that defines an operator==().

I would like to propose another extension to the switch statement, to
allow
multiple selectors. Let's give an example of such a multi-selector
switch
in CHILL (CCITT High-Level Language):

 case z_state, z_control_code of
   (e_statc_idle), (e_cntlc_open_disp, e_cntlc_open_dyn) :
  statements
   (e_statc_idle), (e_cntlc_open_mod) :
  statements
   (e_statc_disp), (e_cntlc_open_dyn) :
  statements
   (*), (e_cntlc_user_abort):
  statements
   else    /* default in C/C++ */
  statements
 esac;

Some explanation:

1) z_state an z_control_code are called selectors. That's why the
   term "multi-selector case" (or switch) is used.
2) CHILL has an implicit break before every case-arm. Fall-through like
   in C/C++ is impossible, but is replaced by an enumeration of the
options
   like in

 (e_cntlc_open_disp, e_cntlc_open_dyn)

   This explains the use of parentheses to group the options for each
   selector in a case-arm.
3) In the example, (*) covers all values of z_state for which
   there was no explicit case-arm in combination with
e_cntlc_user_abort.
4) The case statement is terminated by "esac", which is just "case"
read
   from right to left.

Motivations for the introduction of a multi-selector switch in C/C++:

1) Although a multi-selector switch can always be replaced by nested
   switch statements, a multi-selector switch is more natural in
situations
   where there is no "hierarchical" difference between the selector
variables.
   Nesting may introduce a kind of artificial hierarchy - Why did you
   take this variable for the outer switch?

2) A multi-selector switch takes less lines of code and, in many cases,
   this code will be more readable than the code with nested switch
statements.

One drawback: multi-selector switches are probably harder to compile.

This is how it might look like in C/C++:

 switch (z_state, z_control_code)
 {
   case e_statc_idle, e_cntlc_open_disp :
   case e_statc_idle, e_cntlc_open_dyn :
  statements
  break;
   case e_statc_idle, e_cntlc_open_mod :
  statements
  break;
   case e_statc_disp, e_cntlc_open_dyn :
  statements
  break;
   case *,  e_cntlc_user_abort:
  statements
  break;
   default:
  statements
 }

This extension does not break existing code; the switch with one
selector
is a special case of the multi-selector switch.

-----------------------------------------------------------------------
Johan Vanslembrouck - SE99                 Tel    : +32 3 2407739
Alcatel Bell Telephone                     Telex  : 72128 Bella B
Francis Wellesplein  1                     Fax    : +32 3 2409932
B-2018 Antwerp                             e-mail : jvsb@ra.alcbel.be
Belgium
-----------------------------------------------------------------------




Author: a904209@server1.tiuk.ti.com (Nick Ing-Simmons)
Date: Mon, 9 Aug 1993 09:03:36 GMT
Raw View
jvsb@ra.alcbel.be (Johan Vanslembrouck) writes :
  his is how it might look like in C/C++:

   switch (z_state, z_control_code)
   {
     case e_statc_idle, e_cntlc_open_disp :
     case e_statc_idle, e_cntlc_open_dyn :
    statements
.....
    break;
     default:
    statements
   }

  This extension does not break existing code; the switch with one
  selector
  is a special case of the multi-selector switch.

But switch(fred(),harry) is legal (if rare) already,
as list of expressions separated by ',' evaluates them all
and returns value of last; so just ','
separating multiple selectors is not enough.








Author: ajacobs@nyx.cs.du.edu (Andrew Jacobs)
Date: Wed, 4 Aug 93 13:55:26 GMT
Raw View
Is there any interest (other than myself) in extending the switch
statement in C++ to include any class that defines an operator==().
This would even include int's which were not possible in straight C.

Some advantages are:
  Easier to read the case syntax
  Easier to see that all comparisons are with same variable
  Would allow fall-through that would otherwise have to be coded with
    multiple if's

I don't think it would break any existing code.  Implementations should
be able to produce code at least as efficient as if it were coded with
if's, so there should be no loss in efficiencyfor a programmer using
the new feature.

Any thoughts?  Things I missed?
--
                                  *     *
 - Andy Jacobs                       *
                                  \_____/




Author: tjm@netcom.com (Thomas J. Merritt)
Date: Wed, 4 Aug 1993 17:55:25 GMT
Raw View
In article <1993Aug4.135526.27658@mnemosyne.cs.du.edu> ajacobs@nyx.cs.du.edu (Andrew Jacobs) writes:
|Is there any interest (other than myself) in extending the switch
|statement in C++ to include any class that defines an operator==().
|This would even include int's which were not possible in straight C.
|
|Some advantages are:
|  Easier to read the case syntax
|  Easier to see that all comparisons are with same variable
|  Would allow fall-through that would otherwise have to be coded with
|    multiple if's
|
|I don't think it would break any existing code.  Implementations should
|be able to produce code at least as efficient as if it were coded with
|if's, so there should be no loss in efficiencyfor a programmer using
|the new feature.
|
|Any thoughts?  Things I missed?

It sounds great and has been asked for over the years.  The only problem is
what are the semantics for the following code.  Are the semantics clear?

    void
    foo(int s, int x, int y)
    {
 switch (s)
 {
 case x:
     statement1;
     break;
 case y:
     statement2;
     break;
 default:
     statement3;
     break;
 }
    }

    ...
 foo(3, 3, 3);

-------------------------------------------------------------------------------
Thomas J. Merritt    |      Code Generation      |    PO Box 192746
tjm@netcom.com       |           Technology      |    San Francisco, CA  94119
-------------------------------------------------------------------------------