Previous Contents Next

3.9   Compilation units

A join-calculus program is made of compilation units, also called modules. The source for compilation units reside in different files.

A compilation unit mod is made of two source files: the interface source (in a mod.j file) implementation source (in a mod.ji file). The Interface specifies the objects that the module exports to the external world, while the implementation contains the join-calculus source for them. (See join-specification below).

Additionally, interfaces may be used to connect the join-calculus and Objective Caml, by specifying the join-calculus types of external objects defined in Objective Caml. (See caml-specification below).

3.9.1   Interfaces

module-type ::= { join-specification }
  | { caml-specification }
join-specification ::= val name :   typexpr
  | open module-name
caml-specification ::= external name :   typexpr =   string-literal
  | primitive name :   typexpr =   string-literal
  | type [ ( ' ident   { , ' ident } )]   typeconstr-name   [ = string-literal ]
  | open module-name

Value specifications

The specification of a value exported by an interface is written val name :   typexpr , where name is the name of the value and typexpr its expected type.

External specifications

The specification external name :   typexpr =   external-declaration , specifies that name may be used in join-calculus programs, with the type typexpr . The string external-declaration is an Objective Caml expression that is the actual definition of name . The exact nature of what is bound to name depends on the type typexpr . It can either be a primitive, when typexpr is synchronous channel type, or some basic or external value otherwise.

The form primitive name :   typexpr =   primitive-declaration is similar, except that name is implemented directly by join-calculus bytecode instructions, as specified in primitive-declaration . It is only used in the sys module from the standard library.

The type specification type [ ( ' ident   { , 'ident } )]   typeconstr-name informs the join-calculus compiler that typeconstr-name is a type constructor whose arity is given by the number of type variables in the part ' ident   { , 'ident } if present, and is zero otherwise. Parenthesis are optional when only one type variable ' ident is present.

The extended type specification type [ ( ' ident   { , 'ident } )]   typeconstr-name =   caml-type is similar, except that it specifies the Objective Caml type that implements typeconstr-name . This extra-information is used to generate automatic type coercions in calls of externals. It is in fact required for external modules written by users.

Opening a module

The expression open module-name in an interface does not specify any components. It simply affects the parsing of the following items of the interface, allowing components of the module denoted by module-name to be referred to by their simple names name instead of path accesses module-path .   name . The scope of the open stops at the end of the interface file.

3.9.2   Implementations

module-expr ::= { top-expr   [ ;;] }
top-expr ::= decl
  | do expr
  | spawn process
  | open module-name

Implementations evaluate by executing top-level expressions in the order they are given.

Value definitions

The declaration decl defines new values and bind them to new identifiers, in the same way that a decl in ... construct does (see 3.8.1). The scope of the defined names extends to the end of the implementation file. Such top-level bound values are the components of the module mod. They may or may not be visible from other modules, depending upon the interface file for mod. More precisely, a top-level defined variable name is exported form mod if the interface of mod contains a value specification for val name :   typexpr . Additionnaly, the exported type typexpr must be an instance of the type inferred by the compiler for the actual value that is bound to name .

Expression evaluation

The top-level expression do expr evaluate expression expr , which must return an empty result.

Process spawning

The top-level expression spawn process concurrently launches process and returns an empty result. This is equivalent to do spawn { process }.

Opening a module path

The declaration open module-name in an implementation does not define any components nor perform any bindings. It simply affects the parsing of the following items of the structure, allowing components of the module denoted by module-name to be referred to by their simple names name instead of path accesses module-name .   name . The scope of the open stops at the end of the implementation file.


Previous Contents Next