Chapter 9  The toplevel system (ocaml)

This chapter describes the toplevel system for OCaml, that permits interactive use of the OCaml system through a read-eval-print loop. In this mode, the system repeatedly reads OCaml phrases from the input, then typechecks, compile and evaluate them, then prints the inferred type and result value, if any. The system prints a # (sharp) prompt before reading each phrase.

Input to the toplevel can span several lines. It is terminated by ;; (a double-semicolon). The toplevel input consists in one or several toplevel phrases, with the following syntax:

toplevel-input::=definition }+ ;;  
  expr ;;  
  # ident  [ directive-argument ] ;;  
 
directive-argument::= string-literal  
  integer-literal  
  value-path  
  true ∣  false

A phrase can consist of a definition, like those found in implementations of compilation units or in structend module expressions. The definition can bind value names, type names, an exception, a module name, or a module type name. The toplevel system performs the bindings, then prints the types and values (if any) for the names thus defined.

A phrase may also consist in a value expression (section 6.7). It is simply evaluated without performing any bindings, and its value is printed.

Finally, a phrase can also consist in a toplevel directive, starting with # (the sharp sign). These directives control the behavior of the toplevel; they are listed below in section 9.2.

Unix:   The toplevel system is started by the command ocaml, as follows:
        ocaml options objects                # interactive mode
        ocaml options objects scriptfile        # script mode
options are described below. objects are filenames ending in .cmo or .cma; they are loaded into the interpreter immediately after options are set. scriptfile is any file name not ending in .cmo or .cma.

