Contents Index Previous Next
3.5 Scalar Types
1
{scalar type} Scalar
types comprise enumeration types, integer types, and real types.
{discrete
type} Enumeration types and integer types
are called
discrete types;
{position number}
each value of a discrete type has a
position number
which is an integer value.
{numeric type}
Integer types and real types are called
numeric
types. [All scalar types are ordered, that is, all relational operators
are predefined for their values.]
Syntax
2
range_constraint
::= range range
3
range
::= range_attribute_reference
|
simple_expression ..
simple_expression
3.a
Discussion: These need
to be simple_expressions rather
than more general expressions because
ranges appear in membership tests and other contexts where expression
.. expression would be ambiguous.
4
{range} {lower
bound (of a range)} {upper
bound (of a range)} {type
of a range} A
range has a
lower
bound and an
upper bound and specifies a subset of the values
of some scalar type (the
type of the range). A range with lower
bound L and upper bound R is described by ``L .. R''.
{null
range} If R is less than L, then the range
is a
null range, and specifies an empty set of values. Otherwise,
the range specifies the values of the type from the lower bound to the
upper bound, inclusive.
{belong (to a range)}
A value
belongs to a range if it is of the
type of the range, and is in the subset of values specified by the range.
{satisfies (a range constraint) [partial]}
A value
satisfies a range constraint if it
belongs to the associated range.
{included (one range
in another)} One range is
included
in another if all values that belong to the first range also belong to
the second.
Name Resolution Rules
5
{expected type (range_constraint
range) [partial]} For a
subtype_indication
containing a
range_constraint, either
directly or as part of some other
scalar_constraint,
the type of the
range shall resolve
to that of the type determined by the
subtype_mark
of the
subtype_indication.
{expected
type (range simple_expressions) [partial]} For
a
range of a given type, the
simple_expressions
of the
range (likewise, the
simple_expressions
of the equivalent
range for a
range_attribute_reference)
are expected to be of the type of the
range.
5.a
Discussion: In Ada 95,
constraints only appear within subtype_indications;
things that look like constraints that appear in type declarations are
called something else like range_specifications.
5.b
We say "the expected type is ..."
or "the type is expected to be ..." depending on which reads better.
They are fundamentally equivalent, and both feed into the type resolution rules
of clause 8.6.
5.c
In some cases, it doesn't work to use expected
types. For example, in the above rule, we say that the ``type of the range
shall resolve to ...'' rather than ``the expected type for the range
is ...''. We then use ``expected type'' for the bounds. If we used ``expected''
at both points, there would be an ambiguity, since one could apply the rules
of 8.6 either on determining the type of the range,
or on determining the types of the individual bounds. It is clearly important
to allow one bound to be of a universal type, and the other of a specific type,
so we need to use ``expected type'' for the bounds. Hence, we used ``shall resolve
to'' for the type of the range as a whole. There are other situations where
``expected type'' is not quite right, and we use ``shall resolve to'' instead.
Static Semantics
6
{base range (of a scalar type)
[distributed]} The
base range of a
scalar type is the range of finite values of the type that can be represented
in every unconstrained object of the type; it is also the range supported
at a minimum for intermediate values during the evaluation of expressions
involving predefined operators of the type.
6.a
Implementation Note: Note
that in some machine architectures intermediates in an expression (particularly
if static), and register-resident variables might accommodate a wider
range. The base range does not include the values of this wider range
that are not assignable without overflow to memory-resident objects.
6.b
Ramification: {base
range (of an enumeration type) [partial]} The
base range of an enumeration type is the range of values of the enumeration
type.
6.c
Reason: If the representation
supports infinities, the base range is nevertheless restricted to include
only the representable finite values, so that 'Base'First and 'Base'Last
are always guaranteed to be finite.
6.d
To be honest: By a "value
that can be assigned without overflow" we don't mean to restrict
ourselves to values that can be represented exactly. Values between machine
representable values can be assigned, but on subsequent reading, a slightly
different value might be retrieved, as (partially) determined by the
number of digits of precision of the type.
7
{constrained (subtype)}
{unconstrained (subtype)}
[A constrained scalar subtype is one to which a range
constraint applies.]
{range (of a scalar subtype)}
The
range of a constrained scalar subtype
is the range associated with the range constraint of the subtype. The
range of an unconstrained scalar subtype is the base range of
its type.
Dynamic Semantics
8
{compatibility (range with a
scalar subtype) [partial]} A range is
compatible with a scalar subtype if and only if it is either a
null range or each bound of the range belongs to the range of the subtype.
{compatibility (range_constraint with a scalar subtype)
[partial]} A
range_constraint
is
compatible with a scalar subtype if and only if its range is
compatible with the subtype.
8.a
Ramification: Only range_constraints
(explicit or implicit) impose conditions on the values of a scalar subtype.
The other scalar_constraints, digit_constraints
and delta_constraints impose conditions
on the subtype denoted by the subtype_mark
in a subtype_indication, but don't
impose a condition on the values of the subtype being defined. Therefore,
a scalar subtype is not called constrained if all that applies
to it is a digits_constraint. Decimal
subtypes are subtle, because a digits_constraint
without a range_constraint nevertheless
includes an implicit range_constraint.
9
{elaboration (range_constraint)
[partial]} The elaboration of a
range_constraint
consists of the evaluation of the
range.
{evaluation (range) [partial]} The
evaluation of a
range determines
a lower bound and an upper bound. If
simple_expressions
are given to specify bounds, the evaluation of the
range
evaluates these
simple_expressions
in an arbitrary order, and converts them to the type of the
range.
{implicit subtype conversion (bounds of a range)
[partial]} If a
range_attribute_reference
is given, the evaluation of the
range
consists of the evaluation of the
range_attribute_reference.
10
Attributes
11
For every scalar
subtype S, the following attributes are defined:
12
- S'First
-
S'First denotes the lower bound
of the range of S. The value of this attribute is of the type of S.
12.a
Ramification: Evaluating
S'First never raises Constraint_Error.
13
- S'Last
-
S'Last denotes the upper bound
of the range of S. The value of this attribute is of the type of S.
13.a
Ramification: Evaluating
S'Last never raises Constraint_Error.
14
- S'Range
-
S'Range is equivalent to the
range S'First .. S'Last.
15
- S'Base
-
S'Base denotes an unconstrained
subtype of the type of S. This unconstrained subtype is called the base
subtype of the type. {base subtype (of a type)}
16
- S'Min
-
S'Min denotes a function with
the following specification:
17
function S'Min(Left, Right : S'Base)
return S'Base
18
- The function returns the lesser of the values of
the two parameters.
18.a
Discussion: {italics (formal
parameters of attribute functions)} The formal parameter
names are italicized because they cannot be used in calls -- see 6.4.
Such a specification cannot be written by the user because an attribute_reference
is not permitted as the designator of a user-defined function, nor can its formal
parameters be anonymous.
19
- S'Max
-
S'Max denotes a function with
the following specification:
20
function S'Max(Left, Right : S'Base)
return S'Base
21
- The function returns the greater of the values of
the two parameters.
22
- S'Succ
-
S'Succ denotes a function with
the following specification:
23
function S'Succ(Arg : S'Base)
return S'Base
24
- {Constraint_Error (raised by failure of
run-time check)} For an enumeration type, the
function returns the value whose position number is one more than that of
the value of Arg; {Range_Check [partial]}
{check, language-defined (Range_Check)}
Constraint_Error is raised if there is no such value of
the type. For an integer type, the function returns the result of adding one
to the value of Arg. For a fixed point type, the function returns the
result of adding small to the value of Arg. For a floating point
type, the function returns the machine number (as defined in 3.5.7)
immediately above the value of Arg; {Range_Check
[partial]} {check, language-defined
(Range_Check)} Constraint_Error is raised if
there is no such machine number.
24.a
Ramification: S'Succ for
a modular integer subtype wraps around if the value of Arg is
S'Base'Last. S'Succ for a signed integer subtype might raise Constraint_Error
if the value of Arg is S'Base'Last, or it might return the out-of-base-range
value S'Base'Last+1, as is permitted for all predefined numeric operations.
25
- S'Pred
-
S'Pred denotes a function with
the following specification:
26
function S'Pred(Arg : S'Base)
return S'Base
27
- {Constraint_Error (raised by failure of
run-time check)} For an enumeration type, the
function returns the value whose position number is one less than that of
the value of Arg; {Range_Check [partial]}
{check, language-defined (Range_Check)}
Constraint_Error is raised if there is no such value of
the type. For an integer type, the function returns the result of subtracting
one from the value of Arg. For a fixed point type, the function returns
the result of subtracting small from the value of Arg. For a
floating point type, the function returns the machine number (as defined in
3.5.7) immediately below the value of Arg;
{Range_Check [partial]} {check,
language-defined (Range_Check)} Constraint_Error
is raised if there is no such machine number.
27.a
Ramification: S'Pred for
a modular integer subtype wraps around if the value of Arg is
S'Base'First. S'Pred for a signed integer subtype might raise Constraint_Error
if the value of Arg is S'Base'First, or it might return the out-of-base-range
value S'Base'First-1, as is permitted for all predefined numeric operations.
28
- S'Wide_Image
-
S'Wide_Image denotes a function
with the following specification:
29
function S'Wide_Image(Arg : S'Base)
return Wide_String
30
- {image (of a value)}
The function returns an image of the value
of Arg, that is, a sequence of characters representing the value
in display form. The lower bound of the result is one.
31
- The image of an integer value is the corresponding
decimal literal, without underlines, leading zeros, exponent, or trailing
spaces, but with a single leading character that is either a minus sign
or a space.
31.a
Implementation Note: If
the machine supports negative zeros for signed integer types, it is not
specified whether "-0" or " 0" should be returned
for negative zero. We don't have enough experience with such machines
to know what is appropriate, and what other languages do. In any case,
the implementation should be consistent.
32
- {nongraphic character}
The image of an enumeration value is either the corresponding
identifier in upper case or the corresponding character literal (including
the two apostrophes); neither leading nor trailing spaces are included.
For a nongraphic character (a value of a character type that has
no enumeration literal associated with it), the result is a corresponding
language-defined or implementation-defined name in upper case (for example,
the image of the nongraphic character identified as nul is ``NUL''
-- the quotes are not part of the image).
32.a
Implementation Note: For
an enumeration type T that has ``holes'' (caused by an enumeration_representation_clause),
{Program_Error (raised by failure of run-time check)} T'Wide_Image
should raise Program_Error if the value is one of the holes (which is
a bounded error anyway, since holes can be generated only via uninitialized
variables and similar things.
33
- The image of a floating point value is a decimal real literal
best approximating the value (rounded away from zero if halfway between) with
a single leading character that is either a minus sign or a space, a single
digit (that is nonzero unless the value is zero), a decimal point, S'Digits-1
(see 3.5.8) digits after the decimal point (but
one if S'Digits is one), an upper case E, the sign of the exponent (either
+ or -), and two or more digits (with leading zeros if necessary) representing
the exponent. If S'Signed_Zeros is True, then the leading character is a minus
sign for a negatively signed zero.
33.a
To be honest: Leading zeros
are present in the exponent only if necessary to make the exponent at
least two digits.
33.b
Reason: This image is intended
to conform to that produced by Text_IO.Float_IO.Put in its default format.
33.c
Implementation Note: The
rounding direction is specified here to ensure portability of output
results.
34
- The image of a fixed point value is a decimal real literal
best approximating the value (rounded away from zero if halfway between) with
a single leading character that is either a minus sign or a space, one or
more digits before the decimal point (with no redundant leading zeros), a
decimal point, and S'Aft (see 3.5.10) digits
after the decimal point.
34.a
Reason: This image is intended
to conform to that produced by Text_IO.Fixed_IO.Put.
34.b
Implementation Note: The
rounding direction is specified here to ensure portability of output
results.
34.c
Implementation Note: For
a machine that supports negative zeros, it is not specified whether "-0.000"
or " 0.000" is returned. See corresponding comment above about
integer types with signed zeros.
35
- S'Image
-
S'Image denotes a function with
the following specification:
36
function S'Image(Arg : S'Base)
return String
37
- The function returns an image of the value of Arg
as a String. The lower bound of the result is one. The image has the
same sequence of graphic characters as that defined for S'Wide_Image
if all the graphic characters are defined in Character; otherwise the
sequence of characters is implementation defined (but no shorter than
that of S'Wide_Image for the same value of Arg).
37.a
Implementation defined: The
sequence of characters of the value returned by S'Image when some of
the graphic characters of S'Wide_Image are not defined in Character.
38
- S'Wide_Width
-
S'Wide_Width denotes the maximum
length of a Wide_String returned by S'Wide_Image over all values of the
subtype S. It denotes zero for a subtype that has a null range. Its type
is universal_integer.
39
- S'Width
-
S'Width denotes the maximum length
of a String returned by S'Image over all values of the subtype S. It
denotes zero for a subtype that has a null range. Its type is universal_integer.
40
- S'Wide_Value
-
S'Wide_Value denotes a function
with the following specification:
41
function S'Wide_Value(Arg : Wide_String)
return S'Base
42
- This function returns a value given an image of
the value as a Wide_String, ignoring any leading or trailing spaces.
43
- {evaluation (Wide_Value) [partial]}
{Constraint_Error (raised by failure
of run-time check)} For the evaluation
of a call on S'Wide_Value for an enumeration subtype S, if the sequence
of characters of the parameter (ignoring leading and trailing spaces)
has the syntax of an enumeration literal and if it corresponds to a literal
of the type of S (or corresponds to the result of S'Wide_Image for a
nongraphic character of the type), the result is the corresponding enumeration
value; {Range_Check [partial]} {check,
language-defined (Range_Check)} otherwise
Constraint_Error is raised.
43.a
Discussion: It's not crystal
clear that Range_Check is appropriate here, but it doesn't seem worthwhile
to invent a whole new check name just for this weird case, so we decided
to lump it in with Range_Check.
43.a.1/1
To be honest: {8652/0096}
A sequence of characters corresponds to the result of S'Wide_Image if it
is the same ignoring case. Thus, the case of an image of a nongraphic character
does not matter. For example, Character'Wide_Value("nul") does not
raise Constraint_Error, even though Character'Wide_Image returns "NUL"
for the nul character.
44
- {Constraint_Error (raised by failure
of run-time check)} For the evaluation
of a call on S'Wide_Value (or S'Value) for an integer subtype S, if the
sequence of characters of the parameter (ignoring leading and trailing
spaces) has the syntax of an integer literal, with an optional leading
sign character (plus or minus for a signed type; only plus for a modular
type), and the corresponding numeric value belongs to the base range
of the type of S, then that value is the result; {Range_Check
[partial]} {check, language-defined
(Range_Check)} otherwise Constraint_Error
is raised.
44.a
Discussion: We considered allowing
'Value to return a representable but out-of-range value without a Constraint_Error.
However, we currently require (see 4.9) in an assignment_statement
like "X := <numeric_literal>;" that the value of the numeric-literal
be in X's base range (at compile time), so it seems unfriendly and confusing
to have a different range allowed for 'Value. Furthermore, for modular types,
without the requirement for being in the base range, 'Value would have to handle
arbitrarily long literals (since overflow never occurs for modular types).
45
- For the evaluation of a call on S'Wide_Value (or
S'Value) for a real subtype S, if the sequence of characters of the parameter
(ignoring leading and trailing spaces) has the syntax of one of the following:
46
47
48
49
- base#based_numeral.#[exponent]
50
- base#.based_numeral#[exponent]
51
- {Constraint_Error (raised by failure
of run-time check)} with an optional leading
sign character (plus or minus), and if the corresponding numeric value
belongs to the base range of the type of S, then that value is the result;
{Range_Check [partial]} {check,
language-defined (Range_Check)} otherwise
Constraint_Error is raised. The sign of a zero value is preserved (positive
if none has been specified) if S'Signed_Zeros is True.
52
- S'Value
-
S'Value denotes a function with
the following specification:
53
function S'Value(Arg : String)
return S'Base
54
- This function returns a value given an image of
the value as a String, ignoring any leading or trailing spaces.
55
- {evaluation (Value) [partial]}
{Constraint_Error (raised by failure
of run-time check)} For the evaluation
of a call on S'Value for an enumeration subtype S, if the sequence of
characters of the parameter (ignoring leading and trailing spaces) has
the syntax of an enumeration literal and if it corresponds to a literal
of the type of S (or corresponds to the result of S'Image for a value
of the type), the result is the corresponding enumeration value; {Range_Check
[partial]} {check, language-defined
(Range_Check)} otherwise Constraint_Error
is raised. For a numeric subtype S, the evaluation of a call on S'Value
with Arg of type String is equivalent to a call on S'Wide_Value
for a corresponding Arg of type Wide_String.
55.a
Reason: S'Value is subtly
different from S'Wide_Value for enumeration subtypes since S'Image might
produce a different sequence of characters than S'Wide_Image if the enumeration
literal uses characters outside of the predefined type Character. That
is why we don't just define S'Value in terms of S'Wide_Value for enumeration
subtypes. S'Value and S'Wide_Value for numeric subtypes yield the same
result given the same sequence of characters.
Implementation Permissions
56
An implementation may extend the Wide_Value,
[Value, Wide_Image, and Image] attributes of a floating point type to
support special values such as infinities and NaNs.
56.a
Proof: The permission is
really only necessary for Wide_Value, because Value is defined in terms
of Wide_Value, and because the behavior of Wide_Image and Image is already
unspecified for things like infinities and NaNs.
56.b
Reason: This is to allow implementations
to define full support for IEEE arithmetic. See also the similar permission
for Get in A.10.9.
57
19 The evaluation of S'First
or S'Last never raises an exception. If a scalar subtype S has a nonnull
range, S'First and S'Last belong to this range. These values can, for
example, always be assigned to a variable of subtype S.
57.a
Discussion: This paragraph addresses
an issue that came up with Ada 83, where for fixed point types, the end points
of the range specified in the type definition were not necessarily within the
base range of the type. However, it was later clarified (and we reconfirm it
in 3.5.9, ``Fixed Point
Types'') that the First and Last attributes reflect the true bounds chosen
for the type, not the bounds specified in the type definition (which might be
outside the ultimately chosen base range).
58
20 For a subtype of a scalar
type, the result delivered by the attributes Succ, Pred, and Value might
not belong to the subtype; similarly, the actual parameters of the attributes
Succ, Pred, and Image need not belong to the subtype.
59
21 For any value V (including
any nongraphic character) of an enumeration subtype S, S'Value(S'Image(V))
equals V, as does S'Wide_Value(S'Wide_Image(V)). Neither expression ever
raises Constraint_Error.
Examples
60
Examples of
ranges:
61
-10 .. 10
X .. X + 1
0.0 .. 2.0*Pi
Red .. Green -- see 3.5.1
1 .. 0 -- a null range
Table'Range -- a range attribute reference (see 3.6)
62
Examples of
range constraints:
63
range -999.0 .. +999.0
range S'First+1 .. S'Last-1
Incompatibilities With Ada 83
63.a/1
{incompatibilities with Ada
83} S'Base is no longer defined for nonscalar
types. One conceivable existing use of S'Base for nonscalar types is
S'Base'Size where S is a generic formal private type. However, that is
not generally useful because the actual subtype corresponding to S might
be a constrained array or discriminated type, which would mean that S'Base'Size
might very well overflow (for example, S'Base'Size where S is a constrained
subtype of String will generally be 8 * (Integer'Last + 1)). For derived
discriminated types that are packed, S'Base'Size might not even be well
defined if the first subtype is constrained, thereby allowing some amount
of normally required ``dope'' to have been squeezed out in the packing.
Hence our conclusion is that S'Base'Size is not generally useful in a
generic, and does not justify keeping the attribute Base for nonscalar
types just so it can be used as a prefixprefix.
Extensions to Ada 83
63.b
{extensions to Ada 83}
The attribute S'Base for a scalar subtype is now
permitted anywhere a subtype_mark
is permitted. S'Base'First .. S'Base'Last is the base range of the type.
Using an attribute_definition_clause,
one cannot specify any subtype-specific attributes for the subtype denoted
by S'Base (the base subtype).
63.c
The attribute S'Range is now allowed
for scalar subtypes.
63.d
The attributes S'Min and S'Max
are now defined, and made available for all scalar types.
63.e
The attributes S'Succ, S'Pred,
S'Image, S'Value, and S'Width are now defined for real types as well
as discrete types.
63.f
Wide_String versions of S'Image
and S'Value are defined. These are called S'Wide_Image and S'Wide_Value
to avoid introducing ambiguities involving uses of these attributes with
string literals.
Wording Changes from Ada 83
63.g
We now use the syntactic category
range_attribute_reference since
it is now syntactically distinguished from other attribute references.
63.h
The definition of S'Base has been
moved here from 3.3.3 since it now applies only to scalar types.
63.i
More explicit rules are provided
for nongraphic characters.
Contents Index Previous Next Legal