The Twelf implementation defines a number of ML functions embedded in
structures which can be called to load files, execute queries, and set
environment parameters such as the verbosity level of the interaction.
These functions and parameters are available in the Twelf
structure. If you open the Twelf structure with

open Twelf

after compiling and loading Twelf, you do not have to type the
`Twelf.' to the functions shown below.

Previous implementations of Elf offered a stand-alone command
interpreter but this has not yet been ported. To exit Twelf and
ML call Twelf.OS.exit ();.

Groups of Twelf files are managed in configurations. A
configuration is defined by a file, by convention called
`sources.cfg', which resides in the same directory as the Twelf
source files. The configuration file must contain at most one
Twelf source file per line, and the files must be listed in
dependency order. A configuration config can then be
defined from the file by the ML declaration

val config = Twelf.Config.read "sources.cfg";

By convention, the filenames end in the extensions

`.elf'

for constant declarations and definitions or mixed files,

`.quy'

for files which contain query declarations,

`.thm'

for files which contain %theorem and %proof declarations.

File names may not contain whitespace. They are interpreted relative to
the current working directory of ML, but resolved into absolute path
names when the configuration file is read. To change the current
working directory call

As an example, we show how the Mini-ML configuration is defined and
loaded, assuming your current working directory is the root directory of
Twelf.

Twelf.make "examples/mini-ml/sources.cfg";

The call to Twelf.make returns either Twelf.OK or
Twelf.ABORT. It reads each file in turn, starting from an empty
signature, printing the results of type reconstruction and search based
on the value of the Twelf.chatter variable (see section 10.3 Environment Parameters). If another configuration or file has previously been
read, all the declarations will first be deleted so that
Twelf.make always starts from the same state.

Loading a configuration will stop at the first error encountered, issue
an appropriate message and return Twelf.ABORT. If there is an
unexpected internal error (which indicates a bug in the Twelf
implementation), it raises an uncaught exception instead and returns
to the ML top-level.

To explore the behavior of programs interactively, you may call the
Twelf top-level with

Twelf also allows direct management of the signature by loading
individual files. This is generally not recommended because successive
declarations simply accumulate in the global signature which may lead to
unexpected behavior. The relevant function calls are

Twelf.reset ();
Twelf.loadFile "file";

where Twelf.reset () resets the current global signature to
be empty and Twelf.readFile "file" loads the given
file whose name is interpreted relative to the current working
directory.

Caution: Reading a file twice will not replace the declarations
of the first pass by the second, but simply add them to the current
signature. If names are reused, old declarations will be shadowed, but
they are still in the global signature and might be used in the search
for a solution to a query or in theorem proving, leading to unexpected
behavior. When in doubt, use configurations (see section 10.1 Configurations) or
call Twelf.reset ().

Various flags and parameters can be used to modify the behavior of Twelf
and the messages it issues. They are given below with the assignment
of the default value.

Twelf.chatter := 3;

Controls the detail of the information which is printed when signatures
are read.

0

Nothing.

1

Just file names.

2

File names and number of query solutions.

3

Each declarations after type reconstruction.

4

Debug information.

5

More debug information.

Twelf.doubleCheck := false;

If true, each declaration is checked again for type correctness
after type reconstruction. This is expensive and useful only for your
peace of mind, since type checking is significantly simpler than
type reconstruction.

Twelf.unsafe := false;

If true it will allow the %assert declaration to assert
theorems without proof.

The first prints the signature, using only forward arrows ->, the
second will print the signature interpreted as a logic programming using
backward arrows <-. Depending on your goals, one or the other
might be easier to use.

Output can also be generated in TeX format. The necessary library
files can be found in the `tex/' subdirectory of the distribution.
To print the current signature using TeX format, use

Twelf.Print.TeX.sgn ();
Twelf.Print.TeX.prog ();

with the same interpretation as the plain text printing commands
above.

Twelf no incorporates some rudimentary tracing facilities for
the logic programming interpreter of signatures. This is best used
within the Emacs server, but it is also available within the ML
Interface.

A tracing specification may be associated with constants in
a signature.

Twelf has a few utilities to collect run-time statistics which are
useful mainly for the developers. They are collected in the
structure Timers. Timing information is cumulative
in an ML session.

Twelf.Timers.show ();

Show the value of timers and reset them to zero.

Twelf.Timers.reset ();

Simply reset all timers to zero.

Twelf.Timers.check ();

Display the value of timers, but do not reset them.

Caution: Normally, the various times are exclusive, except that
the runtime includes the garbage collection time which is shown
separately. However, there is a problem the time for printing the
answer substitution to a query is charged both to Printing and
Solving.