The expression module-path evaluates to the module bound to the name
module-path.

The expression (module-expr) evaluates to the same module as
module-expr.

The expression (module-expr:module-type) checks that the
type of module-expr is a subtype of module-type, that is, that all
components specified in module-type are implemented in
module-expr, and their implementation meets the requirements given
in module-type. In other terms, it checks that the implementation
module-expr meets the type specification module-type. The whole
expression evaluates to the same module as module-expr, except that
all components not specified in module-type are hidden and can no
longer be accessed.

Structures struct ... end are collections of definitions for
value names, type names, exceptions, module names and module type
names. The definitions are evaluated in the order in which they appear
in the structure. The scope of the bindings performed by the
definitions extend to the end of the structure. As a consequence, a
definition may refer to names bound by earlier definitions in the same
structure.

For compatibility with toplevel phrases (chapter 9)
and with Caml Light, an optional ;; is allowed after each
definition in a structure. The ;; has no semantic meaning. Also for
compatibility, ;;expr is allowed as a component of a structure,
meaning let_=expr, i.e. evaluate expr for its side-effects.

Value definitions

A value definition let [rec] let-binding { andlet-binding }
bind value names in the same way as a let ... in ... expression
(see section 6.7.1). The value names appearing in the
left-hand sides of the bindings are bound to the corresponding values
in the right-hand sides.

A definition of one or several type components is written
typetypedef { andtypedef } and consists of a sequence
of mutually recursive definitions of type names.

Exception definitions

Exceptions are defined with the syntax exceptionconstr-decl
or exceptionconstr-name=constr.

Class definitions

A definition of one or several classes is written classclass-binding { andclass-binding } and consists of a sequence of
mutually recursive definitions of class names. Class definitions are
described more precisely in section 6.9.3.

Class type definitions

A definition of one or several classes is written
classtypeclasstype-def { andclasstype-def } and consists of
a sequence of mutually recursive definitions of class type names.
Class type definitions are described more precisely in
section 6.9.5.

Module definitions

The basic form for defining a module component is
modulemodule-name=module-expr, which evaluates module-expr and binds
the result to the name module-name.

A definition for a module type is written
moduletypemodtype-name=module-type.
It binds the name modtype-name to the module type denoted by the
expression module-type.

Opening a module path

The expression openmodule-path in a structure 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-path 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 structure expression.

Including the components of another structure

The expression include module-expr in a structure re-exports in
the current structure all definitions of the structure denoted by
module-expr. For instance, if the identifier S is bound to the
module

struct type t = int let x = 2 end

the module expression

struct include S let y = (x + 1 : t) end

is equivalent to the module expression

struct type t = int let x = 2 let y = (x + 1 : t) end

The difference between open and include is that open
simply provides short names for the components of the opened
structure, without defining any components of the current structure,
while include also adds definitions for the components of the
included structure.

The expression functor(module-name:module-type)->module-expr evaluates to a functor that takes as argument modules of
the type module-type1, binds module-name to these modules,
evaluates module-expr in the extended environment, and returns the
resulting modules as results. No restrictions are placed on the type of the
functor argument; in particular, a functor may take another functor as
argument (``higher-order'' functor).

Functor application

The expression module-expr1(module-expr2) evaluates
module-expr1 to a functor and module-expr2 to a module, and
applies the former to the latter. The type of module-expr2 must
match the type expected for the arguments of the functor module-expr1.