4.5 Operators and Expression Evaluation
[
The language
defines the following six categories of operators (given in order of
increasing precedence). The corresponding
operator_symbols,
and only those, can be used as
designators
in declarations of functions for user-defined operators. See
6.6,
“
Overloading of Operators”.]
Syntax
logical_operator ::= and |
or |
xor
relational_operator ::= = | /= | < | <= | > | >=
binary_adding_operator ::= + | – | &
unary_adding_operator ::= + | –
multiplying_operator ::= * | / |
mod |
rem
highest_precedence_operator ::= ** |
abs |
not
Discussion: Some of the above syntactic
categories are not used in other syntax rules. They are just used for
classification. The others are used for both classification and parsing.
Static Semantics
For a sequence of operators of the same precedence
level, the operators are associated with their operands in textual order
from left to right. Parentheses can be used to impose specific associations.
Discussion: The left-associativity is
not directly inherent in the grammar of
4.4,
though in
1.1.4 the definition of the metasymbols
{} implies left associativity. So this could be seen as redundant,
depending on how literally one interprets the definition of the
{}
metasymbols.
See the Implementation Permissions below regarding
flexibility in reassociating operators of the same precedence.
For each
form of type definition, certain of the above operators are
predefined;
that is, they are implicitly declared immediately after the type definition.
For
each such implicit operator declaration, the parameters are called Left
and Right for
binary operators; the single parameter is called
Right for
unary operators. [An expression of the form X op Y,
where op is a binary operator, is equivalent to a
function_call
of the form "op"(X, Y). An expression of the form op Y, where
op is a unary operator, is equivalent to a
function_call
of the form "op"(Y). The predefined operators and their effects
are described in subclauses
4.5.1 through
4.5.6.]
Dynamic Semantics
[
The predefined operations on
integer types either yield the mathematically correct result or raise
the exception Constraint_Error. For implementations that support the
Numerics Annex, the predefined operations on real types yield results
whose accuracy is defined in
Annex G, or raise
the exception Constraint_Error. ]
To be honest: Predefined operations on
real types can “silently” give wrong results when the Machine_Overflows
attribute is false, and the computation overflows.
Proof: For integer types, this is normatively
stated in the Dynamic Semantics of
3.5.4.
For floating point types, this is normatively stated at the end of the
Implementation Requirements of
G.2.1. For
fixed point types, this is normatively stated at the end of the Implementation
Requirements of
G.2.3.
Implementation Requirements
The implementation of a predefined
operator that delivers a result of an integer or fixed point type may
raise Constraint_Error only if the result is outside the base range of
the result type.
The implementation of a predefined
operator that delivers a result of a floating point type may raise Constraint_Error
only if the result is outside the safe range of the result type.
To be honest: An exception is made for
exponentiation by a negative exponent in
4.5.6.
Implementation Permissions
For a sequence of predefined operators of the same
precedence level (and in the absence of parentheses imposing a specific
association), an implementation may impose any association of the operators
with operands so long as the result produced is an allowed result for
the left-to-right association, but ignoring the potential for failure
of language-defined checks in either the left-to-right or chosen order
of association.
Discussion: Note that the permission
to reassociate the operands in any way subject to producing a result
allowed for the left-to-right association is not much help for most floating
point operators, since reassociation may introduce significantly different
round-off errors, delivering a result that is outside the model interval
for the left-to-right association. Similar problems arise for division
with integer or fixed point operands.
Note that this permission does not apply to
user-defined operators.
NOTE The two operands of an expression
of the form X op Y, where op is a binary operator, are evaluated in an
arbitrary order, as for any
function_call
(see
6.4).
Examples
Examples of precedence:
not Sunny or Warm -- same as (not Sunny) or Warm
X > 4.0 and Y > 0.0 -- same as (X > 4.0) and (Y > 0.0)
-4.0*A**2 -- same as –(4.0 * (A**2))
abs(1 + A) + B -- same as (abs (1 + A)) + B
Y**(-3) -- parentheses are necessary
A / B * C -- same as (A/B)*C
A + (B + C) -- evaluate B + C before adding it to A
Wording Changes from Ada 83
We don't give a detailed definition of precedence,
since it is all implicit in the syntax rules anyway.
The permission to reassociate is moved here
from RM83-11.6(5), so it is closer to the rules defining operator association.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe