comp.lang.ada
 help / color / mirror / Atom feed
From: NCOHEN@IBM.COM ("Norman H. Cohen")
Subject: constraint error question for language lawyers
Date: 9 Nov 90 14:36:18 GMT	[thread overview]
Message-ID: <9011091437.AA20896@ajpo.sei.cmu.edu> (raw)

Alex Blakemore asks why, given the declarations

  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

the statements

  Dummy := (Len => 0, Text => "");
  Dummy := (Len  => Dummy.Len + 1,
            Text => Dummy.Text & 'a');

raise Constraint_Error in the second assignment.

The surprise results from the fact that the catenation

   Dummy.Text & 'a'

(where Dummy.Text = "") has bounds of 0 .. 0.  Since the Text component
of type Var_Text has a lower bound of 1, the evaluation of the aggregate

   (Len  => Dummy.Len + 1,
    Text => Dummy.Text & 'a');

raises Constraint_Error.

Now to the legal citations.  RM 4.5.3(4), in discussing the result of a
catenation, states:

     The lower bound of this result is the lower bound of the left
     operand, unless the left operand is a null array, in which case
     the result of the catenation is the right operand.

In this case the left operand IS a null array, so the lower bound must
be that of the right operand.  In this case, however, the right operand
is not an array, but a character, so it has no lower bound.  The next
RM paragraph, 4.5.3(5), provides a rule to cover this case:

     If either operand is of the component type of an array type,
     the result of the catenation is given by the above rules, using
     in place of this operand an array having this operand as its only
     component and having the lower bound of the index subtype of the
     array type as its lower bound.

That is, 'a' is taken to be a shorthand for (Short'First => a).  Since
Short'First, or 0, is lower bound of the right operand, and since the
left operand is null, 0 is the lower bound of the catenation.

The actual raising of Constraint_Error is governed by RM 4.3.1(3),
which discusses the evaluation of record aggregates and states:

     A check is made that the value of each subcomponent of the
     aggregate belongs to the subtype of this subcomponent.
     The exception CONSTRAINT_ERROR is raised if this check fails.

The only questionable rule in all of this is the rule that the value of
L&R, where L is a null array, is the value of R.  This seems natural at
first glance, but since Ada can have null arrays with different bounds
(0 .. -1, 1 .. 0, etc.) this conflicts with the usual rule (for L
nonnull) that the lower bound of the result is that of its left operand.
Alex Blakemore has provided an example where this nonuniform rule leads
to a nasty surprise.

I would modify the program as follows:  Add the subtype declaration

   subtype Positive_Short is Short range 1 .. Short'Last;

and use Positive_Short rather than Short as the index subtype of the
array type Data.  Since the Text component of the record type Var_Text
has a lower bound of one, this is more appropriate.  The Ada rules
tend to work more sensibly when the lower bound of an array is the lower
bound of its index subtype.  (In this case, 'a' would be taken as a
shorthand for (Positive_Short'First => 'a'), which has a lower bound of
1, so the catenation ""&'a' would have a lower bound of 1.)

             reply	other threads:[~1990-11-09 14:36 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1990-11-09 14:36 "Norman H. Cohen" [this message]
1990-11-30 16:02 ` constraint error question for language lawyers James THIELE
  -- strict thread matches above, loose matches on Subject: below --
1990-11-08 17:18 Alex Blakemore
1990-11-09 14:12 ` David Collard
1990-11-10  1:08 ` Charles H. Sampson
1990-11-17 10:12 ` Jean Pierre Rosen
replies disabled

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