comp.lang.ada
 help / color / mirror / Atom feed
* Re: Ada Enumerations
  1997-12-03  0:00 Ada Enumerations Jeffrey Harris
@ 1997-12-03  0:00 ` James S. Rogers
  1997-12-03  0:00   ` Robert Dewar
  1997-12-04  0:00 ` Ada Enumerations Stephen Leake
  1 sibling, 1 reply; 28+ messages in thread
From: James S. Rogers @ 1997-12-03  0:00 UTC (permalink / raw)



Jeffrey Harris <harris@newman.pcisys.net> wrote in article
<662cs9$b34$1@newman.pcisys.net>...
> 
> NewLocation: Integer := DataTypes.LASTTYPE + 1;  -- Newlocation = 101
> 
> The compiler isn't letting me do this.  I've tried to use 'value, 'pos,
and
> 'val to no avail, how do I convert an Ada enumerated type into an integer
value?

The 'Pos attribute returns the position of the enumeration value.  This is
unaffected by the representation clause.  To obtain the representation
value
you must instantiate Ada.Unchecked_Conversion. for your enumeration 
type.

Jim Rogers
Colorado Springs,  Colorado




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-03  0:00 ` James S. Rogers
@ 1997-12-03  0:00   ` Robert Dewar
  1997-12-03  0:00     ` Stanley R. Allen
  0 siblings, 1 reply; 28+ messages in thread
From: Robert Dewar @ 1997-12-03  0:00 UTC (permalink / raw)



Jim Rogers said

<<The 'Pos attribute returns the position of the enumeration value.  This is
unaffected by the representation clause.  To obtain the representation
value
you must instantiate Ada.Unchecked_Conversion. for your enumeration
type.
>>

If you are using GNAT, you can use the 'Enum_Rep attribute to get the
representation value for an enumeration literal. This seems a generally
useful attribute, it would be nice if other Ada 95 compilers would
implement it.

Robert Dewar
Ada Core Technologies





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-03  0:00   ` Robert Dewar
@ 1997-12-03  0:00     ` Stanley R. Allen
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
                         ` (6 more replies)
  0 siblings, 7 replies; 28+ messages in thread
From: Stanley R. Allen @ 1997-12-03  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> Jim Rogers said
> 
> you must instantiate Ada.Unchecked_Conversion. for your enumeration
> type.
> >>
> 
> If you are using GNAT, you can use the 'Enum_Rep attribute to get the
> representation value for an enumeration literal. This seems a generally
> useful attribute, it would be nice if other Ada 95 compilers would
> implement it.
> 

Hear, Hear!  I was surprised that Ada95 didn't correct this obvious
deficiency in Ada83.  I've been frustrated with the unchecked_conversion
approach for quite a while.  Here is the problem:

    type Value_List_Type is array (Natural range <>) of Integer;
    generic
        type Enum is (<>);
    function Value_List return Value_List_Type;

If the function Value_List is to allow instantiation of any enumeration
type, the size (in bits) of the actual type must be taken into account
if Unchecked_Conversion is used.  And this is very ugly.  With the
'Enum_Rep clause, it's easy to do this:

    function Value_List return Value_List_Type is
        Tmp : Value_List_Type (Enum'Pos (Enum'First) ..
                               Enum'Pos (Enum'Last));
    begin
        for I in Tmp'Range loop
            Tmp (I) := Enum'Enum_Rep (Enum'Val (I));
        end loop;
        return Tmp;
    end Value_List;

The functionality of the clause is worth the trade-off of the ugly
name.  Most of the ACT-chosen names for implementation-defined
attributes are depressing (e.g., 'Img, 'Elab_Spec -- ugh.)

While we are on the subject, it would be nice if the GNAT-defined
'Object_Size (a better name than the equivalent DEC-Ada-defined
'Machine_Size) attribute was universally adopted as well.  Those
of us who must work at the bit level get frustrated when we cannot
get at the actual number of bits that will be allocated for an
entity, rather than the "minumum" given by <type>'Size.

-- 
Stanley Allen
mailto:s_allen@hso.link.com




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Ada Enumerations
@ 1997-12-03  0:00 Jeffrey Harris
  1997-12-03  0:00 ` James S. Rogers
  1997-12-04  0:00 ` Ada Enumerations Stephen Leake
  0 siblings, 2 replies; 28+ messages in thread
From: Jeffrey Harris @ 1997-12-03  0:00 UTC (permalink / raw)



I have created an Ada Enumeration called DataTypes, afterwards I've created a
'use' clause where I give each element an integer value.  The last Enumeration
is LASTTYPE and is given a value of 100.

Now to the problem.  I'd like to be able to do something like the following..


NewLocation: Integer := DataTypes.LASTTYPE + 1;  -- Newlocation = 101

The compiler isn't letting me do this.  I've tried to use 'value, 'pos, and
'val to no avail, how do I convert an Ada enumerated type into an integer value?


Thanx... Please e-mail me at harris@pcisys.net

Jeff Harris




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-03  0:00     ` Stanley R. Allen
                         ` (4 preceding siblings ...)
  1997-12-04  0:00       ` Ada Enumerations Matthew Heaney
