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

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

!standard A.19(4/3)          12-12-28 AI12-0037-1/02
!class binding interpretation 12-11-29
!status Amendment 202x 12-12-28
!status ARG Approved 7-0-3 12-12-07
!status work item 12-11-29
!status received 12-08-06
!priority Low
!difficulty Easy
!subject New types in Ada.Locales can't be converted to/from strings
!summary
Types Ada.Locales.Language_Code and Ada.Locales.Country_Code should be derived from type String.
!question
It is difficult to output objects of type Ada.Locales.Language_Code or Ada.Locales.Country_Code; you can't give them to Text_IO.Put because their type isn't String, but you also can't convert them to String because they run afoul of 4.6(24.5/2) which requires that component subtypes must statically match.
Should some change be made in order to make this easier? (Yes.)
!recommendation
(See summary.)
!wording
Replace A.19(4/3) with:
type Language_Code is new String(1 .. 3) with Dynamic_Predicate => (for all E of Language_Code => E in 'a' .. 'z'); type Country_Code is new String(1 .. 2) with Dynamic_Predicate => (for all E of Country_Code => E in 'A' .. 'Z');
Add an AARM note following:
These types are declared as derived from type String so that they can easily be converted to or from type String. That's important if one of these values needs to be input or displayed (via Text_IO, perhaps). We use the predicate to ensure that only possible component values are used. Ada does not allow converting between unrelated types with components that don't statically match, so We cannot declare new types with constrained components if we want conversions to or from type String.
!discussion
The use of a predicate rather than constrained component subtypes means that this change is inconsistent with the original Ada 2012 definition - the exception raised on failure is changed. We don't consider that important as it is unlikely that users will construct these values and when they do, it is highly unlikely that they would handle any resulting exception (which would represent a bug).
We could have used a raise_expression as described in AI12-0022-1 to avoid this inconsistency, but the exception raised wasn't considered important enough to use the extra machinery. (We also avoid the problem addressed by AI12-0054-1 by using this formulation; any technique for raising Constraint_Error would suffer from that problem.)
The predicate could have been written in a number of other ways; this one doesn't depend explicitly on the bounds of the subtypes, so it is preferred. Of course, an implementation can replace this by anything equivalent if that will provide better performance.
!corrigendum A.19(4/3)
Replace the paragraph:
type Language_Code is array (1 .. 3) of Character range 'a' .. 'z'; type Country_Code is array (1 .. 2) of Character range 'A' .. 'Z';
by:
type Language_Code is new String(1 .. 3) with Dynamic_Predicate =
(for all E of Language_Code => E in 'a' .. 'z'); type Country_Code is new String(1 .. 3) with Dynamic_Predicate => (for all E of Country_Code => E in 'A' .. 'Z');>
!ACATS test
An ACATS C-Test should be created to test that Language_Codes and Country_Codes can be converted to type String for output via Put_Line.
!appendix

!topic New types in Ada.Locales can't be converted to/from strings
!reference A.19
!from Adam Beneschan 12-08-06
!discussion

It was just pointed out on comp.lang.ada that it is difficult to
output objects of type Language_Code or Country_Code; you can't give
them to Text_IO.Put because their type isn't String, but you also
can't convert them to String because they run afoul of 4.6(24.5/2)
which requires that component subtypes must statically match.

Assuming that it's desirable to keep the range constraint on the
component subtype, I'd suggest adding To_String and From_String
functions to Ada.Locales:

   function To_String (C : Language_Code) return String;
   function To_String (C : Country_Code) return String;

   function From_String (S : String) return Language_Code;
   function From_String (S : String) return Country_Code;

with From_String raising Constraint_Error if S has the wrong length or
any character in S is out of range.

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

From: Randy Brukardt
Sent: Thursday, August 9, 2012  6:08 PM

That's the "easy" solution, but it seems very, very strange that you
can't do these conversions directly (surely you would expect to be able
to do so).

I'd suggest changing to a rule where the component types still have to
be the same, but the constraints get rechecked (possibly requiring a
loop). That would not require making a copy of the array (other than
in cases where it is already required to do so, that is, when the component
sizes are different), but would give more flexibility for cases like this.

Alternatively, we could only require convertability for elementary types
(I'd be dubious of expanding that for composite types), and let copies be
required sometimes. (Compilers probably already can make such copies,
because of the component size difference cases.)

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

Editor's note: This solution was suggested by Bob Duff in private mail.
He deserves credit (or blame!) for this clever idea.

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

Questions? Ask the ACAA Technical Agent