comp.lang.ada
 help / color / mirror / Atom feed
* Rules for Representation of Subtypes
@ 1996-09-22  0:00 Matthew Heaney
  1996-09-23  0:00 ` David C. Hoos, Sr.
  1996-09-23  0:00 ` Robert A Duff
  0 siblings, 2 replies; 73+ messages in thread
From: Matthew Heaney @ 1996-09-22  0:00 UTC (permalink / raw)



I've always been curious about the rules for representation of subtypes. 
For example, if I make a declaration like this:

   A_Small_Integer : Integer range 0 .. 255;  -- assume type Integer is 4 bytes

then is an implementation allowed to use fewer than 4 bytes to represent
A_Small_Integer?

Suppose I'm on a Unix system and I do this

   read (fd, A_Small_Integer'Address, 4);

If the representation of A_Small_Integer is only 1 byte, then obviously I'm
in trouble.  Am I required to specify the size of objects?

   A_Small_Integer : Integer range 0 .. 255;
   for A_Small_Integer'Size use 32;                     -- required?

matt
mheaney@ni.net

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-22  0:00 Rules for Representation of Subtypes Matthew Heaney
@ 1996-09-23  0:00 ` David C. Hoos, Sr.
  1996-09-23  0:00   ` Robert A Duff
                     ` (3 more replies)
  1996-09-23  0:00 ` Robert A Duff
  1 sibling, 4 replies; 73+ messages in thread
From: David C. Hoos, Sr. @ 1996-09-23  0:00 UTC (permalink / raw)



Matthew Heaney <mheaney@ni.net> wrote in article
<mheaney-ya023080002209961353500001@news.ni.net>...
> I've always been curious about the rules for representation of subtypes. 
> For example, if I make a declaration like this:
> 
>    A_Small_Integer : Integer range 0 .. 255;  -- assume type Integer is 4
bytes
> 
> then is an implementation allowed to use fewer than 4 bytes to represent
> A_Small_Integer?
> 
> Suppose I'm on a Unix system and I do this
> 
>    read (fd, A_Small_Integer'Address, 4);
> 
> If the representation of A_Small_Integer is only 1 byte, then obviously
I'm
> in trouble.  Am I required to specify the size of objects?
> 
>    A_Small_Integer : Integer range 0 .. 255;
>    for A_Small_Integer'Size use 32;                     -- required?
> 
> matt
> mheaney@ni.net
> 
> --------------------------------------------------------------------
> Matthew Heaney
> Software Development Consultant
> mheaney@ni.net
> (818) 985-1271
> 
Hi Matthew,

My understanding of the rules for representation clauses for types is that
the size attribute may only be specified for the first subtype, so for any
subtype of integer you would get the same size as Integer.
In fact, I just tried to specify a size of 8 bits for your object
"A_Small_Integer", with gnat 3.04a on Win95, and found that the compiler
gave no warning, and ignored the clause.  Printing out the 'size attribute
yielded 32.

However, as far as your "UNIX" example is concerned (I say "UNIX", because
this would apply to any OS where you're doing what you appear to be doing
here -- i.e. interfacing to the C library), why not write the code in a
manner where it doesn't matter how the compiler represents the object --
i.e., write:

    read (fd, A_Small_Integer'Address, A_Small_Integer'Size /
System.Storage_Unit);

The division is a compile-time operation, so there is no run-time
difference.

I hope this helps
-- 
David C. Hoos, Sr.,
http://www.dbhwww.com
http://www.ada95.com






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

* Re: Rules for Representation of Subtypes
  1996-09-22  0:00 Rules for Representation of Subtypes Matthew Heaney
  1996-09-23  0:00 ` David C. Hoos, Sr.
@ 1996-09-23  0:00 ` Robert A Duff
  1996-09-24  0:00   ` Matthew Heaney
  1 sibling, 1 reply; 73+ messages in thread
From: Robert A Duff @ 1996-09-23  0:00 UTC (permalink / raw)



In article <mheaney-ya023080002209961353500001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>I've always been curious about the rules for representation of subtypes. 
>For example, if I make a declaration like this:
>
>   A_Small_Integer : Integer range 0 .. 255;  -- assume type Integer is 4 bytes
>
>then is an implementation allowed to use fewer than 4 bytes to represent
>A_Small_Integer?

Yes.

>Suppose I'm on a Unix system and I do this
>
>   read (fd, A_Small_Integer'Address, 4);
>
>If the representation of A_Small_Integer is only 1 byte, then obviously I'm
>in trouble.  Am I required to specify the size of objects?

Well, you could.  But a better solution is to always say "aliased" when
you have a variable you want to take 'Address of.  Aliased variables
will generally be represented the same way, for all variables of the
type.

Also, the number 4 is questionable.  What are you trying to do?  Read 4
bytes of data?  Well in that case, you want to make sure the target
variable is 4 bytes (which your code doesn't do).  Or are you trying to
read however-many-bytes it takes to fill up A_Small_Integer?  In that
case, you should be asking for that number of bytes, not 4 bytes.  (You
can calculate it based on 'Size, which, unfortunately, is in bits.)

>   A_Small_Integer : Integer range 0 .. 255;
>   for A_Small_Integer'Size use 32;                     -- required?

That will make it the right size.  But if you read 4 non-zero bytes,
your program will be erroneous.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-23  0:00 ` David C. Hoos, Sr.
@ 1996-09-23  0:00   ` Robert A Duff
  1996-09-23  0:00   ` Samuel T. Harris
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-23  0:00 UTC (permalink / raw)



In article <01bba947$d8990620$188371a5@dhoossr.iquest.com>,
David C. Hoos, Sr. <david.c.hoos.sr@ada95.com> wrote:
>My understanding of the rules for representation clauses for types is that
>the size attribute may only be specified for the first subtype, so for any
>subtype of integer you would get the same size as Integer.

No, that's not quite right.  You're right about the rules for rep
clauses.  But that certainly does *not* imply that all subtypes of
integer have the same size as Integer -- you can't *ask* the compiler to
use 8 bits for a subtype of Integer, but the compiler can use 8 bits.
In fact, 13.3(55) requires that they do *not* have the same size, in
general.

Besides, the A_Small_Integer in the example was a variable, not a
subtype.  You can specify its size as 8 bits, if you want.  Or 32 bits.

Also, it's good to keep in mind that if you have subtype S and object X
of subtype S, it is NOT always the case that S'Size = X'Size.  In fact,
it is unusual for these to be equal.

>In fact, I just tried to specify a size of 8 bits for your object
>"A_Small_Integer", with gnat 3.04a on Win95, and found that the compiler
>gave no warning, and ignored the clause.  Printing out the 'size attribute
>yielded 32.

GNAT is not the definition of the Ada language.  ;-)

>However, as far as your "UNIX" example is concerned (I say "UNIX", because
>this would apply to any OS where you're doing what you appear to be doing
>here -- i.e. interfacing to the C library), why not write the code in a
>manner where it doesn't matter how the compiler represents the object --
>i.e., write:
>
>    read (fd, A_Small_Integer'Address, A_Small_Integer'Size /
>System.Storage_Unit);

Yes, that's better than "4".

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-23  0:00 ` David C. Hoos, Sr.
  1996-09-23  0:00   ` Robert A Duff
@ 1996-09-23  0:00   ` Samuel T. Harris
  1996-09-26  0:00     ` David C. Hoos, Sr.
  1996-09-24  0:00   ` Robert Dewar
  1996-09-24  0:00   ` Robert Dewar
  3 siblings, 1 reply; 73+ messages in thread
From: Samuel T. Harris @ 1996-09-23  0:00 UTC (permalink / raw)



David C. Hoos, Sr. wrote:
> i.e., write:
> 
>     read (fd, A_Small_Integer'Address, A_Small_Integer'Size /
> System.Storage_Unit);
> 

More safe (in a general sense) is ...

(A_Small_Integer'Size + System.Storage_Unit - 1) / System.Storage_Unit

... to handle those rare weird-sized entities with
involve non-zero remainders to the poster's division.

-- 
Samuel T. Harris, Senior Engineer
Hughes Training, Inc. - Houston Operations
2224 Bay Area Blvd. Houston, TX 77058-2099
"If you can make it, We can fake it!"




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

* Re: Rules for Representation of Subtypes
  1996-09-23  0:00 ` Robert A Duff
@ 1996-09-24  0:00   ` Matthew Heaney
  1996-09-26  0:00     ` Robert A Duff
  0 siblings, 1 reply; 73+ messages in thread
From: Matthew Heaney @ 1996-09-24  0:00 UTC (permalink / raw)



In article <Dy78qJ.MDr@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:

>>I've always been curious about the rules for representation of subtypes. 
>>For example, if I make a declaration like this:
>>
>>   A_Small_Integer : Integer range 0 .. 255;  -- assume type Integer is 4
bytes
>>
>>then is an implementation allowed to use fewer than 4 bytes to represent
>>A_Small_Integer?
>
>Yes.
>
>>Suppose I'm on a Unix system and I do this
>>
>>   read (fd, A_Small_Integer'Address, 4);
>>
>>If the representation of A_Small_Integer is only 1 byte, then obviously I'm
>>in trouble.  Am I required to specify the size of objects?
>
>Well, you could.  But a better solution is to always say "aliased" when
>you have a variable you want to take 'Address of.  Aliased variables
>will generally be represented the same way, for all variables of the
>type.

You say "generally" be represented the same way: can you be more specific? 
Under what circumstances can they be different?

>Also, the number 4 is questionable.  What are you trying to do?  Read 4
>bytes of data?  Well in that case, you want to make sure the target
>variable is 4 bytes (which your code doesn't do).  Or are you trying to
>read however-many-bytes it takes to fill up A_Small_Integer?  In that
>case, you should be asking for that number of bytes, not 4 bytes.  (You
>can calculate it based on 'Size, which, unfortunately, is in bits.)

Perhaps this was a poor example: I would never actually do it that way in
real code.  I just needed an example to ask my question about size of
objects of subtypes. 

Better is:

   A_Small_Integer: Interfaces.Integer_32 range 0 .. 255;

But of course, if I'm going to read 4 bytes from an OS call, then

   The_Value : Interfaces.Integer_32;

is best.


BTW: Why doesn't Ada have a 'Storage_Size clause for (non-access) types or
objects?  If everywhere I want storage units, I have to do this:

   read (fd, O'Address, O'Size / System.Storage_Unit);

If "number of storage units" is required so much, and the expression
O'Size/System.Storage_Unit is so popular, then why didn't the Ada designers
save me the trouble, so I could say

   read (fd, O'Address, O'Storage_Units);

or even

   read (fd, O'Address, O'Number_Of_Bytes);

I've seen this kind of error often, where the programmer sends the 'Size
without dividing by 8 first.  The error is exacerbated when documentation
(say, on a Unix box) refers to size, and means "number of bytes."  So easy
to forget to divide O'Size by 8!

Byte-size is an undeniably popular unit of measure in programming.  The
fact that there's no *direct* support for it in Ada seems to me to be an
egregious oversight.  (But I'm sure there was a reason...)


Here's another question:

   type T is new Interfaces.Integer_32 range 0 .. 255;

What is the size of T?  Do I need to specify a size clause to ensure that
objects of type T are 4 bytes?

>>   A_Small_Integer : Integer range 0 .. 255;
>>   for A_Small_Integer'Size use 32;                     -- required?
>
>That will make it the right size.  But if you read 4 non-zero bytes,
>your program will be erroneous.

You are of course correct.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-23  0:00 ` David C. Hoos, Sr.
                     ` (2 preceding siblings ...)
  1996-09-24  0:00   ` Robert Dewar
@ 1996-09-24  0:00   ` Robert Dewar
  3 siblings, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-09-24  0:00 UTC (permalink / raw)



I meant to add more on the issue of Size, but accidentally termianted
transmission early!

One thing we have done in GNAT is the following:

First, objects of a subtype by default have the same size as the size
of the first subtype, even though Ada 95 does NOT require this, and in
fact makes an implementation suggestion to the contrary:

50   If the Size of a subtype is specified, and allows for efficient
independent addressability (see 9.10) on the target architecture, then the
Size of the following objects of the subtype should equal the Size of the
subtype:

   51  Aliased objects (including components).

   52  Unaliased components, unless the Size of the component is
       determined by a component_clause or Component_Size clause.


We at first followed this advice and found it caused compatibility chaos!
So, that's the first point, David's guess as the the behavior of subtypes
is in fact corect WITH RESPECT TO OBJECTS in GNAT. This is of course in the
absence of a specific attribute representation clause. 

Second, we have provided two new attributes

Value_Size is just like Size in the RM, except that it can be applied to
subtypes other than the first subtype. 

Object_Size is the size that will be used by default for objects of the
type or subtype. It need not be the same as Value_Size. The default value
of Object_Size is close to what most Ada 83 compilers provided for Size.
It can be specified for subtypes other than the first subtype.

Value_Size, like Size in the RM, is used for packing and for unchecked
conversion, but not much else.





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

* Re: Rules for Representation of Subtypes
  1996-09-23  0:00 ` David C. Hoos, Sr.
  1996-09-23  0:00   ` Robert A Duff
  1996-09-23  0:00   ` Samuel T. Harris
@ 1996-09-24  0:00   ` Robert Dewar
  1996-09-26  0:00     ` Keith Thompson
  1996-09-24  0:00   ` Robert Dewar
  3 siblings, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-09-24  0:00 UTC (permalink / raw)



Matthew Heaney <mheaney@ni.net> wrote in article

  mheaney-ya023080002209961353500001@news.ni.net>...
   I've always been curious about the rules for representation of subtypes.
   For example, if I make a declaration like this:
  
      A_Small_Integer : Integer range 0 .. 255;  -- assume type Integer is 4
  ytes
  
   then is an implementation allowed to use fewer than 4 bytes to represent
   A_Small_Integer?
  
   Suppose I'm on a Unix system and I do this
  
      read (fd, A_Small_Integer'Address, 4);
  
   If the representation of A_Small_Integer is only 1 byte, then obviously
  'm
   in trouble.  Am I required to specify the size of objects?
  
      A_Small_Integer : Integer range 0 .. 255;
      for A_Small_Integer'Size use 32;                     -- required?
  
   matt
   mheaney@ni.net

David wrote

Hi Matthew,

  My understanding of the rules for representation clauses for types is that
  the size attribute may only be specified for the first subtype, so for any
  subtype of integer you would get the same size as Integer.
  In fact, I just tried to specify a size of 8 bits for your object
  "A_Small_Integer", with gnat 3.04a on Win95, and found that the compiler
  gave no warning, and ignored the clause.  Printing out the 'size attribute
  yielded 32.
  
  However, as far as your "UNIX" example is concerned (I say "UNIX", because
  this would apply to any OS where you're doing what you appear to be doing
  here -- i.e. interfacing to the C library), why not write the code in a
  manner where it doesn't matter how the compiler represents the object --
  i.e., write:
  
      read (fd, A_Small_Integer'Address, A_Small_Integer'Size /
  System.Storage_Unit);
  
  The division is a compile-time operation, so there is no run-time
  difference.
  
  I hope this helps

David's understanding is a bit confused, and so may not help :-)

This in fact is a place where Ada 95, somewhat accidentally, is incompatible
with most Ada 83 implementations. What Ada 95 did was to specify things that
are left unspecified in the Ada 83 reference manual, and to do it in a manner
that was compatible with the Intermetrics compiler, but not most other Ada
83 compilers, so this is something to be on the watch for.

David's first significant misunderstanding is that the size of an object
is not strongly related to the size of the type. So of course in GNAT, if
you specify the size of an object as 8, it will be 8, but this will not
affect the size of the type.

Second, in Ada 95, the size of a subtype is required to be the minimum
number of bits, so it is NOT AT ALL the case that a subtype has the same
size as the first subtype. On the contrary, this would be an incorrect
implementation.

For example, Natural'Size is required to be Integer'Size MINUS ONE, i.e.
31, not 32, on most machines. This can cause chaos if a program assumes
that Natural'Size is 32, as it was on many Ada 83 implementations.

In GNAT, we have implemented the Size attribute as described in the RM,
but generally the behavior of size is rather odd to most people:

   type x is range 1 .. 10;    -- x'size = 4
   subtype y is x range 1 .. 10; -- y'size = 4
   subtype z is x range 1 .. 9;  -- z'size = 4

Now use a size attribute clause

   type x is range 1 .. 10;    -- x'size = 16
   for x'size use 16;
   subtype y is x range 1 .. 10; -- y'size = 16
   subtype z is x range 1 .. 9;  -- z'size = 4
 
--
   Suppose I'm on a Unix system and I do this
  
      read (fd, A_Small_Integer'Address, 4);

Normally, you don't need to worry about the size of things, but if you
are interfacing to C, you ought to specify the size of the object, or in this
case, not simply use (A_Small_Integer'Size + Storage_Unit - 1)/Storage_Unit
for 4. This is similar to David's suggestion, except that he made an
unjustified assumption that the size of A_SMall_Integer would be a multiple
of Storage Unit.

Incidentally, we have considered adding an attribute Size_In_Storage_Units
to GNAT. It is annoyingly missing, and would often be useful.
                     







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

* Re: Rules for Representation of Subtypes
  1996-09-23  0:00   ` Samuel T. Harris
@ 1996-09-26  0:00     ` David C. Hoos, Sr.
  0 siblings, 0 replies; 73+ messages in thread
From: David C. Hoos, Sr. @ 1996-09-26  0:00 UTC (permalink / raw)



Samuel T. Harris <u61783@gsde.hso.link.com> wrote in article
<32474889.6EEA@gsde.hso.link.com>...
> David C. Hoos, Sr. wrote:
> > i.e., write:
> > 
> >     read (fd, A_Small_Integer'Address, A_Small_Integer'Size /
> > System.Storage_Unit);
> > 
> 
> More safe (in a general sense) is ...
> 
> (A_Small_Integer'Size + System.Storage_Unit - 1) / System.Storage_Unit
> 
> ... to handle those rare weird-sized entities with
> involve non-zero remainders to the poster's division.

You're absolutely correct, and I always code it that way.  Why I didn't put
it in my posting is probably because I don't desk-check e-mail and
newsgroup postings like I do real code -- with marker in hand and hard
copy.
-- 
David C. Hoos, Sr.,
http://www.dbhwww.com
http://www.ada95.com






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

* Re: Rules for Representation of Subtypes
  1996-09-24  0:00   ` Matthew Heaney
@ 1996-09-26  0:00     ` Robert A Duff
  1996-09-26  0:00       ` Larry Kilgallen
  1996-09-27  0:00       ` Rules for Representation of Subtypes Matthew Heaney
  0 siblings, 2 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-26  0:00 UTC (permalink / raw)



In article <mheaney-ya023080002409960726040001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>You say "generally" be represented the same way: can you be more specific? 
>Under what circumstances can they be different?

Well, aliased Strings could be different sizes, for example.

>BTW: Why doesn't Ada have a 'Storage_Size clause for (non-access) types or
>objects?

It should.

>Here's another question:
>
>   type T is new Interfaces.Integer_32 range 0 .. 255;
>
>What is the size of T?  Do I need to specify a size clause to ensure that
>objects of type T are 4 bytes?

Yes.

But this is all very obscure.  If you're interfacing to hardware, or to
C, or to something else where the interface is a low-level binary
interface, the best thing to do is make the types match the hardware, or
the C, or whatever it is.  Don't use constraints on the Ada side of the
interface, just because the logical properties would warrant a
constraint.

For example, suppose you call a C function that takes a pointer to an
int, and the function updates the pointed-to int.  The documentation
promises that the value will always be in 1..10.  DO NOT say "type T is
range 1..10;", or "subtype T is Interfaces.C.int range 1..10;" on the
Ada side.  Because, if the documentation lies, your program will be
erroneous.  If, on the other hand, you use Interfaces.C.int, at the
interface, and *then* assign it into a constrained thing, you will get a
Constraint_Error for the bad data.  Or, you can write an "if" statement
to check for bad data.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-24  0:00   ` Robert Dewar
@ 1996-09-26  0:00     ` Keith Thompson
  1996-09-26  0:00       ` Matthew Heaney
  1996-09-27  0:00       ` Robert A Duff
  0 siblings, 2 replies; 73+ messages in thread
From: Keith Thompson @ 1996-09-26  0:00 UTC (permalink / raw)



In <dewar.843570543@schonberg> dewar@cs.nyu.edu (Robert Dewar) writes:
[...]
> This in fact is a place where Ada 95, somewhat accidentally, is incompatible
> with most Ada 83 implementations. What Ada 95 did was to specify things that
> are left unspecified in the Ada 83 reference manual, and to do it in a manner
> that was compatible with the Intermetrics compiler, but not most other Ada
> 83 compilers, so this is something to be on the watch for.
[...]
> Second, in Ada 95, the size of a subtype is required to be the minimum
> number of bits, so it is NOT AT ALL the case that a subtype has the same
> size as the first subtype. On the contrary, this would be an incorrect
> implementation.
> 
> For example, Natural'Size is required to be Integer'Size MINUS ONE, i.e.
> 31, not 32, on most machines. This can cause chaos if a program assumes
> that Natural'Size is 32, as it was on many Ada 83 implementations.

The Ada 83 reference manual's description of the 'Size attribute is
rather vague.  AI-00536 was an attempt to clarify this description.
Among other things, it says:

        If the size of a type or a subtype S has not been determined by
        a length clause and S is either a scalar subtype, a constrained
        array subtype, a constrained subtype with discriminants, an
        access type, a task type, or a private type whose full type is
        one of these types, then S'SIZE yields the smallest number of
        bits that an implementation will allocate for an object declared
        with the subtype indication S; objects whose size is determined
        by a record component clause are not considered in determining
        the value of S'SIZE.

        For the predefined type BOOLEAN, BOOLEAN'SIZE is one.

In other words, the 'Size for a subtype is the smallest size that can be
allocated for an object of that subtype, including standalone objects
and components of (possibly packed) arrays and records, but excluding
components affected by record component clauses.

For an Ada 83 implementation that can pack a Natural and a Boolean into
a single word in a packed record, Natural'Size should be Integer'Size - 1.

Note in particular that Boolean'Size was required to be one, even though
a standalone Boolean object is very likely to occupy 8 bits or more.

I seem to recall that this interpretation was enforced by the 1.11 ACVCs,
though I don't remember the exact details.

Of the two Ada 83 implementations I have access to, one uses
Natural'Size=31.  The other uses Natural'Size=32, but it doesn't support
pragma Pack on records.

(Publicly disputing Robert Dewar is always dangerous.  Fortunately it's
a bounded error; the effect is limited to learning something.)

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00     ` Robert A Duff
@ 1996-09-26  0:00       ` Larry Kilgallen
  1996-09-27  0:00         ` Robert A Duff
                           ` (2 more replies)
  1996-09-27  0:00       ` Rules for Representation of Subtypes Matthew Heaney
  1 sibling, 3 replies; 73+ messages in thread
From: Larry Kilgallen @ 1996-09-26  0:00 UTC (permalink / raw)



In article <DyCF97.7zp@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:

> But this is all very obscure.  If you're interfacing to hardware, or to
> C, or to something else where the interface is a low-level binary
> interface, the best thing to do is make the types match the hardware, or
> the C, or whatever it is.  Don't use constraints on the Ada side of the
> interface, just because the logical properties would warrant a
> constraint.
> 
> For example, suppose you call a C function that takes a pointer to an
> int, and the function updates the pointed-to int.  The documentation
> promises that the value will always be in 1..10.  DO NOT say "type T is
> range 1..10;", or "subtype T is Interfaces.C.int range 1..10;" on the
> Ada side.  Because, if the documentation lies, your program will be
> erroneous.  If, on the other hand, you use Interfaces.C.int, at the
> interface, and *then* assign it into a constrained thing, you will get a
> Constraint_Error for the bad data.  Or, you can write an "if" statement
> to check for bad data.

Like:

	if X'Valid

?  I would think that as being an argument in _favor_ of declaring
the C-updated object in a tightly constrained fashion.

Larry Kilgallen




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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00     ` Keith Thompson
@ 1996-09-26  0:00       ` Matthew Heaney
  1996-09-27  0:00         ` Robert Dewar
  1996-09-27  0:00         ` Robert A Duff
  1996-09-27  0:00       ` Robert A Duff
  1 sibling, 2 replies; 73+ messages in thread
From: Matthew Heaney @ 1996-09-26  0:00 UTC (permalink / raw)



In article <DyC5xn.K3L@thomsoft.com>, kst@thomsoft.com (Keith Thompson) wrote:

>The Ada 83 reference manual's description of the 'Size attribute is
>rather vague.  AI-00536 was an attempt to clarify this description.
>Among other things, it says:
>
>        If the size of a type or a subtype S has not been determined by
>        a length clause and S is either a scalar subtype, a constrained
>        array subtype, a constrained subtype with discriminants, an
>        access type, a task type, or a private type whose full type is
>        one of these types, then S'SIZE yields the smallest number of
>        bits that an implementation will allocate for an object declared
>        with the subtype indication S; objects whose size is determined
>        by a record component clause are not considered in determining
>        the value of S'SIZE.
>
>        For the predefined type BOOLEAN, BOOLEAN'SIZE is one.
>
>In other words, the 'Size for a subtype is the smallest size that can be
>allocated for an object of that subtype, including standalone objects
>and components of (possibly packed) arrays and records, but excluding
>components affected by record component clauses.

Yes, but what's even more interesting is a preceding paragraph of that AI
which states:

"If the size of a type of a first named subtype T has been specified by a
length clause, the T'Size yields the specified size, AND THE SIZE OF EVERY
SUBTYPE OF T IS ALSO THIS VALUE [my emphasis]."

If my interpretation is correct (I'm waiting for an opinion, Bob...), then
this would solve my original problem, which was

   type Integer_32 is ...;
   for Integer_32'Size use 32;

   subtype T is Integer_32 range 0 .. 255;

   O : T;

According to the AI, object O should occupy 32  bits, not 8.  Right?

>Keith Thompson (The_Other_Keith) kst@thomsoft.com

matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00     ` Robert A Duff
  1996-09-26  0:00       ` Larry Kilgallen
@ 1996-09-27  0:00       ` Matthew Heaney
  1996-09-27  0:00         ` Robert A Duff
  1 sibling, 1 reply; 73+ messages in thread
From: Matthew Heaney @ 1996-09-27  0:00 UTC (permalink / raw)



In article <DyCF97.7zp@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:

>But this is all very obscure.  If you're interfacing to hardware, or to
>C, or to something else where the interface is a low-level binary
>interface, the best thing to do is make the types match the hardware, or
>the C, or whatever it is.  Don't use constraints on the Ada side of the
>interface, just because the logical properties would warrant a
>constraint.
>
>For example, suppose you call a C function that takes a pointer to an
>int, and the function updates the pointed-to int.  The documentation
>promises that the value will always be in 1..10.  DO NOT say "type T is
>range 1..10;", or "subtype T is Interfaces.C.int range 1..10;" on the
>Ada side.  Because, if the documentation lies, your program will be
>erroneous.  If, on the other hand, you use Interfaces.C.int, at the
>interface, and *then* assign it into a constrained thing, you will get a
>Constraint_Error for the bad data.  Or, you can write an "if" statement
>to check for bad data.

I agree.  As a matter of fact, this is what I do already, and what I tell
all my clients to do.  Most aren't savvy enough about Ada to realize that
their program (execution) is erroneous if the data they just read off the
interface doesn't match the constraints of their Ada type, and most people
expect (incorrectly) that Ada will just raise Constraint_Error if the data
is out of range.

So the moral of the story is, if you're reading data off an interface, read
it into a an object of a first named subtype without constraints.  Your
progam won't be erroneous (because no range constraints will be violated),
and first named subtypes seem to be the only place where the size of
objects of that type match the value of size specified in the length clause
for the type.  (Readers: holler if this last statement is incorrect.)

>- Bob

-Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00       ` Larry Kilgallen
@ 1996-09-27  0:00         ` Robert A Duff
  1996-09-27  0:00           ` Mark A Biggar
  1996-09-28  0:00           ` Larry Kilgallen
  1996-10-02  0:00         ` Valid Attribute and Unchecked Conversion Robert I. Eachus
  1996-10-02  0:00         ` George Haddad
  2 siblings, 2 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-27  0:00 UTC (permalink / raw)



In article <1996Sep26.191257.1@eisner>,
Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>Like:
>
>	if X'Valid
>
>?  I would think that as being an argument in _favor_ of declaring
>the C-updated object in a tightly constrained fashion.

No, that won't work.  By the time you get to that if statement, the
program execution is already erroneous.  Compilers can and do (and
should) take advantage of that fact to generate faster code that doesn't
work.  An unchecked conversion is a function call, and there's no way to
capture the result of it without assigning it somewhere, which causes
erroneousness if the result is bad.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-27  0:00       ` Rules for Representation of Subtypes Matthew Heaney
@ 1996-09-27  0:00         ` Robert A Duff
  0 siblings, 0 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-27  0:00 UTC (permalink / raw)



In article <mheaney-ya023180002709960713140001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>So the moral of the story is, if you're reading data off an interface, read
>it into a an object of a first named subtype without constraints.  ...

ANd make sure the first-named subtype matches the hardware data types.
E.g., use Interfaces.C.int.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-27  0:00         ` Robert A Duff
@ 1996-09-27  0:00           ` Mark A Biggar
  1996-09-30  0:00             ` Robert A Duff
  1996-09-28  0:00           ` Larry Kilgallen
  1 sibling, 1 reply; 73+ messages in thread
From: Mark A Biggar @ 1996-09-27  0:00 UTC (permalink / raw)



In article <DyEr6p.38H@world.std.com> bobduff@world.std.com (Robert A Duff) writes:
>In article <1996Sep26.191257.1@eisner>,
>Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>>Like:
>>	if X'Valid
>>?  I would think that as being an argument in _favor_ of declaring
>>the C-updated object in a tightly constrained fashion.
>No, that won't work.  By the time you get to that if statement, the
>program execution is already erroneous.  Compilers can and do (and
>should) take advantage of that fact to generate faster code that doesn't
>work.  An unchecked conversion is a function call, and there's no way to
>capture the result of it without assigning it somewhere, which causes
>erroneousness if the result is bad.

I'm not sure about this as I always thought that the RM was pretty clear
that only the USE of an abnormal value was erroneous, but that simply
assigning it was safe, at least I'm sure that was the intent, otherwise
X'VALID after an unchecked conversion is useless, but that is one of the
explisit examples of its intended use in the RM.

--
Mark Biggar
mab@wdl.lmco.com







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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00     ` Keith Thompson
  1996-09-26  0:00       ` Matthew Heaney
@ 1996-09-27  0:00       ` Robert A Duff
  1 sibling, 0 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-27  0:00 UTC (permalink / raw)



In article <DyC5xn.K3L@thomsoft.com>, Keith Thompson <kst@thomsoft.com> wrote:
>I seem to recall that this interpretation was enforced by the 1.11 ACVCs,
>though I don't remember the exact details.

I don't think so, since I know at least one Ada 83 compiler (validated)
had Boolean'Size = 8.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00       ` Matthew Heaney
  1996-09-27  0:00         ` Robert Dewar
@ 1996-09-27  0:00         ` Robert A Duff
  1996-09-27  0:00           ` Robert Dewar
  1 sibling, 1 reply; 73+ messages in thread
From: Robert A Duff @ 1996-09-27  0:00 UTC (permalink / raw)



In article <mheaney-ya023180002609962246250001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>"If the size of a type of a first named subtype T has been specified by a
>length clause, the T'Size yields the specified size, AND THE SIZE OF EVERY
>SUBTYPE OF T IS ALSO THIS VALUE [my emphasis]."
>
>If my interpretation is correct (I'm waiting for an opinion, Bob...), then
>this would solve my original problem, which was

I'm not sure if I'm the Bob being addressed, but...   I think your
interpretation is correct.  However, in Ada 95, such a rule can't work.
Consider:

    type T is range 0..15;
    for T'Size use 4;
    subtype Bigger is T'Base range -15..15;

Clearly, Bigger'Size cannot be 4.

Also, note that the size of an object can be bigger than the size of its
subtype (in both Ada 83 and 95).  In other words, specifying the size of
an object gives much more exact control, and is desirable in many
low-level situations (despite the fact that it is rather verbose).

Also, any rule that begins "if the so-and-so attribute is specified..."
is suspect, because you don't want the meaning of 'Whatever to depend on
whether the user chose it or the compiler chose it.  For example, if I
print out Foo'Whatever, and find out it's 123, and then I add "for
Foo'Whatever use 123;", the meaning of my program shouldn't change.

Unfortunately, though, Robert is correct that the new rules cause some
problems with porting code from Ada 83 to Ada 95.  On the other hand,
there were already problems porting between Ada 83 compilers, so I don't
know.  Sigh.

The Java language designers had it much easier -- they simply say that
the predefined types are 8, 16, 32, and 64 bits, and if you're running
on a 36-bit machine, tough.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-27  0:00         ` Robert A Duff
@ 1996-09-27  0:00           ` Robert Dewar
  0 siblings, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-09-27  0:00 UTC (permalink / raw)



Bob said

"I'm not sure if I'm the Bob being addressed, but...   I think your
interpretation is correct.  However, in Ada 95, such a rule can't work.
Consider:

    type T is range 0..15;
    for T'Size use 4;
    subtype Bigger is T'Base range -15..15;

Clearly, Bigger'Size cannot be 4.
"



This is a baby and bathwater case!

Yes, of course the rule cannot apply to the unusual case of Bigger here, but
that is NOT a sufficient reason to throw out the entire rule, causing
incompatibilities.

In GNAT, we regard Bigger as a subtpye of the base type of T, not a subtype
of T for the purposes of the size ingheritance rules that apply to object
size (which is like the old Ada 83 size).





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

* Re: Rules for Representation of Subtypes
  1996-09-26  0:00       ` Matthew Heaney
@ 1996-09-27  0:00         ` Robert Dewar
  1996-09-27  0:00         ` Robert A Duff
  1 sibling, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-09-27  0:00 UTC (permalink / raw)



Matthew says

""If the size of a type of a first named subtype T has been specified by a
length clause, the T'Size yields the specified size, AND THE SIZE OF EVERY
SUBTYPE OF T IS ALSO THIS VALUE [my emphasis].""

This is an Ada 83 AI. For whatever  reasons, the Ada 95 RM does not follow
this AI, or permit compilers to follow it. RM 95 requires that subtypes
have a different size from the first subtype if the range is static and
a smaller type is possible.





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

* Re: Rules for Representation of Subtypes
  1996-09-27  0:00         ` Robert A Duff
  1996-09-27  0:00           ` Mark A Biggar
@ 1996-09-28  0:00           ` Larry Kilgallen
  1996-09-29  0:00             ` Robert A Duff
  1996-10-03  0:00             ` Robert Dewar
  1 sibling, 2 replies; 73+ messages in thread
From: Larry Kilgallen @ 1996-09-28  0:00 UTC (permalink / raw)



In article <DyEr6p.38H@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:
> In article <1996Sep26.191257.1@eisner>,
> Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>>Like:
>>
>>	if X'Valid
>>
>>?  I would think that as being an argument in _favor_ of declaring
>>the C-updated object in a tightly constrained fashion.
> 
> No, that won't work.  By the time you get to that if statement, the
> program execution is already erroneous.  Compilers can and do (and
> should) take advantage of that fact to generate faster code that doesn't
> work.  An unchecked conversion is a function call, and there's no way to
> capture the result of it without assigning it somewhere, which causes
> erroneousness if the result is bad.

If the assignment of the output causes erroneousness,
then why isn't the name of the operation Checked Conversion ?

Larry Kilgallen




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

* Re: Rules for Representation of Subtypes
  1996-09-29  0:00             ` Robert A Duff
  1996-09-29  0:00               ` Larry Kilgallen
@ 1996-09-29  0:00               ` Matthew Heaney
  1996-09-30  0:00                 ` Robert Dewar
  1996-09-30  0:00                 ` Robert A Duff
  1 sibling, 2 replies; 73+ messages in thread
From: Matthew Heaney @ 1996-09-29  0:00 UTC (permalink / raw)



In article <DyGwtp.Bs1@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:

>In article <1996Sep28.155354.1@eisner>,
>Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>>If the assignment of the output causes erroneousness,
>>then why isn't the name of the operation Checked Conversion ?
>
>Heh?  If it were checked, it would do something sensible, like raise an
>exception, or return a well-defined result, or give a compile-time
>error.  The UNchecked means, it's *not* checked -- if you do something
>wrong, you get unpredictable behavior, i.e. erroneous execution.

I think his comment was in reaction a previous post, which stated that the
compiler would make all kinds of optimizations based on what it knew was an
illegal program as a result of a call to unchecked_conversion.  If the
compiler does something "special" to handle a "bad" program because of
unchecked_conversion, well, the conversion is not really "unchecked,"
right?

>- Bob

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-29  0:00               ` Larry Kilgallen
@ 1996-09-29  0:00                 ` Matthew Heaney
  1996-09-30  0:00                 ` Robert A Duff
  1 sibling, 0 replies; 73+ messages in thread
From: Matthew Heaney @ 1996-09-29  0:00 UTC (permalink / raw)



In article <1996Sep29.082143.1@eisner>, kilgallen@eisner.decus.org (Larry
Kilgallen) wrote:

>But my X'valid should still work.  And compilers are not allowed to
>change the flow of a program.
>
>        X := my_unchecked_conversion(Y);
>
>        if X'valid
>        then
>                Z(247) := X;
>        else
>                raise my_exception;
>        end if;
>
>No optimizer should stash my X into Z until it determines the
>result of my conditional.  Likewise for:
>
>        X:= my_unchecked_conversion(Y);
>
>        if not X'valid then raise my_exception; end if;
>
>        Z(247) := X;
>
>no optimizer should stash my X into Z until it knows the result
>of the possible flow control change represented by raise my_exception.

You raise a good point: no optimizer "should" stash X into Z until the
expression is evalutated.  But what is the rule for optimization of
expressions involving the Valid attribute?  The AARM95, Section 13.9.2
discusses the use of that attribute, but doesn't have anything to say about
whether it is allowed to be optimized away.

My hunch is that a compiler will not optimize away the use of the Valid
attribute to check the results of Unchecked_Conversion, because that is one
the cases explicity called out in the RM95 for its use.

>Larry Kilgallen

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-28  0:00           ` Larry Kilgallen
@ 1996-09-29  0:00             ` Robert A Duff
  1996-09-29  0:00               ` Larry Kilgallen
  1996-09-29  0:00               ` Matthew Heaney
  1996-10-03  0:00             ` Robert Dewar
  1 sibling, 2 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-29  0:00 UTC (permalink / raw)



In article <1996Sep28.155354.1@eisner>,
Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>If the assignment of the output causes erroneousness,
>then why isn't the name of the operation Checked Conversion ?

Heh?  If it were checked, it would do something sensible, like raise an
exception, or return a well-defined result, or give a compile-time
error.  The UNchecked means, it's *not* checked -- if you do something
wrong, you get unpredictable behavior, i.e. erroneous execution.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-29  0:00             ` Robert A Duff
@ 1996-09-29  0:00               ` Larry Kilgallen
  1996-09-29  0:00                 ` Matthew Heaney
  1996-09-30  0:00                 ` Robert A Duff
  1996-09-29  0:00               ` Matthew Heaney
  1 sibling, 2 replies; 73+ messages in thread
From: Larry Kilgallen @ 1996-09-29  0:00 UTC (permalink / raw)



In article <DyGwtp.Bs1@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:
> In article <1996Sep28.155354.1@eisner>,
> Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>>If the assignment of the output causes erroneousness,
>>then why isn't the name of the operation Checked Conversion ?
> 
> Heh?  If it were checked, it would do something sensible, like raise an
> exception, or return a well-defined result, or give a compile-time
> error.  The UNchecked means, it's *not* checked -- if you do something
> wrong, you get unpredictable behavior, i.e. erroneous execution.

But my X'valid should still work.  And compilers are not allowed to
change the flow of a program.

	X := my_unchecked_conversion(Y);

	if X'valid
	then
		Z(247) := X;
	else
		raise my_exception;
	end if;

No optimizer should stash my X into Z until it determines the
result of my conditional.  Likewise for:

	X:= my_unchecked_conversion(Y);

	if not X'valid then raise my_exception; end if;

	Z(247) := X;

no optimizer should stash my X into Z until it knows the result
of the possible flow control change represented by raise my_exception.

Larry Kilgallen




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

* Re: Rules for Representation of Subtypes
  1996-09-27  0:00           ` Mark A Biggar
@ 1996-09-30  0:00             ` Robert A Duff
  1996-10-01  0:00               ` Larry Kilgallen
  0 siblings, 1 reply; 73+ messages in thread
From: Robert A Duff @ 1996-09-30  0:00 UTC (permalink / raw)



In article <52hnvh$li0@wdl1.wdl.lmco.com>,
Mark A Biggar <mab@dst17.wdl.loral.com> wrote:
>I'm not sure about this as I always thought that the RM was pretty clear
>that only the USE of an abnormal value was erroneous, but that simply
>assigning it was safe, at least I'm sure that was the intent, otherwise
>X'VALID after an unchecked conversion is useless, but that is one of the
>explisit examples of its intended use in the RM.

Well, assignment is a USE -- you can't assign from an abnormal object
without going erroneous.  But that's beside the point -- the case I was
talking about is defined as erroneous, not as abnormal.

13.9.1(12) says:

12   {erroneous execution} A call to an imported function or an instance of
Unchecked_Conversion is erroneous if the result is scalar, and the result
object has an invalid representation.

The AARM gives an example:

        12.c   Consider the following example:

12.d        type My_Int is range 0..99;
            function Safe_Convert is new Unchecked_Conversion(My_Int, Integer);
            function Unsafe_Convert is new Unchecked_Conversion(My_Int, Positiv\
e);
            X : Positive := Safe_Convert(0); -- Raises Constraint_Error.
            Y : Positive := Unsafe_Convert(0); -- Erroneous.

        12.e   The call to Unsafe_Convert causes erroneous execution.  The
        call to Safe_Convert is not erroneous.  The result object is an
        object of subtype Integer containing the value 0.  The assignment to
        X is required to do a constraint check; the fact that the conversion
        is unchecked does not obviate the need for subsequent checks required
        by the language rules.

The point is that you should convert to a type that "fills all the
bits".  That is, there are no possible bit patterns that don't represent
valid data.  Then, *after* the unchecked conversion, you can do an
assignment that does a constraint check.  Checking Y'Valid in the above
example would not help, since the program is already erroneous.  The
'Valid feature is just like anything else -- it won't work as advertised
if the execution is already erroneous.

Or you can use an if statement:

    Z: Integer := Safe_Convert(0);
    ...
    if Z not in My_Int then
        raise Horrible_Bug;

The same applies to imported functions.  So, for example, if you have a
C function that returns 'int', and the documentation says this 'int'
will be in the range 1..10, it's best to use Interfaces.C.int as the
result subtype, and do some checking *after* it returns.  This is
because Interfaces.C.int matches the type 'int' in C.  Unless you
really, really trust that documentation.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-29  0:00               ` Larry Kilgallen
  1996-09-29  0:00                 ` Matthew Heaney
@ 1996-09-30  0:00                 ` Robert A Duff
  1996-10-01  0:00                   ` Ken Garlington
  1996-10-06  0:00                   ` Robert Dewar
  1 sibling, 2 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-30  0:00 UTC (permalink / raw)



In article <1996Sep29.082143.1@eisner>,
Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
>But my X'valid should still work.  And compilers are not allowed to
>change the flow of a program.
>
>	X := my_unchecked_conversion(Y);
>
>	if X'valid

It depends on how you instantiated my_unchecked_conversion.  If you used
a constrained integer, such that some values of Y will produce
out-of-range results, then it's erroneous, and the 'Valid will *not*
work.  Hence, my advice to always unchecked_convert to types that match
the hardware.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-29  0:00               ` Matthew Heaney
  1996-09-30  0:00                 ` Robert Dewar
@ 1996-09-30  0:00                 ` Robert A Duff
  1 sibling, 0 replies; 73+ messages in thread
From: Robert A Duff @ 1996-09-30  0:00 UTC (permalink / raw)



In article <mheaney-ya023180002909961030520001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>I think his comment was in reaction a previous post, which stated that the
>compiler would make all kinds of optimizations based on what it knew was an
>illegal program as a result of a call to unchecked_conversion.  If the
 ^^^^^^^ You mean "erroneous".
>compiler does something "special" to handle a "bad" program because of
>unchecked_conversion, well, the conversion is not really "unchecked,"
>right?

No, no, the compiler doesn't *know* the program is bad.  It just does an
optimization that will work if the program is good, and might not work
if the program is bad.

If the compiler *knows* the program is bad, then it should of course
give a warning message.  But usually such things aren't knowable.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-29  0:00               ` Matthew Heaney
@ 1996-09-30  0:00                 ` Robert Dewar
  1996-09-30  0:00                   ` Matthew Heaney
  1996-09-30  0:00                 ` Robert A Duff
  1 sibling, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-09-30  0:00 UTC (permalink / raw)



Matthew said

"I think his comment was in reaction a previous post, which stated that the
compiler would make all kinds of optimizations based on what it knew was an
illegal program as a result of a call to unchecked_conversion.  If the
compiler does something "special" to handle a "bad" program because of
unchecked_conversion, well, the conversion is not really "unchecked,"
right?"

Can you be clearer as to what you mean? For a start I assume that the
use of the word illegal should be erroneous? right?
unchecked simply means that the compiler is not required to generate
checking code for some error conditions, what else do you read into the
word?





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

* Re: Rules for Representation of Subtypes
  1996-09-30  0:00                 ` Robert Dewar
@ 1996-09-30  0:00                   ` Matthew Heaney
  0 siblings, 0 replies; 73+ messages in thread
From: Matthew Heaney @ 1996-09-30  0:00 UTC (permalink / raw)



In article <dewar.844114166@schonberg>, dewar@schonberg.cs.nyu.edu (Robert
Dewar) wrote:

>"I think his comment was in reaction a previous post, which stated that the
>compiler would make all kinds of optimizations based on what it knew was an
>illegal program as a result of a call to unchecked_conversion.  If the
>compiler does something "special" to handle a "bad" program because of
>unchecked_conversion, well, the conversion is not really "unchecked,"
>right?"
>
>Can you be clearer as to what you mean? For a start I assume that the
>use of the word illegal should be erroneous? right?
>unchecked simply means that the compiler is not required to generate
>checking code for some error conditions, what else do you read into the
>word?

You're right; I should have said "...knew would cause erroneous program
execution..."  Honestly, though, I'm a little shaky about the difference
between "erroneous execution," "bounded errors," "non portability," and
"illegal program."  Guess I better hit the books before TRI-Ada!

I intended "unchecked" to mean as you suggested: don't put in checks for
error conditions (on the object that is returned by the call to
Unchecked_Conversion).

The author of the post (I think it was Larry K) just wanted to make sure
that the expression containing the Valid attribute didn't get optimized
away.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-10-01  0:00               ` Larry Kilgallen
  1996-10-01  0:00                 ` Samuel Tardieu
@ 1996-10-01  0:00                 ` Robert A Duff
  1 sibling, 0 replies; 73+ messages in thread
From: Robert A Duff @ 1996-10-01  0:00 UTC (permalink / raw)



In article <1996Oct1.100608.1@eisner>,
>So can someone give an example of how Z'Valid _might_ be useful
>after an unchecked conversion, as seems to be indicated by the
>Reference Manual.

If you unchecked_convert to a record (which is the usual case), then you
can usefully use 'Valid on the components.  Be sure that the record
doesn't contain fancy stuff (details in the RM), but a record containing
scalar fields and constrained arrays will work.

- Bob




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

* Re: Rules for Representation of Subtypes
  1996-09-30  0:00                 ` Robert A Duff
@ 1996-10-01  0:00                   ` Ken Garlington
  1996-10-02  0:00                     ` Robert A Duff
  1996-10-06  0:00                   ` Robert Dewar
  1 sibling, 1 reply; 73+ messages in thread
From: Ken Garlington @ 1996-10-01  0:00 UTC (permalink / raw)



Robert A Duff wrote:
> 
> In article <1996Sep29.082143.1@eisner>,
> Larry Kilgallen <kilgallen@eisner.decus.org> wrote:
> >But my X'valid should still work.  And compilers are not allowed to
> >change the flow of a program.
> >
> >       X := my_unchecked_conversion(Y);
> >
> >       if X'valid
> 
> It depends on how you instantiated my_unchecked_conversion.  If you used
> a constrained integer, such that some values of Y will produce
> out-of-range results, then it's erroneous, and the 'Valid will *not*
> work.  Hence, my advice to always unchecked_convert to types that match
> the hardware.

I seem to remember some AI about using unchecked_conversion when the sizes of X and 
Y are different. Maybe it's compiler dependent, but I thought you were at least 
guaranteed that the unchecked_conversion of Y would _fit_ into the space allocated 
for X, although of course Y might be outside the range of X. In that case, X'Valid 
should work, shouldn't it?

> 
> - Bob

-- 
LMTAS - "Our Brand Means Quality"




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

* Re: Rules for Representation of Subtypes
  1996-10-01  0:00                 ` Samuel Tardieu
@ 1996-10-01  0:00                   ` Ken Garlington
  1996-10-01  0:00                   ` Valid Attribute and Unchecked Conversion Matthew Heaney
  1 sibling, 0 replies; 73+ messages in thread
From: Ken Garlington @ 1996-10-01  0:00 UTC (permalink / raw)



Samuel Tardieu wrote:
> 
> >>>>> "Larry" == Larry Kilgallen <kilgallen@eisner.decus.org> writes:
> 
> Larry> So can someone give an example of how Z'Valid _might_ be useful
> Larry> after an unchecked conversion, as seems to be indicated by the
> Larry> Reference Manual.
> 
> I don't think that the Valid attribute has been put in the language to
> be used after an Unchecked_Conversion, but rather to be used after
> calls to imported subprograms and calls to Read attributes (data
> coming from a stream).

I don't know much, but I do know this: I specifically wrote a revision
request to Ada 83 to handle the following situation:

  type Foo is range 1 .. 10;
  X: Foo; -- assume that this takes up a storage unit with a range
          -- greater than 1 .. 10
  ...

  Read(X); -- some I/O operation, unchecked conversion, whatever
           -- that might put a bit pattern in X that is not in 1 .. 10

  if X in Foo then
    raise Some_Exception; -- rarely works in Ada 83 due to optimization
  end if;

I thought one of the important uses of X'Valid was to be able to test 
for a legal bit pattern, and never mind the optimizations. If it doesn't 
work, then why did I go to all the trouble to write the RR?

-- 
LMTAS - "Our Brand Means Quality"




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

* Valid Attribute and Unchecked Conversion
  1996-10-01  0:00                 ` Samuel Tardieu
  1996-10-01  0:00                   ` Ken Garlington
@ 1996-10-01  0:00                   ` Matthew Heaney
  1996-10-02  0:00                     ` Robert A Duff
  1 sibling, 1 reply; 73+ messages in thread
From: Matthew Heaney @ 1996-10-01  0:00 UTC (permalink / raw)



In article <qw6buemy9ea.fsf@gargantua.enst.fr>, Samuel Tardieu
<sam@ada.eu.org> wrote:

>I don't think that the Valid attribute has been put in the language to
>be used after an Unchecked_Conversion, but rather to be used after
>calls to imported subprograms and calls to Read attributes (data
>coming from a stream).

That's odd, because RM95, section 13.9.2 states that "The valid attribute
can be used to check the validity of data produced by unchecked
conversion,..."

Note 19 in that section (of the AARM) states that "invalid data" can be
created as "the result of unchecked conversion."

Note 20 states that since X'Valid is not considered a read of X, it is not
an error the check the validity of invalid data.

So it's legal to check (using the valid attribute) the value of a (scalar)
object with an invalid representation, right?

Given the following program:

   declare
      type T is range 1 .. 10;
      function To_T is new Unchecked_Conversion (Integer, T);
      O : constant T := To_T (0);
   begin
      if O'Valid then
         ...
   end;

I want to know if the program is correct.  Is it erroneous, yes or no?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Rules for Representation of Subtypes
  1996-09-30  0:00             ` Robert A Duff
@ 1996-10-01  0:00               ` Larry Kilgallen
  1996-10-01  0:00                 ` Samuel Tardieu
  1996-10-01  0:00                 ` Rules for Representation of Subtypes Robert A Duff
  0 siblings, 2 replies; 73+ messages in thread
From: Larry Kilgallen @ 1996-10-01  0:00 UTC (permalink / raw)



In article <DyKC85.Gqx@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:

> The point is that you should convert to a type that "fills all the
> bits".  That is, there are no possible bit patterns that don't represent
> valid data.  Then, *after* the unchecked conversion, you can do an
> assignment that does a constraint check.  Checking Y'Valid in the above
> example would not help, since the program is already erroneous.  The
> 'Valid feature is just like anything else -- it won't work as advertised
> if the execution is already erroneous.

So can someone give an example of how Z'Valid _might_ be useful
after an unchecked conversion, as seems to be indicated by the
Reference Manual.

Larry Kilgallen




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

* Re: Rules for Representation of Subtypes
  1996-10-01  0:00               ` Larry Kilgallen
@ 1996-10-01  0:00                 ` Samuel Tardieu
  1996-10-01  0:00                   ` Ken Garlington
  1996-10-01  0:00                   ` Valid Attribute and Unchecked Conversion Matthew Heaney
  1996-10-01  0:00                 ` Rules for Representation of Subtypes Robert A Duff
  1 sibling, 2 replies; 73+ messages in thread
From: Samuel Tardieu @ 1996-10-01  0:00 UTC (permalink / raw)
  To: Larry Kilgallen


>>>>> "Larry" == Larry Kilgallen <kilgallen@eisner.decus.org> writes:

Larry> So can someone give an example of how Z'Valid _might_ be useful
Larry> after an unchecked conversion, as seems to be indicated by the
Larry> Reference Manual.

I don't think that the Valid attribute has been put in the language to
be used after an Unchecked_Conversion, but rather to be used after
calls to imported subprograms and calls to Read attributes (data
coming from a stream).

  Sam
-- 
  Samuel Tardieu -- sam@ada.eu.org




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

* Re: Rules for Representation of Subtypes
  1996-10-01  0:00                   ` Ken Garlington
@ 1996-10-02  0:00                     ` Robert A Duff
  1996-10-02  0:00                       ` Ken Garlington
  0 siblings, 1 reply; 73+ messages in thread
From: Robert A Duff @ 1996-10-02  0:00 UTC (permalink / raw)



In article <325155A5.2E50@lmtas.lmco.com>,
Ken Garlington  <garlingtonke@lmtas.lmco.com> wrote:
>I seem to remember some AI about using unchecked_conversion when the
>sizes of X and Y are different. Maybe it's compiler dependent, but I
>thought you were at least guaranteed that the unchecked_conversion of Y
>would _fit_ into the space allocated for X, although of course Y might
>be outside the range of X. In that case, X'Valid should work, shouldn't
>it?

No.  See 13.9.1(12).  Nothing, not even 'Valid, can be assumed to work,
if the execution is erroneous.

- Bob




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-01  0:00                   ` Valid Attribute and Unchecked Conversion Matthew Heaney
@ 1996-10-02  0:00                     ` Robert A Duff
  1996-10-04  0:00                       ` Keith Thompson
  0 siblings, 1 reply; 73+ messages in thread
From: Robert A Duff @ 1996-10-02  0:00 UTC (permalink / raw)



In article <mheaney-ya023180000110962027510001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>So it's legal to check (using the valid attribute) the value of a (scalar)
         ^^^^^ you me "not erroneous".
>object with an invalid representation, right?

Right.

>Given the following program:
>
>   declare
>      type T is range 1 .. 10;
>      function To_T is new Unchecked_Conversion (Integer, T);
>      O : constant T := To_T (0);

I can't read that clearly on my screen, but I assume the variable name
is the letter oh, and the expression is the number zero.  ;-)

>   begin
>      if O'Valid then
>         ...
>   end;
>
>I want to know if the program is correct.  Is it erroneous, yes or no?

This is essentially the same as the example in 13.9.1(12.d), which I
posted a couple of days ago.  It is erroneous, by 13.9.1(12).  This has
nothing to do with the 'Valid attribute -- the above program becomes
erroneous before it gets to the 'Valid.  What I mean is, it's not that
'Valid doesn't work.  It's that Unchecked_Conversion is explicitly
defined to be erroneous in the above case.

Note that the rules for I/O are somewhat different than for
unchecked_conversion, primarily because function results are different
from 'out' parameters.

- Bob




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

* Re: Valid Attribute and Unchecked Conversion
  1996-09-26  0:00       ` Larry Kilgallen
  1996-09-27  0:00         ` Robert A Duff
@ 1996-10-02  0:00         ` Robert I. Eachus
  1996-10-02  0:00           ` Matthew Heaney
  1996-10-02  0:00         ` George Haddad
  2 siblings, 1 reply; 73+ messages in thread
From: Robert I. Eachus @ 1996-10-02  0:00 UTC (permalink / raw)



In article <mheaney-ya023180000110962027510001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes:

  > So it's legal to check (using the valid attribute) the value of a (scalar)
  > object with an invalid representation, right?

  Right, but...

  > Given the following program:

  >    declare
  >	 type T is range 1 .. 10;
  >	 function To_T is new Unchecked_Conversion (Integer, T);
  >	 O : constant T := To_T (0);
  >    begin
  >	 if O'Valid then
  >	    ...
  >    end;

  > I want to know if the program is correct.  Is it erroneous, yes or no?

   It is erroneous.  That is the point of this discussion change to:

     declare
         type T is range 1 .. 10;
         for T'SIZE use Integer'SIZE;
  	 function To_T is new Unchecked_Conversion (Integer, T'Base);
  	 O : constant T := To_T (0);
      begin
  	 if O'Valid then
  	    ...
      end;

    Now To_T returns a bit pattern that is legal for the type (T'Base),
and the constraint check occurs on the assignment.  You never get to
the call to O'Valid.

    Change to:

     declare
         type T is range 1 .. 10;
         for T'SIZE use Integer'SIZE;
  	 function To_T is new Unchecked_Conversion (Integer, T'Base);
  	 O : T;
      begin
        begin
          O := To_T (0);
        exception when others => null;
        end;

   	if O'Valid then
  	  ...
      end;

      ...and you still don't get what you want.  In this case the
O'Valid check may or may not succeed, depending on the initial junk in
that stack location.

      'Valid is very useful for validating fields of record objects.
But for scalars that may be invalid, you usually want to produce a
(potentially) invalid value of the base type then do a (constraint
checked) assignment.

 
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Valid Attribute and Unchecked Conversion
  1996-09-26  0:00       ` Larry Kilgallen
  1996-09-27  0:00         ` Robert A Duff
  1996-10-02  0:00         ` Valid Attribute and Unchecked Conversion Robert I. Eachus
@ 1996-10-02  0:00         ` George Haddad
  1996-10-03  0:00           ` John Herro
  2 siblings, 1 reply; 73+ messages in thread
From: George Haddad @ 1996-10-02  0:00 UTC (permalink / raw)



Robert I. Eachus wrote:
>     Change to:
> 
>      declare
>          type T is range 1 .. 10;
>          for T'SIZE use Integer'SIZE;
>          function To_T is new Unchecked_Conversion (Integer, T'Base);
>          O : T;
>       begin
>         begin
>           O := To_T (0);
>         exception when others => null;
>         end;
> 
>         if O'Valid then
>           ...
>       end;
> 
>       ...and you still don't get what you want.  In this case the
> O'Valid check may or may not succeed, depending on the initial junk in
> that stack location.

   So, what about:

      declare
        type T is range 1 .. 10;
        function To_T is new Unchecked_Conversion (Integer, T);
        X : T;
      begin
        if To_T(0)'Valid then
           X := To_T(0);
           ...
      end;

   I realize that this involves calling the same function twice (which 
is probably not a problem given that the function is an instance of 
Unchecked_Conversion), but is the fragment above erroneous?
-- 
I found these opinions on my doorstep, would you please give them a good 
home?




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

* Re: Rules for Representation of Subtypes
  1996-10-02  0:00                     ` Robert A Duff
@ 1996-10-02  0:00                       ` Ken Garlington
  0 siblings, 0 replies; 73+ messages in thread
From: Ken Garlington @ 1996-10-02  0:00 UTC (permalink / raw)
  To: Robert A Duff; +Cc: dewar


Robert A Duff wrote:
> 
> In article <325155A5.2E50@lmtas.lmco.com>,
> Ken Garlington  <garlingtonke@lmtas.lmco.com> wrote:
> >I seem to remember some AI about using unchecked_conversion when the
> >sizes of X and Y are different. Maybe it's compiler dependent, but I
> >thought you were at least guaranteed that the unchecked_conversion of Y
> >would _fit_ into the space allocated for X, although of course Y might
> >be outside the range of X. In that case, X'Valid should work, shouldn't
> >it?
> 
> No.  See 13.9.1(12).  Nothing, not even 'Valid, can be assumed to work,
> if the execution is erroneous.
> 
> - Bob

So all that discussion in the Ada 83 AI-00590 is wasted when we get to Ada 95?
What a crock!

I'd also say that 13.9.2:1 and 13.9.2:4-12 are very misleading, at best, if
this is the case. It sounds like I would have to write a kludge, wrapping
my scalar inside a record, as the result of my input routine, unchecked conversion,
etc. I hope GNAT and the other compilers raise a warning if I apply 'Valid to
something that is not a record component!

-- 
LMTAS - "Our Brand Means Quality"
For more info, see http://www.lmtas.com or http://www.lmco.com




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-02  0:00         ` Valid Attribute and Unchecked Conversion Robert I. Eachus
@ 1996-10-02  0:00           ` Matthew Heaney
  0 siblings, 0 replies; 73+ messages in thread
From: Matthew Heaney @ 1996-10-02  0:00 UTC (permalink / raw)



In article <EACHUS.96Oct2161139@spectre.mitre.org>,
eachus@spectre.mitre.org (Robert I. Eachus) wrote:

>     declare
>         type T is range 1 .. 10;
>         for T'SIZE use Integer'SIZE;
>         function To_T is new Unchecked_Conversion (Integer, T'Base);
>         O : constant T := To_T (0);
>      begin
>         if O'Valid then
>            ...
>      end;
>
>Now To_T returns a bit pattern that is legal for the type (T'Base),
>and the constraint check occurs on the assignment.  You never get to
>the call to O'Valid.

Thank you!  That clears it up.  I didn't realize that a Constraint_Check
ever could ever occur upon assignment of a value returned by an
instantiation of Unchecked_Conversion.

But your method forces a Constraint_Check to occur by making the type of
object O a subtype of the type returned by the function.  (Technically,
makes the function return a supertype of O's type.  Did I get that right?)

Very nice!

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-02  0:00         ` George Haddad
@ 1996-10-03  0:00           ` John Herro
  1996-10-04  0:00             ` Karl Cooper {46901}
  1996-10-05  0:00             ` Robert Dewar
  0 siblings, 2 replies; 73+ messages in thread
From: John Herro @ 1996-10-03  0:00 UTC (permalink / raw)



I could be wrong, but I thought that Unchecked_Conversion is erroneous in
_any_ case.  I heard that the first validated Ada compiler, Ada/Ed, took
advantage of that fact and generated code to raise Program_Error wherever
the program tried to make use of Unchecked_Conversion.

Is this true, and if so, has any of it changed with Ada 95 and the new
'Valid attribute?

Someone please enlighten me.

- John Herro
Software Innovations Technology
http://members.aol.com/AdaTutor
ftp://members.aol.com/AdaTutor




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

* Re: Rules for Representation of Subtypes
  1996-09-28  0:00           ` Larry Kilgallen
  1996-09-29  0:00             ` Robert A Duff
@ 1996-10-03  0:00             ` Robert Dewar
  1 sibling, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-10-03  0:00 UTC (permalink / raw)



Larry said

"If the assignment of the output causes erroneousness,
then why isn't the name of the operation Checked Conversion ?

Larry Kilgallen"


There is some serious misconception in the above question, serious enough
so it is hard to figure out what Larry is getting at. In any case, the
fact that something might be erroneus has nothing to do with implying
the presence of checks -- in fact the exact opposite is true.





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

* Re: Valid Attribute and Unchecked Conversion
@ 1996-10-03  0:00 Franco Mazzanti
  0 siblings, 0 replies; 73+ messages in thread
From: Franco Mazzanti @ 1996-10-03  0:00 UTC (permalink / raw)



Robert I. Eachus wrote:

>    It is erroneous.  That is the point of this discussion change to:
> 
>      declare
>          type T is range 1 .. 10;
>          for T'SIZE use Integer'SIZE;
>          function To_T is new Unchecked_Conversion (Integer, T'Base);
>          O : constant T := To_T (0);
>       begin
>          if O'Valid then
>             ...
>       end;
> 
>     Now To_T returns a bit pattern that is legal for the type (T'Base),
> and the constraint check occurs on the assignment.  You never get to
> the call to O'Valid.
> 

However, we must be very careful not to generalize this approach.
E.g.  in the following very similar case:

      declare
          type T1 is new Integer range 1 .. 10;
          type T2 is new Integer range 1 .. 10;
          for T2'SIZE use T1'SIZE;
          function To_T is new Unchecked_Conversion (T1, T2'Base);
          S1:T1;  -- maybe initialized with zero
          S2:T2;
       begin
          S2:= 1;
          ...
          S2:= To_T2(S1);
          ...
          if O'Valid then
             ...
       end;

if S1 is not initialized, and has an invalid value, the call of To_T2 is
still directly erroneous (because the unchecked conversion still tries to
return an invalid scalar value!). 

It seems, in fact, that it is a generic principle in the Reference
Manual that invalid objects can be created ONLY by a missing initialization.
Once initialized, an object can no-more become "invalid". It can become,
at best, abnormal, and just storing its value in an object is erroneous.

My impression is that the safest generic approach still requires the use of 
a "Checked_Scalar_Conversion" as shown inside the previous thread
(Re: Rules for Representation of Subtypes).

Franco Mazzanti




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                       ` Keith Thompson
@ 1996-10-04  0:00                         ` Matthew Heaney
  1996-10-07  0:00                           ` Robert Dewar
  1996-10-04  0:00                         ` Robert A Duff
                                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 73+ messages in thread
From: Matthew Heaney @ 1996-10-04  0:00 UTC (permalink / raw)



In article <DyqAKA.DJn@thomsoft.com>, kst@thomsoft.com (Keith Thompson) wrote:

>So, suppose I have a sparse enumeration type:
>
>    type Enum is (Ten, Twenty, Thirty);
>    for Enum use (10, 20, 30);
>    for Enum'Size use 8;
>
>and a corresponding integer type:
>
>    type Int_Type is range 0 .. 31;
>    for Int_Type'Size use 8;
>
>Given an arbitrary value of type Int_Type, is there any non-erroneous
>way to get the corresponding Enum value if there is one, or raise
>an exception if there isn't?  By "corresponding", I mean 10 => Ten,
>20 => Twenty, 30 => Thirty.  Creating a lookup table that duplicates
>the information in the enumeration representation clause doesn't count;
>consider that Enum might be a generic formal type.  The 'Val attribute
>won't work, since it uses the position number (0, 1, 2) rather than the
>internal representation (10, 20, 30).

The answer would appear to be, No, there is no way to automatically get Ada
to raise an exception.  You have to check for a correct value before
unchecked converting to type Enum:

   function To_Enum is new Unchecked_Conversion (Int_Type, Enum);

   I : Int_Type := ...;
   E : Enum;
begin
   case I is
      when 10 | 20 | 30 =>
         E := To_Enum (I);
      when others =>
         raise <your favorite error>;
   end case;
end;

You raise an interesting point, though: this solution is complicated by the
fact that the representation values of type Enum are sparse.  Had they been
contiguous, you could force Ada to raise Constraint_Error via type
qualification:

   type ET is (E1, E2, E3);
   for ET use (3, 4, 5);
   for ET'Size use 8;

   type IT is range 0 .. 31;
   for IT'Size use 8;

   function To_ET is new Unchecked_Conversion (IT, ET);
   subtype ET_Rep is IT range 3 .. 5;

   I : IT := ...; 
   E : ET;
begin
   E := To_ET (ET_Rep'(I));  -- will raise Constraint_Error if I not in 3 .. 5, 
                                            -- thus preventing erroneous
execution

Of course, you could always instantiate Unchecked_Conversion using
the subtype ET_Rep directly.

Type qualification is useful technique for doing a kind of assertion
checking, forcing Ada to raise Constraint_Error when a value doesn't
satisfy a range constraint "precondition."  It's much hipper than the
explicit tests you see all the time:

   if I not in ET_Rep then          -- why bother?
      raise <I is bad error>;     
   end if;                               

  <handle good value here>

Type qualification gives you this for free.

For a static subtype, qualification means you don't have to include all the
branches in a case statement:

   case ET_Rep'(I) is    -- will raise Constraint_Error if I not in 3 .. 5
      when ET_Rep =>    -- other values for I don't have to be handled
         E := To_ET (I);
   end case;

A similar technique is to use a subtype indication to enforce a precondition:

   I : IT range ET_Rep'Range := ...;

After the expression on the right hand side is evaluated, Ada will check to
make sure that it lies within the range of ET_Rep before making the
assignment, raising Constraint_Error if the "precondition" isn't satisfied.

A subtype indication is also a useful documentation tool:

   Max_Value : constant FT := ...;

   Value : constant FT := ...;

   Normalized_Value : constant FT range 0.0 .. 1.0 := Value / Max_Value;

I'm giving the reader information, namely, that a "normalized value" means
that it has the range 0.0 .. 1.0.  I can use Ada to document this rather
than resorting to a comment.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                       ` Keith Thompson
  1996-10-04  0:00                         ` Matthew Heaney
@ 1996-10-04  0:00                         ` Robert A Duff
  1996-10-04  0:00                           ` Robert Dewar
                                             ` (3 more replies)
  1996-10-07  0:00                         ` Kenneth Almquist
  1996-10-07  0:00                         ` Robert Dewar
  3 siblings, 4 replies; 73+ messages in thread
From: Robert A Duff @ 1996-10-04  0:00 UTC (permalink / raw)



In article <DyqAKA.DJn@thomsoft.com>, Keith Thompson <kst@thomsoft.com> wrote:
>Are sparse enumeration types are really used all that much in real life?

They shouldn't be, because, as you explained, they don't work.  Using
sparse enums is asking for erroneousness.

Well, it's not *quite* that bad: You can use a sparse enum for sending
data from Ada to the outside world (e.g. doing output, passing
parameters *to* an imported subprogram, unchecked converting *from* a
sparse enum, etc).  But the other direction doesn't always work, and
should be avoided, IMHO.

The whole feature causes an awful lot of complexity in compilers,
given that it's not very useful.  Sigh.

- Bob




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-03  0:00           ` John Herro
@ 1996-10-04  0:00             ` Karl Cooper {46901}
  1996-10-07  0:00               ` Mark A Biggar
  1996-10-05  0:00             ` Robert Dewar
  1 sibling, 1 reply; 73+ messages in thread
From: Karl Cooper {46901} @ 1996-10-04  0:00 UTC (permalink / raw)



John Herro wrote:
> 
> I could be wrong, but I thought that Unchecked_Conversion is erroneous in
> _any_ case.  I heard that the first validated Ada compiler, Ada/Ed, took
> advantage of that fact and generated code to raise Program_Error wherever
> the program tried to make use of Unchecked_Conversion.
> 
> Is this true, and if so, has any of it changed with Ada 95 and the new
> 'Valid attribute?
> 
No, see the Ada83 reference manual 13.10, and the Ada95 reference
manual 13.9 and 13.9.1.  Unchecked_Conversion leads to erroneous
behavior in some cases, but not in others.  In my opinion, the
Ada95 reference manual is clearer when describing the safe uses
of Unchecked_Conversion.

What is true is that an implementation is permitted to place
restrictions on the use of Unchecked_Conversion.  These should
be documented in one of the Appendices which describes the
implementation-dependent things defined by the implementation,
of course.  Again, the Ada95 reference manual gives more insight
into what sort of restrictions might be expected, as well as what
support for Unchecked_Conversion is recommended to implementors.

Because of the additional detail provided in the Ada95 LRM about
the safe uses of Unchecked_Conversion, I would suspect that a
validation suite could be created which would cause the behavior
you describe (unconditional Program_Error for each call to
Unchecked_Conversion) to be a failure of the valildation.
-- 
Karl T. Cooper               
Senior Software Engineer
Raytheon Electronic Systems
ktc@swl.msd.ray.com           <intelligence with intelligibility>




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                         ` Robert A Duff
@ 1996-10-04  0:00                           ` Robert Dewar
  1996-10-11  0:00                             ` Norman H. Cohen
  1996-10-06  0:00                           ` Keith Thompson
                                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-10-04  0:00 UTC (permalink / raw)



In article <DyqAKA.DJn@thomsoft.com>, Keith Thompson <kst@thomsoft.com> wrote:
>Are sparse enumeration types are really used all that much in real life?



In our experience they are used very extensively. Furthermore, we found that
we had to add the additional complexity of makeing sure that arrays indexed
by such types were compact (rather than mapped sparsely), since a couple of
large customers required this support.

Robert Dewar
Ada Core Technologies






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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-02  0:00                     ` Robert A Duff
@ 1996-10-04  0:00                       ` Keith Thompson
  1996-10-04  0:00                         ` Matthew Heaney
                                           ` (3 more replies)
  0 siblings, 4 replies; 73+ messages in thread
From: Keith Thompson @ 1996-10-04  0:00 UTC (permalink / raw)



In <Dynt6I.5D1@world.std.com> bobduff@world.std.com (Robert A Duff) writes:
[...]
> This is essentially the same as the example in 13.9.1(12.d), which I
> posted a couple of days ago.  It is erroneous, by 13.9.1(12).  This has
> nothing to do with the 'Valid attribute -- the above program becomes
> erroneous before it gets to the 'Valid.  What I mean is, it's not that
> 'Valid doesn't work.  It's that Unchecked_Conversion is explicitly
> defined to be erroneous in the above case.

RM95-13.9.1(12) says:

	A call to an imported function or an instance of
	Unchecked_Conversion is erroneous if the result
	is scalar, and the result object has an invalid
	representation.

(To answer someone else's question, applying 'Valid directly to the
result of the Unchecked_Conversion is still erroneous.  (Note that
function results are considered (constant) objects in Ada 95, unlike in
Ada 83 where they're just values; one ramification is that you can now
rename a function result.  (But I digress.)))

The following paragraph in the AARM, 13.0.1(12.a), says:

        Ramification:  In a typical implementation, every
        bit pattern that fits in an object of an integer
        subtype will represent a value of the type, if not of
        the subtype.  However, for an enumeration or floating
        point type, there are typically bit patterns that do
        not represent any value of the type.  In such cases,
        the implementation ought to define the semantics of
        operations on the invalid representations in the
        obvious manner (assuming the bounded error is not
        detected):  a given representation should be equal
        to itself, a representation that is in between
        the internal codes of two enumeration literals
        should behave accordingly when passed to comparison
        operators and membership tests, etc.  We considered
        requiring such sensible behavior, but it resulted in
        too much arcane verbiage, and since implementations
        have little incentive to behave irrationally, such
        verbiage is not important to have.

Note that this annotation is *not* part of the standard.

So, suppose I have a sparse enumeration type:

    type Enum is (Ten, Twenty, Thirty);
    for Enum use (10, 20, 30);
    for Enum'Size use 8;

and a corresponding integer type:

    type Int_Type is range 0 .. 31;
    for Int_Type'Size use 8;

Given an arbitrary value of type Int_Type, is there any non-erroneous
way to get the corresponding Enum value if there is one, or raise
an exception if there isn't?  By "corresponding", I mean 10 => Ten,
20 => Twenty, 30 => Thirty.  Creating a lookup table that duplicates
the information in the enumeration representation clause doesn't count;
consider that Enum might be a generic formal type.  The 'Val attribute
won't work, since it uses the position number (0, 1, 2) rather than the
internal representation (10, 20, 30).

I'm beginning to think the "arcane verbiage" might have been worth it.

Are sparse enumeration types are really used all that much in real life?
My own interest is based, not on any actual usage, but on the gray hairs
I earned a few years ago while implementing them.

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Valid Attribute and Unchecked Conversion
@ 1996-10-04  0:00 Franco Mazzanti
  0 siblings, 0 replies; 73+ messages in thread
From: Franco Mazzanti @ 1996-10-04  0:00 UTC (permalink / raw)



(Keith Thompson) wrote:
> 
> >So, suppose I have a sparse enumeration type:
> >
> >    type Enum is (Ten, Twenty, Thirty);
> >    for Enum use (10, 20, 30);
> >    for Enum'Size use 8;
> >
> >and a corresponding integer type:
> >
> >    type Int_Type is range 0 .. 31;
> >    for Int_Type'Size use 8;
> >
> >Given an arbitrary value of type Int_Type, is there any non-erroneous
> >way to get the corresponding Enum value if there is one, or raise
> >an exception if there isn't? 


Matthew Heaney wrote:
> 
> The answer would appear to be, No, there is no way to automatically get Ada
> to raise an exception. 

Instead I think that there is a non-erroneous way to get corresponding
Enum value, or raise an exception:
(sorry to repost here a fragment of code previously posted in a different
thread)
Just use the following "checked" conversion:

generic
   type Source(<>) is limited private;
   type Target is (<>);
function Checked_Scalar_Conversion (S:Source) return Target;

with Unchecked_Conversion;
function Checked_Scalar_Conversion (S : Source) return Target is
   type My_Rec is record
      Scalar : Target;
   end record;
   Tmp : My_Rec;
   My_Scalar: Target renames Tmp.Scalar;
   -- small trick: even if Tmp as a whole record becomes abnormal
   -- its scalar component can still be safely checked for validity
   -- without "using" the abnormal record object.

   function Unchecked_Cvt is new Unchecked_Conversion (Source, My_Rec);
begin
   if My_Rec'Size /= Source'Size or
        My_rec'Alignment /= Source'Alignment then
      raise Program_Error;
   end if;
   Tmp := Unchecked_Cvt (S);
   if My_Scalar'Valid then
      return My_Scalar;
   else
      raise Program_Error;
   end if;
end Checked_Scalar_Conversion;

Now you can instantiate the Checked conversion with your types:


function Cvt is new Checked_Scalar_Conversion (Int_Type, Enum);

and use it

   N: Enum;
   N := Cvt (10);   -- OK
   N := Cvt (20);   -- OK
   N := Cvt (30);   -- OK
   N := Cvt (25);   -- raises Program_Error


Franco Mazzanti
(mazzanti@iei.pi.cnr.it)




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-03  0:00           ` John Herro
  1996-10-04  0:00             ` Karl Cooper {46901}
@ 1996-10-05  0:00             ` Robert Dewar
  1996-10-06  0:00               ` Keith Thompson
  1 sibling, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-10-05  0:00 UTC (permalink / raw)



John Herror said

"I could be wrong, but I thought that Unchecked_Conversion is erroneous in
_any_ case.  I heard that the first validated Ada compiler, Ada/Ed, took
advantage of that fact and generated code to raise Program_Error wherever
the program tried to make use of Unchecked_Conversion."

This is completely wrong. In both Ada 83 and Ada 95, there is nothing
erroneous about unchecked conversion unless an invalid result is 
produced. The wording from the Ada 83 RM for section 13.10.2 mentions
erroneousness only in one place:

"Whenever unchecked conversions are used, it is the programmers
responsibility to ensure that these conversions maintain the properties
that are guaranteed by the language for objects of the target type.
Programs that violate these properties by means of unchecked conversions
are erroneous."

The ACVC 1.11 suite contains a number of uses of unchecked conversion
that are required to work on all compilers and are not only NOT erroneous,
but are not even implementation dependent.

Now it is certainly the case that UC is implementation dependent, and an
implementation is allowed to place restrictions. In the case of Ada/Ed,
which is what you referred to, unchecked conversion made no sense in the
virtual machine used for the implementation, so all UC's were rejected.
Later on, Ada/Ed did implement many UC's, including those required by
the ACVC suite.

Never use the word erroneous casually, it is not a blanket term meaning
{undefined, implementation defined, wrong, illegal, inadvisable etc ..}
Only a few things in Ada 83 or Ada 95 are erroneous (fewer in Ada 95), and
the RM is very careful to document exactly what is and what is not
erroneous, so don't go by "I thought" here, read the RM carefully!

Note that in Ada 95, more uses of unchecked conversion are non-erroneous,
since a program can generate an abnormal value using UC, and then stay
non-erroneous as long as only 'Valid is used to query the result. 

Indeed the Ada 95 section on unchecked conversion (section 13.9) does not
mention the word erroneous at all, so an unchecked conversoin BY ITS SELF
never makes a program execution erroneous in Ada 95.






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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-05  0:00             ` Robert Dewar
@ 1996-10-06  0:00               ` Keith Thompson
  1996-10-14  0:00                 ` Robert A Duff
  0 siblings, 1 reply; 73+ messages in thread
From: Keith Thompson @ 1996-10-06  0:00 UTC (permalink / raw)



In <dewar.844516953@schonberg> dewar@schonberg.cs.nyu.edu (Robert Dewar) writes:
[...]
> Indeed the Ada 95 section on unchecked conversion (section 13.9) does not
> mention the word erroneous at all, so an unchecked conversoin BY ITS SELF
> never makes a program execution erroneous in Ada 95.

But RM95-13.9.1(12) says:
	A call to an imported function or an instance of
	Unchecked_Conversion is erroneous if the result
	is scalar, and the result object has an invalid
	representation.

Probably that paragraph should have been in 13.9 rather than 13.9.1.

Note that there are several paragraphs after this in the AARM encouraging
implementations to behave sensibly:

	[...] We considered requiring such sensible behavior,
	but it resulted in too much arcane verbiage, and
	since implementations have little incentive to behave
	irrationally, such verbiage is not important to have.

So implementations are encouraged to implement sensibly something that
users are encouraged to avoid.

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                         ` Robert A Duff
  1996-10-04  0:00                           ` Robert Dewar
@ 1996-10-06  0:00                           ` Keith Thompson
  1996-10-07  0:00                             ` Robert Dewar
  1996-10-07  0:00                           ` Ken Garlington
  1996-10-08  0:00                           ` Alan Brain
  3 siblings, 1 reply; 73+ messages in thread
From: Keith Thompson @ 1996-10-06  0:00 UTC (permalink / raw)



In <Dyr7Dt.HqL@world.std.com> bobduff@world.std.com (Robert A Duff) writes:
[...]
> They shouldn't be, because, as you explained, they don't work.  Using
> sparse enums is asking for erroneousness.
[...]
> The whole feature causes an awful lot of complexity in compilers,
> given that it's not very useful.  Sigh.

Especially since it wouldn't have been difficult to make them useful.

The root of the problem, I think, is Ada 83's emphasis (not entirely
successful) on guaranteeing that representation clauses affect only
representation, not semantics.  In the case of enumeration types, this
was carried just a little too far, IMHO.

For example, the language could have defined two additional attributes,
analagous to 'Pos and 'Val, but operating on the internal representation
of an enumeration type.  If the argument is an invalid representation,
simply raise Constraint_Error.  GNAT provides half of this with its
'Enum_Rep attribute.

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Rules for Representation of Subtypes
  1996-09-30  0:00                 ` Robert A Duff
  1996-10-01  0:00                   ` Ken Garlington
@ 1996-10-06  0:00                   ` Robert Dewar
  1 sibling, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-10-06  0:00 UTC (permalink / raw)



Bob Duff said

"It depends on how you instantiated my_unchecked_conversion.  If you used
a constrained integer, such that some values of Y will produce
out-of-range results, then it's erroneous, and the 'Valid will *not*
work.  Hence, my advice to always unchecked_convert to types that match
the hardware."

I don't see this, please give an exact example of what you are talking
about, and then exactly justify your statement above from the Ada 95 RM.





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-06  0:00                           ` Keith Thompson
@ 1996-10-07  0:00                             ` Robert Dewar
  1996-10-09  0:00                               ` Keith Thompson
  0 siblings, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-10-07  0:00 UTC (permalink / raw)



Keith says

"For example, the language could have defined two additional attributes,
analagous to 'Pos and 'Val, but operating on the internal representation
of an enumeration type.  If the argument is an invalid representation,
simply raise Constraint_Error.  GNAT provides half of this with its
'Enum_Rep attribute."


The intention in Ada 95 is that both operations are achievbable using
unchecked conversion. It is a bug in the RM if this is not the case.

However, in practice, of coruse this works, no matter what it says in
the RM, so this point can be left moot without having any pragmatic 
effect.





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                       ` Keith Thompson
                                           ` (2 preceding siblings ...)
  1996-10-07  0:00                         ` Kenneth Almquist
@ 1996-10-07  0:00                         ` Robert Dewar
  1996-10-10  0:00                           ` Ken Garlington
  3 siblings, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-10-07  0:00 UTC (permalink / raw)



iKeith says

"        A call to an imported function or an instance of
        Unchecked_Conversion is erroneous if the result
        is scalar, and the result object has an invalid
        representation.

(To answer someone else's question, applying 'Valid directly to the
result of the Unchecked_Conversion is still erroneous.  (Note that
function results are considered (constant) objects in Ada 95, unlike in
Ada 83 where they're just values; one ramification is that you can now
rename a function result.  (But I digress.)))"


Keith is right, this is in the RM, but I think the RM is definitely wrong
here. I take part of the blame, I simply did not notice this particular
mistake. Obviously for scalar types, unchecked conversion (where the sizes
are the same) should not result in erroneous behavior, and a subsequent
call to 'Valid should also be non-erroneous.

I simply missed this because it is in the wrong section (not under UC).
Anyway, certainly GNAT behaves in a sensible manner here, and hopefully
all other Ada 95 compilers will too, so this mistake should have only
very limited impact.





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00             ` Karl Cooper {46901}
@ 1996-10-07  0:00               ` Mark A Biggar
  1996-10-08  0:00                 ` Robert Dewar
  0 siblings, 1 reply; 73+ messages in thread
From: Mark A Biggar @ 1996-10-07  0:00 UTC (permalink / raw)



In article <32550731.167EB0E7@swl.msd.ray.com> Karl Cooper {46901} <ktc@swl.msd.ray.com> writes:
>John Herro wrote:
>> I could be wrong, but I thought that Unchecked_Conversion is erroneous in
>> _any_ case.  I heard that the first validated Ada compiler, Ada/Ed, took
>> advantage of that fact and generated code to raise Program_Error wherever
>> the program tried to make use of Unchecked_Conversion.
>> Is this true, and if so, has any of it changed with Ada 95 and the new
>> 'Valid attribute?
>No, see the Ada83 reference manual 13.10, and the Ada95 reference
>manual 13.9 and 13.9.1.  Unchecked_Conversion leads to erroneous
>behavior in some cases, but not in others.  In my opinion, the
>Ada95 reference manual is clearer when describing the safe uses
>of Unchecked_Conversion.

Why was the Unchecked_Conversion of an invalid scalar made erroneous in LM 95 
instead of a bounded error like the coresponding uninitialized variable case?

--
Mark Biggar
mab@wdl.lmco.com







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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                         ` Robert A Duff
  1996-10-04  0:00                           ` Robert Dewar
  1996-10-06  0:00                           ` Keith Thompson
@ 1996-10-07  0:00                           ` Ken Garlington
  1996-10-08  0:00                           ` Alan Brain
  3 siblings, 0 replies; 73+ messages in thread
From: Ken Garlington @ 1996-10-07  0:00 UTC (permalink / raw)



Robert A Duff wrote:
> 
> In article <DyqAKA.DJn@thomsoft.com>, Keith Thompson <kst@thomsoft.com> wrote:
> >Are sparse enumeration types are really used all that much in real life?
> 
> They shouldn't be, because, as you explained, they don't work.  Using
> sparse enums is asking for erroneousness.
> 
> Well, it's not *quite* that bad: You can use a sparse enum for sending
> data from Ada to the outside world (e.g. doing output, passing
> parameters *to* an imported subprogram, unchecked converting *from* a
> sparse enum, etc).  But the other direction doesn't always work, and
> should be avoided, IMHO.

Or, you can do an unchecked conversion to a record with a single
component of the sparse enum type, right?

> The whole feature causes an awful lot of complexity in compilers,
> given that it's not very useful.  Sigh.
> 
> - Bob

-- 
LMTAS - "Our Brand Means Quality"
For more info, see http://www.lmtas.com or http://www.lmco.com




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                       ` Keith Thompson
  1996-10-04  0:00                         ` Matthew Heaney
  1996-10-04  0:00                         ` Robert A Duff
@ 1996-10-07  0:00                         ` Kenneth Almquist
  1996-10-07  0:00                         ` Robert Dewar
  3 siblings, 0 replies; 73+ messages in thread
From: Kenneth Almquist @ 1996-10-07  0:00 UTC (permalink / raw)



kst@thomsoft.com (Keith Thompson) writes:
> RM95-13.9.1(12) says:
>
>	 A call to an imported function or an instance of
>	 Unchecked_Conversion is erroneous if the result
>	 is scalar, and the result object has an invalid
>	 representation.
[snip]
> So, suppose I have a sparse enumeration type:
>
>     type Enum is (Ten, Twenty, Thirty);
>     for Enum use (10, 20, 30);
>     for Enum'Size use 8;
>
> and a corresponding integer type:
>
>     type Int_Type is range 0 .. 31;
>     for Int_Type'Size use 8;
>
> Given an arbitrary value of type Int_Type, is there any non-erroneous
> way to get the corresponding Enum value if there is one, or raise
> an exception if there isn't?  By "corresponding", I mean 10 => Ten,
> 20 => Twenty, 30 => Thirty.

Do an unchecked conversion to a nonscalar type.

-- Convert Int_Type to Enum, raising constraint error if the result is
-- invalid.
function To_Enum(I : Int_Type) return Enum is
    type Wrapped_Enum is record
        Value : Enum;
    end record;
    for Wrapped_Enum'size use Enum'size;

    function To_Wrapped_Enum is new
        Ada.Unchecked_Conversion(Int_Type, Wrapped_Enum);
 
    W : Wrapped_Enum;
begin
    W := To_Wrapped_Enum(I);
    if W.Value'valid then
        return W.Value;
    else
        raise Constraint_Error;
    end if;
end To_Enum;




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                         ` Matthew Heaney
@ 1996-10-07  0:00                           ` Robert Dewar
  1996-10-09  0:00                             ` Keith Thompson
  0 siblings, 1 reply; 73+ messages in thread
From: Robert Dewar @ 1996-10-07  0:00 UTC (permalink / raw)



Note that in practice, of course unchecked conversion followed by 'Valid
will work fine for the case of enumeration types with holes. This was
specifically intended as far as I am concerned, and the fact that the
final wordking of the RM contradicts this is a mistake that should be
fixed.





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                         ` Robert A Duff
                                             ` (2 preceding siblings ...)
  1996-10-07  0:00                           ` Ken Garlington
@ 1996-10-08  0:00                           ` Alan Brain
  3 siblings, 0 replies; 73+ messages in thread
From: Alan Brain @ 1996-10-08  0:00 UTC (permalink / raw)



Robert A Duff wrote:
> 
> In article <DyqAKA.DJn@thomsoft.com>, Keith Thompson <kst@thomsoft.com> wrote:
> >Are sparse enumeration types are really used all that much in real life?
> 
> They shouldn't be, because, as you explained, they don't work.  Using
> sparse enums is asking for erroneousness.
> 
> Well, it's not *quite* that bad: You can use a sparse enum for sending
> data from Ada to the outside world (e.g. doing output, passing
> parameters *to* an imported subprogram, unchecked converting *from* a
> sparse enum, etc).  But the other direction doesn't always work, and
> should be avoided, IMHO.

Beg to differ; many systems send 0001, 0010, 0100, 1000 for the 4
different valid states, etc. You often get it coming and going in real
time apps. Even some disc controllers.
So you use a base type without representation (internally), and convert
to a represented derived type for output, and from a (maybe different)
represented derived type for input.

----------------------      <> <>    How doth the little Crocodile
| Alan & Carmel Brain|      xxxxx       Improve his shining tail?
| Canberra Australia |  xxxxxHxHxxxxxx _MMMMMMMMM_MMMMMMMMM
---------------------- o OO*O^^^^O*OO o oo     oo oo     oo  
                    By pulling Maerklin Wagons, in 1/220 Scale




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-07  0:00               ` Mark A Biggar
@ 1996-10-08  0:00                 ` Robert Dewar
  0 siblings, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-10-08  0:00 UTC (permalink / raw)



Mark says

"Why was the Unchecked_Conversion of an invalid scalar made erroneous in LM 95
instead of a bounded error like the coresponding uninitialized variable case?"

For discrete types, I think this is an excellent question and cannot think of
any reasonable response.

For floating-point, you might have trouble with signalling NaN's, though
this could certainly be handled too.





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-07  0:00                             ` Robert Dewar
@ 1996-10-09  0:00                               ` Keith Thompson
  0 siblings, 0 replies; 73+ messages in thread
From: Keith Thompson @ 1996-10-09  0:00 UTC (permalink / raw)



In <dewar.844696412@schonberg> dewar@schonberg.cs.nyu.edu (Robert Dewar) writes:
> Keith says
> 
> "For example, the language could have defined two additional attributes,
> analagous to 'Pos and 'Val, but operating on the internal representation
> of an enumeration type.  If the argument is an invalid representation,
> simply raise Constraint_Error.  GNAT provides half of this with its
> 'Enum_Rep attribute."
> 
> The intention in Ada 95 is that both operations are achievbable using
> unchecked conversion. It is a bug in the RM if this is not the case.

Ok, but unchecked conversion to what?  Since you can't get at the
underlying representation values as static expressions, there's no
portable way (that I know of) to declare an integer type of the same
size as an arbitrary enumeration type.  If I could write

    type Int_Type is range Enum_Type'Blorch(Enum_Type'First) ..
                           Enum_Type'Blorch(Enum_Type'Last);

(where 'Blorch is the non-existent attribute that returns the internal
code for an enumeration value), I could safely do unchecked conversions
between Int_Type and Enum_Type (if I ignore 13.9.1(12)).

Something like this is *probably* close enough:

    type Enum_Type is (...);
    for Enum_Type use (...);
    type Int_Type is range 0 .. 2**Enum_Type'Size-1;
    -- OR type Int_Type is mod 2**Enum_Type'Size;
    for Int_Type'Size use Enum_Type'Size; -- superfluous?
    function To_Int  is new Ada.Unchecked_Conversion(Enum_Type, Int_Type);
    function To_Enum is new Ada.Unchecked_Conversion(Int_Type, Enum_Type);

but it won't quite work if some of the enumeration codes are negative.

> However, in practice, of coruse this works, no matter what it says in
> the RM, so this point can be left moot without having any pragmatic 
> effect.

Moot in both senses of the word!  8-)}

I don't agree that there's no pragmatic effect.  The effect is not on
implementers, but on users.  Even if all implementations happen to behave
"sensibly" in this area, a careful user trying to write portable code
will avoid anything that the RM says is erroneous.

I think we need a binding interpretatin saying something like "When we
said 'erroneous' in 13.9.1(12), we were only kidding.  Yeah, there's
the ticket!"  8-)}  8-)}

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-07  0:00                           ` Robert Dewar
@ 1996-10-09  0:00                             ` Keith Thompson
  0 siblings, 0 replies; 73+ messages in thread
From: Keith Thompson @ 1996-10-09  0:00 UTC (permalink / raw)



In <dewar.844696010@schonberg> dewar@schonberg.cs.nyu.edu (Robert Dewar) writes:
> Note that in practice, of course unchecked conversion followed by 'Valid
> will work fine for the case of enumeration types with holes. This was
> specifically intended as far as I am concerned, and the fact that the
> final wordking of the RM contradicts this is a mistake that should be
> fixed.

I've sent a message to this effect to ada-comment.  Maybe something will
actually happen.

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-07  0:00                         ` Robert Dewar
@ 1996-10-10  0:00                           ` Ken Garlington
  1996-10-11  0:00                             ` Robert Dewar
  0 siblings, 1 reply; 73+ messages in thread
From: Ken Garlington @ 1996-10-10  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> Keith is right, this is in the RM, but I think the RM is definitely wrong
> here. I take part of the blame, I simply did not notice this particular
> mistake. Obviously for scalar types, unchecked conversion (where the sizes
> are the same) should not result in erroneous behavior, and a subsequent
> call to 'Valid should also be non-erroneous.
> 
> I simply missed this because it is in the wrong section (not under UC).
> Anyway, certainly GNAT behaves in a sensible manner here, and hopefully
> all other Ada 95 compilers will too, so this mistake should have only
> very limited impact.

Can't we go a little further, and write an AI (similar to the Ada 83 AI on
unchecked conversion between scalars of the same size) to formally document
what should happen? It's good that the AARM says "act sensibly," but wouldn't
an AI be better?


-- 
LMTAS - "Our Brand Means Quality"
For more info, see http://www.lmtas.com or http://www.lmco.com




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-04  0:00                           ` Robert Dewar
@ 1996-10-11  0:00                             ` Norman H. Cohen
  1996-10-12  0:00                               ` Robert Dewar
  0 siblings, 1 reply; 73+ messages in thread
From: Norman H. Cohen @ 1996-10-11  0:00 UTC (permalink / raw)



Concerning sparse enumeration types, Robert Dewar wrote:

>                                                   Furthermore, we found that
> we had to add the additional complexity of makeing sure that arrays indexed
> by such types were compact (rather than mapped sparsely), since a couple of
> large customers required this support.

But the work necessary to do this (mapping sparse encodings to a
contiguous set of values that can be used for array indexing) is already
necessary anyway to implement the 'Pos attribute.  

The Ada-83 RM contained a note (RM83-13.3(6)) warning that operations
such as 'Succ, 'Pred, 'Pos, and array indexing are likely to be less
efficient for sparse enumeration types than for ordinary ones.  The
warning is gone from the corresponding note in the Ada-95 RM
(RM95-14.4(11)), but surely the expectation of slower operations is
still there.

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-10  0:00                           ` Ken Garlington
@ 1996-10-11  0:00                             ` Robert Dewar
  1996-10-14  0:00                               ` Keith Thompson
  1996-10-14  0:00                               ` Ken Garlington
  0 siblings, 2 replies; 73+ messages in thread
From: Robert Dewar @ 1996-10-11  0:00 UTC (permalink / raw)



"Can't we go a little further, and write an AI (similar to the Ada 83 AI on
unchecked conversion between scalars of the same size) to formally document
what should happen? It's good that the AARM says "act sensibly," but wouldn't
an AI be better?"