@ 1997-12-04  0:00       ` Robert Dewar
  1997-12-04  0:00         ` Stanley R. Allen
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
  6 siblings, 1 reply; 28+ messages in thread
From: Robert Dewar @ 1997-12-04  0:00 UTC (permalink / raw)



Stanley said

<<The functionality of the clause is worth the trade-off of the ugly
name.  Most of the ACT-chosen names for implementation-defined
attributes are depressing (e.g., 'Img, 'Elab_Spec -- ugh.)
>>

Actually it is Ada 83 that clearly established the precedent of using
abbreviations for attributes (Pred, Succ, ...) and Ada 95 continues
the tradition (Max, Min, Trunc, ..) so it seems quite appropriate
to abbreviate. I guess you can't choose names to make everyone happy!

Note that 'Img is very specifically intended for writing quick debugging

code, so it is quite deliberate to give it a very short name, and if you
don't like the name, fine, it should not appear in any of your final
code anyway. After all the ONLY point of Img is to shorten things
(from e.g. Integer'Image (K) to K'Img), so it would be pretty pointless
to give it a long name!

I must say I don't see so much of a problem with Unchecked_Conversion for
replacing Enum_Rep unless you have a really hostile compiler. For types
like this, Unchecked_Conversion should work as expected in cases where
the number of bits of the source and target differs.






^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-03  0:00 Ada Enumerations Jeffrey Harris
  1997-12-03  0:00 ` James S. Rogers
@ 1997-12-04  0:00 ` Stephen Leake
  1997-12-04  0:00   ` Matthew Heaney
  1 sibling, 1 reply; 28+ messages in thread
From: Stephen Leake @ 1997-12-04  0:00 UTC (permalink / raw)



Jeffrey Harris wrote:
> 
> I have created an Ada Enumeration called DataTypes, afterwards I've created a
> 'use' clause where I give each element an integer value.  The last Enumeration
> is LASTTYPE and is given a value of 100.
> 
> Now to the problem.  I'd like to be able to do something like the following..
> 
> NewLocation: Integer := DataTypes.LASTTYPE + 1;  -- Newlocation = 101

It looks like you should use an integer type for DataTypes, rather than
an enumeration type. Take a step back, and consider why you are doing
this in the first place. If you post a discription of your broader
problem, maybe we could give some better advice.

> 
> The compiler isn't letting me do this.  I've tried to use 'value, 'pos, and
> 'val to no avail, how do I convert an Ada enumerated type into an integer value?

If you really, really need to do this, GNAT provides the non-standard
attribute 'Enum_Rep, which gives you the integer you specified for the
enumeration literal. ObjectAda does not provide this attribute - I don't
know about other compilers.
You can use Unchecked_Conversion to get the same result.

> 
> Thanx... Please e-mail me at harris@pcisys.net
> 
> Jeff Harris

-- 
- Stephe




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00 ` Ada Enumerations Stephen Leake
@ 1997-12-04  0:00   ` Matthew Heaney
  1997-12-04  0:00     ` Robert Dewar
  0 siblings, 1 reply; 28+ messages in thread
From: Matthew Heaney @ 1997-12-04  0:00 UTC (permalink / raw)



In article <3486C057.6207@gsfc.nasa.gov>, Stephen.Leake@gsfc.nasa.gov wrote:


>It looks like you should use an integer type for DataTypes, rather than
>an enumeration type.

Good advice.  For low-level I/O, an enumeration type is often not what you
want anyway.  What's wrong with a good old fashioned integer type?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-03  0:00     ` Stanley R. Allen
                         ` (3 preceding siblings ...)
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
@ 1997-12-04  0:00       ` Matthew Heaney
  1997-12-04  0:00         ` Stanley R. Allen
  1997-12-04  0:00       ` Robert Dewar
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
  6 siblings, 1 reply; 28+ messages in thread
From: Matthew Heaney @ 1997-12-04  0:00 UTC (permalink / raw)



In article <3485D2AE.3F54@hso.link.com>, "Stanley R. Allen"
<s_allen@hso.link.com> wrote:

>> If you are using GNAT, you can use the 'Enum_Rep attribute to get the
>> representation value for an enumeration literal. This seems a generally
>> useful attribute, it would be nice if other Ada 95 compilers would
>> implement it.
>> 
>
>Hear, Hear!  I was surprised that Ada95 didn't correct this obvious
>deficiency in Ada83.

Personally, I feel that if you're always looking at the rep of the
enumerands, then you probably don't want an enumeration type anyway.  That
being said, why don't you just perform an instantiation of UC at the point
of declaration of the type?

with Unchecked_Conversion, Interfaces;
package Color_Types is

   type Color is (Red, Green, Blue);
   
   for Color use (Red => 2, Green => 5, Blue => 8);

   for Color'Size use 8;

   function To_Rep is
      new Unchecked_Conversion (Color, Interfaces.Unsigned_8);

