Next: Usage inference and the
Up: 3. System Description
Previous: 3.3 File Names and
Contents
Index
3.4 The Module System of XSB
XSB has been designed as a module-oriented Prolog system. Modules
provide a small step towards logic programming ``in the large''
that facilitates large programs or projects to be put together from
components which can be developed, compiled and tested separately.
Also module systems support the principle of information hiding
and can provide a basis for data abstraction. The module system
of XSB is file based - one module per file - and flat -
modules cannot be nested. In addition, XSB's module system is to some
extent atom-based, where any symbol in a module can be imported,
exported or be a local symbol, as opposed to the predicate-based ones
where this can be done only for predicate symbols 3.3.
By default, files are not treated as modules. In order for a file to
be treated as a module, it must contain one or more export
declarations, which specify that a set of symbols appearing in that
module is visible and therefore can be used by any other module. In
XSB, the module name is equal to the base file name in which the
module is defined. Any file (either module or not) may also contain
import declarations, which allow symbols defined in and exported
by other modules to be used in the current module. In addition, a
module can also contain local declarations, which specify that a
set of symbols are visible by this module only, and therefore
cannot be accessed by any other module. Export, local, and import
declarations can appear anywhere in the source or header files and
have the following forms:
The module system of XSB is file based (one module per
file), atom based (where all non-predicate symbols are normally
assumed to be global to all modules), and flat (modules cannot
:- export
, ...,
.
:- local
, ...,
.
:- import
, ...,
from
.
where
has the form
, and
is a module
name.
We note that only exported symbols can be imported; for example
importing a local symbol will cause an environment conflict
error when the file referred to by the import statement is loaded.
When a non-module file is loaded, its predicates and symbols are
loaded into the module usermod, which is the working module of
the XSB interpreter. Dynamically asserted code is also loaded into
usermod.
For modules, the base file name is stored in its byte code file, which
means that if the byte code file is renamed, the base file name is not
altered, and hence may cause confusion to the user and/or the system.
However, byte code files generated for non-modules can be safely
renamed.
In order to understand the semantics of modules, the user should keep
in mind that in a module oriented system, the name of each symbol is
identified as if it were prefixed with its module name (equivalently
its base file name), hence two symbols of the same
but
different module prefixes are distinct symbols. Currently the
following set of rules is used to determine the module prefix of a
symbol:
- Every predicate symbol appearing in a module (i.e. that appears as
the head of some clause) is assumed by default to be local to that module unless it is declared otherwise (via an
export or import declaration). Symbols that are local to a
given module are not visible to other modules.
- Every other symbol (essentially function symbols) in a module is
assumed to be global (its module prefix is usermod) unless declared otherwise.
- If a symbol is imported from another module (via an explicit import
declaration), the module prefix of the symbol is the module it
is imported from; any other symbol takes the module where the
symbol occurs as its module prefix.
- The XSB command-line interpreter treats usermod as its
working module.
- Symbols that are either defined in non-modules loaded into the
system or that are dynamically created (by the use of standard
predicates such as read/1, functor/3, '=..'/2, etc) are
contained in usermod3.4.
The following facts about the module system of XSB may not be
immediately obvious:
- If users want to use a symbol from another module, they must
explicitly import it otherwise the two symbols are different
even if they are of the same
form.
- A module can only export predicate symbols that are defined in
that module. As a consequence, a module cannot export
predicate symbols that are imported from other modules.
This happens because an import declaration is just a
request for permission to use a symbol from a module where
its definition and an export declaration appear.
- The implicit module for a particular symbol appearing in a
module must be uniquely determined. As a consequence, a
symbol of a specific
cannot be declared
as both exported and local, or both exported and imported from
another module, or declared to be imported from more than one
module, etc. These types of environment conflicts are
detected at compile-time and abort the compilation.
- It is an error to import a symbol from a module that does not
export it. This error is not detected at compile-time
but at run-time when a call to that symbol is made. If the
symbol is defined in, but not exported from the module that
defines it, an environment conflict error will take place.
If the symbol is not defined in that module an undefined
predicate/function error will be be reported to the user.
- In the current implementation, at any time only one symbol of
a specific
form can appear in a module. As an
immediate consequence of this fact, only one
symbol can be loaded into the current working module ( usermod). An attempt to load a module that redefines that
symbol results in a warning to the user and the newly loaded
symbol overrides the definition of the previously loaded
one.
Subsections
Next: Usage inference and the
Up: 3. System Description
Previous: 3.3 File Names and
Contents
Index
Terrance Swift
2007-10-05