Well the first step is for someone to write a question and send it to
the appopriate email address (see Ada 95 RM). This will usually result
in an AI prepared by Bob Duff, although he will be happy to have help!

But this is not an easy AI to write. In particular, I suggest restricting
it to discrete types rather than scalar types, since floating-point types
are contentious because of signalling Nan's.

Also, be sure to think in terms of conversion between scalar *types* and
not scalar *objects*, since this is what UC is about. I am not quite
sure what the abbreviation scalars means above, but it smacks of scalar
object to me!





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-11  0:00                             ` Norman H. Cohen
@ 1996-10-12  0:00                               ` Robert Dewar
  0 siblings, 0 replies; 73+ messages in thread
From: Robert Dewar @ 1996-10-12  0:00 UTC (permalink / raw)



iNorman Cohen says

"But the work necessary to do this (mapping sparse encodings to a
contiguous set of values that can be used for array indexing) is already
necessary anyway to implement the 'Pos attribute."



My goodness, that's perhaps 10% of the effort involved, that's the easy
part. If you want to investigate this statement further, feel free to
examine the GNAT sources. Have a look at exp_pakd.adb where most, but 
certainly not all the work is done. Luckly in GNAT we could piggyback off
the packed array stuff, which was already done in the front end (it might
be better to do it in the backend, but that's for the future, and luckily
for this particular issue, was not done yet!)

