Version 1.4 of ai12s/ai12-0304-1.txt

Unformatted version of ai12s/ai12-0304-1.txt version 1.4
Other versions for file ai12s/ai12-0304-1.txt

!standard 4.10(0)          19-05-09 AI12-0304-1/03
!class Amendment 19-01-11
!status Amendment 1-2012 19-05-09
!status ARG Approved 11-0-0 19-05-09
!status work item 19-04-11
!status ARG Approved 10-0-0 19-04-09
!status work item 19-01-11
!status received 19-01-10
!priority Low
!difficulty Easy
!subject Image attributes of language-defined types
!summary
Image attributes of some language-defined private types are specified.
!problem
Now that we have Image attributes for all types, we need to decide what (if anything) we are going to say about the Image for each language-defined private type.
!proposal
(See Summary.)
!wording
Append to the end of the new (as of AI12-0020) 4.10 Images section.
Implementation Permissions
For each language-defined nonscalar type T, T'Put_Image may be specified.
AARM Note: This permission applies, in particular, to nonscalar types declared in language-defined generic packages, and to any language-defined private type, even if an implementation chooses to complete it as a scalar type.
AARM Note: For any language-defined scalar type T, T'Put_Image should not be specified; the Image attribute needs to return the language-defined image for such types. This is important for compatibility: the Image attribute has been available for scalar types for many Ada revisions, and programs can (and do!) depend on its behavior.
Implementation Requirements
For each language-defined container type T (that is, each of the Vector, List, Map, Set, Tree, and Holder types defined in the various children of Ada.Containers), T'Put_Image shall be specified so that T'Image produces a result consistent with array aggregate syntax (using "[" and "]" as delimiters) as follows:
- Vector images shall be consistent with the default image of
an array type with the same index and component types.
AARM Note: In particular, this means that the format is that of a named array aggregate. We have no recommendation on how to handle empty elements; if the implementation can identify them, it may wish to display them specially, but otherwise, they're just uninitialized elements.
- Map images shall be consistent with named array aggregate
syntax, using key value images in place of discrete choice names. For example, "[Key1 => Value1, Key2 => Value2]".
AARM Note: There is no recommendation about the order in which key/element pairs occur within a map image. In the case of multiple key values whose corresponding element values have the same image, there is no recommendation about factoring (that is, generating "Key1 | Key2 => Some_Value" instead of "Key1 => Some_Value, Key2 => Some_Value").
- Set, List, and Holder images shall be consistent with
positional array aggregate syntax. List elements should occur in order within an image of a list. The image of an empty holder should be "[]".
AARM Note: There is no recommendation about the order in which set elements occur within the image of a set.
- Tree images (and images of subtrees of trees) shall be
consistent with positional array aggregate syntax. For example, "[[1, 2], [111, 222, 333]]".
For each language-defined nonscalar type T that has a primitive language-defined Image function whose profile is type conformant with that of T'Image (for example, Ada.Numerics.Float_Random.State has such an Image function), T'Put_Image should be specified so that T'Image yields the same result as that Image function.
Implementation Advice
For each language-defined private type T, T'Image should generate an image that would be meaningful based only on the relevant public interfaces, as opposed to requiring knowledge of the implementation of the private type.
!discussion
One could imagine going into great detail specifying the behavior of the image attributes of all of the various nonscalar predefined types.
That does not seem like a good idea (do we really want to spend any time considering what images should look like for the private type Ada.Text_IO.Editing.Picture?).
But the container types are of particular interest, so we ought to say something about them.
---
We don't need to normatively prohibit specifying T'Put_Image for a language-defined scalar type T, as arbitrary changes to language-defined packages are not permitted (with a handful of exceptions). In any case, we do not want the behavior of T'Image (and T'Wide_Image, and so on), for all language-defined scalar types T, to change from what it was before the Put_Image aspect was introduced.
In two places, the wording says "T'Put_Image should be specified so that" some condition is satisfied. I presume that it goes without saying that there is no need to specify T'Put_Image if the default aspect value satisfies the condition - this wording is not intended to impose a requirement that T'Put_Image must be explicitly specified in the case where the default implementation would be just fine.
[Editor's note: I think the recently added "as-if" AARM Note {A(5.d/5)} would cover this. The only way this would matter is if there exists some program that could tell the difference. I don't know of such a way.]
!corrigendum 4.10(0)
Insert new clause:
A fake to force a conflict; the actual text is in the conflict file.
!ASIS
No ASIS effect.
!ACATS test
ACATS B- and C-Tests are needed to check that the new capabilities are supported.
!appendix