end Color_Types;

What's the big deal?  It's only 1 extra declaration (the instantiation of UC).

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00       ` Ada Enumerations Matthew Heaney
@ 1997-12-04  0:00         ` Stanley R. Allen
  1997-12-07  0:00           ` Keith Thompson
  0 siblings, 1 reply; 28+ messages in thread
From: Stanley R. Allen @ 1997-12-04  0:00 UTC (permalink / raw)



Matthew Heaney wrote:
> 
> 
> Personally, I feel that if you're always looking at the rep of the
> enumerands, then you probably don't want an enumeration type anyway.

That's a dead argument on the face of it.  If the language
permits me to *specify* the representation, then why doesn't
it permit me to *query* the specified values?  Permission is
granted in the case of 'Address and 'Size, so are the rules
different for enumeration representations?  In fact, a similar
attribute could be used, with the same orthogonality:

    for Color'Representation use
        (Red => 2, Green => 5, Blue => 8);
    ....
    X := Color'Representation (C);

(Much nicer than 'Enum_Rep, don't you think? :)

In any case, as you will see below, not using enumeration
types is not an option for me as an API developer.  Walk
a mile in my shoes.

>  That
> being said, why don't you just perform an instantiation of
> UC at the point of declaration of the type?
> 
> with Unchecked_Conversion, Interfaces;
> package Color_Types is
> 
>    type Color is (Red, Green, Blue);
>    for Color use (Red => 2, Green => 5, Blue => 8);
>    for Color'Size use 8;
>    function To_Rep is
>       new Unchecked_Conversion (Color, Interfaces.Unsigned_8);
> end Color_Types;
> 
> What's the big deal?  It's only 1 extra declaration
> (the instantiation of UC).
> 

It's ugly for one thing.  But it's also not my situation.
I'm not creating the enum types, my users are.

What if you are developing an interface so that users
can instantiate your software with *any* of their own
enumeration types?  My interface looks like this:

    generic
        type Enum is (<>);
    procedure Register_Enum_Type (Name : String);

This is part of a toolset that builds symbol table
information for user-defined types.  All of the Ada
information about the type must be captured in the
table, including the representation information.  It
is not possible to disallow types like your "Color"
type -- the users of the symbol table may depend on
that kind of thing.

We have restricted the user to 8, 16, and 32 bit
enumeration types, though this is potentially a
problem.  The way I am implementing this now is:

procedure Register_Enum_Type (Name : String) is
    E : Enum; -- dummy variable
    I8 : Integer_8;
    I16 : Integer_16;
    I32 : Integer_32;
    Values : array (Enum) of Integer;
begin
    for I in Enum loop
        case E'Size is
            when 8 =>
                Move1 (I'Address, I8'Address);
                Values (I) := Integer (I8);
            when 16 =>
                Move2 (I'Address, I16'Address);
                Values (I) := Integer (I16);
            when 32 =>
                Move4 (I'Address, I32'Address);
                Values (I) := Integer (I32);
            when others =>
                -- enum value must be 8, 16, or 32 bits
                raise Type_Error;
        end case;
    end loop;
    --- other logic
end Register_Enum_Type;

Move1, Move2, and Move2 are byte-copy operations like
C's memcpy.  This replaced the old way which was to
make three different instances of Unchecked_Conversion
in the body of the function:

    function Eto8 is new
        Unchecked_Conversion (Enum, Integer_8);
    function Eto16 is new
        Unchecked_Conversion (Enum, Integer_16);
    function Eto32 is new
        Unchecked_Conversion (Enum, Integer_32);

and use these instead of Move1, Move2, and Move3.

But then some compilers balked at the "unneeded"
UC instances.  For example, if Enum was 8 bits long,
some compilers would generate warnings or errors
for the other two, since Enum was neither 16 or 32
bits.  Even the warnings were an irritation, because
each user instance of the Register_Enum_Type (of
which there are hundreds) would generate warnings.
Hence the move away from UC altogether in this case.

-- 
Stanley Allen
mailto:s_allen@hso.link.com




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00       ` Robert Dewar
@ 1997-12-04  0:00         ` Stanley R. Allen
  1997-12-18  0:00           ` Wes Groleau
  0 siblings, 1 reply; 28+ messages in thread
From: Stanley R. Allen @ 1997-12-04  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> I must say I don't see so much of a problem with Unchecked_Conversion for
> replacing Enum_Rep unless you have a really hostile compiler. For types
> like this, Unchecked_Conversion should work as expected in cases where
> the number of bits of the source and target differs.

At least you *hope* so; too bad for you if your application
depends on it and the compiler doesn't do it right, or if
you need to port to a "hostile" compiler.  There being no
rule for this in either Ada83 or Ada95 (and apparently no
"implementation advice" to this effect in the new standard),
it is perfectly permissible for compilers to implement
unchecked_conversion in such a way that garbage is there if
the sizes are mismatched, which is one of the potential uses
of the new 'Valid attribute.  There is no clean way to recover
from this situation, either.  Especially when porting, these
are the anomalies that try men's souls.