If no scriptfile is given on the command line, the toplevel system enters interactive mode: phrases are read on standard input, results are printed on standard output, errors on standard error. End-of-file on standard input terminates ocaml (see also the #quit directive in section 9.2).

On start-up (before the first phrase is read), if the file .ocamlinit exists in the current directory, its contents are read as a sequence of OCaml phrases and executed as per the #use directive described in section 9.2. The evaluation outcode for each phrase are not displayed. If the current directory does not contain an .ocamlinit file, but the user’s home directory (environment variable HOME) does, the latter is read and executed as described below.

The toplevel system does not perform line editing, but it can easily be used in conjunction with an external line editor such as ledit, ocaml2 or rlwrap (see the Caml Hump). Another option is to use ocaml under Gnu Emacs, which gives the full editing power of Emacs (command run-caml from library inf-caml).

At any point, the parsing, compilation or evaluation of the current phrase can be interrupted by pressing ctrl-C (or, more precisely, by sending the INTR signal to the ocaml process). The toplevel then immediately returns to the # prompt.

If scriptfile is given on the command-line to ocaml, the toplevel system enters script mode: the contents of the file are read as a sequence of OCaml phrases and executed, as per the #use directive (section 9.2). The outcome of the evaluation is not printed. On reaching the end of file, the ocaml command exits immediately. No commands are read from standard input. Sys.argv is transformed, ignoring all OCaml parameters, and starting with the script file name in Sys.argv.(0).

In script mode, the first line of the script is ignored if it starts with #!. Thus, it should be possible to make the script itself executable and put as first line #!/usr/local/bin/ocaml, thus calling the toplevel system automatically when the script is run. However, ocaml itself is a #! script on most installations of OCaml, and Unix kernels usually do not handle nested #! scripts. A better solution is to put the following as the first line of the script:

        #!/usr/local/bin/ocamlrun /usr/local/bin/ocaml
Windows:   In addition to the text-only command ocaml.exe, which works exactly as under Unix (see above), a graphical user interface for the toplevel is available under the name ocamlwin.exe. It should be launched from the Windows file manager or program manager. This interface provides a text window in which commands can be entered and edited, and the toplevel responses are printed.

1  Options

The following command-line options are recognized by the ocaml command.

-absname
Force error messages to show absolute paths for file names.
-I directory
Add the given directory to the list of directories searched for source and compiled files. By default, the current directory is searched first, then the standard library directory. Directories added with -I are searched after the current directory, in the order in which they were given on the command line, but before the standard library directory.

If the given directory starts with +, it is taken relative to the standard library directory. For instance, -I +labltk adds the subdirectory labltk of the standard library to the search path.

Directories can also be added to the list once the toplevel is running with the #directory directive (section 9.2).

-init file
Load the given file instead of the default initialization file. The default file is .ocamlinit in the current directory if it exists, otherwise .ocamlinit in the user’s home directory.
-labels
Labels are not ignored in types, labels may be used in applications, and labelled parameters can be given in any order. This is the default.
-no-app-funct
Deactivates the applicative behaviour of functors. With this option, each functor application generates new types in its result and applying the same functor twice to the same argument yields two incompatible structures.
-noassert
Do not compile assertion checks. Note that the special form assert false is always compiled because it is typed specially.
-nolabels
Ignore non-optional labels in types. Labels cannot be used in applications, and parameter order becomes strict.
-noprompt
Do not display any prompt when waiting for input.
-nopromptcont
Do not display the secondary prompt when waiting for continuation lines in multi-line inputs. This should be used e.g. when running ocaml in an emacs window.
-nostdlib
Do not include the standard library directory in the list of directories searched for source and compiled files.
-ppx command
After parsing, pipe the abstract syntax tree through the preprocessor command. The module Ast_mapper, described in chapter ??, implements the external interface of a preprocessor.
-principal
Check information paths during type-checking, to make sure that all types are derived in a principal way. When using labelled arguments and/or polymorphic methods, this flag is required to ensure future versions of the compiler will be able to infer types correctly, even if internal algorithms change. All programs accepted in -principal mode are also accepted in the default mode with equivalent types, but different binary signatures, and this may slow down type checking; yet it is a good idea to use it once before publishing source code.
-rectypes
Allow arbitrary recursive types during type-checking. By default, only recursive types where the recursion goes through an object type are supported.
-safe-string
Enforce the separation between types string and bytes, thereby making strings read-only. This will become the default in a future version of OCaml.
-short-paths
When a type is visible under several module-paths, use the shortest one when printing the type’s name in inferred interfaces and error and warning messages. Identifier names starting with an underscore _ or containing double underscores __ incur a penalty of +10 when computing their length.
-stdin
Read the standard input as a script file rather than starting an interactive session.
-strict-sequence
Force the left-hand part of each sequence to have type unit.
-strict-formats
Reject invalid formats that were accepted in legacy format implementations. You should use this flag to detect and fix such invalid formats, as they will be rejected by future OCaml versions.
-unsafe
See the corresponding option for ocamlc, chapter 8. Turn bound checking off on array and string accesses (the v.(i) and s.[i] constructs). Programs compiled with -unsafe are therefore slightly faster, but unsafe: anything can happen if the program accesses an array or string outside of its bounds.
-unsafe-string
Identify the types string and bytes, thereby making strings writable. For reasons of backward compatibility, this is the default setting for the moment, but this will change in a future version of OCaml.
-version
Print version string and exit.
-vnum
Print short version number and exit.
-w warning-list
Enable or disable warnings according to the argument warning-list. See section 8.2 for the syntax of the argument.
-warn-error warning-list
Mark as fatal the warnings enabled by the argument warning-list. See section 8.2 for the syntax of the argument.
-warn-help
Show the description of all available warning numbers.
- file
Use file as a script file name, even when it starts with a hyphen (-).
-help or --help
Display a short usage summary and exit.
Unix:   The following environment variables are also consulted:
LC_CTYPE
If set to iso_8859_1, accented characters (from the ISO Latin-1 character set) in string and character literals are printed as is; otherwise, they are printed as decimal escape sequences (\ddd).
TERM
When printing error messages, the toplevel system attempts to underline visually the location of the error. It consults the TERM variable to determines the type of output terminal and look up its capabilities in the terminal database.
HOME
Directory where the .ocamlinit file is searched.

2  Toplevel directives

The following directives control the toplevel behavior, load files in memory, and trace program execution.

Note: all directives start with a # (sharp) symbol. This # must be typed before the directive, and must not be confused with the # prompt displayed by the interactive loop. For instance, typing #quit;; will exit the toplevel loop, but typing quit;; will result in an “unbound value quit” error.

General
#help;;
Prints a list of all available directives, with corresponding argument type if appropriate.
#quit;;
Exit the toplevel loop and terminate the ocaml command.
Loading codes
#cd "dir-name";;
Change the current working directory.
#directory "dir-name";;
Add the given directory to the list of directories searched for source and compiled files.
#remove_directory "dir-name";;
Remove the given directory from the list of directories searched for source and compiled files. Do nothing if the list does not contain the given directory.
#load "file-name";;
Load in memory a bytecode object file (.cmo file) or library file (.cma file) produced by the batch compiler ocamlc.
#load_rec "file-name";;
Load in memory a bytecode object file (.cmo file) or library file (.cma file) produced by the batch compiler ocamlc. When loading an object file that depends on other modules which have not been loaded yet, the .cmo files for these modules are searched and loaded as well, recursively. The loading order is not specified.
#use "file-name";;
Read, compile and execute source phrases from the given file. This is textual inclusion: phrases are processed just as if they were typed on standard input. The reading of the file stops at the first error encountered.
#mod_use "file-name";;
Similar to #use but also wrap the code into a top-level module of the same name as capitalized file name without extensions, following semantics of the compiler.
Environment queries
#show_class class-path;;
#show_class_type class-path;;
#show_exception ident;;
#show_module module-path;;
#show_module_type modtype-path;;
#show_type typeconstr;;
#show_val value-path;;
Print the signature of the corresponding component.
#show ident;;
Print the signatures of components with name ident in all the above categories.
Pretty-printing
#install_printer printer-name;;
This directive registers the function named printer-name (a value path) as a printer for values whose types match the argument type of the function. That is, the toplevel loop will call printer-name when it has such a value to print.

The printing function printer-name should have type Format.formatter -> t -> unit, where t is the type for the values to be printed, and should output its textual representation for the value of type t on the given formatter, using the functions provided by the Format library. For backward compatibility, printer-name can also have type t -> unit and should then output on the standard formatter, but this usage is deprecated.

#print_depth n;;
Limit the printing of values to a maximal depth of n. The parts of values whose depth exceeds n are printed as ... (ellipsis).
#print_length n;;
Limit the number of value nodes printed to at most n. Remaining parts of values are printed as ... (ellipsis).
#remove_printer printer-name;;
Remove the named function from the table of toplevel printers.
Tracing
#trace function-name;;
After executing this directive, all calls to the function named function-name will be “traced”. That is, the argument and the result are displayed for each call, as well as the exceptions escaping out of the function, raised either by the function itself or by another function it calls. If the function is curried, each argument is printed as it is passed to the function.
#untrace function-name;;
Stop tracing the given function.
#untrace_all;;
Stop tracing all functions traced so far.
Compiler options
#labels bool;;
Ignore labels in function types if argument is false, or switch back to default behaviour (commuting style) if argument is true.
#ppx "file-name";;
After parsing, pipe the abstract syntax tree through the preprocessor command.
#principal bool;;
If the argument is true, check information paths during type-checking, to make sure that all types are derived in a principal way. If the argument is false, do not check information paths.
#rectypes;;
Allow arbitrary recursive types during type-checking. Note: once enabled, this option cannot be disabled because that would lead to unsoundness of the type system.
#warn_error "warning-list";;
Treat as errors the warnings enabled by the argument and as normal warnings the warnings disabled by the argument.
#warnings "warning-list";;
Enable or disable warnings according to the argument.

3  The toplevel and the module system

Toplevel phrases can refer to identifiers defined in compilation units with the same mechanisms as for separately compiled units: either by using qualified names (Modulename.localname), or by using the open construct and unqualified names (see section 6.3).

However, before referencing another compilation unit, an implementation of that unit must be present in memory. At start-up, the toplevel system contains implementations for all the modules in the the standard library. Implementations for user modules can be entered with the #load directive described above. Referencing a unit for which no implementation has been provided results in the error Reference to undefined global `...'.

Note that entering open Mod merely accesses the compiled interface (.cmi file) for Mod, but does not load the implementation of Mod, and does not cause any error if no implementation of Mod has been loaded. The error “reference to undefined global Mod” will occur only when executing a value or module definition that refers to Mod.

4  Common errors

This section describes and explains the most frequently encountered error messages.

Cannot find file filename
The named file could not be found in the current directory, nor in the directories of the search path.

If filename has the format mod.cmi, this means you have referenced the compilation unit mod, but its compiled interface could not be found. Fix: compile mod.mli or mod.ml first, to create the compiled interface mod.cmi.

If filename has the format mod.cmo, this means you are trying to load with #load a bytecode object file that does not exist yet. Fix: compile mod.ml first.

If your program spans several directories, this error can also appear because you haven’t specified the directories to look into. Fix: use the #directory directive to add the correct directories to the search path.

This expression has type t1, but is used with type t2
See section 8.4.
Reference to undefined global mod
You have neglected to load in memory an implementation for a module with #load. See section 9.3 above.

5  Building custom toplevel systems: ocamlmktop

The ocamlmktop command builds OCaml toplevels that contain user code preloaded at start-up.

The ocamlmktop command takes as argument a set of .cmo and .cma files, and links them with the object files that implement the OCaml toplevel. The typical use is:

        ocamlmktop -o mytoplevel foo.cmo bar.cmo gee.cmo

This creates the bytecode file mytoplevel, containing the OCaml toplevel system, plus the code from the three .cmo files. This toplevel is directly executable and is started by:

        ./mytoplevel

This enters a regular toplevel loop, except that the code from foo.cmo, bar.cmo and gee.cmo is already loaded in memory, just as if you had typed:

        #load "foo.cmo";;
        #load "bar.cmo";;
        #load "gee.cmo";;

on entrance to the toplevel. The modules Foo, Bar and Gee are not opened, though; you still have to do

        open Foo;;

yourself, if this is what you wish.

6  Options

The following command-line options are recognized by ocamlmktop.

-cclib libname
Pass the -llibname option to the C linker when linking in “custom runtime” mode. See the corresponding option for ocamlc, in chapter 8.
-ccopt option
Pass the given option to the C compiler and linker, when linking in “custom runtime” mode. See the corresponding option for ocamlc, in chapter 8.
-custom
Link in “custom runtime” mode. See the corresponding option for ocamlc, in chapter 8.
-I directory
Add the given directory to the list of directories searched for compiled object code files (.cmo and .cma).
-o exec-file
Specify the name of the toplevel file produced by the linker. The default is a.out.