Yes, conceptually, the only issue is the mapping, but the problem is that
you have a situation where the conceptual type and the implementation
type are different (the conceptual type is indexed by the enumeration type,
the actual type by the representation of the enumeration type, for us these
are two separate types). As always, it is the implementation details, not
the algorithms that are the hard work!





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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-11  0:00                             ` Robert Dewar
@ 1996-10-14  0:00                               ` Keith Thompson
  1996-10-14  0:00                               ` Ken Garlington
  1 sibling, 0 replies; 73+ messages in thread
From: Keith Thompson @ 1996-10-14  0:00 UTC (permalink / raw)



In <dewar.845050338@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes:
> "Can't we go a little further, and write an AI (similar to the Ada 83 AI on
> unchecked conversion between scalars of the same size) to formally document
> what should happen? It's good that the AARM says "act sensibly," but wouldn't
> an AI be better?"
> 
> Well the first step is for someone to write a question and send it to
> the appopriate email address (see Ada 95 RM). This will usually result
> in an AI prepared by Bob Duff, although he will be happy to have help!

I've already done this.  See reference "96-5719.a Keith Thompson 96-10-7".

-- 
Keith Thompson (The_Other_Keith) kst@thomsoft.com <*>
TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2706
FIJAGDWOL




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-06  0:00               ` Keith Thompson
@ 1996-10-14  0:00                 ` Robert A Duff
  0 siblings, 0 replies; 73+ messages in thread
From: Robert A Duff @ 1996-10-14  0:00 UTC (permalink / raw)



In article <Dyvo0w.7Dr@thomsoft.com>, Keith Thompson <kst@thomsoft.com> wrote:
>But RM95-13.9.1(12) says:
>	A call to an imported function or an instance of
>	Unchecked_Conversion is erroneous if the result
>	is scalar, and the result object has an invalid
>	representation.
>
>Probably that paragraph should have been in 13.9 rather than 13.9.1.

True.

>Note that there are several paragraphs after this in the AARM encouraging
>implementations to behave sensibly:
>
>	[...] We considered requiring such sensible behavior,
>	but it resulted in too much arcane verbiage, and
>	since implementations have little incentive to behave
>	irrationally, such verbiage is not important to have.
>
>So implementations are encouraged to implement sensibly something that
>users are encouraged to avoid.

No, no.  The "sensible" comment in the AARM is *not* referring to the
paragraph about erroneousness of unchecked conversions.  It is referring
to the run-time behavior of "invalid" values, which can arise from many
things, but mainly uninitialized variables.  The intent is that (for
example):

    if X = Red and X /= Red then ...

should be True, despite the fact that X is not initialized (assuming the
compiler fails to catch the bounded error, and raise an exception).

This has nothing to do with the erroneousness defined in paragarph 12,
which would have been clearer if the AARM comment were after paragraph
11, rather than after paragraph 12.

- Bob




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

* Re: Valid Attribute and Unchecked Conversion
  1996-10-11  0:00                             ` Robert Dewar
  1996-10-14  0:00                               ` Keith Thompson
@ 1996-10-14  0:00                               ` Ken Garlington
  1 sibling, 0 replies; 73+ messages in thread