See my other post for other reasons to dislike UC for this.

-- 
Stanley Allen
mailto:s_allen@hso.link.com




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00   ` Matthew Heaney
@ 1997-12-04  0:00     ` Robert Dewar
  1997-12-06  0:00       ` Jean-Pierre Rosen
  0 siblings, 1 reply; 28+ messages in thread
From: Robert Dewar @ 1997-12-04  0:00 UTC (permalink / raw)



Matthew says

<<Good advice.  For low-level I/O, an enumeration type is often not what you
want anyway.  What's wrong with a good old fashioned integer type?
>>

For one thing, it provides operations like addition, which are probably
meaningless nonsense.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* GNAT'Object_Size
  1997-12-03  0:00     ` Stanley R. Allen
                         ` (5 preceding siblings ...)
  1997-12-04  0:00       ` Robert Dewar
@ 1997-12-04  0:00       ` Mats Weber
  6 siblings, 0 replies; 28+ messages in thread
From: Mats Weber @ 1997-12-04  0:00 UTC (permalink / raw)



Stanley R. Allen wrote:

> While we are on the subject, it would be nice if the GNAT-defined
> 'Object_Size (a better name than the equivalent DEC-Ada-defined
> 'Machine_Size) attribute was universally adopted as well.  Those
> of us who must work at the bit level get frustrated when we cannot
> get at the actual number of bits that will be allocated for an
> entity, rather than the "minumum" given by <type>'Size.

And also generalize 'Object_Size so that it works on objects as well as types,
and returns the size actually allocated for an object, so that the following
code can be made to work:

generic
   type T (<>) is private;
procedure Receive (M : out T) is
   
   function Read (FD     : Integer;
                  Buffer : System.Address;
                  Count  : Integer) return Integer;

   pragma Import(C, Read);

   Length : Integer;

begin
   Length := Read(Socket,
                  M'Address,
                  M'Object_Size / System.Storage_Unit);
end;

Using 'Size in this situation is not portable because some compilers take it
to mean the size of the current value, not that of the object (which can be
different in the case of unconstrained types).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* GNAT'Object_Size
  1997-12-03  0:00     ` Stanley R. Allen
@ 1997-12-04  0:00       ` Mats Weber
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
                         ` (5 subsequent siblings)
  6 siblings, 0 replies; 28+ messages in thread
From: Mats Weber @ 1997-12-04  0:00 UTC (permalink / raw)



Stanley R. Allen wrote:

> While we are on the subject, it would be nice if the GNAT-defined
> 'Object_Size (a better name than the equivalent DEC-Ada-defined
> 'Machine_Size) attribute was universally adopted as well.  Those
> of us who must work at the bit level get frustrated when we cannot
> get at the actual number of bits that will be allocated for an
> entity, rather than the "minumum" given by <type>'Size.

And also generalize 'Object_Size so that it works on objects as well as types,
and returns the size actually allocated for an object, so that the following
code can be made to work:

generic
   type T (<>) is private;
procedure Receive (M : out T) is
   
   function Read (FD     : Integer;
                  Buffer : System.Address;
                  Count  : Integer) return Integer;

   pragma Import(C, Read);

   Length : Integer;

