Chapter 9 | The toplevel system (ocaml)

This chapter describes the toplevel system for Objective Caml, that permits interactive use of the Objective Caml system through a read-eval-print loop. In this mode, the system repeatedly reads Caml 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` | ::= | { `toplevel-phrase` } `;;`
`toplevel-phrase` | ::= | `definition`
| | | `expr`
| | | `#` `ident` `directive-argument`
`definition` | ::= | `let` [`rec`] `let-binding` { `and` `let-binding` }
| | | `external` `value-name` `:` `typexpr` `=` `external-declaration`
| | | `type-definition`
| | | `exception-definition`
| | | `module` `module-name` [ `:` `module-type` ] `=` `module-expr`
| | | `module` `type` `modtype-name` `=` `module-type`
| | | `open` `module-path`
`directive-argument` | ::= | `nothing`
| | | `string-literal`
| | | `integer-literal`
| | | `value-path`

A phrase can consist of a definition, similar to those found in implementations of compilation units or in `struct` ... `end` 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 `open` directive (see section 6.11), or a value expression (section 6.7). Expressions are simply evaluated, without performing any bindings, and the value of the expression 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               # interactive mode
>             ocaml options scriptfile        # script mode

> If no filename 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 Objective Caml phrases and executed as per the `#use` directive described in section 9.2. The evaluation outcode for each phrase are not displayed.
> The toplevel system does not perform line editing, but it can easily be used in conjunction with an external line editor such as `fep`; just run `fep -emacs ocaml` or `fep -vi ocaml`. Another option is to use `ocaml` under Gnu Emacs, which gives the full editing power of Emacs (see the subdirectory `emacs` of the Objective Caml distribution).
> 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 `sigintr` signal to the `ocaml` process). The toplevel then immediately returns to the `#` prompt.
> If a filename 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 Objective Caml 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 Objective Caml 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 is theoretically 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 Objective Caml, and Unix kernels usually do not handle nested `#!` scripts.

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.
> The ``Terminal'' windows is split in two panes. Phrases are entered and edited in the bottom pane. The top pane displays a copy of the input phrases as they are processed by the Caml Light toplevel, interspersed with the toplevel responses. The ``Return'' key sends the contents of the bottom pane to the Caml Light toplevel. The ``Enter'' key inserts a newline without sending the contents of the Input window. (This can be configured with the ``Preferences'' menu item.)
> The contents of the input window can be edited at all times, with the standard Windows interface. An history of previously entered phrases is maintained and displayed in a separate window.
> To quit the `Camlwin` application, either select ``Quit'' from the ``File'' menu, or use the `quit` function described below.
> At any point, the parsing, compilation or evaluation of the current phrase can be interrupted by selecting the ``Interrupt Caml Light'' menu item. This goes back to the `#` prompt.

9.1 | Options

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

`-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 search path once the toplevel is running with the `#directory` directive (section 9.2).
`-labels`
  Switch to the commuting label mode of compilation, meaning that labeling rules are applied strictly, and commutation between arguments is allowed. (See section 4.1.4.)
`-rectypes`
  Allow arbitrary recursive types during type-checking. By default, only recursive types where the recursion goes through an object type are supported.
`-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.
`-w` warning-list
  Enable or disable warnings according to the argument warning-list.

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.

9.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.

`#quit;;`
  Exit the toplevel loop and terminate the `ocaml` command.
`#labels` bool`;;`
  Switch to commuting label style if argument is `true`, or back to classic (non-commuting) style if argument is `false`. (See section 4.1.4.)
`#warnings "`warning-list`";;`
  Enable or disable warnings according to the argument.
`#directory "`dir-name`";;`
  Add the given directory to the list of directories searched for source and compiled files.
`#cd "`dir-name`";;`
  Change the current working directory.
`#load "`file-name`";;`
  Load in memory a bytecode object file (`.cmo` file) produced by the batch compiler `ocamlc`.
`#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.
`#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.
`#remove``_``printer` printer-name`;;`
  Remove the named function from the table of toplevel printers.
`#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.
`#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).

9.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.

9.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.

9.5 | Building custom toplevel systems: `ocamlmktop`

The `ocamlmktop` command builds Objective Caml 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 Objective Caml toplevel. The typical use is:

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

This creates the bytecode file `mytoplevel`, containing the Objective Caml 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.

9.6 | Options

The following command-line options are recognized by `ocamlmktop`.

`-cclib` libname
  Pass the `-l` libname 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`.