Contents   Index   Search   Previous   Next

3.5.5 Operations of Discrete Types

Static Semantics

   For every discrete subtype S, the following attributes are defined:
S'Pos denotes a function with the following specification:
function S'Pos(Arg : S'Base)
  return universal_integer
This function returns the position number of the value of Arg, as a value of type universal_integer.
S'Val denotes a function with the following specification:
function S'Val(Arg : universal_integer)
  return S'Base
{evaluation (Val) [partial]} {Constraint_Error (raised by failure of run-time check)} This function returns a value of the type of S whose position number equals the value of Arg. {Range_Check [partial]} {check, language-defined (Range_Check)} For the evaluation of a call on S'Val, if there is no value in the base range of its type with the given position number, Constraint_Error is raised.
Ramification: By the overload resolution rules, a formal parameter of type universal_integer allows an actual parameter of any integer type.
Reason: We considered allowing S'Val for a signed integer subtype S to return an out-of-range value, but since checks were required for enumeration and modular types anyway, the allowance didn't seem worth the complexity of the rule.

Implementation Advice

   For the evaluation of a call on S'Pos for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type [(perhaps due to an uninitialized variable)], then the implementation should raise Program_Error. {Program_Error (raised by failure of run-time check)} This is particularly important for enumeration types with noncontiguous internal codes specified by an enumeration_representation_clause.
Reason: We say Program_Error here, rather than Constraint_Error, because the main reason for such values is uninitialized variables, and the normal way to indicate such a use (if detected) is to raise Program_Error. (Other reasons would involve the misuse of low-level features such as Unchecked_Conversion.)
28  Indexing and loop iteration use values of discrete types.
29  {predefined operations (of a discrete type) [partial]} The predefined operations of a discrete type include the assignment operation, qualification, the membership tests, and the relational operators; for a boolean type they include the short-circuit control forms and the logical operators; for an integer type they include type conversion to and from other numeric types, as well as the binary and unary adding operators - and +, the multiplying operators, the unary operator abs, and the exponentiation operator. The assignment operation is described in 5.2. The other predefined operations are described in Section 4.
30  As for all types, objects of a discrete type have Size and Address attributes (see 13.3).
31  For a subtype of a discrete type, the result delivered by the attribute Val might not belong to the subtype; similarly, the actual parameter of the attribute Pos need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes:
   S'Val(S'Pos(X)) = X
   S'Pos(S'Val(N)) = N


    Examples of attributes of discrete subtypes:
--  For the types and subtypes declared in subclause 3.5.1 the following hold: 
--  Color'First   = White,   Color'Last   = Black
--  Rainbow'First = Red,     Rainbow'Last = Blue
--  Color'Succ(Blue) = Rainbow'Succ(Blue) = Brown
--  Color'Pos(Blue)  = Rainbow'Pos(Blue)  = 4
--  Color'Val(0)     = Rainbow'Val(0)     = White

Extensions to Ada 83

{extensions to Ada 83} The attributes S'Succ, S'Pred, S'Width, S'Image, and S'Value have been generalized to apply to real types as well (see 3.5, ``Scalar Types'').

Contents   Index   Search   Previous   Next   Legal