.sh 1 "Interaction Statements"
.(b
interaction_statement  ::=  |1invocation_statement   #   implementation_statement   #
                            /1resource_control_statement   #   concurrent_statement
.)b
.lp
Interaction statements are used to invoke and service
operations and to create and destroy instances of resources.
.sh 2 "Operation Invocation"
.(b
invocation_statement  ::=  call_statement   #   send_statement   # V_statement
.)b
.(b
call_statement  ::=  @call@{{o}}  operation  (  expression  @,@{{*}}  )
.)b
.(b
send_statement  ::=  @send@  operation  (  expression  @,@{{*}}  )
.)b
.(b
V_statement  ::=  @V@  ( operation_indication  )
.)b
.(b
operation   ::=   denotation
.)b
.pp
The @call@ and @send@ statements generate a new invocation of the
denoted operation.
An operation denotation is either the value of a capability
variable or the name of an operation declared in the domain
of the invocation statement.
(An operation name is implicitly a capability for that operation.)
.pp
An invocation statement is executed by first
evaluating the argument expressions;
these must agree in number and type with the corresponding formal parameters.
If the denoted operation is implemented by a @proc@,
a new process is then created to execute the operation.
If the denoted operation is implemented by one
or more input statements,
the argument expressions are placed on
the queue associated with the operation (see next section).
Invocations of the same operation by the same invoking
process are queued in the order they are invoked.
.pp
A @call@ statement terminates when the operation has been serviced
and results (if any) have been returned.
A @send@ statement terminates when a service process has been created
or when the arguments have been queued, depending on how
the operation is implemented.
Execution of @call@ is thus #synchronous\(emthe caller waits
for the operation to be executed.
In contrast, @send@ is #asynchronous\(emthe sender waits
only until the operation has been started or queued.
Note that the keyword @call@ is optional in a @call@ statement.
.pp
A @V@ statement is an abbreviation for a @send@ statement that
invokes a parameterless operation.
It is typically used with a @sem@ operation to cause the
usual effect of executing @V@ on the semaphore.
.pp
Operations that are functions (i.e., have return values)
are usually called.
However, a function may be invoked by @send@ if its
operation restriction permits; in this case the
return value is simply discarded.
Similarly, values of result parameters are discarded
and values of @var@ parameters do not change.
.pp
Execution of an invocation statement causes a run-time error
if the denoted operation is a capability with value @null@.
In general, execution of an invocation statement has no effect if the denoted
operation is a capability with value @noop@;
however, if the invocation appears in an expression, the return value
is undefined.
.pp
At present, all failures and exceptions\(emsuch as inability
to deliver an invocation\(emresult in termination
of the entire SR program.
Eventually failure-handling mechanisms will be added to the language.
.PS L
%Examples:
.sp .5
	call insert(person("andrews", 42))
	position := differ("now is the time", "now is not the time")
	tty_write('\en')   # write newline character
	send query(lookup_key, myanswer)
	send reply_channel(20)
	sc.push(5)
	V(mutex)
	V(fork[2])
.PE
.sh 2 "Operation Implementation"
.(b
implementation_statement  ::=  |1input_statement   #   receive_statement   #  P_statement
                               /1return_statement   #   reply_statement
.)b
.(b
input_statement  ::=  @in@  operation_command  []{{+}}  else_command{{o}}  @ni@
.)b
.(b
receive_statement  ::=  @receive@  operation_indication  (  variable  ,{{*}}  )
.)b
.(b
P_statement  ::=  @P@  (  operation_indication  )
.)b
.(b
return_statement  ::=  @return@
.)b
.(b
reply_statement  ::=  @reply@
.)b
.(b
operation_command  ::=  |1interaction_quantifier{{o}}  operation_guard
                        /1     scheduling_expression{{o}}  ->  block
.)b
.(b
operation_guard  ::=  |1operation_indication  (  formal_identifier  ,{{*}}  )
                      /1     return_clause{{o}}  synchronization_expression{{o}}
.)b
.(b
interaction_quantifier  ::=  (  quantifier  ,{{+}}  )
.)b
.(b
operation_indication  ::=  operation_identifier operation_subscripts{{o}}
.)b
.(b
operation_subscripts  ::=  [  expression  ]   #   [  expression  ,  expression  ]
.)b
.(b
return_clause  ::=  @returns@  return_identifier
.)b
.(b
synchronization_expression  ::=  and_operator  boolean_expression   #   @st@  boolean_expression
.)b
.(b
scheduling_expression  ::=  @by@  arithmetic_expression
.)b
.lp
An input statement delays the executing
process until some invocation is selectable.
An invocation is #selectable if the boolean-valued
synchronization expression in the corresponding operation
guard is true.
The synchronization expression is optional; if omitted
it is implicitly true.
When an input statement contains an @else@ command, that command is
selected if no invocation is selectable.
.pp
In general, the oldest selectable invocation is serviced.
However, if the corresponding operation command
contains a scheduling expression, the invocation that
is serviced is the oldest one that is selectable
and also minimizes the scheduling expression.
An invocation is serviced by executing the block in the
corresponding operation command, with the
formal identifiers bound to the arguments of the invocation.
Both synchronization and scheduling expressions can reference
invocation arguments since they are in the scope of the
formal identifiers in an operation command.
Hence selection can be based on invocation arguments
in addition to other variables and parameters.
.pp
An input statement terminates when the selected block terminates
or when a @return@ statement is executed.
Executing @exit@ or @next@ also terminates execution
of an input statement that is within an iterative statement.
If the invocation serviced by an input statement was called,
results are returned to the caller when the input statement
terminates.
.pp
An operation command without a quantifier specifies one operation,
which may be an element of an array of operations.
The order in which subscript expressions are evaluated is non-deterministic;
furthermore, they may be re-evaluated an arbitrary number
of times during execution of the input statement.
An operation command that begins with a quantifier is short-hand
for a collection of operation commands, one per combination of bound variable values.
The quantifier might be re-evaluated an arbitrary number of times;
hence the series of operation guards might change dynamically
if the expressions in the quantifier change value.
If the quantifier is empty\(emi.e., there are no values between
the two bounds\(emthere are no operations to be selected.
An input statement containing only empty quantifiers and no @else@
command will thus block permanently.
.pp
A \fIresource operation\fR is one that
is declared global to @proc@ and @process@
declarations, and that is implemented by input statements.
Such an operation may be implemented by input statements
in more than one process.
Thus, several processes might compete for invocations
of resource operations.
To identify and control possible conflicts in access to invocations
by such competing processes,
operations are grouped into #classes
based on their appearance in input statements.
We define over the set of operations the relation
.(b
#same = { (a,b) | a and b are operations implemented by the same input statement }
.)b
The transitive closure of #same is an equivalence relation,
the equivalence classes of which are our classes of operations.
Note that operations declared within a @proc@ are also included in
the domain of #same;
such an operation may be in the same class as a resource operation
and, if so, may consequently
be in the same class as an operation declared within another @proc@.
Also note that the only way an operation is in a class
by itself is if it is implemented only by input statements
that implement no other operations.
.pp
At most one process at a time is allowed access
to a given class.
That is, for a given class, at most one process at a time
can be selecting an invocation to service or appending
a new invocation.
Access to the invocations in a class is assumed to be fair
in the sense that processes are given access to both pending
and new invocations in
a first-come, first-served (FCFS) order.
Thus, a process waiting to access the invocations
in a class will eventually obtain access as
long as all functions in synchronization
and scheduling expressions in input statements eventually terminate.
.pp
A @receive@ statement is an abbreviation
for an input statement that merely waits for the next invocation
of the named operation,
then assigns the contents of the received
message to the denoted variables (if the received operation has parameters).
In particular,
.PS
receive operid(v1, ...,vN)
.PE
is an abbreviation for
.PS
in operid(f1, ...,fN) -> v1 := f1; ...; vN := fN ni
.PE
where the @f@'s are identifiers different from the @v@'s.
It is permissible to receive from a value-returning operation,
but the return value in that case is discarded.
.pp
A @P@ statement is an abbreviation for a @receive@ statement that
waits for an invocation of a parameterless operation.
It is typically used with a @sem@ operation to cause the
usual effect of executing @P@ on the semaphore.
.pp
Executing a @return@ or @reply@ statement causes
the invocation being serviced by the
smallest enclosing @proc@  or operation command to terminate,
if it was called.
Executing @return@ also causes
the smallest enclosing @proc@ or operation command to terminate.\**
.(f
\**Executing @return@ or @reply@ within an @else@ command
terminates execution of the @proc@ or operation command that
encloses the input statement in which the @else@ command occurs.
.)f
In contrast, a process that executes @reply@
continues executing with the statement following @reply@.
Such a process may continue to reference the
formals until it leaves their scope;
however, no subsequent change
to formal parameters or to the return value
is reflected back to the caller.
A @reply@ to an invocation for which a @reply@ has already been executed
has no effect.
.pp
Resource initialization and finalization components may also
contain @return@ or @reply@.
The effects are similar to those for a @proc@.
Executing a @return@ statement causes the component
to terminate early and terminates the corresponding @create@
or @destroy@ statement.
Executing a @reply@ statement terminates the
corresponding @create@ or @destroy@ statement, but
lets the initialization or finalization component
continue executing.
Again, executing an extra @reply@ has no effect.
.PS L
%Examples:
.sp .5
	# shortest-job-next allocator
	in request(time) and free by time -> free := false
	[] release() -> free := true
	ni
.PE
.PS L
	in query(key, reply_channel) ->
	    # look up value using key
	    send reply_channel(value)
	ni
.PE
.PS L
	receive my_answer(result)

	# wait for any one of signal[1:4] to be sent
	in (i := 1 to 4) signal[i]() ->  skip  ni

	P(mutex)
	P(fork[i])
.PE
.sh 2 "Resource Control"
.(b
resource_control_statement  ::=  create_statement   #   destroy_statement
.)b
.(b
create_statement  ::=  variable  :=  @create@  resource_name  (  expression  ,{{*}}  )  location{{o}}
.)b
.(b
resource_name  ::=  resource_identifier   #   @vm@
.)b
.(b
location  ::=  resource_location   #   vm_location
.)b
.(b
resource_location  ::=  @on@  denotation
.)b
.(b
vm_location  ::=  @on@  integer_expression
.)b
.(b
destroy_statement  ::=  @destroy@  denotation
.)b
.lp
The @create@ statement is used to create an instance of the named resource.
When @create@ is executed,
space for a new resource is allocated,
arguments are passed by value to it,
and a process is created to execute the resource initialization code.\**
.(f
\**Recall that there is implicit initialization code even
if there is no explicit, programmer-supplied initialization component.
.)f
Execution of @create@ terminates once the
initialization process returns or replies.
A #resource #capability is returned by @create@
and stored in the denoted variable,
which must have type `cap resource_identifier.'
This capability is subsequently used to invoke operations
exported by the resource, or to destroy the resource.
.pp
By default, a newly created resource instance is placed
in the same #virtual #machine (address space) as that
of the resource executing @create@.
It is possible to place a new resource in a specific,
possibly different address space by appending
`@on vmcap@' to the @create@ statement, where
@vmcap@ denotes a virtual machine.
.pp
Virtual machines are themselves created by
creating an instance of the @vm@ pseudo-resource,
which is a special resource predefined by the language.
When an instance of @vm@ is created, a new
address space is constructed and a capability
of type `@cap vm@' is returned.
(A @null@ capability is returned if @vm@ cannot
be created.)
By default, a new virtual machine is placed on
the same physical machine as the creator.
A new instance of @vm@ can be placed on a specific
physical machine (network node) by appending `@on intexpr@' to
the virtual-machine creation statement,
where @intexpr@ is an integer-valued expression.
The mapping between the values of such expressions
and specific machines is implementation specific.
(See Appendix 3 for details.)
.pp
The @destroy@ statement destroys a resource
or virtual machine and terminates all activity in it.
When a resource is destroyed,
first servicing of further invocations of the
resource's operations is prevented.
Second, the optional finalization code in the resource is executed.
Third, all processes in the resource are destroyed.
Finally, storage and descriptors allocated to the resource are reclaimed.
Execution of @destroy@ terminates at this time.
.pp
When a virtual machine is destroyed,
first creation of new resources in the virtual machine is prevented.
Then each existing resource in the virtual
machine is implicitly destroyed as described above.
Finally, the address space of the virtual machine
is destroyed.
.pp
Execution of @destroy@ causes a run-time error
if the denoted capability has the value @null@ or
if the the resource has already been destroyed.
Execution of @destroy@ has no effect
if the denoted capability has the value @noop@.
.PS L
%Examples:
.sp .5
	factorial_cap := create factorial()
	sc := create Stack(100)
	destroy sc
	vmcap := create vm() on 1
	sc := create Stack(50) on vmcap
.PE
.sh 2 "Concurrent Invocation"
.(b
concurrent_statement  ::=  @co@  concurrent_command  @//@{{+}}  @oc@
.)b
.(b
concurrent_command  ::=  interaction_quantifier{{o}}  concurrent_invocation   post_processing{{o}}
.)b
.(b
concurrent_invocation  ::=  call_statement   #   assignment_statement   #   send_statement
.)b
.(b
post_processing  ::=  @->@   block
.)b
.lp
The concurrent statement generates invocations
for each concurrent command in the statement.
Only user-defined operations may be invoked within @co@; pre-defined
functions may not since they are implemented differently.
An interaction quantifier is used to specify a collection
of concurrent commands,
one for each combination of values of the bound variables,
as in for-all statements.
The expression in an assignment statement appearing as a concurrent invocation
may consist of only a single invocation of a user-defined function.
.pp
Execution of @co@ first starts all invocations.
Then, as each invocation terminates,
the corresponding post-processing block is executed, if there is one.
Post-processing blocks are executed one at a time.
Execution of co terminates when
all post-processing blocks have terminated or when
some post-processing block executes @exit@.
If @co@ terminates before all invocations have terminated,
the outstanding invocations are not canceled;
they will still be serviced (barring failure)
but the invoker will not wait for them to complete nor get back results.
Execution of @next@ within a post-processing block
causes execution of that post-processing block to terminate;
the enclosing @co@ statement then delays until another invocation
terminates, or the @co@ statement terminates if all invocations
have terminated.
.PS L
%Examples:
.sp .5
	# update all copies of a replicated file
	# and continue immediately
	co (i := 1 to 3) send fd[i].write(values) oc

	# read one copy of a replicated file,
	# recording which response was received first
	co (i := 1 to 3) fd[i].read(arguments) ->
	    which_one := i; exit
	oc
.PE
