CVS difference for ais/ai-00186.txt

Differences between 1.3 and version 1.4
Log of other versions for file ais/ai-00186.txt

--- ais/ai-00186.txt	2004/04/06 19:56:56	1.3
+++ ais/ai-00186.txt	2004/04/06 22:31:52	1.4
@@ -1,4 +1,4 @@
-!standard 03.05.04 (14)                               04-03-23  AI95-00186/03
+!standard 03.05.04 (14)                               04-04-01  AI95-00186/04
 !standard 03.04 (9)
 !class binding interpretation 99-03-21
 !status work item 97-03-19
@@ -9,11 +9,12 @@
-An implementation may support integer or modular types which include
-values outside the range System.Min_Int..System.Max_Int. In some cases
-evaluation of a non-static root_integer expression outside this range is
-required not to raise an exception. In most other such cases, the behavior
-is defined to be implementation dependent.
+The base range of root_integer is extended to include extra positive values
+corresponding to modulartypes.  The evaluation of expressions of type
+root_integer is defined to be a bounded error in some cases where an
+implementation cannot possibly find a type to perform the evaluation at run-
+time. In other cases, such an evaluation is safe and portable, even in generics
+with formal discrete types.
@@ -34,109 +35,113 @@
-If an implementation supports a modular type whose range exceeds
-0..System.Max_Int, or a nonstandard integer type with values outside
-System.Min_Int..System.Max_Int, non-static expressions which involve only
-variables, constants, and attributes of the a type T or its subtypes, or
-numeric_literals and other values of type root_integer may only raise
-Constraint_Error if the process of evaluating the expression exceeds the
-range of type T.
-If a non-static expression contains arithmetic operators of type root_real,
-it is implementation defined whether or not Constraint_Error will be raised
-if the result is outside the range of root_real, even if the result of the
-expression is within the range of the target type.
-Let T be an integer or modular type which has values outside the range
-System.Min_Int..System.Max_Int. If a non-static expression of type
-root_integer has both an attribute, variable or result of type T and an
-attribute, variable or result of some other type, it is erroneous for the
-value of the expression to exceed the range of root_integer.
+The base range of root_integer shall include at least System.Min_Int .. M where
+M is the maximum of System.Max_Int and System.Max_Nonbinary_Modulus - 1.
-An implementation is allowed to choose a range for root_real that exceeds
+Let T be a discrete type. It is a bounded error to evaluate an expression of
+type root_integer if it contains simple_expressions of types T or T'Base
+   o all simple_expressions of a discrete type are of types T, T'Base or
+     universal_integer; and
+   o all subexpressions of type universal_integer or root_integer, as well as
+     the result of applying the T'Pos attribute to all subexpressions of types
+     T or T'Base, belong to the range:
+      o System.Min_Int .. System.Max_Int if T is a signed integer type; or
+      o 0 .. System.Max_Nonbinary_Modulus - 1 if T is an enumeration or a
+        modular type.
+The possible outcomes are that the expression is evaluated correctly,
+Constraint_Error is raised, or Program_Error is raised.
+<<Author's note: for enumeration types, the above rules work well in the absence
+of an enumeration representation clause.  However, if there is a clause that
+gives negative representations for some literals, using a modular type for
+internal computations won't work.  Do we care?  I want to make sure that
+Wide_Wide_Character works, but enumeration representation clauses for huge
+enumeration types are not too exciting.>>
-The second sentence of paragraph 3.4(9) should read:
+See !recommendation.  I'll write the words if we agree on the intent.
-"For a scalar type {declared by a derived_type_definition}, the
-base range of the derived type is the same as that of the parent type."
-Paragraph 3.5.4(14) should read:
-"A type defined by an integer_type_definition is implicitly derived
-from _root_integer_, an anonymous predefined (specific) integer type,
-whose base range is {at least} System.Min_Int..System.Max_Int. However,
-the base range of the new type is not inherited from root_integer, but is
-instead determined by the range or modulus specified by the
-integer_type_definition. Integer literals are all of the type
-_universal_integer_, the universal type (see 3.4.1) for the class rooted at
-_root_integer_, allowing thier use with the operations of any integer type."
-The first wording change above is just to eliminate an apparent conflict in
-the standard. The second sentence of 3.5.4(14) is correct, but since all
-integer types are derived types, the paragraphs conflict.
-The main problem dealt with here is caused by the preference rule (see
-8.6(29)) for root_integer. In theory this can cause expressions which
-appear to involve only operations of of one numeric type to actually be
-evaluated using the operations of root_integer. Consider for instance the
-expression T'Val(T'Pos(X) - 3) where X is of type T.
-Although all the values in the expression are of either type T or
-universal_integer, the subtraction operation is that of root_integer.
-This seems irksome, but unlikely to occur even inside a generic with a
-formal of a discrete type. However, there are more troubling cases.
-Consider the Boolean expression S'Modulus > T'Modulus, where S and T are
-modular subtypes. When is this illegal, guaranteed to work, or can
-possibly raise Constraint_Error?  If the answer depends on the staticness
-of the subtypes, that way lies madness. (Note that in this particular
-case, the expression can always be evaluated at compile time even if the
-subtypes are static or generic formal subtypes.)
-Even more troubling is this case:
-type Modular is mod System.Max_Binary_Modulus;
-subtype Mod is Modular range...;
-Base_Modulus: constant := Mod'Modulus;
-Does this or should this raise Constraint_Error, or is it implementation
-dependent? (It is implementation dependent if the subtype is non-static.)
-Now let's look at the other side for a minute. There are some truly ugly
-cases such as  X: Integer := Modular'Pos(Y) + Integer'Pos(Z); where Y and Z
-are variables of the respective types. Here we have an expression that can
-only be evaluated at run-time, and possibly no machine arithmetic types
-that can be used safely, assuming that Integer and Modular are the largest
-available integer and modular types respectively.
-The conclusion is that implementations should always be allowed to "do the
-right thing" in the reasonable cases, and required not to raise
-Constraint_Error in expressions without attributes of a single type but no
-arithmetic operations. But rather than force implementations not to
-provide otherwise useful types by requiring support of some pathological
-cases, these case are made erroneous. It would be possible to make these
-cases a bounded error, but such mixed expressions can (and should) always
-be rewritten to make explicit which operations should be modular and where
-overflow is wanted. By making such expressions erroneous only if they
-exceed the range of root_integer, programmers can still use such
-expressions if they know the possible ranges of all intermediate results.
-Finally this AI allows the range of root_integer to exceed
-System.Min_Int..System.Max_Int. There is no point in allowing nonstandard
-integer types if the implementations are then restricted from using them
-where appropriate. For example, on a machine with a double-width
-multiplication result and easy addition and subtraction for such values, it
-would be useful to have that type as a nonstandard integer type, even if
-some multiplication operators were not provided, and you couldn't use it
-for indexing. It would be silly to prohibit using that type for evaluating
-expressions of type root_real. Where possible this is the best solution to
-the problem.
+The main problem dealt with in this is that, because of the preference rule for
+root_integer (8.6(29)) some expressions are evaluated at run-time using
+root_integer. But in practice there is no good choice of range for root_integer
+because it would ideally have to cover three ranges:
+	System.Min_Int .. System.Max_Int       -- For signed integer types.
+	0 .. System.Max_Binary_Modulus - 1     -- For binary modular types.
+	0 .. System.Max_Nonbinary_Modulus - 1  -- For nonbinary modular types.
+On a typical 32-bit machine, these ranges might be:
+	-2 ** 31 .. 2 ** 31 - 1
+	0 .. 2 ** 32 - 1
+	0 .. 2 ** 32 - 2
+It is clear that a 33-bit integer would be needed to cover their union.  And
+even such a type would not be able to represent T'Modulus for the largest
+modular type. At any rate, we don't want to require implementations to have to
+do multiple precision in the root_integer arithmetic.
+What we are doing here is essentially to specify circumstances under which an
+implementation is _not_ allowed to raise Constraint_Error during evaluation of
+an expression of type root_integer. This is phrased in terms of a bounded
+error, because we want implementations to be able to detect anomalies by raising
+an exception, or to do the correct evaluation, but we don't want to allow it to
+go berserk. So this is not an erroneous situation.
+From the user's perspective, this AI guarantees that there is a class of
+expressions which can always be evaluated safely (i.e., without raising an
+exception) and portably, even in a generic with a formal discrete type. The
+expression mentioned in the question is an example of this case. On the other
+hand, evaluating the expression:
+	T'Modulus > 3
+is a bounded error if T is the largest modular type because T'Modulus cannot in
+general be represented using root_integer.  On the other hand, the expression:
+	T'Last >= 3
+is safe.
+The restriction on the expressions are intended to make it possible to evaluate
+expressions of type root_integer using the largest signed integer type (if T is
+signed) or the largest unsigned integer type (if T is modular or enumeration).
+The rules ensure that an implementation doesn't have to handle expressions
+involving mixed discrete types, as in:
+	Signed_Int'Pos (Signed_Int'First) + Unsigned_Int'Pos (Unsigned_Int'Last)
+because such expressions could require multiple precision. An implementation
+could just recognize this situation (at compile-time) and raise Program_Error.
+Or it could use a signed integer and raise Constraint_Error on the conversion
+of Unsigned_Int'Last.
+For macro-expanded generics, the nature of actual types is always known in an
+instance, so it should be straightforward to generate signed or unsigned
+arithmetic as needed. For shared generics the situation is a bit more
+complicated (as usual) but a possible implementation technique is to generate
+both signed and unsigned code, and select the appropriate code based on the
+nature of the type.
+Finally this AI revises the base range of root_integer. It is clear that we
+want to allow extra positive values to support modular and enumeration types,
+so the range System.Min_Int .. System.Max_Int is too restrictive.  root_integer
+must include all the values up to System.Max_Nonbinary_Modulus - 1.
+Also, the base range of root_integer is not prevented from containing extra
+(negative or positive) values, to help support nonstandard integer types. There
+is no point in allowing nonstandard integer types if the implementations are
+then restricted from using them for root_integer computations. There might of
+course be implementation-defined restrictions in the case, but the language
+should not get in the way.
 !ACATS Test

Questions? Ask the ACAA Technical Agent