begin
   Length := Read(Socket,
                  M'Address,
                  M'Object_Size / System.Storage_Unit);
end;

Using 'Size in this situation is not portable because some compilers take it
to mean the size of the current value, not that of the object (which can be
different in the case of unconstrained types).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* GNAT'Object_Size
  1997-12-03  0:00     ` Stanley R. Allen
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
@ 1997-12-04  0:00       ` Mats Weber
  1997-12-08  0:00         ` GNAT'Object_Size Mats Weber
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
                         ` (4 subsequent siblings)
  6 siblings, 1 reply; 28+ messages in thread
From: Mats Weber @ 1997-12-04  0:00 UTC (permalink / raw)



Stanley R. Allen wrote:

> While we are on the subject, it would be nice if the GNAT-defined
> 'Object_Size (a better name than the equivalent DEC-Ada-defined
> 'Machine_Size) attribute was universally adopted as well.  Those
> of us who must work at the bit level get frustrated when we cannot
> get at the actual number of bits that will be allocated for an
> entity, rather than the "minumum" given by <type>'Size.

And also generalize 'Object_Size so that it works on objects as well as types,
and returns the size actually allocated for an object, so that the following
code can be made to work:

generic
   type T (<>) is private;
procedure Receive (M : out T) is
   
   function Read (FD     : Integer;
                  Buffer : System.Address;
                  Count  : Integer) return Integer;

   pragma Import(C, Read);

   Length : Integer;

begin
   Length := Read(Socket,
                  M'Address,
                  M'Object_Size / System.Storage_Unit);
end;

Using 'Size in this situation is not portable because some compilers take it
to mean the size of the current value, not that of the object (which can be
different in the case of unconstrained types).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* GNAT'Object_Size
  1997-12-03  0:00     ` Stanley R. Allen
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
@ 1997-12-04  0:00       ` Mats Weber
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
                         ` (3 subsequent siblings)
  6 siblings, 0 replies; 28+ messages in thread
From: Mats Weber @ 1997-12-04  0:00 UTC (permalink / raw)



Stanley R. Allen wrote:

> While we are on the subject, it would be nice if the GNAT-defined
> 'Object_Size (a better name than the equivalent DEC-Ada-defined
> 'Machine_Size) attribute was universally adopted as well.  Those
> of us who must work at the bit level get frustrated when we cannot
> get at the actual number of bits that will be allocated for an
> entity, rather than the "minumum" given by <type>'Size.

And also generalize 'Object_Size so that it works on objects as well as types,
and returns the size actually allocated for an object, so that the following
code can be made to work:

generic
   type T (<>) is private;
procedure Receive (M : out T) is
   
   function Read (FD     : Integer;
                  Buffer : System.Address;
                  Count  : Integer) return Integer;

   pragma Import(C, Read);

   Length : Integer;

begin
   Length := Read(Socket,
                  M'Address,
                  M'Object_Size / System.Storage_Unit);
end;

Using 'Size in this situation is not portable because some compilers take it
to mean the size of the current value, not that of the object (which can be
different in the case of unconstrained types).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* GNAT'Object_Size
  1997-12-03  0:00     ` Stanley R. Allen
                         ` (2 preceding siblings ...)
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
@ 1997-12-04  0:00       ` Mats Weber
  1997-12-05  0:00         ` GNAT'Object_Size Mats Weber
  1997-12-04  0:00       ` Ada Enumerations Matthew Heaney
                         ` (2 subsequent siblings)
  6 siblings, 1 reply; 28+ messages in thread
From: Mats Weber @ 1997-12-04  0:00 UTC (permalink / raw)



Stanley R. Allen wrote:

> While we are on the subject, it would be nice if the GNAT-defined
> 'Object_Size (a better name than the equivalent DEC-Ada-defined
> 'Machine_Size) attribute was universally adopted as well.  Those
> of us who must work at the bit level get frustrated when we cannot
> get at the actual number of bits that will be allocated for an
> entity, rather than the "minumum" given by <type>'Size.

And also generalize 'Object_Size so that it works on objects as well as types,
and returns the size actually allocated for an object, so that the following
code can be made to work:

generic
   type T (<>) is private;
procedure Receive (M : out T) is
   
   function Read (FD     : Integer;
                  Buffer : System.Address;
                  Count  : Integer) return Integer;

   pragma Import(C, Read);

   Length : Integer;

begin
   Length := Read(Socket,
                  M'Address,
                  M'Object_Size / System.Storage_Unit);
end;

Using 'Size in this situation is not portable because some compilers take it
to mean the size of the current value, not that of the object (which can be
different in the case of unconstrained types).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: GNAT'Object_Size
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
@ 1997-12-05  0:00         ` Mats Weber
  0 siblings, 0 replies; 28+ messages in thread
From: Mats Weber @ 1997-12-05  0:00 UTC (permalink / raw)



sorry about the multiple posting of this article (news server problem).




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00     ` Robert Dewar
@ 1997-12-06  0:00       ` Jean-Pierre Rosen
  1997-12-06  0:00         ` Making Predefined Operators Abstract Matthew Heaney
  0 siblings, 1 reply; 28+ messages in thread
From: Jean-Pierre Rosen @ 1997-12-06  0:00 UTC (permalink / raw)



Robert Dewar said
>Matthew says
>
><<Good advice.  For low-level I/O, an enumeration type is often not what
you
>want anyway.  What's wrong with a good old fashioned integer type?
>>>
>
>For one thing, it provides operations like addition, which are probably
>meaningless nonsense.
>
Sure, but don't forget that you can forbid direct calls by redefining the
functions as abstract.

(Just taking the opportunity to remind people of that relatively unknown
feature)






^ permalink raw reply	[flat|nested] 28+ messages in thread

* Making Predefined Operators Abstract
  1997-12-06  0:00       ` Jean-Pierre Rosen
@ 1997-12-06  0:00         ` Matthew Heaney
  0 siblings, 0 replies; 28+ messages in thread
From: Matthew Heaney @ 1997-12-06  0:00 UTC (permalink / raw)



In article <66c2rb$hdg$1@peuplier.wanadoo.fr>, "Jean-Pierre Rosen"
<rosen.adalog@wanadoo.fr> wrote:

>Robert Dewar said
>>Matthew says
>>
>><<Good advice.  For low-level I/O, an enumeration type is often not what
>you
>>want anyway.  What's wrong with a good old fashioned integer type?
>>>>
>>
>>For one thing, it provides operations like addition, which are probably
>>meaningless nonsense.
>>
>Sure, but don't forget that you can forbid direct calls by redefining the
>functions as abstract.
>
>(Just taking the opportunity to remind people of that relatively unknown
>feature)

I like to do that so I don't use the predefined equality for arrays or
records accidently, because the predefined equality of the component
reemerges.  For example, if I implemented a stack this way

generic
   type Stack_Item is private;
   Max_Depth : Positive;
package Stacks is
   type Bounded_Stack is tagged private;
  
   function "=" (L, R : Bounded_Stack) return Boolean;
...
private

   subtype Top_Range is Natural range 0 .. Max_Depth;

   subtype Item_Array_Range is Top_Range range 1 .. Top_Range'Last;
   type Item_Array is array (Item_Array_Range) of Stack_Item;

   type Bounded_Stack is
      tagged record
         Items : Item_Array;
         Top     : Top_Range := 0;
      end record;

end Stacks;

package body Stacks is

   function "=" (L, R : Bounded_Stack) return Boolean is
   begin
      return L.Items (1 .. L.Top) = R.Items (1..R.Top);
   end;
...
end Bounded_Stacks;

The problem with this implementation of equality is that it's probably
wrong.  The predefined equality operation for Stack_Item reemerged by not
explicitly importing the equality operation as a formal operation.  So I
would do this:

generic
   type Stack_Item is private;
   with function "=" (L, R : Stack_Item) return Boolean is <>;
package Bounded_Stacks is ...;

However, the equality operation for Stack that I defined above is still
wrong!  The problem now is that predefined equality reemerged as a result
of making Stack_Item an array component  Array comparisons use the
predefined equality of the component, in spite of the fact that equality
was imported as a formal operation.  The solution is to not use array
comparison at all to implement stack comparision:

   function "=" (L, R : Bounded_Stack) return Boolean is
   begin
      if L.Top /= R.Top then
         return False;
      end if;

      for Index in Item_Array_Range range 1 .. L.Top loop
         if L.Items (Index) /= R.Items (Index) then
            return False;
         end if;
      end loop;
  
      return True;
   end "=";

All of this was leading up to making a predefined operation abstract. 
Because we definately do not want to use array comparison, we take it away
as follows:

private
   ...
   type Item_Array is array (Item_Array_Range) of Stack_Item;

   function "=" (L, R : Item_Array) return Boolean is abstract;  -- Note
this line

   type Bounded_Stack is ...;

Now neither you nor a naive maintenance programmer can accidently use array
equality, because that operation is abstract.

A guideline for writers of data structures is to always import equality (to
give the client the opportunity to use his own definition) and to not use
predefined array equality for an array having the imported type as a
component.  You must invoke the imported equality of the component type
directly.  Declaring the array equality as abstract enforces this.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00         ` Stanley R. Allen
@ 1997-12-07  0:00           ` Keith Thompson
  1997-12-07  0:00             ` Matthew Heaney
  1997-12-07  0:00             ` Robert Dewar
  0 siblings, 2 replies; 28+ messages in thread
From: Keith Thompson @ 1997-12-07  0:00 UTC (permalink / raw)



Stanley R. Allen (s_allen@hso.link.com) wrote:
> Matthew Heaney wrote:
> > Personally, I feel that if you're always looking at the rep of the
> > enumerands, then you probably don't want an enumeration type anyway.
> 
> That's a dead argument on the face of it.  If the language
> permits me to *specify* the representation, then why doesn't
> it permit me to *query* the specified values?

Because, IMHO, enumeration representation clauses weren't thought out as
well as they should have been when Ada 83 was designed, and the problems
weren't corrected in the Ada 95 revision.  If the language had defined
attributes to convert between an enumeration type and Universal_Integer,
analogous to 'Val and 'Pos but using the underlying representation rather
than the position value, along with a good way to determine whether
an enumeration value from an external source is valid, enumeration
representation clauses would have been much more useful.

There are some partial solutions for these problems.  Unchecked_Conversion
can be used to query the representation; the problem is determining an
integer type that matches a given enumeration type, especially if the
representation includes negative values.  GNAT provides the 'Enum_Rep
attribute (but not 'Enum_Val), but it's not portable.  The 'Valid
attribute should be usable to validate external data, but straightforward
use of it is erroneous by RM95-13.9.1; see also AI95-00167.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-07  0:00           ` Keith Thompson
  1997-12-07  0:00             ` Matthew Heaney
@ 1997-12-07  0:00             ` Robert Dewar
  1997-12-08  0:00               ` Keith Thompson
  1 sibling, 1 reply; 28+ messages in thread
From: Robert Dewar @ 1997-12-07  0:00 UTC (permalink / raw)



Keith says

<<attribute (but not 'Enum_Val), but it's not portable.  The 'Valid
attribute should be usable to validate external data, but straightforward
use of it is erroneous by RM95-13.9.1; see also AI95-00167.>>

The 'Valid attribute *is* usable for this purpose.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-08  0:00               ` Keith Thompson
@ 1997-12-07  0:00                 ` Matthew Heaney
  1997-12-11  0:00                   ` John G. Volan
  0 siblings, 1 reply; 28+ messages in thread
From: Matthew Heaney @ 1997-12-07  0:00 UTC (permalink / raw)



In article <881544004.778618@wagasa.cts.com>, kst@king.cts.com (Keith
Thompson) wrote:


>Unfortunately, RM95-13.9.1(12) says that a call to an instance of
>Unchecked_Conversion is erroneous if the result is scalar and has an
>invalid representation, so I get unpredictable behavior before I even
>have a chance to use 'Valid.  I can work around this by wrapping the
>scalar in a record, but I shouldn't have to.

This is what I was alluding to when I said that it's often the case that an
integer is prefered over an enumeration.  Instead of

1) read value into integer
2) convert integer to enumeration
3) check that enumeration is valid

