Contents Index Search 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 registerresident 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 memoryresident 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 userdefined 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 runtime 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, languagedefined
(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, languagedefined
(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 outofbaserange
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 runtime 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, languagedefined
(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, languagedefined
(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 outofbaserange
value S'Base'First1, 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 languagedefined or implementationdefined
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 runtime 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'Digits1 (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 runtime 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, languagedefined (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 runtime 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, languagedefined
(Range_Check)} otherwise Constraint_Error
is raised.
44.a
Discussion: We considered
allowing 'Value to return a representable but outofrange 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 numericliteral
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 runtime 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, languagedefined (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 runtime 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,
languagedefined (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'Last1
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 prefix prefix.
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 subtypespecific 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 Search Previous Next Legal