4.5.1 Logical Operators and Short-circuit Control Forms
Name Resolution Rules
consisting of two relation
connected by and then
or or else
(a short-circuit control
) shall resolve to be of some boolean type;
expected type for both relation
is that same boolean type.
Reason: This rule is written this way
so that overload resolution treats the two operands symmetrically; the
resolution of overloading present in either one can benefit from the
resolution of the other. Furthermore, the type expected by context can
following logical operators are predefined for every boolean type T
for every modular type T
, and for every one-dimensional array
whose component type is a boolean type:
function "and"(Left, Right : T) return T
function "or" (Left, Right : T) return T
function "xor"(Left, Right : T) return T
For these operators, we are talking about the type without any (interesting)
subtype, and not some subtype with a constraint or exclusion. Since it's
possible that there is no name for the “uninteresting” subtype,
we denote the type with an italicized T
. This applies to the italicized
in many other predefined operators and attributes as well.
In many cases, there is a subtype with the correct properties available.
The italicized T
T'Base, for scalars;
the first subtype of T, for tagged
a subtype of the type T without any
constraint or null exclusion, in other cases.
Note that “without a constraint”
is not the same as unconstrained. For instance, a record type with no
discriminant part is considered constrained; no subtype of it has a constraint,
but the subtype is still constrained.
Thus, the last case often is the same as the
first subtype of T
, but that isn't the case for constrained array
types (where the correct subtype is unconstrained) and for access types
with a null_exclusion
(where the correct subtype does not exclude null).
This italicized T is used for defining
operators and attributes of the language. The meaning is intended to
be as described here.
For boolean types, the predefined logical operators
and, or, and xor perform the conventional operations
of conjunction, inclusive disjunction, and exclusive disjunction, respectively.
For modular types, the predefined logical operators
are defined on a bit-by-bit basis, using the binary representation of
the value of the operands to yield a binary representation for the result,
where zero represents False and one represents True. If this result is
outside the base range of the type, a final subtraction by the modulus
is performed to bring the result into the base range of the type.
The logical operators on arrays are performed on
a component-by-component basis on matching components (as for equality
— see 4.5.2
), using the predefined
logical operator for the component type. The bounds of the resulting
array are those of the left operand.
The short-circuit control forms
and or else
deliver the same result as the corresponding
operators for boolean types, except
that the left operand is always evaluated first, and the right operand
is not evaluated if the value of the left operand determines the result.
For the logical
operators on arrays, a check is made that for each component of the left
operand there is a matching component of the right operand, and vice
Also, a check is made
that each component of the result belongs to the component subtype.
exception Constraint_Error is raised if either of the above checks fails.
Discussion: The check against the component
subtype is per AI83-00535.
14 The conventional
meaning of the logical operators is given by the following truth table:
A B (A and B) (A or B) (A xor B)
True True True True False
True False False True True
False True False True True
False False False False False
Examples of logical
Filter(1 .. 10) and
Filter(15 .. 24) -- see 3.6.1
Examples of short-circuit
Next_Car.Owner /= null and then
Next_Car.Owner.Age > 25 -- see 3.10.1
N = 0 or else
A(N) = Hit_Value
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe