The need to have two modules reference one another often occurs when building systems. In OmniMark solves this problem by providing a mechanism to split a module into an interface definition module and an implementation module. The interface module contains all of the exported definitions and the implementation module contains the execution code that implements the exported functionality. This division of the module allows users to have modules that directly reference or import one another's definitions. The following example shows a module declaration for an interface:
; points.xif module interface shared as "points.xif" export record point field integer x field integer y export point function plot (value integer x, value integer y) elsewhere
The implementation of this module might read like this:
; points.xmp module implements "points.xif" export record point field integer x initial { 0 } field integer y initial { 0 } export point function plot (value integer x, value integer y) as local point p set p:x to x set p:y to y return p
The standard suffix for a module interface file is .xif
(pronounced zif
), while the standard suffix for a module implementation file is .xmp
(pronounced chimp
).
This example demonstrates how interface and implementation modules are to be used:
; main.xom import "point.xif" unprefixed process local point p set p to point (7, 12) import "point.xmp" unprefixed
To use the split modules, you have to include both of them in your program
like this:
import "point.xif" unprefixed import "point.xmp" unprefixed
It is not necessary to have them one after the other, but they both must be imported. The interface module must be imported before the first use of one of the exported types, variables or functions occurs.
An interface module can contain:
Only shared modules can be split into interfaces and implementation modules.
An interface module cannot contain code or initial values. Therefore, it cannot contain
The implementation module contains the definitions for everything defined in the interface file, as well as the definitions of any private things that it may require. An implementation module can only export those things declared in its interface module. It is not permitted to extend the interface in any way.
Interface and implementation modules solve the problem of mutually-recursive imports, just like function pre-definitions solve the problem of mutually-recursive functions.