mirror of
https://github.com/PDP-10/its.git
synced 2026-01-13 15:27:28 +00:00
200 lines
7.6 KiB
Plaintext
200 lines
7.6 KiB
Plaintext
.sr sect_except Section`12
|
||
.sr sect_for_stmt Section`11.5.2
|
||
.sr sect_decl_w_init Section`8.2.2
|
||
.sr sect_update_sugars Section`11.2
|
||
.
|
||
.chapter "Assignment and Invocation"
|
||
.para
|
||
The two fundamental actions of CLU are assignment
|
||
of computed objects to variables, and invocation of
|
||
procedures (and iterators) to compute objects.
|
||
All other actions are merely compositions of these two.
|
||
Since the correctness of assignments and invocations depends on a
|
||
type-checking rule, we describe that rule first,
|
||
then assignment, and finally invocation.
|
||
.section "Type Inclusion"
|
||
.para
|
||
CLU is designed to allow compile-time type-checking.
|
||
The type of each variable is known by the compiler.
|
||
Furthermore, the type of objects that could result from
|
||
the evaluation of an expression (invocation) is known at compile-time.
|
||
Hence, every assignment can be checked at compile-time to make
|
||
sure that the variable is only assigned objects of its declared type.
|
||
The rule is that an assignment 2v*`:=`2E* is legal only if
|
||
the set of objects defined by the type of 2E*
|
||
(loosely,
|
||
the set of all objects that could possibly result from evaluating the expression)
|
||
must be included in the set of all objects that could be denoted by 2v*.
|
||
.para
|
||
Instead of speaking of the set of objects defined by a type,
|
||
we generally speak of the type and say that
|
||
the type of the expression must be 2included in* the type of the variable.
|
||
If it were not for the type any, the inclusion rule
|
||
would be an equality rule.
|
||
This leads to a simple interpretation of the type inclusion rule:
|
||
.show 2
|
||
.fi
|
||
.ir +500m
|
||
The type of a variable being assigned an expression
|
||
must be either the type of the expression, or any.
|
||
.ir -500m
|
||
.nf
|
||
.eshow
|
||
.section "Assignment"
|
||
.para
|
||
Assignment is the means of causing a variable to denote an object.
|
||
Some assignments are implicit, i.e., performed as part of the execution
|
||
of various mechanisms of the language
|
||
(most notably procedure invocation, iterator invocation,
|
||
exception handling, and the tagcase statement).
|
||
All assignments, whether implicit or explicit,
|
||
are subject to the type inclusion rule.
|
||
The remainder of this section discusses explicit assignments.
|
||
.para
|
||
The assignment symbol ":=" is used in
|
||
two other syntactic forms that are not true assignments,
|
||
but rather abbreviations for certain invocations.
|
||
These forms are used for updating structures such as records and arrays
|
||
(see sect_update_sugars).
|
||
.subsection "Simple Assignment"
|
||
.para
|
||
The simplest form of assignment is:
|
||
.show
|
||
idn := expression
|
||
.eshow
|
||
In this case the expression is evaluated, and the
|
||
resulting object is assigned to the variable.
|
||
The expression must return a single object
|
||
(whose type must be included in that of the variable).
|
||
Examples of simple assignments are:
|
||
.show 5
|
||
x := 1 s(1)% x's type must include int, i.e., it must be int or any
|
||
y := string$substr (s, 5, n)t(1)% y's type must include string
|
||
a := array [int]$new ()t(1)% a's type must include array [int]
|
||
p := array [int]$create(3)t(1)% p's type must include array [int]
|
||
z := (foo = bar) t(1)% z's type must include bool
|
||
.eshow
|
||
It is also possible to declare a variable and assign to it in a single
|
||
statement; this is called a declaration with initialization,
|
||
and was discussed in sect_decl_w_init.
|
||
.subsection "Multiple Assignment"
|
||
.para
|
||
There are two forms of assignment that assign to more than one variable at once:
|
||
.show
|
||
idn, etc := expression, etc
|
||
.eshow
|
||
and
|
||
.show
|
||
idn, etc := invocation
|
||
.eshow
|
||
.para
|
||
The first form of multiple assignment is a generalization of the simple assignment.
|
||
The first variable is assigned the first expression,
|
||
the second variable the second expression, and so on.
|
||
The expressions are all evaluated (from left to right)
|
||
before any assignments are performed.
|
||
The number of variables in the list must equal the number of expressions,
|
||
no variable may occur more than once,
|
||
and the type of each variable must include the type of the corresponding expression.
|
||
.para
|
||
This form of multiple assignment allows easy permutation
|
||
of the objects denoted by several variables:
|
||
.show 2
|
||
x, y := y, x
|
||
i, j, k := j, k, i
|
||
.eshow
|
||
and similar simultaneous assignments of variables that would
|
||
otherwise require temporary variables:
|
||
.show 2
|
||
a, b := (a + b), (a - b)
|
||
quotient, remainder := (u / v), (u // v)
|
||
.eshow
|
||
Notice that there is no form of this statement with declarations.
|
||
.para
|
||
The second form of multiple assignment allows
|
||
us to retain the objects resulting from an invocation
|
||
returning two or more objects.
|
||
The first variable is assigned the first object,
|
||
the second variable the second object, and so on.
|
||
The order of the objects is the same as in the return statement
|
||
of the invoked routine.
|
||
The number of variables must equal the number of objects returned,
|
||
no variable may occur more than once,
|
||
and the type of each variable must include the type of the corresponding expression.
|
||
.para
|
||
Here are two examples of this statement, one without declarations, and one with:
|
||
.show 2
|
||
first, last, balance := acct$query (acct_no)
|
||
x, y, z: real := vector$components (v)
|
||
.eshow
|
||
.section "Invocation"
|
||
.para
|
||
Invocation is the other fundamental action of CLU.
|
||
In this section we discuss procedure invocation;
|
||
iterator invocation is discussed in sect_for_stmt.
|
||
However, up to and including passing of arguments,
|
||
the two are the same.
|
||
.para
|
||
Invocations take the form:
|
||
.show
|
||
primary ( lbkt expression, etc rbkt )
|
||
.eshow
|
||
A primary is a slightly restricted from of expression,
|
||
which includes variables and routine names,
|
||
among other things.
|
||
(See next section.)
|
||
.para
|
||
The sequence of activities in performing an invocation are as follows:
|
||
.nlist
|
||
The primary is evaluated.
|
||
It must evaluate to a procedure or iterator.
|
||
.nnext
|
||
The expressions are evaluated, from left to right.
|
||
.nnext
|
||
New variables are introduced corresponding to the formal arguments
|
||
of the routine being invoked (i.e., a new environment is created
|
||
for the invoked routine to execute in).
|
||
.nnext
|
||
The objects resulting from evaluating the expressions
|
||
(the actual arguments) are assigned to the corresponding new variables
|
||
(the formal arguments).
|
||
The first formal is assigned the first actual,
|
||
the second formal the second actual, and so on.
|
||
The type of each object must be included in the type of the
|
||
corresponding formal argument.
|
||
.nnext
|
||
Control is transferred to the routine at the start of its body.
|
||
.end_list
|
||
An invocation is considered legal in exactly
|
||
those situations where all the (implicit) assignments
|
||
involved in its execution are legal.
|
||
.para
|
||
commentary
|
||
It is permissible for a routine to assign to a formal argument variable;
|
||
the effect is just as if it assigned to any of its other variables.
|
||
From the point of view of the invoked routine, the only difference
|
||
between its formal argument variables and its other local variables
|
||
is that the formals are initialized by its caller.
|
||
.para
|
||
When an invoked procedure terminates, it returns zero or more result objects,
|
||
agreeing in number, order, and type with the information in the procedure header.
|
||
However, procedures can terminate in two ways:
|
||
they can terminate 2normally*,
|
||
returning zero or more objects,
|
||
or they can terminate 2exceptionally*,
|
||
signalling an exceptional condition.
|
||
When a procedure terminates normally, the result objects
|
||
become available to the caller,
|
||
and will (sometimes) be assigned to variables.
|
||
When a procedure terminates exceptionally,
|
||
the flow of control will not go to the point of return
|
||
of the invocation, but rather will go elsewhere as described
|
||
in sect_except.
|
||
.para
|
||
Here are some examples of invocations:
|
||
.show 2
|
||
p () s(1)% invoking a procedure taking no arguments
|
||
array [int]$create (-1)t(1)% invoking an operation of a type
|
||
routine_table [index] (input)t(1)% invoking a procedure fetched from an array
|
||
.eshow
|