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 >