From: Steve Baird
Sent: Thursday, January 10, 2019  2:31 PM

The definition of Image attributes for non-scalar types (AI12-0020) implicitly 
introduces questions about the behavior of the Image attributes of predefined 
types.

One of my homework assignments is to open an AI to deal with this question, 
so I am doing that here.

One could imagine going into great detail specifying the behavior of the 
image attributes of all of the various non-scalar predefined types.

That does not seem like a good idea (do we really want to spend any time 
considering what images should look like for the private type 
Ada.Text_IO.Editing.Picture?).

But the container types do seem to be of particular interest, so perhaps we 
ought to say something about them. (Incidentally, is there anything that we 
want to say about the Image attributes of the various cursor types?).

With all of this in mind, I propose the following (!wording only at this point).

The first rule (the prohibition on specifying T'Put_Image for a 
language-defined scalar type T) is intended to ensure that the behavior of 
T'Image (and T'Wide_Image, etc.) remains unchanged from what it was before the 
Put_Image aspect was introduced.

In two places, the wording says "T'Put_Image should be specified so that" some 
condition is satisfied. I presume that it goes without saying that there is no 
need to specify T'Put_Image if the default aspect value satisfies the 
condition - this wording is not intended to impose a requirement that 
T'Put_Image must be explicitly specified in the case where the default 
implementation would be just fine.

====

!wording

Append to the end of the new (as of AI12-0020) 4.10 Images section.

    For any language-defined scalar type T, T'Put_Image shall not
    be specified.

    Implementation Permissions

    For each language-defined non-scalar type T, T'Put_Image
    may be specified.

    AARM note: This permission applies, in particular, to
    non-scalar types declared in language-defined generic packages,
    and to any language-defined private type which an implementation
    chooses to complete as a scalar type.

    Implementation Advice

    For each language-defined container type T (i.e., each of the Vector,
    List, Map, Set, Tree, and Holder types defined in the various
    children of Ada.Containers), T'Put_Image should be specified so
    that T'Image produces a result consistent with array aggregate
    syntax (using "[" and "]" as delimiters) as follows:
        - Map images should be consistent with named array aggregate
          syntax, using key value images in place of discrete choice
          names. For example, "[Key1 => Value1, Key2 => Value2]".

          AARM Note:
            There is no recommendation about the order in which
            key/element pairs occur within a map image. In the case of
            multiple key values whose corresponding element values have
            the same image, there is no recommendation about factoring
            (e.g., generating "Key1 | Key2 => Some_Value" instead of
            "Key1 => Some_Value, Key2 => Some_Value").

        - Set, List, and Holder images should be consistent with
          positional array aggregate syntax. List elements should
          occur in order within an image of a list. The image of an empty 
          holder should be "[]".

          AARM Note:
            There is no recommendation about the order in which
            set elements occur within the image of a set.

        - Tree images (and images of subtrees of trees) should be
          consistent with positional array aggregate syntax.
          For example, "[[1, 2], [111, 222, 333]]".

    For each language-defined type T that has a primitive
    language-defined Image function whose profile is type conformant with
    that of T'Image (e.g., Ada.Numerics.Float_Random.State has such an
    Image function), T'Put_Image should be specified so that T'Image
    yields the same result as that Image function.

    AARM Note:
    For each language-defined private type T, implementations are
    encouraged to ensure that T'Image generates images that would be
    meaningful based only on the relevant public interfaces, as opposed
    to requiring knowledge of the implementation of the private type.

****************************************************************

From: Tucker Taft
Sent: Thursday, January 10, 2019  2:40 PM

Looks like a good start.

****************************************************************

From: Steve Baird
Sent: Thursday, January 10, 2019  4:51 PM

> - Set, List, and Holder images should be consistent with
>           positional array aggregate syntax. List elements should
>           occur in order within an image of a list.

We should probably add another rule here:

    The image of an empty holder should be "[]".

One might argue that this is already implied by the preceding "should be 
consistent with positional array aggregate syntax" advice, but Randy pointed 
out (in private communication) that

> An empty holder isn't quite the same as a null array (it's more like 
> an array of length one with null in place of the element)

So it seems worthwhile to say *something* about the case of an empty holder.

****************************************************************

From: Randy Brukardt
Sent: Friday, January 11, 2019  1:55 AM

A few thoughts while I should be doing something else (like creating an agenda).

...
> One could imagine going into great detail specifying the behavior of 
> the image attributes of all of the various non-scalar predefined 
> types.
> 
> That does not seem like a good idea (do we really want to spend any 
> time considering what images should look like for the private type 
> Ada.Text_IO.Editing.Picture?).

I think it might be a good idea to make a list of every language-defined type. 
Trying to remember them from memory is bound to miss some. 

For instance, I just ran across private type Imaginary in the complex package. 
Bizarrely, the private part of that package is specified. It is supposed to 
completed with a real type. It would seem reasonable to require the image of 
that to be the real value.

I do agree that for many types, the Image is questionable. What is the Image 
of a File_Type? The Name might be a good idea, but it also might be useful 
to show some of the underlying implementation (such as a file handle).
Probably not worth deciding.
 
...

BTW, I used most of your message as the !discussion of the AI. I know better 
than to expect I'll get more without asking several times. ;-) And I can't 
wait tonight anyway.

...
>     Implementation Advice
> 
>     For each language-defined container type T (i.e., each of the Vector,

We don't say "i.e." in the Standard. No one is quite sure if it is used it 
right, and is easier to say "that is" anyway.

More important: Personally, I would prefer this is an Implementation 
Requirement. If we think it is important to specify the Image for an array 
(and we did), we ought to give the same treatment to the containers. After 
all, a Vector is as close as we can make it to an array with a sticky lower 
bound. You've specified to about the same level as we specified the array 
and record aggregates, so it should be fine as a requirement.

It definitely seems valuable to be able to depend on the Image much like 
one can depend on the streaming to work. And if an implementation wants to 
show some debugging info, they shouldn't pollute the user view with that.

...
>     For each language-defined type T that has a primitive
>     language-defined Image function whose profile is type conformant with
>     that of T'Image (e.g., Ada.Numerics.Float_Random.State has such an
>     Image function), T'Put_Image should be specified so that T'Image
>     yields the same result as that Image function.

This seems like a good idea. Unfortunately, Imaginary does have an Image
function. (I have no idea why Imaginary is private and Complex is visible, 
that seems bizzare.)

>     AARM Note:
>     For each language-defined private type T, implementations are
>     encouraged to ensure that T'Image generates images that would be
>     meaningful based only on the relevant public interfaces, as opposed
>     to requiring knowledge of the implementation of the private type.

*This* seems like relevant Implementation Advice.

****************************************************************

From: Randy Brukardt
Sent: Friday, January 11, 2019  2:19 AM

...
> I think it might be a good idea to make a list of every 
> language-defined type. Trying to remember them from memory is bound to 
> miss some.

I just remembered that I had to make such a list for nonlimited private types 
for the ACATS objectives. (There's a rule that every nonlimited private type 
has an equality that composes properly.) Here's the list of nonlimited types:

