3.5.5 Operations of Discrete Types
Static Semantics
For every discrete
subtype S, the following attributes are defined:
S'Pos
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
S'Val denotes a function with
the following specification:
function S'Val(Arg : universal_integer)
return S'Base
This
function returns a value of the type of S whose position number equals
the value of
Arg.
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.
{
AI05-0297-1}
For every static discrete subtype S for which there
exists at least one value belonging to S that satisfies any predicate
of S, the following attributes are defined:
S'First_Valid
{
AI05-0297-1}
S'First_Valid denotes
the smallest value that belongs to S and satisfies the predicate of S.
The value of this attribute is of the type of S.
S'Last_Valid
{
AI05-0297-1}
S'Last_Valid denotes
the largest value that belongs to S and satisfies the predicate of S.
The value of this attribute is of the type of S.
{
AI05-0297-1}
[First_Valid and Last_Valid attribute_references
are always static expressions. Any explicit predicate of S can only have
been specified by a Static_Predicate aspect.]
Proof: An attribute_reference
is static if the prefix is a static subtype (see 4.9),
(true by definition) and any arguments are static (there are none). Similarly,
a dynamic predicate always makes a subtype nonstatic. QED.
Reason: We require
there to be at least one value so that these are always values of the
subtype. (This sidesteps the question of what to return for a subtype
with no values.)
Discussion: These
attributes are intended primarily for use in the case where the Static_Predicate
aspect of S has been specified; First and Last are equivalent if these
are allowed and there is no predicate.
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.
This
is particularly important for enumeration types with noncontiguous internal
codes specified by an
enumeration_representation_clause.
Implementation Advice:
Program_Error should be raised for the
evaluation of S'Pos for an enumeration type, if the value of the operand
does not correspond to the internal code for any enumeration literal
of the type.
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.)
33 Indexing and loop iteration use values
of discrete types.
34 {
AI05-0299-1}
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
Clause Section
4.
35 As for all types, objects of a discrete
type have Size and Address attributes (see
13.3).
36 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
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
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”).
Extensions to Ada 2005
{
AI05-0297-1}
The attributes S'First_Valid
and S'Last_Valid are new.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe