[comp.lang.ada] assigning variant records

simon@cs.washington.edu (Kevin Simonson) (10/30/90)

He-e-e-elp!

     I have gotten the following Ada code to compile on a Verdix compiler
used by the P-3 project at Boeing A&E, and have run it several times.  Now
that I'm a grad student at the University of Washington it still compiles,
but when I try to run it, inputting into "get_line" a string of length 1 or
more (as shown in the following debugging sessions), I get an
'"Illegal instruction" [4]' message, followed by
'--> Software trap: range check', as soon as I try to assign "Y.all := X;".

     Can anybody make any sense out of this?  What am I doing wrong?  I'd
really appreciate any advice anyone can give me.  Thanks,

                                             ---Kevin Simonson

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    

with TEXT_IO;  use TEXT_IO;

procedure VACH_PR is

   subtype DIGS is integer range 0..9;

   type XX (A : DIGS := 0) is record
      S : string (1..A);
   end record;

   type YY is access XX;

   X : XX;

   Y : YY;

   Z : string(1..20);

   I : integer;

begin

   Y := new XX;

   loop
      put ("String:  ");
      get_line (Z, I);
      exit when I = 1 and then Z(1) = 'q';
      X := (I, Z(1..I));
      Y.all := X;
      put_line ("Entered string is [" & Y.S & ']');
   end loop;

end VACH_PR;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2
    3  procedure VACH_PR is
    4
    5     subtype DIGS is integer range 0..9;
    6
    7     type XX (A : DIGS := 0) is record
    8        S : string (1..A);
    9     end record;
   10
   11     type YY is access XX;
   12
   13     X : XX;
   14
   15     Y : YY;
   16
   17     Z : string(1..20);
   18
   19     I : integer;
   20
   21  begin
   22
   23     Y := new XX;
   24
   25     loop
   26        put ("String:  ");
   27        get_line (Z, I);
   28        exit when I = 1 and then Z(1) = 'q';
   29        X := (I, Z(1..I));
   30*=      Y.all := X;
   31        put_line ("Entered string is [" & Y.S & ']');
   32     end loop;
   33
   34  end VACH_PR;
-*-------------------------------------------------------------------vach_pr.a-





Debugging: /george4/simon/ada/vach_pr
VADS_library: /george4/simon/ada
library search list:
        /george4/simon/ada
        /indra1/local/ada/verdixlib
        /indra1/local/ada/standard
:b 30
vach_pr
String:
Entered string is []
String:  a

  ^
  |
before
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
after
  |
  V

    2
    3  procedure VACH_PR is
    4
    5     subtype DIGS is integer range 0..9;
    6
    7     type XX (A : DIGS := 0) is record
    8        S : string (1..A);
    9     end record;
   10
   11     type YY is access XX;
   12
   13     X : XX;
   14
   15     Y : YY;
   16
   17     Z : string(1..20);
   18
   19     I : integer;
   20
   21  begin
   22
   23     Y := new XX;
   24
   25     loop
   26        put ("String:  ");
   27        get_line (Z, I);
   28        exit when I = 1 and then Z(1) = 'q';
   29        X := (I, Z(1..I));
   30*=      Y.all := X;
   31        put_line ("Entered string is [" & Y.S & ']');
   32     end loop;
   33
   34  end VACH_PR;
-*-------------------------------------------------------------------vach_pr.a-
        /george4/simon/ada
        /indra1/local/ada/verdixlib
        /indra1/local/ada/standard
:b 30
vach_pr
String:
Entered string is []
String:  a
 stopped at "/george4/simon/ada/vach_pr.a":8 in xx'2..SIZE
   8        S : string (1..A);
 stopped 9 instructions after "/geoge4/simon/ada/vach_pr.a":30 in vach_pr'2
  30        Y.all := X;
"Illegal instruction" [4]
--> Software trap: range check
 stopped 15 instructions after "/george4/simon/ada/vach_pr.a":30 in vach_pr'2
  30        Y.all := X;
-- 
Murphy's Law of Aerodynamics:  When the weight of the paperwork equals the
                               weight of the airplane, the airplane flies.

NCOHEN@IBM.COM ("Norman H. Cohen") (10/30/90)

Kevin Simonson encounters CONSTRAINT_ERROR in the following program:

 >with TEXT_IO;  use TEXT_IO;
 >
 >procedure VACH_PR is
 >
 >   subtype DIGS is integer range 0..9;
 >
 >   type XX (A : DIGS := 0) is record
 >      S : string (1..A);
 >   end record;
 >
 >   type YY is access XX;
 >
 >   X : XX;
 >
 >   Y : YY;
 >
 >   Z : string(1..20);
 >
 >   I : integer;
 >
 >begin
 >
 >   Y := new XX;
 >
 >   loop
 >      put ("String:  ");
 >      get_line (Z, I);
 >      exit when I = 1 and then Z(1) = 'q';
 >      X := (I, Z(1..I));
 >      Y.all := X;
 >      put_line ("Entered string is [" & Y.S & ']');
 >   end loop;
 >
 >end VACH_PR;

When a record with discriminants is created by an allocator, the
allocated object is constrained.  That is, the value of the discriminant
is fixed at the time of allocation.  In particular, the statement
"Y := new XX;" causes Y to point to a record whose discriminant is
fixed to be zero.  (Since there is no initial value in the allocator,
the default discriminant value is used.)  Thus the record value
(0, Z(1 .. 0)) can be assigned to Y.all, but an attempt to assign
(N, Z(1 .. N)) for N/=0 raises Constraint_Error. If

   X := (I, Z(1..I));
   Y.all := X;

is replaced by

   Y := new XX'(I, Z(1 . I));

the Constraint_Error will be avoided, because Y will now point to a
NEW record whose discriminant value is fixed to be the current value of
I.  (On the other hand, if the program runs long enough, the repeated
allocation of new records could lead to Storage_Error.  This can be
avoided by implementing the first garbage-collecting Ada compiler or,
more practically, by calling an instance of Unchecked_Deallocation with
the old value of Y just before the assignment.)

Norman H. Cohen

stt@inmet.inmet.com (11/20/90)

Re:  assigning variant records

> /* Written 6:48pm Oct 29,1990 by simon@cs.washington.edu */
> 
> He-e-e-elp!
> 
>      I have gotten the following Ada code to compile on a Verdix compiler
> used by the P-3 project at Boeing A&E, and have run it several times.  Now
> that I'm a grad student at the University of Washington it still compiles,
> but when I try to run it, inputting into "get_line" a string of length 1 or
> more (as shown in the following debugging sessions), I get an
> '"Illegal instruction" [4]' message, followed by
> '--> Software trap: range check', as soon as I try to assign "Y.all := X;".

Your problem is that objects created by an allocator are always
constrained, even if the declaration of the record
type has defaults for all discriminants.

RM 4.8:5 states: "If the type of the created object is an array type
  or a type with discriminants then the created
  object is always constrained.  If the allocator includes a subtype
  indication, the created object is constrained either by
  the subtype or by the default discriminant values."

In your case, you had "Y := new XX;".  This creates
an object which is constrained by the default discriminant value,
which is 0.  It rejects your attempt to assign a value into
it with a different discriminant.

>      Can anybody make any sense out of this?  What am I doing wrong?  I'd
> really appreciate any advice anyone can give me.  Thanks,
> 
>                                              ---Kevin Simonson

I hope this helped.

S. Tucker Taft
Intermetrics, Inc.
Cambridge, MA  02138