System.Addess
Ada.String.Maps.Character_Set
Ada.String.Wide_Maps.Wide_Character_Set
Ada.String.Wide_Wide_Maps.Wide_Wide_Character_Set
Bounded_String (from an instance Ada.String.Bounded) 
Ada.Strings.Unbounded.Unbounded_String
Ada.Task_Identification.Task_Id
Cursor (from an instance of an Ada.Containers) 
Wide_Bounded_String (from an instance Ada.Strings.Wide_Bounded) 
Ada.Strings.Wide_Unbounded.Wide_Unbounded_String
Wide_Wide_Bounded_String
Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Unbounded_String
State (from an instance Ada.Numerics.Discrete_Random) 
Ada.Numerics.Float_Random.State 
Ada.Real_Time.Time_Span 
Ada.Real_Time.Time 
Imaginary (from an instance Ada.Numerics.Generic_Complex_Types)
Ada.Calendar.Time
Ada.Exceptions.Exception_Id
Interfaces.C.Strings.chars_ptr
Ada.Execution_Time.CPU_Time
Ada.Text_IO.Editing.Picture

---
Limited private types are probably less likely to need an image. These include 
Random Generators, the various File_Types, Directories Search_Type and 
Directory_Entry_Type, Exceptions Exception_Occurrence, Root_Subpool in 
Subpools (this is more of an interface), Root_Stream_Type, Limited_Controlled 
(another interface), and a bunch of types in Annex D (Suspension_Object, 
Synchronous_Barrier, Timer, Timing_Event, Group_Budget, and 
Dispatching_Domain). (I just searched for "limited private", so I suppose it's 
possible I missed something.)

****************************************************************

From: Steve Baird
Sent: Friday, January 11, 2019  5:39 PM

> I think it might be a good idea to make a list of every 
> language-defined type. Trying to remember them from memory is bound to miss some.

In particular, we might want this AI to say something about images for 
System.Address (at least in the case where the implementation advice 
suggesting that System.Address should be declared as a private type is 
followed) and for Ada.Tags.Tag.

>>      For each language-defined container type T (i.e., each of the 
>> Vector,
...
> More important: Personally, I would prefer this is an Implementation 
> Requirement. If we think it is important to specify the Image for an 
> array (and we did), we ought to give the same treatment to the 
> containers. After all, a Vector is as close as we can make it to an 
> array with a sticky lower bound. You've specified to about the same 
> level as we specified the array and record aggregates, so it should be fine 
> as a requirement.

Makes sense. The key point is, as you point out, to treat container types 
consistently with concrete composite types.

>>      AARM Note:
>>      For each language-defined private type T, implementations are
>>      encouraged to ensure that T'Image generates images that would be
>>      meaningful based only on the relevant public interfaces, as opposed
>>      to requiring knowledge of the implementation of the private type.
> 
> *This* seems like relevant Implementation Advice.

The other alternative I was considering (as opposed to an AARM note) was to 
say nothing at all on the grounds that this should just be common sense. 
Making it implementation advice seems more like an attempt to legislate 
good taste.

****************************************************************

From: Randy Brukardt
Sent: Friday, January 11, 2019  6:17 PM

> > I think it might be a good idea to make a list of every 
> > language-defined type. Trying to remember them from memory
> > is bound to miss some.
> 
> In particular, we might want this AI to say something about images for 
> System.Address (at least in the case where the implementation advice 
> suggesting that System.Address should be declared as a private type is 
> followed) and for Ada.Tags.Tag.

I would say that type Imaginary (since it is supposed to be numeric) also 
qualifies.

Bounded_String and Unbounded_String also seem important (in that they're 
heavily used), but maybe not as much since there are other ways to get an 
string value from them.
 
...
> >>      AARM Note:
> >>      For each language-defined private type T, implementations are
> >>      encouraged to ensure that T'Image generates images that would be
> >>      meaningful based only on the relevant public interfaces, as opposed
> >>      to requiring knowledge of the implementation of the private type.
> > 
> > *This* seems like relevant Implementation Advice.
> 
> The other alternative I was considering (as opposed to an AARM note) 
> was to say nothing at all on the grounds that this should just be 
> common sense. Making it implementation advice seems more like an 
> attempt to legislate good taste.

Since when do implementers have common sense or good taste?? :-)

I think this is important enough to at least mention, since I can see (from 
the implementation prespective) reasons for doing the easiest thing -- which
is nothing and just letting the default implementation (which would show all 
of the private components) show through. But this is *not* what we want, nor,
I suspect, what most users would want. And it's important to tell the Ada user
that the intent isn't to let random implementation junk show through, thus 
suggesting IA. Maybe just a Note would be better.