I prefer to avoid the potential erroneousness of step 2  by doing this

1) read value into integer
2) check that integer has an acceptable value
3) convert integer to enumeration

I don't disagree that 13.9.1 (12) is an issue, but the validity check and
type conversion should be hidden inside an interface object anyway, so
what's the big deal about checking the value manually?

Furthermore, I don't understand why you even bothered reading into an
integer.  Why not just read into an enumeration type directly?  How about

1) read value into enumeration object
2) check validity

Now no conversion is required at all, and 13.9.1 (12) doesn't even come up.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-07  0:00           ` Keith Thompson
@ 1997-12-07  0:00             ` Matthew Heaney
  1997-12-07  0:00             ` Robert Dewar
  1 sibling, 0 replies; 28+ messages in thread
From: Matthew Heaney @ 1997-12-07  0:00 UTC (permalink / raw)



In article <881531533.459982@wagasa.cts.com>, kst@king.cts.com (Keith
Thompson) wrote:


>There are some partial solutions for these problems.  Unchecked_Conversion
>can be used to query the representation; the problem is determining an
>integer type that matches a given enumeration type, especially if the
>representation includes negative values.

Why is this a problem?  If you specify a representation, then you probably
specified a size too, because you're transferring the data to an external
device.  So why not declare an instantiation of Unchecked_Conversion at the
point of declaration of the enumeration type?

