Version 1.3 of ai12s/ai12-0295-1.txt

Unformatted version of ai12s/ai12-0295-1.txt version 1.3
Other versions for file ai12s/ai12-0295-1.txt

!standard 4.2(6)          19-03-19 AI12-0295-1/03
!standard 4.2(10)
!standard 4.2(11)
!standard 3.6.3(1)
!standard 4.2.1(0)
!standard 4.9(26/3)
!class Amendment 18-01-22
!status Amendment 1-2012 18-11-29
!status ARG Approved 6-0-4 18-10-22
!status work item 18-01-22
!status received 15-03-20
!priority Low
!difficulty Medium
!subject User-defined string literals
!summary
A mechanism for giving a user-defined meaning to string literals is added to Ada.
!problem
AI12-0249-1 provides a mechanism to use user-defined numeric literals. These bring the advantages of numeric literals to abstract data types such as bignums.
However, string literals are just as useful as numeric literals. These would be useful for abstract data types for similar reasons as numeric literals. String abstractions like unbounded strings could have been substantially simplified had literals been available when they were defined. In addition, literals are always directly visible, which simplifies the use of ADTs for which they would be appropriate.
!proposal
Aspects will be defined to allow (lexical) string literals to be defined to be used with a (non-string) type. The aspect identifies a subprogram to be used to interpret the literal as a value of the type.
String literals already rely on there being a single expected type (see RM 4.2). Interestingly, you don't have to look "inside" a string literal until after you know its type.
Since no types currently have Literal aspects, there is no immediate upward compatibility issue. However, if we decide to add Literal aspects to any existing language-defined types (such as Unbounded_String), we will be potentially creating ambiguities.
We need to decide how to represent the literals, and how to convert them. For string literals, we have Wide_Wide_Strings, so this represents "universal" representations which can accommodate any character set known in the universe. So long as all conversions of literals are propagated to a library-unit elaboration procedure for library-level types, and to the point of declaration of the type for nested types, the overhead of converting literals can be kept manageable.
This proposal builds on the one made in AI12-0249-1.
!wording
Modify paragraph 3.6.3(1):
A one-dimensional array type whose component type is a character type is called a /string/ type{, as is a type with a specified String_Literal aspect (see 4.2.1)}.
Modify paragraph 4.2(6)
{If the expected type for a string_literal is a one-dimensional array type with a component type that is an enumeration type, then} [F]{f}or each character of [a]{the} string_literal [with a given expected string type,] there shall be a corresponding defining_character_literal of the [component type of the expected string type]{enumeration type}.
Modify paragraph 4.2(10):
The evaluation of a string_literal that is a primary {and has an expected type that is a one-dimensional array type with a character type as its component type,} yields an array value containing the value of each character of the sequence of characters of the string_literal, as defined in 2.6. The bounds of this array value are determined according to the rules for positional_array_aggregates (see 4.3.3), except that for a null string literal, the upper bound is the predecessor of the lower bound.
Modify paragraph 4.2(11):
For the evaluation of a string_literal of type T, {if T is a one-dimensional array type with a component subtype that is a constrained subtype of a character type,} a check is made that the value of each character of the string_literal belongs to the component subtype of T. For the evaluation of a null string literal, a check is made that its lower bound is greater than the lower bound of the base range of the index type. The exception Constraint_Error is raised if either of these checks fails.
Add after 4.2.1(4/5): [As defined in AI12-0249-1]
String_Literal
This aspect is specified by a /function_/name that denotes a primitive function of T with one parameter of type Wide_Wide_String and a result type of T.
[Redundant: A type with a specified String_Literal aspect is considered a /string/ type.]
Add to 4.2.1(5/5) before the last sentence:
The String_Literal aspect shall not be specified for a type T if the full view of T is a string type (in the absence of the String_Literal aspect specification).
Add after 4.2.1(6/5):
For the evaluation of a string_literal with expected type having a String_Literal aspect specified, the value is the result of a call on the function specified by the aspect, with the parameter being a Wide_Wide_String with lower bound one that corresponds to the literal.
Modify 4.9(26/3):
A static subtype is either a static scalar subtype or a static string subtype. A static scalar subtype is an unconstrained scalar subtype whose type is not a descendant of a formal type, or a constrained scalar subtype formed by imposing a compatible static constraint on a static scalar subtype. A static string subtype is {a string subtype that does not have a specified String_Literal aspect, and that is} an unconstrained [string]{array} subtype whose index subtype and component subtype are static, or a constrained [string]{array} subtype formed by imposing a compatible static constraint on a static string subtype. In any case, the subtype of a generic formal object of mode in out, and the result subtype of a generic formal function, are not static. Also, a subtype is not static if any Dynamic_Predicate specifications apply to it.
!discussion
The !proposal section includes a relatively complete discussion of the issues. But here are a few other interesting questions or issues:
* We do not want to have a situation where a literal may be usable on a
partial view but not on the full view, for example, because the full view is a type that already has meaning for the same sort of literal. This avoids problems with full conformance checking when the meaning of a literal might be different in the visible and private parts of a package.
* More generally, we chose to allow user-defined literals on almost
any sort of type, so long as that sort of type didn't already allow that sort of literal. The thought was that you could imagine a floating point type that would allow the use of string literals for certain special values like "NaN" or "+inf".
* We have decided not to use this feature for existing language-defined
packages (such as Unbounded_Strings). We believe it would be safer to define (in some future standard) a new package and move the original Unbounded_Strings package to Annex J.
!examples
type Varying_String is private with String_Literal => To_Varying_String;
function To_Varying_String (Source : Wide_Wide_String) return Varying_String;
...
X : constant Varying_String := "This is a test"; -- Equivalent to: -- X : constant Varying_String := -- To_Varying_String -- (Wide_Wide_String'("This is a test"));
!comment AI12-0325-1 undoes the change to 3.6.3(1), so it cannot appear here.
!corrigendum 4.2(6)
Replace the paragraph:
For each character of a string_literal with a given expected string type, there shall be a corresponding defining_character_literal of the component type of the expected string type.
by:
If the expected type for a string_literal is a one-dimensional array type with a component type that is an enumeration type, then for each character of the string_literal there shall be a corresponding defining_character_literal of the enumeration type.
!corrigendum 4.2(10)
Replace the paragraph:
The evaluation of a string_literal that is a primary yields an array value containing the value of each character of the sequence of characters of the string_literal, as defined in 2.6. The bounds of this array value are determined according to the rules for positional_array_aggregates (see 4.3.3), except that for a null string literal, the upper bound is the predecessor of the lower bound.
by:
The evaluation of a string_literal that is a primary and has an expected type that is a one-dimensional array type with a character type as its component type, yields an array value containing the value of each character of the sequence of characters of the string_literal, as defined in 2.6. The bounds of this array value are determined according to the rules for positional_array_aggregates (see 4.3.3), except that for a null string literal, the upper bound is the predecessor of the lower bound.
!corrigendum 4.2(11)
Replace the paragraph:
For the evaluation of a string_literal of type T, a check is made that the value of each character of the string_literal belongs to the component subtype of T. For the evaluation of a null string literal, a check is made that its lower bound is greater than the lower bound of the base range of the index type. The exception Constraint_Error is raised if either of these checks fails.
by:
For the evaluation of a string_literal of type T, if T is a one-dimensional array type with a component subtype that is a constrained subtype of a character type, a check is made that the value of each character of the string_literal belongs to the component subtype of T. For the evaluation of a null string literal, a check is made that its lower bound is greater than the lower bound of the base range of the index type. The exception Constraint_Error is raised if either of these checks fails.
!corrigendum 4.2.1(0)
Insert new clause:
Just enough to cause a conflict; the real changes are in the conflict file.
!comment AI12-0325-1 undoes the change to 4.9(26/3), so it cannot appear here.
!ASIS
[Not sure. Might need new aspect names, but I didn't check - Editor.]
!ACATS test
ACATS B and C-Tests are needed to check that the new capabilities are supported, and that error cases are detected.
!appendix

[Editor's note: Split from AI12-0249-1 by vote at ARG meeting #60.]

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


Questions? Ask the ACAA Technical Agent