From: Ken Garlington @ 1996-10-14  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> "Can't we go a little further, and write an AI (similar to the Ada 83 AI on
> unchecked conversion between scalars of the same size) to formally document
> what should happen? It's good that the AARM says "act sensibly," but wouldn't
> an AI be better?"
> 
> Well the first step is for someone to write a question and send it to
> the appopriate email address (see Ada 95 RM). This will usually result
> in an AI prepared by Bob Duff, although he will be happy to have help!
> 
> But this is not an easy AI to write. In particular, I suggest restricting
> it to discrete types rather than scalar types, since floating-point types
> are contentious because of signalling Nan's.
> 
> Also, be sure to think in terms of conversion between scalar *types* and
> not scalar *objects*, since this is what UC is about. I am not quite
> sure what the abbreviation scalars means above, but it smacks of scalar
> object to me!

It does, indeed, smack of scalar object, for the reason that 'Valid is applied to
scalar objects, not scalar types.  I agree that UC is defined in terms of types,
but at some level it will have to be tied to the properties of scalar (more likely
discrete, as you said) objects, won't it? Otherwise, we may still have the
annoying proposition that:

   Y := Unchecked_Whatever(Z);
   if not Y'Valid then
     raise Whatever_Error;
   end if;

is not guaranteed to work for any given compiler, even assuming some reasonable 
restrictions on Y and Z (e.g., Y'Size >= Z'Size, both are discrete).

