Contents Index Previous Next
5.2 Assignment Statements
1
[An assignment_statement
replaces the current value of a variable with the result of evaluating
an expression.]
Syntax
2
assignment_statement
::=
variable_name :=
expression;
3
The execution of an
assignment_statement
includes the evaluation of the
expression
and the
assignment of the value of the
expression
into the
target.
{assignment operation [distributed]}
{assign: See assignment operation}
[An assignment operation (as opposed to an
assignment_statement)
is performed in other contexts as well, including object initialization
and by-copy parameter passing.]
{target (of an assignment
operation)} {target (of
an assignment_statement)} The
target
of an assignment operation is the view of the object to which a value
is being assigned; the target of an
assignment_statement
is the variable denoted by the
variable_name.
3.a
Discussion: Don't confuse
this notion of the ``target'' of an assignment with the notion of the
``target object'' of an entry call or requeue.
3.b
Don't confuse the term ``assignment operation''
with the assignment_statement. The assignment
operation is just one part of the execution of an assignment_statement.
The assignment operation is also a part of the execution of various other constructs;
see 7.6.1, ``Completion
and Finalization'' for a complete list. Note that when we say, ``such-and-such
is assigned to so-and-so'', we mean that the assignment operation is being applied,
and that so-and-so is the target of the assignment operation.
Name Resolution Rules
4
{expected type (assignment_statement
variable_name) [partial]} The
variable_name
of an
assignment_statement is expected
to be of any nonlimited type.
{expected type (assignment_statement
expression) [partial]} The expected type
for the
expression is the type of
the target.
4.a
Implementation
Note: An assignment_statement
as a whole is a "complete context," so if the variable_name
of an assignment_statement is overloaded,
the expression can be used to help
disambiguate it. For example:
4.b
type P1 is access R1;
type P2 is access R2;
4.c
function F return P1;
function F return P2;
4.d
X : R1;
begin
F.all := X; -- Right hand side helps resolve left hand side
Legality Rules
5
The target [denoted by the variable_name]
shall be a variable.
6
If the target is of a tagged class-wide
type
T'Class, then the
expression
shall either be dynamically tagged, or of type
T and tag-indeterminate
(see
3.9.2).
6.a
Reason: This is consistent
with the general rule that a single dispatching operation shall not have
both dynamically tagged and statically tagged operands. Note that for
an object initialization (as opposed to the assignment_statement),
a statically tagged initialization expression is permitted, since there
is no chance for confusion (or Tag_Check failure). Also, in an object
initialization, tag-indeterminate expressions of any type covered by
T'Class would be allowed, but with an assignment_statement,
that might not work if the tag of the target was for a type that didn't
have one of the dispatching operations in the tag-indeterminate expression.
Dynamic Semantics
7
{execution (assignment_statement)
[partial]} For the execution of an
assignment_statement,
the
variable_name and the
expression are first evaluated in
an arbitrary order.
7.a
Ramification: Other rules
of the language may require that the bounds of the variable be determined
prior to evaluating the expression,
but that does not necessarily require evaluation of the variable_name,
as pointed out by the ACID.
8
When the type of
the target is class-wide:
9
- {controlling tag value (for the expression in
an assignment_statement) [partial]} If the
expression is tag-indeterminate (see
3.9.2), then the controlling tag value for the
expression is the tag of the target;
9.a
10
- {Tag_Check [partial]} {check,
language-defined (Tag_Check)} {Constraint_Error
(raised by failure of run-time check)} Otherwise
[(the expression is dynamically
tagged)], a check is made that the tag of the value of the expression
is the same as that of the target; if this check fails, Constraint_Error
is raised.
11
The value of the
expression
is converted to the subtype of the target. [The conversion might raise an exception
(see
4.6).]
{implicit subtype conversion
(assignment_statement) [partial]}
11.a
Ramification: 4.6,
``Type Conversions'' defines what actions and checks
are associated with subtype conversion. For non-array subtypes, it is just a
constraint check presuming the types match. For array subtypes, it checks the
lengths and slides if the target is constrained. ``Sliding'' means the array
doesn't have to have the same bounds, so long as it is the same length.
12
In cases involving controlled types,
the target is finalized, and an anonymous object might be used as an intermediate
in the assignment, as described in
7.6.1, ``
Completion
and Finalization''.
{assignment operation} {assignment
operation (during execution of an assignment_statement)} In
any case, the converted value of the
expression
is then
assigned to the target, which consists of the following two steps:
12.a
To be honest: 7.6.1
actually says that finalization happens always, but unless controlled types
are involved, this finalization during an assignment_statement
does nothing.
13
- The value of the target becomes the converted value.
14
- If any part of the target is controlled, its value is adjusted
as explained in clause 7.6. {adjustment
(as part of assignment) [partial]}
14.a
Ramification: If any parts
of the object are controlled, abort is deferred during the assignment
operation itself, but not during the rest of the execution of an assignment_statement.
15
2 The tag of an object never
changes; in particular, an assignment_statement
does not change the tag of the target.
16
3 The values of the discriminants
of an object designated by an access value cannot be changed (not even
by assigning a complete value to the object itself) since such objects
are always constrained; however, subcomponents of such objects may be
unconstrained.
16.a
Ramification: The implicit
subtype conversion described above for assignment_statements
is performed only for the value of the right-hand side expression as
a whole; it is not performed for subcomponents of the value.
16.b
The determination of the type of the variable
of an assignment_statement may require
consideration of the expression if the variable name can be interpreted as the
name of a variable designated by the access value returned by a function call,
and similarly, as a component or slice of such a variable (see 8.6,
``The Context of Overload Resolution'').
Examples
17
Examples of
assignment statements:
18
Value := Max_Value - 1;
Shade := Blue;
19
Next_Frame(F)(M, N) := 2.5; -- see 4.1.1
U := Dot_Product(V, W); -- see 6.3
20
Writer := (Status => Open, Unit => Printer, Line_Count => 60); -- see 3.8.1
Next_Car.all := (72074, null); -- see 3.10.1
21
Examples involving
scalar subtype conversions:
22
I, J : Integer range 1 .. 10 := 5;
K : Integer range 1 .. 20 := 15;
...
23
I := J; -- identical ranges
K := J; -- compatible ranges
J := K; -- will raise Constraint_Error if K > 10
24
Examples involving
array subtype conversions:
25
A : String(1 .. 31);
B : String(3 .. 33);
...
26
A := B; -- same number of components
27
A(1 .. 9) := "tar sauce";
A(4 .. 12) := A(1 .. 9); -- A(1 .. 12) = "tartar sauce"
28
4 Notes on the examples:
Assignment_statements are allowed
even in the case of overlapping slices of the same array, because the
variable_name and expression
are both evaluated before copying the value into the variable. In the
above example, an implementation yielding A(1 .. 12) = "tartartartar"
would be incorrect.
Extensions to Ada 83
28.a
Wording Changes from Ada 83
28.b
The special case of array assignment
is subsumed by the concept of a subtype conversion, which is applied
for all kinds of types, not just arrays. For arrays it provides ``sliding''.
For numeric types it provides conversion of a value of a universal type
to the specific type of the target. For other types, it generally has
no run-time effect, other than a constraint check.
28.c
We now cover in a general way in 3.7.2
the erroneous execution possible due to changing the value of a discriminant
when the variable in an assignment_statement
is a subcomponent that depends on discriminants.
Contents Index Previous Next Legal