Previous Contents Next

3.8   Processes and expressions

process ::= full-name (   expr-list )
  | reply expr-list   [ to name ]
  |  
  | process |   process
  | expr ;   process
  | if expr then {   process }   [ else { process }]
  | decl in   process
  | { process }
expr ::= constant
  | full-name
  | full-name (   expr-list )
  | expr   full-infix-name   expr
  | expr ;   expr
  | spawn { process }
  | if expr then   expr   [ else expr ]
  | decl in   expr
  | ( expr )
expr-list ::= [ expr   { , expr } ]
decl ::= let process-decl
  | let expr-decl
  | loc agent-decl end
process-decl ::= join-pattern =   process   { and join-pattern =   process }
expr-decl ::= name   { , name } =   expr   { and name   { , name } =   expr }
agent-decl ::= agent   { and agent }
agent ::= ident   [ with process-decl ]   [ init process ]

The join-calculus possesses two base syntactic classes: processes and expressions. Processes form the skeleton of the join-calculus as a concurrent language, whereas expressions are more oriented toward functional programming. Both processes and expressions have a similar concrete syntax. Generally, they are discriminated by context: expressions are adequate in a context where a result is needed (such as arguments to message sending), whereas processes occur where some actions are to be performed.

A noticeable exception to the uniformity of concrete syntax is grouping, which is performed using curly braces {...} in the process case, and parenthesis (...) in the expression case. Such groupings can be used to disambiguate between processes and expressions. This trick is mandatory in the branches of the conditional construct if... then... else... , where curly braces {...} must be used in the process case.

The table below shows the relative precedences and associativity of operators and non-closed constructions. The constructions with higher precedence come first. For infix symbols, we write ``*...'' to mean ``any symbol starting with *''.

Construction or operator Associativity
!... #... $... ``.''... ~... left
^...@... right
*.../...%... left
+...-... left
<...>...=... --
|...&... left
if --
, left
; left
| right
let loc --

3.8.1   Basic constructs

Empty process

The empty process ``'' does nothing. Its presence can be emphasized by using process grouping { } .

Constants

Expressions consisting in a constant evaluate to this constant.

Names as expressions

When occurring alone in an expression context, names evaluate to the value they are bound to. Names bound to primitives are not allowed as expressions, and cause a runtime-error.

Message passing

The construct a (   expr 1 , ... ,   expr n ) denotes sending the results of the evaluations of expr 1 , ..., expr n on the port name (or the primitive) a . The expressions expr 1 , ..., expr n are evaluated in some unspecified order. In a process context, the name a must be asynchronous, whereas in an expression context, the name a must be synchronous. This constraint is checked when typing programs.

Note that channels are polyadic in their arguments. Polyadicity also occur at the result level: a synchronous channel takes n arguments and gives back m result, where n and m are any integer greater than or equal to zero.

Some synchronous binary channels can be invoked using infix notation: expr 1   full-infix-name   expr 2 is equivalent to full-infix-name (   expr 1 ,   expr 2 ).

Continuation invocation

The process reply expr 1, ... ,   expr n to   name executes by sending the message expr 1, ..., expr n on the continuation of name . As the continuation of name is an implicit argument to name , the reply ... to name construct may only occur in a process guarded by a join pattern that defines name (see below). In the current implementation, some additional restrictions apply to continuation usage (see section 7.4).

When name is the only channel being defined, the to name part can be omitted.

Channel definitions

New channels are defined by the process-decl construct. The simple declaration join-pattern =   process is both a definition for some fresh channel names and the specification of a synchronization pattern on these names (see section 3.7). This synchronization guards process .

Channel definitions are recursive definitions: if a is a port named defined by join-pattern above, then a may occur free inside process and its occurrence refers to the channel defined by the declaration join-pattern =   process .

The composite declaration join-pattern 1 =   process 1 and ... and   join-pattern n =   process n is a definition for all the names that the simple declarations join-pattern 1 =   process 1, ...join-pattern n =   process n define. The same channel name a may be defined by several simple declarations inside a composite declaration. Then, only one fresh channel a is defined and channel a takes part to several synchronizations.

Value binding

Any value in the language can be bound to a name by using the expr-decl construct. Evaluating a declaration x 1 , ... ,   x n =   expr is evaluating expr , which must return n values, which are then bound to x 1 , ..., x n. Basically, expr is a message sending construct on a synchronous channel that gives back n results. Such basic n-ary expressions can be combined by using other language constructs such as conditionals or local definitions.

Value bindings are non-recursive: in x 1 , ... ,   x n =   expr , the scope of x 1, ..., x n does not comprise expr . Similarily, the scope of the x ji in x 11 , ... ,   x n1 =   expr 1 and ... and   x 1m , ... ,   x pm =   expr m , does not comprise the expr j. Such composite value binding are evaluated in some unspecified order and all the names they bind must be different.

Location definitions

The simple location definition loc name with   process-decl init   process end executes by making a new location, which is bound to name , whose initial active channels are defined by process-decl , and whose initial active process is process . Note that both initial active channels definition and initial active process may be omitted.

The composite location definition agent 1 and ... and   agent n is the simultaneous definition of n locations. Such a declaration is recursive, that is the scope of the location and initial port names defined by agent 1, ...agent n comprises the whole composite definition.

Local definitions

The decl in   process and decl in   expr constructs bind values locally both inside processes and expressions.

They are evaluated by first evaluating decl , binding some new names, then evaluating expr or executing process in an environment extended by the new names defined in decl . In an expression context, the result of evaluating the decl in   expr construct is the result of evaluating expr .

3.8.2   Control structures

Sequence

The expression expr 1 ;   expr 2 evaluates expr 1 first, then expr 2, and returns the value of expr 2. The process expr 1 ;   process 2 executes expr 1 first, then it executes process 2. The expression expr 1 must return an empty result. In fact, sequence is a shorthand for a zero-ary local value binding let = expr in ....

Concurrent execution

The process process 1 |   process 2 executes by concurrently executing process 1 and process 2. The expression spawn { process } launches the concurrent execution of process and returns an empty result.

Conditional

The process if expr 1 then {   process 2 } else {   process 3 } executes process 2 if expr 1 evaluates to the boolean true, and process 3 if expr 1 evaluates to the boolean false. The else process 3 part can be omitted, in which case it defaults to else {}.

The expression if expr 1 then   expr 2 else   expr 3 evaluates to the value of expr 2 if expr 1 evaluates to the boolean true, and to the value of expr 3 if expr 1 evaluates to the boolean false. The else expr 3 part can be omitted, in which case it defaults to an expression that returns zero result.

3.8.3   Operators

Symbols from the class infix-symbols can appear in infix position (between two expressions). Infix symbols do not have a fixed meaning: they are simply interpreted as message sending on the channels corresponding to the symbols.

The table below lists the symbols defined in the initial environment and their initial meaning. (See the description of the standard library module sys in chapter 4 for more details). Their meaning may be changed at any time using let infix-op (   x 1 ,   x 2 ) = ...

Operator Initial meaning
+ Integer addition.
- Integer subtraction.
* Integer multiplication.
/ Integer division. Crashes the system if the second argument is zero. The result is unspecified if either argument is negative.
% Integer modulus. Crashes the system if the second argument is zero. The result is unspecified if either argument is negative.
^ String concatenation.
= Structural equality test.
<> Structural inequality test.
< Test ``less than''.
<= Test ``less than or equal''.
> Test ``greater than''.
>= Test ``greater than or equal''
|| Boolean disjunction
&& Boolean conjunction
not Boolean negation


Previous Contents Next