-- 
LMTAS - "Our Brand Means Quality"
For more info, see http://www.lmtas.com or http://www.lmco.com




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

end of thread, other threads:[~1996-10-14  0:00 UTC | newest]

Thread overview: 73+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-09-22  0:00 Rules for Representation of Subtypes Matthew Heaney
1996-09-23  0:00 ` David C. Hoos, Sr.
1996-09-23  0:00   ` Robert A Duff
1996-09-23  0:00   ` Samuel T. Harris
1996-09-26  0:00     ` David C. Hoos, Sr.
1996-09-24  0:00   ` Robert Dewar
1996-09-26  0:00     ` Keith Thompson
1996-09-26  0:00       ` Matthew Heaney
1996-09-27  0:00         ` Robert Dewar
1996-09-27  0:00         ` Robert A Duff
1996-09-27  0:00           ` Robert Dewar
1996-09-27  0:00       ` Robert A Duff
1996-09-24  0:00   ` Robert Dewar
1996-09-23  0:00 ` Robert A Duff
1996-09-24  0:00   ` Matthew Heaney
1996-09-26  0:00     ` Robert A Duff
1996-09-26  0:00       ` Larry Kilgallen
1996-09-27  0:00         ` Robert A Duff
1996-09-27  0:00           ` Mark A Biggar
1996-09-30  0:00             ` Robert A Duff
1996-10-01  0:00               ` Larry Kilgallen
1996-10-01  0:00                 ` Samuel Tardieu
1996-10-01  0:00                   ` Ken Garlington
1996-10-01  0:00                   ` Valid Attribute and Unchecked Conversion Matthew Heaney
1996-10-02  0:00                     ` Robert A Duff
1996-10-04  0:00                       ` Keith Thompson
1996-10-04  0:00                         ` Matthew Heaney
1996-10-07  0:00                           ` Robert Dewar
1996-10-09  0:00                             ` Keith Thompson
1996-10-04  0:00                         ` Robert A Duff
1996-10-04  0:00                           ` Robert Dewar
1996-10-11  0:00                             ` Norman H. Cohen
1996-10-12  0:00                               ` Robert Dewar
1996-10-06  0:00                           ` Keith Thompson
1996-10-07  0:00                             ` Robert Dewar
1996-10-09  0:00                               ` Keith Thompson
1996-10-07  0:00                           ` Ken Garlington
1996-10-08  0:00                           ` Alan Brain
1996-10-07  0:00                         ` Kenneth Almquist
1996-10-07  0:00                         ` Robert Dewar
1996-10-10  0:00                           ` Ken Garlington
1996-10-11  0:00                             ` Robert Dewar
1996-10-14  0:00                               ` Keith Thompson
1996-10-14  0:00                               ` Ken Garlington
1996-10-01  0:00                 ` Rules for Representation of Subtypes Robert A Duff
1996-09-28  0:00           ` Larry Kilgallen
1996-09-29  0:00             ` Robert A Duff
1996-09-29  0:00               ` Larry Kilgallen
1996-09-29  0:00                 ` Matthew Heaney
1996-09-30  0:00                 ` Robert A Duff
1996-10-01  0:00                   ` Ken Garlington
1996-10-02  0:00                     ` Robert A Duff
1996-10-02  0:00                       ` Ken Garlington
1996-10-06  0:00                   ` Robert Dewar
1996-09-29  0:00               ` Matthew Heaney
1996-09-30  0:00                 ` Robert Dewar
1996-09-30  0:00                   ` Matthew Heaney
1996-09-30  0:00                 ` Robert A Duff
1996-10-03  0:00             ` Robert Dewar
1996-10-02  0:00         ` Valid Attribute and Unchecked Conversion Robert I. Eachus
1996-10-02  0:00           ` Matthew Heaney
1996-10-02  0:00         ` George Haddad
1996-10-03  0:00           ` John Herro
1996-10-04  0:00             ` Karl Cooper {46901}
1996-10-07  0:00               ` Mark A Biggar
1996-10-08  0:00                 ` Robert Dewar
1996-10-05  0:00             ` Robert Dewar
1996-10-06  0:00               ` Keith Thompson
1996-10-14  0:00                 ` Robert A Duff
1996-09-27  0:00       ` Rules for Representation of Subtypes Matthew Heaney
1996-09-27  0:00         ` Robert A Duff
  -- strict thread matches above, loose matches on Subject: below --
1996-10-03  0:00 Valid Attribute and Unchecked Conversion Franco Mazzanti
1996-10-04  0:00 Franco Mazzanti

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