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

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

!standard 4.9(9)          17-07-19 AI12-0201-1/02
!standard 4.9(19)
!standard 4.9(20)
!standard 4.9(24)
!class Amendment 16-08-18
!status Amendment 1-2012 17-07-19
!status ARG Approved 8-0-0 17-06-18
!status work item 16-08-18
!status received 16-07-29
!priority Low
!difficulty Easy
!subject Missing operations of static string types
!summary
Relational operators and type conversions of static string types are now static.
!problem
The general model for static predicates is that if you replace the current instance with a static expression, then the whole predicate expression would end up static (see discussion in AI05-0153-3: " ... Every predicate-static expression necessarily has the property that if you plug in a static expression in place of every occurrence of the current instance, you get a static expression. ... "). However, for string subtypes, this model breaks down. As currently defined, a static predicate for a string can use relational operators on strings (RM 3.2.4(19/3)), whereas a static expression on strings cannot, because the corresponding operators are not "static functions" (RM 4.9(19)).
Now that we have static membership tests for strings (e.g. S in "abc" -- RM 4.9(11/4)) it seems odd to not permit static equality tests for strings (e.g. S = "abc"). We should be extending static functions to include relational operators on strings.
!proposal
(See Summary.)
!wording
Add after AARM 4.9(1.d):
Reason: We support static string expressions so that, for example, the aspect_definition for a Link_Name aspect can contain a concatenation. We don't support static aggregates (even for string types) or non-string static nonscalar types; we're trying to keep it cheap and simple (from the implementer's viewpoint).
[Editor's note: Most of this was moved from 4.9(24.b), which was mainly about the (now deleted) length limit. The remainder is more general text that should be at the start. Note that this text admits that static strings are really a hack; this AI makes them a little bit less hacky, but there seems to be little reason that (say) an array of scalar couldn't also be static.]
Modify 4.9(9):
* a type_conversion whose subtype_mark denotes a static
[scalar]{@Redundant[(scalar or string)]} subtype, and whose operand is a static expression;
Add after 4.9(19):
* a predefined relational operator whose parameters are of a string type
that is not a descendant of a formal array type;
Modify 4.9(20):
* a predefined concatenation operator whose result type is a string type
{that is not a descendant of a formal array type};
[Editor's note: A formal array type can be a string type (it can be one-dimensional with a character type as a component), and since we don't allow predefined operators of formal scalar types, it seems that we need the matching case for formal string types. Why we'd allow that for formal string types and not for formal scalar types is beyond me, so I consider it an omission and fixed the concatenation rule.]
Modify 4.9(24):
A static constant is a constant view declared by a full constant declaration or an object_renaming_declaration with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression[ whose value has a length not exceeding the maximum length of a string_literal in the implementation].
Delete AARM 4.9(24.b/3 and 24.c).
!discussion
There are three items where static strings have limited capabilities compared to static scalar types: operators, type conversions, and literals (aggregates). It's not clear why any of these were excluded originally -- perhaps the entire static string capability was more a hack than a designed feature. (This interpretation is backed up by 4.(24.b), which says that the feature was intended to be "cheap and simple".)
The problem covered the uses for operators. Type conversions can be useful if a bounds change or a representation change is needed. A string literal is supposed to be equivalent to a positional array aggregate, but the aggregate is not static while the literal is.
We make changes to cover the first two cases. The wording needed to allow aggregates seems extensive and complex, so we don't bother. (Static strings still is a hack. ;-)
Note that for a type conversion, it might be necessary to change the representation of the components (if the compiler uses the final representation for the components in the internal static representation). This operation is similar to the one needed to process string literals, so it shouldn't provide an implementation hardship.
We also remove the length limit for static strings. This limit bizarrely only applied to constant declarations; a string of concatenated static strings could exceed this limit without error. Thus, compilers have to support storing "giant strings" (as AARM 4.9(24.b/3) justifies the limit), at least momentarily, and it's hard to imagine that this limit saves much if any implementation effort. It mainly provides a "road hazard" making code illegal mysteriously, so we eliminate it.
!corrigendum 4.9(9)
Replace the paragraph:
by:
!corrigendum 4.9(19)
Insert after the paragraph:
the new paragraph:
!corrigendum 4.9(20)
Replace the paragraph:
by:
!corrigendum 4.9(24)
Replace the paragraph:
A static constant is a constant view declared by a full constant declaration or an object_renaming_declaration with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression whose value has a length not exceeding the maximum length of a string_literal in the implementation.
by:
A static constant is a constant view declared by a full constant declaration or an object_renaming_declaration with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression.
!ASIS
No ASIS effect.
!ACATS test
An ACATS C-Test is needed to check that the new capabilities are supported.
!appendix

From: Tucker Taft
Sent: Friday, July 29, 2016  8:07 AM

The general model for static predicates is that if you replace the current
instance with a static expression, then the whole predicate expression would end
up static (see discussion in AI05-0153-3: " ... Every predicate-static
expression necessarily has the property that if you plug in a static expression
in place of every occurrence of the current instance, you get a static
expression. ... ").  However, for string subtypes, this model breaks down.  As
currently defined, a static predicate for a string can use relational operators
on strings (RM 3.2.4(19/3)), whereas a static expression on strings cannot,
because the corresponding operators are not "static functions" (RM 4.9(19)).

We could leave this inconsistency as is, or we could fix this two different
ways:

   1) Disallow string relational operators in static predicates
   2) Allow string relational operators in static expressions (presumably by
      enlarging the definition of "static function" a bit)

Now that we have static membership tests for strings (e.g. S in "abc" -- RM
4.9(11/4)) it seems odd to not permit static equality tests for strings (e.g. S
= "abc").  So I would recommend extending static functions to include relational
operators on strings.

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

From: Tullio Vardanega
Sent: Monday, August 1, 2016  5:25 AM

I second.

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

From: Randy Brukardt
Sent: Monday, August 1, 2016  4:12 PM

For what it's worth, that was one of the reasons that my attempted extension of
staticness to user-defined types didn't work out very well. The intent was to
replace "static string subtype" with "potentially static subtype", but the fact
that various operations that have no reason not to be static weren't included
(like relational operations) turned the idea into a huge bunch of changes.

In addition to relational operators, type conversions and aggregates aren't
allowed as static for strings. For type conversions, 4.9(9) explicitly only
mentions static scalar subtypes. Why the difference? There doesn't seem to be
any difficulty in supporting that. As for aggregates, I presume the reason that
they weren't allowed was simply a lack of need; but it's a wart as usually
string literals are just a short-hand for a positional array aggregate.

I'd suggest at least including type conversions along with relational operators.
Aggregates are probably more work than they are worth (in the absence of the
generalization I was previously proposing).

You can find my original write-up of my proposed extension to staticness in
AI12-0175-1/01 (make sure you look at version /01; the final AI is very
different). The link is:
http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0175-1.txt?rev=1.2 Not
sure that there is anything else useful there, but I *did* already consider
these issues, it might help to avoid reinventing the wheel.

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

From: Randy Brukardt
Sent: Thursday, August 18, 2016  11:25 PM

> Now that we have static membership tests for strings (e.g. S in "abc" 
> -- RM 4.9(11/4)) it seems odd to not permit static equality tests for 
> strings (e.g. S = "abc").

Attached is the AI I wrote for this thread [this is version /01 of the AI -
Editor]; I'm posting it just in case Tucker gets ambitious -- I'd hate for
him to repeat my work.

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

From: Jeff Cousins
Sent: Tuesday, August 23, 2016  9:30 AM

Looks an ok write-up to me, thanks Randy,

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

From: Jeff Cousins
Sent: Monday, September 5, 2016  8:15 AM

I'm probably going to regret asking this, but...

Whilst we're on the subject of static-ness, what was the background behind
only scalars and strings being static, and no other composites?

It has long confused users that code such as:

package Pure_Test1 is

   pragma Pure;

   type Node_Array_Type is array (0..63) of Boolean;

   type Node_Array_Record_Type is record
      Node_Array : Node_Array_Type;
   end record;

   Null_Node_Array_Record : constant Node_Array_Record_Type := (Node_Array => (others => False));

end Pure_Test1;

is valid, but not:

package Pure_Test2 is

   pragma Pure;

   type Node_Array_Type is array (0..63) of Boolean;

   Null_Node_Array : constant Node_Array_Type := (others => False);

   type Node_Array_Record_Type is record
      Node_Array : Node_Array_Type;
   end record;

   Null_Node_Array_Record : constant Node_Array_Record_Type := (Node_Array => Null_Node_Array);

end Pure_Test2;

even though it is generally preferred to use named objects and types rather
than anonymous ones.

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

From: Bob Duff
Sent: Monday, September 5, 2016  10:42 AM

> Whilst we're on the subject of static-ness, what was the background 
> behind only scalars and strings being static, and no other composites?

Ada 83 was scalars only.  We added static strings in Ada 95 to support pragmas
that need them (link names and so forth).

And there's a 200 character limit, so it's not a fully general feature.

I think concerns were ease of implementation, and ease of efficient
implementation (particular memory use at compile time).

In your example, I'd probably give up on pragma Pure, rather than give up on
the named constant.  I agree it's a bit annoying to have to give up one or the
other.

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

From: Jeff Cousins
Sent: Monday, September 5, 2016  10:54 AM

Thanks Bob.

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


Questions? Ask the ACAA Technical Agent