Copyright © 1996, 1997 Lucent Technologies Inc. All rights reserved.

8.4 General Expressions

The remaining syntax for expressions is


expression: binary-expression lvalue-expression assignment-operator expression ( lvalue-expression-list ) = expression send-expression declare-expression load-expression assignment-operator: one of = &= |= ^= <<= >>= += -= *= /= %=
The left operand of an assignment can take only certain forms, called lvalues.

lvalue-expression: identifier nil term [ expression ] term [ expression : ] term . identifier ( lvalue-expression-list ) * monadic-expression lvalue-expression-list: lvalue lvalue-expression-list , lvalue

8.4.1 Simple assignments with =

In general, the types of the left and right operands must be the same; this type must be a data type. The value of an assignment is its new left operand. All the assignment operators associate right-to-left.

In the ordinary assignment with =, the value of the right side is assigned to the object on the left. For simple assignment only, the left operand may be a parenthesized list of lvalues and the right operand either a tuple or an adt whose data members correspond in number and type to the lvalues in the list. The members of the tuple, or the data members of the adt, are assigned in sequence to lvalues in the list. For example,

	p: Point;
	x, y: int;
	(x, y) = p;
splits out the coordinates of the point into x and y. These rules apply recursively, so that if one of the components of the left side is a parenthesized list of lvalues, it is assigned from a corresponding adt or tuple on the right.

If the left operand of a simple assignment is an adt and the right side is a tuple, then the assignment assigns the members of the tuple to the adt data members; these must correspond in number and type with the members of the tuple.

The constant nil may be assigned to an lvalue of any reference type. This lvalue will compare equal to nil until it is subsequently reassigned. In the Inferno implementation of Limbo, such an assignment also triggers the removal of the object referred to unless other references to it remain.

The left operand of an assignment may be the constant nil to indicate that a value is discarded. This applies in particular to any of the lvalues in a tuple appearing on the left; to extend the examples above,

	(x, nil) = p;
assigns the x member of the Point p to the variable x.

A special consideration applies to strings. If an int containing a Unicode character is assigned to a subscripted string, the subscript is normally required to lie within the string. As a special case, the subscript's value may be equal to the length of the string (that is, just beyond its end); in this case, the character is appended to the string, and the string's length increases by 1.

A final special case applies to array slices in the form e1[e2:]. Such expressions may lie on the left of =. The right side must be an array of the same type as e1, and its length must be less than or equal to (len e1)-e2. In this case, the elements in the array on the right replace the elements of e1 starting at position e2. The length of the array is unchanged.

8.4.2 Compound assignments

A compound assignment with op= is interpreted in terms of the plain assignment;

	e1 op= e2;
is equivalent to
	e1 = (e1) op (e2);
except that e1 is evaluated only once.

8.4.3 Send expressions

A send-expression takes the form


send-expression: lvalue-expression <- = expression
In the expression
	e1 <- = e2
the lvalue e1 must have type chan of type, and e2 must be of that type. The value of e2 is sent over the channel. If no task is executing a channel receive operation on the specified channel, the sender blocks. Task synchronization is discussed in §§9.8 and 9.12 below.

8.4.4 Declare-expressions

A declare-expression is an assignment that also declares identifiers on its left:


declare-expression: lvalue-expression := expression
Each of the constituent terms in the lvalue-expression must be an identifier or nil. A plain identifier on the left is declared as having the type of the expression, and it is initialized with the expression's value. When a parenthesized list of identifiers is given, the expression must be a tuple or an adt, and the individual identifiers in the list are declared and initialized with the members of the tuple, or the data members of the adt. As with ordinary assignments, the keyword nil may stand for an identifier whose declaration and assignment are skipped.

The value and type of a declare-expression are the same as those of the expression.

8.4.5 Load expressions

A load-expression has the form


load-expression: load identifier expression
The identifier is the identifier of a module, that is, the type name declared in a module declaration. The expression following load has type string and names a file containing the compiled form of the module. The load expression yields a handle for referring to the functions provided by a module and its adt.

Execution of load brings the file containing the module into local memory and dynamically type-checks its interface: the run-time system ascertains that the declarations exported by the module are compatible with the module declaration visible in the scope of the load operator (see §11.2). In the scope of a module declaration, the types and constants exported by the module may be referred to without a handle, but the functions and data exported by the module (directly at its top level, or within its adt) may be called only using a valid handle acquired by the load operator.

The value of load is nil if the attempt to load fails, either because the file containing the module can not be found, or because the found module does not export the specified interface.

Each evaluation of load creates a separate instance of the specified module; it does not share data with any other instance.

05/Jun/97