Next: , Previous: , Up: Complex statements   [Contents][Index]


4.7.3 Binding variables

There are four ways to bind a value to a variable:

  1. as part a source or target task description (see Task descriptions)
  2. as part of a range loop (see Range loops)
  3. via a command-line argument (see Command-line arguments)
  4. explicitly using the LET keyword (this section)

The LET statement has the following form:

LET <let_binding>
[ AND <let_binding>]*
WHILE <simple_stmt>

where <let_binding> is defined as follows:

<let_binding> ::= <ident> BE expr
| <source_task>
| A RANDOM TASK [ <random_task_constraints>]

The optional <random_task_constraints> limits the set of tasks from which A RANDOM TASK selects:

<random_task_constraints> ::= OTHER THAN <expr>
| LESS THAN <expr> [ BUT NOT <expr>]
| GREATER THAN <expr> [ BUT NOT <expr>]
| IN[ <expr> ‘, <expr> ‘]’ [ BUT NOT <expr>]

An <ident> bound using the form ‘ LET <ident> BE <source_task>’ represents a group of tasks and must therefore be accessed using the TASK GROUP construct (see Source tasks). For example, in the coNCePTuaL program

LET left BE TASKS t SUCH THAT t < num_tasks/2 WHILE TASK GROUP left
SENDS A 1 KILOBYTE MESSAGE TO TASK num_tasks - left - 1

the ‘ TASK GROUP left’ expression defines ‘left’ as the group of tasks described by ‘ TASKS t SUCH THAT t < num_tasks/2’. The ‘left’ in ‘num_tasks - left - 1’ refers back to that definition of ‘left’, not the let-bound ‘left’. The ‘t’ in the let-binding is used only to specify the group of tasks that will be bound to ‘left’. Its scope is limited to the expression ‘t < num_tasks/2’. In other words, the preceding example is equivalent to

TASKS left SUCH THAT left < num_tasks/2 SEND A 1 KILOBYTE MESSAGE TO
TASK num_tasks - left - 1

The advantage of using LET to define a task group is that the same—possible complex—description of a set of tasks can be reused in multiple statements without having to type it repeatedly.

Here are some further examples of LET:

LET reps BE 3 WHILE FOR reps REPETITIONS TASK 0 OUTPUTS "Laissez les
bons temps rouler."

LET src BE num_tasks-1 AND dest BE num_tasks/2 WHILE TASK src SENDS A
55E6 BIT MESSAGE TO TASK dst

LET hotspot BE A RANDOM TASK WHILE TASKS other SUCH THAT
other<>hotspot SEND 1000 1 MEGABYTE MESSAGES TO TASK hotspot

LET target BE A RANDOM TASK OTHER THAN 3 WHILE TASK 3 SENDS A 24 BYTE
MESSAGE TO TASK target

LET x BE A RANDOM TASK AND y be a RANDOM TASK GREATER THAN x WHILE
TASK 0 OUTPUTS "Did you know that " AND x AND " is less than " AND y
AND "?"

LET nonzero BE A RANDOM TASK LESS THAN 10 BUT NOT 0 WHILE TASK nonzero
SLEEPS FOR 2 SECONDS

LET middles BE A RANDOM TASK IN [1, num_tasks-2] WHILE TASK middles
ASYNCHRONOUSLY SENDS A 10 BYTE MESSAGE TO TASK ends SUCH THAT ends IS
NOT IN [1, num_tasks-2]

LET num BE 1000 AND num BE num*2 WHILE TASK 0 OUTPUTS num
-| 2000

That last example demonstrates that LET can bind a variable to a function of its previous value. It is important to remember, though, that variables in coNCePTuaL cannot be assigned, only bound to a value for the duration of the current scope. They can, however, be bound to a different value for the duration of a child scope. The following example is an attempt to clarify the distinction between binding and assignment:

LET var BE 123 WHILE FOR 5 REPETITIONS LET var BE var+1 WHILE TASK 0
OUTPUTS var
-| 124
-| 124
-| 124
-| 124
-| 124

In that example, ‘var’ is bound to ‘123’ for the scope containing the FOR statement. Then, within the FOR statement, a new scope begins with ‘var’ being given one plus the value it had in the outer scope, resulting in ‘124’. If coNCePTuaL supported assignment instead of variable-binding, the program would have output ‘124’, ‘125’, ‘126’, ‘127’, and ‘128’. Note that if A RANDOM TASK were used in the example instead of ‘var+1’, ‘var’ would get a different value in each iteration.

When a variable is LET-bound to A RANDOM TASK, all tasks agree on the random number. Otherwise, task A might send a message to task B but task B might be expecting to receive the message from task C, thereby leading to a variety of problems. If there are no valid random tasks, as in the following example, A RANDOM TASK will return ‘-1’:

LET invalid_task BE A RANDOM TASK GREATER THAN num_tasks WHILE TASK 0
OUTPUTS invalid_task
-| -1

Furthermore, the <expr> passed to GREATER THAN is bounded from below by ‘0’ and the <expr> passed to LESS THAN is bounded from above by ‘num_tasks-1’. Hence, the following coNCePTuaL statement will always output values less than or equal to ‘num_tasks-1’ (unless num_tasks is greater than 1*10^6, of course, in which case it will always output values less than 1*10^6):

LET valid_task BE A RANDOM TASK LESS THAN 1E6 WHILE TASK valid_task
OUTPUTS "Hello from " AND valid_task

Next: , Previous: , Up: Complex statements   [Contents][Index]

Scott Pakin, pakin@lanl.gov