Libraries and namespaces


Defines the library and namespace mechanism for occam-pi.


Fred Barnes <F.R.M.Barnes@kent.ac.uk>






language modules libraries namespaces

occam-pi currently provides no module system, making libraries awkward to use: the programmer must use the USE directive to indicate to the compiler that a library is being used along with the INCLUDE directive to pull in any related header files, and also supply any necessary -l flags to the kroc program to link with the correct shared libraries. The same information must be supplied in three different ways.

Building libraries is equally complex: an lbb file must be written listing all the tce files in the library, and the ilibr program invoked to build an lbb file; the native linker must also be used to build a corresponding shared library from the object files. No automatic provision is made for libraries that depend upon other occam-pi libraries or upon system libraries.

occam-pi has no concept of namespaces or private symbols, so all symbols declared in libraries -- even internal helper PROCs -- must be globally unique. Collisions are a common problem. This is solved in Python and Haskell by importing library symbols into a new namespace by default, and allowing the programmer to selectively import the symbols they want into the current namespace (with a different name if necessary, which is often useful for choosing between several modules providing the same functionality). Such a mechanism could be provided within occam-pi, where library PROCs are often already named in a way that suggests appropriate namespaces:

PROC out.string (VAL []BYTE str, VAL INT align, CHAN BYTE out!)
PROC out.int (VAL INT n, align, CHAN BYTE out!)

This proposal defines a naming mechanism for library routines, as well as for controlling which procedures and functions in a library are exported. The proposal follows the current implementation in the NOCC compiler.

Files that contribute code to libraries specify the name of the library with a #LIBRARY directive. Indented under this are various optional settings which can control what happens when a library is #USEd by other code. For instance:

#LIBRARY "mylib"
  NAMESPACE "mylib"
  NATIVELIB "libmylib.so"
  INCLUDES "mylib.inc"
  USES "otherlib"

NAMESPACE and NATIVELIB may be specified once each; they define the default namespace and native-code library. If the NAMESPACE is not specified, the library name is used as a default.

Multiple INCLUDES and USES options may be given. These specify additional include-files or libraries that are required in order to use this library.

Within a library itself, routines which are to be exported must be declared PUBLIC. For example:

PUBLIC PROC version (RESULT INT major, minor, patch)

Routines in libraries built this way can be accessed using the existing syntax:

#USE "mylib"

This imports the publicly visible routines in the given library, using its default namespace -- for example, the above version procedure would be visible as mylib.version. A library may also be imported into a different namespace:

#USE "mylib" AS "thing"

The version routine in the library would then be visible as thing.version. One use for this is to switch between multiple libraries that provide the same functionality (a common and useful technique in Python); for example:

#USE "gtk" AS "toolkit"
#USE "qt" AS "toolkit"

This namespace mechanism also works on separately #USEd files, allowing them to be pulled into a particular namespace.

As is apparent in the code fragments above, the namespace separator is a dot . (as used in languages such as Java). The dot can also form part of valid identifiers, producing slightly odd names such as mylib.show.version (where show.version is a routine in the mylib namespace). This should not present any problems, however, as the compiler will ensure that all names are distinct. An alternative would be to use a different character such as _ (or make . illegal in names, and then use .).

The mechanism described here does not have a concept of a default namespace, so a lone version call would not resolve correctly (the namespace must be given).

OEP/130 (last edited 2007-09-27 00:48:23 by ats1)