From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,976a050e0f89277c X-Google-Attributes: gid103376,public From: matthew_heaney@acm.org (Matthew Heaney) Subject: Enumeration Types (was: Urgent question: malloc and ada) Date: 1998/04/12 Message-ID: X-Deja-AN: 343456114 Content-Transfer-Encoding: 8bit References: <352A79C2.15FB7483@nathan.gmd.de> Content-Type: text/plain; charset=ISO-8859-1 Organization: Network Intensive Mime-Version: 1.0 Newsgroups: comp.lang.ada Date: 1998-04-12T00:00:00+00:00 List-Id: In article , gwinn@ma.ultranet.com (Joe Gwinn) wrote: >Most of the trouble has been in passing data structures (records in Ada, >structs in C/C++) from one world to the other. Pragma interface C has >worked mostly as expected, but getting the data across the divide >undamaged has not. This was where the rep spec on an enumeration type >problem first surfaced. One "solution" is to not use enumeration types with rep clauses at all - just use an integer. It seems that the ability to put a representation clause on an enumeration type was a feature only included in the langauge to make it consistant; after all, you can choose the representation of other types, so why not enumeration types too? But it causes all kinds of problems. You'll have lots o' problems if you have a value with a bit pattern not among the legal values (possible because you moved the data over an external interface, and there was some noise during transmission). I find it simpler to avoid that mess altogether and use just integer types across an interface, and writing my own mapping function (array) from integer value to enumeration literal. In practice, using an integer type instead of an enumeration is only marginally less safe. Consider this: type ET is (Red, Green, Blue); for ET use (Red => 1, Green => 3, Blue => 7); for ET'Size use 8; procedure Op (O : ET); Now consider this: type IT is new Interfaces.Unsigned_8; Red : constant IT := 1; Green : constant IT := 3; Blue : constant IT := 7; procedure Op (O : IT); >From a client's point of view, there is no difference between these types (though a case statement now requires an others branch). You call procedure Op the same way in both cases. You can make the argument, "But with the integer version, the client can pass the value 2." But this can only happen because of deliberate misuse, ie Op (2); Here, he's being naughty, and using an integer literal. What he should do is Op (Red); just like he'd do using the enumeration literal. And no, you can't even accidently mix this type up with other integer types, because IT is its own type. You'd have to deliberately convert one integer type into the other. All told, I feel the ability to give an enumeration type a rep clause is an unnecessary, error-prone feature of the Ada language. An enumeration type is at too high a level of abstraction to accomodate such a low-level feature. Giving a rep clause to an enumeration type causes all kinds of other headaches for users and compiler-writers alike, such as using the type to index an array, or taking the successor or predecessor of a value, when type rep clause has holes. Tuck wrote a thoughtful post on this topic a few weeks back. I've included it below. Also, note that there is no such thing as rep "spec." The proper term is rep "clause." >Joe Gwinn (gwinn@res.ray.com) wrote: >: In article , >: stt@houdini.camb.inmet.com (Tucker Taft) wrote: > >: ... >: > As far as enumeration types, as others have pointed out, the Ada 95 >: > standard requires that the internal codes for enumeration types are >: > contiguous and start at zero, so you are not in any danger if you leave >: > out your "confirming" representation clauses. It would be nice if >: > our front end recognized "confirming" enumeration representation >: > clauses, but as usual, there are many possible "optimizations" >: > and this one never made it to the top of the list. >: > One might argue that this is not really an optimization, but >: > it does require special code to recognize, and so represents >: > yet another "special case" that you have to decide the priority >: > of recognizing. > >: The key issue was that we had no way of knowing the dire consequences of >: this innocent looking bit of standard Ada, until we had gone a fair >: distance down that wrong road. > >If you ask anyone who knows me well, you will know that I consider >the enumeration representation clause anything but "innocent looking" ;-). >For what it is worth, we will soon be releasing a new front end >that recognizes the special case of a confirming enumeration >representation clause. > >[ASIDE: > >Although the ability to specify the representation of an enumeration >type initially sounds perfectly reasonable, the fundamental problem is that >Ada also allows such "holey" enumeration types to be used as the >type for a for-loop index, an array index, an entry family index, >or the 'Succ/'Pred attributes. This results in surprising implicit >inefficiencies, something that violates one of the general Ada >language design principles. Your enumeration rep clause simply reconfirmed >the default representation, but suppose it didn't? You would be >stuck with the overhead you managed to eliminate by simply commenting >out the rep clause. Of course, the compiler could recognize various >other specials cases, such as contiguous representation starting at >something other than zero, or evenly distributed "holey" representation >(e.g., even numbers only), or simply not "too" sparse, or ... > >Pretty soon handling these enumeration representation clauses >the way the "innocent" user would "expect" becomes a major artificial >intelligence challenge. During the Ada 9X design process, when we >found one of our new language ideas evoving into this kind of complex >AI pattern matching problem for the compiler, we knew we were on the >wrong track. The user should be designing the algorithms, using >the basic primitives of the language. The primitives shouldn't themselves >be at such a level that the compiler is effectively trying to take over >part of the programming problem. > >Note that in C and C++, allowing the user to specify the values for >enumeration literals creates no similar problem, because there is >no operation that depends on the logical "position" of an enumeration >literal. All semantics of enumeration values in C/C++ depends on the >underlying "code," not the position. > >So in retrospect, I believe enumeration representation >clauses in Ada are a mistake. If a user wants to name >particular values, they should simply use named integer >constants, or perhaps better, named private-type constants. They can build >up various maps of their own if they want to translate to/from some kind >of "holey" representation from/to a contiguous representation. > >END OF ASIDE] > >: ... One wonders what other surprises lay in >: wait. > >In general, the Ada language design philosophy eschewed "innocent" >looking features that were in fact expensive at run-time. >However, in the specific case of enumeration representation clauses, >this useful language design philosophy was not completely followed. >Other cases I know of are interactions between finalization, >exception handling, and abort, where the combination of features >forces some or all of these three to incur more run-time overhead >than you might expect. > >One "innocent" looking construct I once found was: > > (others => Default_Value(Segment)) > >used to initialize a segment of a load module to some default value. >This called the function Default_Value once for each byte of the >segment, and the segment was often 100K bytes or more. > >: ... > >: Joe Gwinn > >-- >-Tucker Taft stt@inmet.com http://www.inmet.com/~stt/ >Intermetrics, Inc. Burlington, MA USA Extra text needed because of my stupid newsreader. Sorry.