type Color is (Red, Green, Blue);

for Color use (Red => -2, Green => 5, Blue => 10);

for Color'Size use 8;

type Color_Rep is new Interfaces.Integer_8;

function To_Rep is new Unchecked_Conversion (Color, Color_Rep);

What's the problem?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-07  0:00             ` Robert Dewar
@ 1997-12-08  0:00               ` Keith Thompson
  1997-12-07  0:00                 ` Matthew Heaney
  0 siblings, 1 reply; 28+ messages in thread
From: Keith Thompson @ 1997-12-08  0:00 UTC (permalink / raw)



Robert Dewar (dewar@merv.cs.nyu.edu) wrote:
> Keith says
> 
> <<attribute (but not 'Enum_Val), but it's not portable.  The 'Valid
> attribute should be usable to validate external data, but straightforward
> use of it is erroneous by RM95-13.9.1; see also AI95-00167.>>
> 
> The 'Valid attribute *is* usable for this purpose.

I should have been more specific.  At least one sensible usage of 'Valid
is not usable, given the current language definition.

Suppose an external interface provides integer values which are expected
to take on any of a specified set of values.  I declare an enumeration
type with a representation clause that matches the externally imposed
representation.  I then use Unchecked_Conversion to convert from the
integer type to my enumeration type.  Since I can't trust the external
interface 100%, I use 'Valid to check whether I have a valid value.

Unfortunately, RM95-13.9.1(12) says that a call to an instance of
Unchecked_Conversion is erroneous if the result is scalar and has an
invalid representation, so I get unpredictable behavior before I even
have a chance to use 'Valid.  I can work around this by wrapping the
scalar in a record, but I shouldn't have to.

It's true that most or all implementations will behave "sensibly" (as
the AARM vaguely encourages them to do), but I'd rather avoid erroneous
execution altogether than depend on this.

See also the minutes of the November ARG meeting in St. Louis.

-- 
Keith Thompson (The_Other_Keith) kst@cts.com <*>
^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H
San Diego, California, USA
Trying to keep my daily caffeine intake between the RDA and the LD50.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: GNAT'Object_Size
  1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
@ 1997-12-08  0:00         ` Mats Weber
  1997-12-10  0:00           ` GNAT'Object_Size Robert Dewar
  0 siblings, 1 reply; 28+ messages in thread
From: Mats Weber @ 1997-12-08  0:00 UTC (permalink / raw)



I wrote:

