[comp.lang.ada] constraint error question for langu

kst@telesoft.UUCP (Keith Thompson @diego) (11/09/90)

> The Question:
>   Why does this procedure raise constraint error?
>   It happens on the second assignment to dummy, but
>   doesn't happen if dummy.len > 0 and appears to have 
>   something to do with the function call "&"

Yes, this is pretty obscure.  Here's what's happening.

The lower bound of the array type Data is Short'First, which is 0.  The
lower bound of Dummy.Text is declared as 1.  After the first
assignment, Dummy.Text is a null array.  By LRM 4.5.3:4, the lower
bound of the result of a catenation is the lower bound of the left
operand, *unless* the left operand is a null array; in that case, the
result is the right operand.  By LRM 4.5.3:5, an operand which is of
the component type of the array type is treated as a single-element
array whose lower bound is the lower bound of the index subtype of the
array type (in this case, 0).  Since implicit array subtype conversion
is done for array assignments, but not for component associations, the
association

   text => dummy.text & 'a' 

raises Constraint_Error, since the component's lower bound of 1 doesn't
match the expression's lower bound of 0.

Here's a modified version of the test program that doesn't raise
Constraint_Error.  Added lines are marked with "--+", changed
lines with "--!".

with text_io;
use text_io;

procedure bozo is
  
  type short is range 0 .. 10;

  type data is array (short range <>) of character;

  type var_text (len : short := 0) is
    record
      text : data (1 .. len);
    end record;

  dummy : var_text; -- unconstrained

  procedure do_nothing (d : data) is 
  begin
    null;
  end do_nothing;

  function shift(text: data) return data is	--+
    result: data(1 .. text'length);		--+
  begin						--+
    result := text;				--+
    return result;				--+
  end shift;					--+
						--+
begin

  put_line ("before");
  dummy := (len => 0, text => "");
  put_line ("during");
  dummy := (len  => dummy.len + 1,
            text => shift(dummy.text & 'a'));	--!
  put_line ("after");

exception

  when constraint_error =>
    put_line ("constraint_error raised");

end bozo;

Here's the output:

before
during
after

--
Keith Thompson (The_Other_Keith)  ucsd.ucsd.edu!telesoft!kst
TeleSoft                          kst@telesoft.com
5959 Cornerstone Court West
San Diego, CA  92121-9891         (619) 457-2700 x121 "hello?"