There definitely is value is lightly explaining what we consider good taste.
They're always welcome to ignore IA, after all (it's never bothered me :-).

****************************************************************

From: Steve Baird
Sent: Friday, January 11, 2019  6:49 PM

> Maybe just a Note would be better.
I said an AARM note or perhaps nothing at all, you said Implementation Advice .

A Note sounds like a good way to split the difference.

****************************************************************

From: Tucker Taft
Sent: Friday, January 11, 2019  9:21 PM

We almost never use Notes directed at implementations.  Notes are almost 
always for the user.  I would stick with Implementation Advice or an AARM 
note.  At this point, I suggest we leave the final decision to an ARG meeting.

****************************************************************

From: Randy Brukardt
Sent: Thursday, April 11, 2019  11:04 PM

(1) I put the AARM note that Put_Image should not be specified for 
    language-defined scalar types after the new Implementation Permission, 
    since it makes the most sense there. I note that it doesn't make sense to 
    have both the Implementation Permission that one *can* specify Put_Image 
    for nonscalar types, and a rule that one *cannot* specify Put_Image for 
    scalar types. One of those has to be true because of existing rules! (And
    we think it is the *cannot* rule.)

(2) There's a number of images written in double quotes thus "[1, 2, 3]"; I'm 
    dropping the quotes and setting these in the example font.

(3) The introduction of the ImplAdvice says that it applies to all containers, 
    but the list of bullets never gives any rule for Vectors! After discussing 
    this with Steve, I added:

        - Vector images should be consistent with the default image of 
          an array type with the same index and component types.

    I wrote it this way to avoid repeating discussion about named notation and 
    what those names are. This is followed by an AARM note (like the others):

          AARM Note: In particular, this means that the format is that
          of a named array aggregate. We have no recommendation on how to 
          handle empty elements; if the implementation can identify them, it
          may wish to display them specially, but otherwise, they're just 
          uninitialized elements.

(4) In the e-mail thread from January, Steve says that we need to add a line 
    saying that "The image of an empty holder should be "[]". We need to 
    mention this because an empty holder isn't so much a null array but rather 
    an array whose single element is "bottom", so the mapping is not obvious.

(5) Also in that thread, there were two questions that I had that we deferred 
    to the ARG meeting. I don't think I have the energy to ask them again, but
     I mention them here so that if anyone cares they can ask to discuss them.

   [A] I thought that the Implementation Advice on the containers should be a 
   requirement, so that users can depend on getting a reasonably consistent 
   Image from the containers. We make requirements about storage management, 
   streaming, and various other things for the containers, so it seems strange 
   that this is just advice. Additionally, I thought that the AARM note about 
   making images relevant to clients rather than exposing implementation 
   details probably should be Implementation Advice, since it is not 
   necessarily an obvious "best practice". Hopefully, neither of these matter 
   much in practice (implementers probably will do the right thing here).

   [B] I thought we should consider specifying a result for some additional 
   types, including "Imaginary" (from Ada.Numerics.Generic_Complex_Types) --
   which is private but required to be completed with a real type; 
   Ada.Calendar.Time, Ada.Real_Time.Time, Ada.Real_Time.Time_Span, and 
   Ada.Execution_Time.CPU_Time. Steve had suggested saying something about 
   System.Address and Ada.Tags.Tag. Again, implementations will hopefully do
   something useful and obvious.

****************************************************************

From: Randy Brukardt
Sent: Thursday, April 11, 2019  11:34 PM

(6) We had

    For each language-defined type T that has a primitive
    language-defined Image function ...

And we also have a note that Put_Image not be changed for scalar types. This 
wording conflicts, if only in theory (I didn't check for Image functions for 
scalar types). So I added "nonscalar" to it:

    For each language-defined nonscalar type T that has a primitive
    language-defined Image function ...

****************************************************************

Questions? Ask the ACAA Technical Agent