> And also generalize 'Object_Size so that it works on objects as well as types,
> and returns the size actually allocated for an object, so that the following
> code can be made to work:
> 
> generic
>    type T (<>) is private;
> procedure Receive (M : out T) is
> 
>    function Read (FD     : Integer;
>                   Buffer : System.Address;
>                   Count  : Integer) return Integer;
> 
>    pragma Import(C, Read);
> 
>    Length : Integer;
> 
> begin
>    Length := Read(Socket,
>                   M'Address,
>                   M'Object_Size / System.Storage_Unit);
> end;
> 
> Using 'Size in this situation is not portable because some compilers take it
> to mean the size of the current value, not that of the object (which can be
> different in the case of unconstrained types).

After a discussion with Robert Dewar, the above approach cannot be made to
work in all cases because a subprogram does not in general know the size of
its actual parameters, so that implementing 'Object_Size for objects would
require an extra parameter, which is an unnecessary overhead most of the time.

Some Ada 83 compilers (Verdix in this case) do smart things for 'Size applied
to parameters: they return the value size for mode in parameters, and the
object size for mode out parameters (how they do it I don't know), which is
exactly what is needed to solve the above problem, but doesn't help when
porting to other compilers.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: GNAT'Object_Size
  1997-12-08  0:00         ` GNAT'Object_Size Mats Weber
@ 1997-12-10  0:00           ` Robert Dewar
  0 siblings, 0 replies; 28+ messages in thread
From: Robert Dewar @ 1997-12-10  0:00 UTC (permalink / raw)



<<Some Ada 83 compilers (Verdix in this case) do smart things for 'Size applied
to parameters: they return the value size for mode in parameters, and the
object size for mode out parameters (how they do it I don't know), which is
exactly what is needed to solve the above problem, but doesn't help when
porting to other compilers.
>>

An obvious, but wrong, approach is to use the 'Constrained bit to indicate
whether the original object is constrained or not. This does not work,
because an originally unconstrained object can appear constrained because
of an intermediate parameter stage.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-07  0:00                 ` Matthew Heaney
@ 1997-12-11  0:00                   ` John G. Volan
  0 siblings, 0 replies; 28+ messages in thread
From: John G. Volan @ 1997-12-11  0:00 UTC (permalink / raw)



Matthew Heaney wrote:
> Furthermore, I don't understand why you even bothered reading into an
> integer.

Because programmers have been brainwashed into believing that computer
memory is somehow composed of "integers," thus if you want to get "close
to the metal", you have to work with these "integers."  But we all know
that computer memory really consists of various addressable aggregations
of microminiaturized binary-state devices.  "Integers" are just one of
many data-type abstractions that we have superimposed upon the reality
of bit-patterns. Certain operations embedded in CPU hardware happen to
provide some direct support for the "integer" abstraction, and all
programming languages heavily support this abstraction as well, so 
integers just happen to be convenient as representations for
bit-patterns.  But for all of that, I don't see "integers" as being any
more "concrete" than anything other data type.

> Why not just read into an enumeration type directly?

Here, here!

-- 
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Raytheon/TI Advanced C3I Systems, San Jose, CA",
   Work_Email => "jvolan@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Ada Enumerations
  1997-12-04  0:00         ` Stanley R. Allen
@ 1997-12-18  0:00           ` Wes Groleau
  0 siblings, 0 replies; 28+ messages in thread
From: Wes Groleau @ 1997-12-18  0:00 UTC (permalink / raw)



> > I must say I don't see so much of a problem with Unchecked_Conversion for
> > replacing Enum_Rep unless you have a really hostile compiler. For types
> > like this, Unchecked_Conversion should work as expected in cases where
> > the number of bits of the source and target differs.
> 
> At least you *hope* so; too bad for you if your application
> depends on it and the compiler doesn't do it right, or if
> you need to port to a "hostile" compiler.  There being no
> rule for this in either Ada83 or Ada95 ....

Well, if your situation is that desperate, you could 
follow the rep. clause in the same source file with 

  Enum_Rep : constant array (Enum_Type)
               of Integer_Type_To_Convert_To := (.........);

This is portable--until you change the rep. spec and forget
to change the table! :-)




^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~1997-12-18  0:00 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-12-03  0:00 Ada Enumerations Jeffrey Harris
1997-12-03  0:00 ` James S. Rogers
1997-12-03  0:00   ` Robert Dewar
1997-12-03  0:00     ` Stanley R. Allen
1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
1997-12-08  0:00         ` GNAT'Object_Size Mats Weber
1997-12-10  0:00           ` GNAT'Object_Size Robert Dewar
1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
1997-12-05  0:00         ` GNAT'Object_Size Mats Weber
1997-12-04  0:00       ` Ada Enumerations Matthew Heaney
1997-12-04  0:00         ` Stanley R. Allen
1997-12-07  0:00           ` Keith Thompson
1997-12-07  0:00             ` Matthew Heaney
1997-12-07  0:00             ` Robert Dewar
1997-12-08  0:00               ` Keith Thompson
1997-12-07  0:00                 ` Matthew Heaney
1997-12-11  0:00                   ` John G. Volan
1997-12-04  0:00       ` Robert Dewar
1997-12-04  0:00         ` Stanley R. Allen
1997-12-18  0:00           ` Wes Groleau
1997-12-04  0:00       ` GNAT'Object_Size Mats Weber
1997-12-04  0:00 ` Ada Enumerations Stephen Leake
1997-12-04  0:00   ` Matthew Heaney
1997-12-04  0:00     ` Robert Dewar
1997-12-06  0:00       ` Jean-Pierre Rosen
1997-12-06  0:00         ` Making Predefined Operators Abstract Matthew Heaney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox