[net.lang.ada] Elaboration of Parameterised Record Types

paul@cernvax.UUCP (paul) (11/03/86)

Elaboration of a parameterised record type:

Please refer to the 14 lines of Ada source program at the end of this
letter.

The program compiles and starts to run but gives NUMERIC_ERROR exception
during the elaboration of TYPE some_string. 

The declaration of type SOME_STRING is intended to be variable length.

The declaration is syntactically correct. 

The run-time NUMERIC_ERROR exception could be correct given the DEC
Vax-Ada interpretation of the declaration statement as described in the
Vax-Ada Programmer's Run-time Reference Manual, Section 3.1.6, "Object
representation and storage" p.3-15 which says: 


   TYPE arr IS ARRAY(INTEGER RANGE <>, INTEGER RANGE <>) OF BOOLEAN;
   SUBTYPE n IS INTEGER RANGE 1..25;
   TYPE off(L : n :=1;
            W : n :=1;) IS
      RECORD
         occ : arr(1..L,1..W);
      END RECORD;
   f : off;
   
   "When an unconstrained object, such as F, is declared, it must be
   allocated enough storage to accomodate a value in which L and W could
   have any value in the range 1..25". 


Applied to the SOME_STRING declaration this interpretation would require
that MAX_INT bytes be allocated for every object of type SOME_STRING.
(NATURAL is 0..MAX_INT). 


However, this seems to conflict with the ARM (Ada Reference Manual) which
gives an example of a specification of a variable length string handling
package (they call it "text" handling to distinguish from the predefined
type STRING). Section 7.6 of the ARM gives the following (I have changed
some of the names to help relieve ambiguity as I see it. Do look at 7.6 to
see what the ARM actually says.) 


   max_possible_string : CONSTANT:=some_value; --Implem defined
   SUBTYPE index IS INTEGER RANGE 0..max_possible_string;
   TYPE text(this_string_maximum : index) IS
   RECORD
      pos : index:=0;
      value : STRING(1..this_string_maximum);
   END RECORD;

Sect 7.6 of the ARM goes on to say:

   "From a user's point of view, a TEXT is a variable length string. Each
   TEXT object has a maximum length, which must be given when the object is
   declared, and a current value, which is a string of some length between
   zero and the maximum." 
                ^^^^^^^

Which maximum??? Dec have assumed max_possible_string. But if this should
be so, why is it necessary to declare, and supply a value for,
"this_string_maximum"? 

On the contrary, it would appear that "this_string_maximum" is what the
(admittedly ambiguous) ARM intended to say. 

My question therefore is:
Is my understanding faulty or is my NUMERIC_ERROR the result of a coding
bug in the DEC Vax-Ada compiler, based on a DEC misinterpretation of the
ARM at this point? I would have thought that DEC should allocate storage
for the record according to the value of the parameter
"this_string_maximum" and not according to the type of
"this_string_maximum". 

In practice, many programs will work under either interpretation and will
give the same external behaviour. Internally however, the DEC
interpretation allocates much more space. Lastly, the DEC interpretation
cannot cope with examples such as the one below.

I took my "some_string" example straight out of the book "Ada for
experienced programmers" by A.N.Habermann and D.E.Perry, Addison-Wesley
1983. 

The "workaround" on Vax-ADA is of course to use a different type for
"this_string_maximum" with a smaller range than NATURAL! 

Paul Burkimsher

Electronic addresses:

   paul@crvxdev.bitnet

   ...mcvax!cernvax!paul

   paul@vxdev.cern

-------------------------------------------------------------------------

-- The following (DEC VAX-ADA) program compiles and links ok but when I 
-- run it, it gives "NUMERIC_ERROR" (integer overflow) during the 
-- elaboration of variable machine_name of TYPE some_string.


WITH text_io; USE text_io;

PROCEDURE demo IS

TYPE some_string(allocated_len : NATURAL := 8) IS
        RECORD
           str : STRING(1..allocated_len);
        END RECORD;

machine_name : some_string;

BEGIN
   machine_name:=(6,"vxcrna");
   put("Hello world");
   new_line;
   put(machine_name.str);
   new_line;
END demo;

markb@sdcrdcf.UUCP (Mark Biggar) (11/05/86)

There is a difference between a discriminant with a default value and one
without.  If you define the discriminant with a default value you are
declaring that the value of the discriminant for any object can be changed
dymanically to any value in the range of the discriminants type.  Thus, the
compiler must allocate enough storage to hold an object with any legal
value of the discriminant.  If you don't give a default value to the
discriminant then the value may not change dynamically and must be set at
the time the object with the discriminant is declared and the compiler can
allocate just enough storage for the object.  The example you sight from
the LRM does NOT define a default value for the discriminant, so each
object in the example is declared with its own fixed discriminant value,
while in your program fragment you DO define a default so the size of the
objects have to be allocated large enough to store any object of any size
and the compiler is upset about it.

Mark Biggar
{allegra,burdvax,cbosgd,hplabs,ihnp4,akgua,sdcsvax}!sdcrdcf!markb