I agree the current rules for the default for Put_Image of an untagged
derived type do not properly handle the case when the discriminants are
replaced.  It should call the parent’s Put_Image only if it has been
specified on the parent or some more distant ancestor. Otherwise it should
default to a component by component construction of the image, given that
the number and names of the discriminants might have changed.
-Tuck

On Fri, Dec 22, 2023 at 11:54 PM Christoph & Ursula Grein <
[email protected]> wrote:

> *!topic* Components of derived untagged discriminated record types
> *!reference* Ada 2022 RM3.7(18-25), RM4.10(7/5,17/5,18/5),
> RM13.13.2(8.2/2-9.1/5)
> *!from* Christoph Grein 2023-12-22
> *!keywords* discriminants, record components, derived types
> *!discussion*
>
> *First of all: Merry Christmas to all of you and Happy New Year*
>
> Which record components of One_Horse_Carriage do exist? Code see at end.
> This is my attempt of an RM exegesis.
> RM 3.7(18) The discriminant Number_Passengers of the parent type Carriage
> is constrained to equal the new discriminant of the derived type
> One_Horse_Carriage; they correspond (and may share storage).
> The discriminant Number_Horses of the parent type Carriage is constrained
> to the value of the expression 1; it is specified.
>
> (19) The component_definition Persons depends on the discriminant
> Number_Passengers.
> The component_definition Horses does not depend on a discriminant.
>
> (23) The component Passengers depends on the discriminant
> Number_Passengers.
> The component Team does not depend on a discriminant.
>
> (25) Each value of a discriminated type includes a value for each
> component of the type that does not depend on a discriminant.
> Thus, Number_Passengers, Coachman and Team are included.
> I'm tempted to say, also the component Number_Horses is included with the
> fixed value 1 - it does not depend on a discriminant.
> The values of discriminants determine which other component values (only
> Passengers here) are present in the value of the discriminated type. Where
> RMss.ss(pp)? According to 3.7.1(11), I would expect something like: Each
> component whose constraint is satisfied.
>
> Obviously, I'm misreading the RM, since Number_Horses allegedly is not
> included, no value may be given in the aggregate. Barnes's book Ada 2012
> also says this in a different example (Boxer) on chapter 18.4.
>
> I'm really astonished that the new attribute 'Image for a record includes
> a value for a nonexistent component.
>
> Image attribute
> ===============
> RM 4.10(7/5) For an untagged derived type, ..., the default implementation
> of T'Put_Image invokes the Put_Image for its parent type on a conversion of
> the parameter of type T to the parent type.
>
> Does this make sense if the parent type has more components than the
> derived type?
>
> (17/5) For a specific, nonderived composite type:
> (18/5) If the default implementation of Put_Image writes components, the
> order in which components are written is the same canonical order in which
> components of a composite type T are written out by the default
> implementation of T'Write. [This is also the order that is used in
> determining the meaning of a positional aggregate of type T.]
>
> Stream attributes
> =================
> RM 13.13.2(8.2/2) The default implementations of the Write and Read
> attributes, where available, execute as follows:
> (9/5) ... For nonderived composite types, the Write or Read attribute for
> each component (excluding those, if any, that are not components of the
> nominal type of the object) is called in ... positional aggregate order for
> a record. ... If T is a discriminated type, discriminants are included only
> if they have defaults. ...
>
> This is funny - discriminants are output although there are no defaults.
>
> (9.1/5) ... For untagged derived types, the Write (resp. Read) attribute
> invokes the corresponding attribute of the parent type, if the attribute is
> available for the parent type.
>
> This last sentence does not make sense for cases like Sulky where a
> certain discriminant is no longer part of the record.
>
> I admit, a lot of ranting. And GNAT has perhaps some bugs (Ada 2022 is not
> yet fully implemented as you can see because it does not accept [] for
> array aggregates, but uses them for output).
>
> This is my sample program:
> ---------------------------
> with Ada.Text_IO;use  Ada.Text_IO;
>
> procedure Coaches is
>
>   subtype Number is Natural range 0 .. 8;
>
>   subtype Person  is Positive;
>   type    Persons is array (Number range <>) of Person;
>
>   subtype Horse  is Positive;
>   type    Horses is array (Number range <>) of Horse;
>
>   type Carriage (Number_Passengers, Number_Horses: Number) is record
>     Coachman  : Person;
>     Passengers: Persons (1 .. Number_Passengers);
>     Team      : Horses  (1 .. Number_Horses);
>   end record;
>
>   type One_Horse_Carriage (Number_Passengers: Number) is
>     new Carriage (Number_Passengers => Number_Passengers, Number_Horses =>
> 1);
>
>   Sulky: One_Horse_Carriage (Number_Passengers => 0) :=
>     (Number_Passengers => 0,
>      Coachman          => 1850,
>      Passengers        => (-5 .. -6 => 1),  -- []  Ada 2022
>      Team              => (1 => 2023));
>
>   Coach      : Carriage           := Carriage (Sulky);            -- Does
> type conversion work ...
>   Sulky_again: One_Horse_Carriage := One_Horse_Carriage (Coach);  -- ...
> in both directions?
>
> begin
>
>   Put_Line ("Sulky");
>   Put_Line ("=====");
>   Put_Line (Sulky.Number_Passengers'Image);
>   --Put_Line (Sulky.Number_Horses'Image);  -- does allegedly not exist,
> yet ...
>   Put_Line (Sulky.Coachman'Image);
>   Put_Line (Sulky.Passengers'Image);
>   Put_Line (Sulky.Team'Image);
>   Put_Line (Sulky'Image);                  -- GNAT prints it out here
>   New_Line;
>
>   Put_Line ("Coach");
>   Put_Line ("=====");
>   Put_Line (Coach.Number_Passengers'Image & Coach.Number_Horses'Image);
>   Put_Line (Coach.Coachman'Image);
>   Put_Line (Coach.Passengers'Image);
>   Put_Line (Coach.Team'Image);
>   Put_Line (Coach'Image);
>   New_Line;
>
>   Put_Line ("Sulky = Sulky_again ?");
>   Put_Line ("=====================");
>   Put_Line (Boolean'Image (Sulky = Sulky_again));
>
> end Coaches;
> -------------------------------------------------
> This is the result:
> -------------------------------------------------
> Sulky
> =====
>  0
>  1850
>
> []
>
> [ 2023]
>
> (NUMBER_PASSENGERS =>  0,
>  NUMBER_HORSES =>  1,
>  COACHMAN =>  1850,
>  PASSENGERS =>
>  [],
>  TEAM =>
>  [ 2023])
>
> Coach
> =====
>  0 1
>  1850
>
> []
>
> [ 2023]
>
> (NUMBER_PASSENGERS =>  0,
>  NUMBER_HORSES =>  1,
>  COACHMAN =>  1850,
>  PASSENGERS =>
>  [],
>  TEAM =>
>  [ 2023])
>
> Sulky = Sulky_again ?
> =====================
> TRUE
>

Reply via email to