Chapter 10 The toplevel system or REPL (ocaml)

This chapter describes the toplevel system for OCaml, that permitsinteractive use of the OCaml systemthrough a read-eval-print loop (REPL). In this mode, the system repeatedlyreads OCaml phrases from the input, then typechecks, compile andevaluate them, then prints the inferred type and result value, ifany. The system prints a # (sharp) prompt before reading eachphrase.

Input to the toplevel can span several lines. It is terminated by ;; (adouble-semicolon). The toplevel input consists in one or severaltoplevel 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 inimplementations of compilation units or in struct … endmodule expressions. The definition can bind value names, type names,an exception, a module name, or a module type name. The toplevelsystem performs the bindings, then prints the types and values (ifany) for the names thus defined.

A phrase may also consist in a value expression(section 7.7). It is simply evaluatedwithout performing any bindings, and its value isprinted.

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

Unix:The toplevel system is started by the command ocaml, as follows:
  1. ocaml options objects # interactive mode ocaml options objects scriptfile # script mode
options are described below.objects are filenames ending in .cmo or .cma; they areloaded 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 systementers interactive mode: phrases are read on standard input, resultsare printed on standard output, errors on standard error. End-of-fileon standard input terminates ocaml (see also the #quit directivein section 10.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 phrasesand executed as per the #use directivedescribed in section 10.2.The evaluation outcode for each phrase are not displayed.If the current directory does not contain an .ocamlinit file, butthe user’s home directory (environment variable HOME) does, thelatter is read and executed as described below.

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

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

If scriptfile is given on the command-line to ocaml, the toplevelsystem enters script mode: the contents of the file are read as asequence of OCaml phrases and executed, as per the #usedirective (section 10.2). The outcome of theevaluation is not printed. On reaching the end of file, the ocamlcommand exits immediately. No commands are read from standard input.Sys.argv is transformed, ignoring all OCaml parameters, andstarting with the script file name in Sys.argv.(0).

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

  1. #!/usr/local/bin/ocamlrun /usr/local/bin/ocaml

10.1 Options

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

  • -absname
  • Force error messages to show absolute paths for file names.
  • -argsfilename
  • Read additional newline-terminated command line arguments from filename.It is not possible to pass a scriptfile via file to the toplevel.
  • -args0filename
  • Read additional null character terminated command line arguments fromfilename.It is not possible to pass a scriptfile via file to the toplevel.
  • -Idirectory
  • Add the given directory to the list of directories searched forsource and compiled files.By default, the current directory is searched first, then the standardlibrary directory. Directories added with -I are searched after thecurrent directory, in the order in which they were given on the command line,but before the standard library directory. See also option -nostdlib.If the given directory starts with +, it is taken relative to thestandard library directory. For instance, -I +unix adds thesubdirectory unix of the standard library to the search path.

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

  • -initfile
  • Load the given file instead of the default initialization file.The default file is .ocamlinit in the current directory if itexists, 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 andapplying the same functor twice to the same argument yields twoincompatible structures.
  • -noassert
  • Do not compile assertion checks. Note that the special formassert false is always compiled because it is typed specially.
  • -nolabels
  • Ignore non-optional labels in types. Labels cannot be used inapplications, 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 continuationlines in multi-line inputs. This should be used e.g. when runningocaml in an emacs window.
  • -nostdlib
  • Do not include the standard library directory in the list ofdirectories searched for source and compiled files.
  • -ppxcommand
  • After parsing, pipe the abstract syntax tree through the preprocessorcommand. The module Ast_mapper, described inchapter 24:Ast_mapper,implements the external interface of a preprocessor.
  • -principal
  • Check information path during type-checking, to make sure that alltypes are derived in a principal way. When using labelled argumentsand/or polymorphic methods, this flag is required to ensure futureversions of the compiler will be able to infer types correctly, evenif internal algorithms change.All programs accepted in -principal mode are also accepted in thedefault mode with equivalent types, but different binary signatures,and this may slow down type checking; yet it is a good idea touse 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 typeare supported.
  • -safe-string
  • Enforce the separation between types string and bytes,thereby making strings read-only. This is the default.
  • -short-paths
  • When a type is visible under several module-paths, use the shortestone when printing the type’s name in inferred interfaces and error andwarning messages. Identifier names starting with an underscore orcontaining double underscores _ incur a penalty of +10 when computingtheir length.
  • -stdin
  • Read the standard input as a script file rather than starting aninteractive 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 formatimplementations. You should use this flag to detect and fix suchinvalid formats, as they will be rejected by future OCaml versions.
  • -unsafe
  • Turn bound checking off for array and string accesses (the v.(i) ands.[i] constructs). Programs compiled with -unsafe are therefore faster, but unsafe: anything can happen if the programaccesses an array or string outside of its bounds.
  • -unsafe-string
  • Identify the types string and bytes, thereby making strings writable.This is intended for compatibility with old source code and should notbe used with new software.
  • -v
  • Print the version number of the compiler and the location of thestandard library directory, then exit.
  • -verbose
  • Print all external commands before they are executed,Useful to debug C library problems.
  • -version
  • Print version string and exit.
  • -vnum
  • Print short version number and exit.
  • -no-version
  • Do not print the version banner at startup.
  • -wwarning-list
  • Enable, disable, or mark as fatal the warnings specified by the argumentwarning-list.Each warning can be enabled or disabled, and each warningcan be fatal or non-fatal.If a warning is disabled, it isn’t displayed and doesn’t affectcompilation in any way (even if it is fatal). If a warning isenabled, it is displayed normally by the compiler whenever the sourcecode triggers it. If it is enabled and fatal, the compiler will alsostop with an error after displaying it.The warning-list argument is a sequence of warning specifiers,with no separators between them. A warning specifier is one of thefollowing:

    • +num
    • Enable warning number num.
    • -num
    • Disable warning number num.
    • @num
    • Enable and mark as fatal warning number num.
    • +num1..num2
    • Enable warnings in the given range.
    • -num1..num2
    • Disable warnings in the given range.
    • @num1..num2
    • Enable and mark as fatal warnings inthe given range.
    • +letter
    • Enable the set of warnings corresponding toletter. The letter may be uppercase or lowercase.
    • -letter
    • Disable the set of warnings corresponding toletter. The letter may be uppercase or lowercase.
    • @letter
    • Enable and mark as fatal the set of warningscorresponding to letter. The letter may be uppercase orlowercase.
    • uppercase-letter
    • Enable the set of warnings correspondingto uppercase-letter.
    • lowercase-letter
    • Disable the set of warnings correspondingto lowercase-letter.Warning numbers and letters which are out of the range of warningsthat are currently defined are ignored. The warnings are as follows.

    • 1

    • Suspicious-looking start-of-comment mark.
    • 2
    • Suspicious-looking end-of-comment mark.
    • 3
    • Deprecated synonym for the ’deprecated’ alert
    • 4
    • Fragile pattern matching: matching that will remain complete evenif additional constructors are added to one of the variant typesmatched.
    • 5
    • Partially applied function: expression whose result has functiontype and is ignored.
    • 6
    • Label omitted in function application.
    • 7
    • Method overridden.
    • 8
    • Partial match: missing cases in pattern-matching.
    • 9
    • Missing fields in a record pattern.
    • 10
    • Expression on the left-hand side of a sequence that doesn’t have typeunit (and that is not a function, see warning number 5).
    • 11
    • Redundant case in a pattern matching (unused match case).
    • 12
    • Redundant sub-pattern in a pattern-matching.
    • 13
    • Instance variable overridden.
    • 14
    • Illegal backslash escape in a string constant.
    • 15
    • Private method made public implicitly.
    • 16
    • Unerasable optional argument.
    • 17
    • Undeclared virtual method.
    • 18
    • Non-principal type.
    • 19
    • Type without principality.
    • 20
    • Unused function argument.
    • 21
    • Non-returning statement.
    • 22
    • Preprocessor warning.
    • 23
    • Useless record with clause.
    • 24
    • Bad module name: the source file name is not a valid OCaml module name.
    • 25
    • Deprecated: now part of warning 8.
    • 26
    • Suspicious unused variable: unused variable that is boundwith let or as, and doesn’t start with an underscore (_)character.
    • 27
    • Innocuous unused variable: unused variable that is not bound withlet nor as, and doesn’t start with an underscore (_)character.
    • 28
    • Wildcard pattern given as argument to a constant constructor.
    • 29
    • Unescaped end-of-line in a string constant (non-portable code).
    • 30
    • Two labels or constructors of the same name are defined in twomutually recursive types.
    • 31
    • A module is linked twice in the same executable.
    • 32
    • Unused value declaration.
    • 33
    • Unused open statement.
    • 34
    • Unused type declaration.
    • 35
    • Unused for-loop index.
    • 36
    • Unused ancestor variable.
    • 37
    • Unused constructor.
    • 38
    • Unused extension constructor.
    • 39
    • Unused rec flag.
    • 40
    • Constructor or label name used out of scope.
    • 41
    • Ambiguous constructor or label name.
    • 42
    • Disambiguated constructor or label name (compatibility warning).
    • 43
    • Nonoptional label applied as optional.
    • 44
    • Open statement shadows an already defined identifier.
    • 45
    • Open statement shadows an already defined label or constructor.
    • 46
    • Error in environment variable.
    • 47
    • Illegal attribute payload.
    • 48
    • Implicit elimination of optional arguments.
    • 49
    • Absent cmi file when looking up module alias.
    • 50
    • Unexpected documentation comment.
    • 51
    • Warning on non-tail calls if @tailcall present.
    • 52 (see 9.5.2)
    • Fragile constant pattern.
    • 53
    • Attribute cannot appear in this context
    • 54
    • Attribute used more than once on an expression
    • 55
    • Inlining impossible
    • 56
    • Unreachable case in a pattern-matching (based on type information).
    • 57 (see 9.5.3)
    • Ambiguous or-pattern variables under guard
    • 58
    • Missing cmx file
    • 59
    • Assignment to non-mutable value
    • 60
    • Unused module declaration
    • 61
    • Unboxable type in primitive declaration
    • 62
    • Type constraint on GADT type declaration
    • 63
    • Erroneous printed signature
    • 64
    • -unsafe used with a preprocessor returning a syntax tree
    • 65
    • Type declaration defining a new ’()’ constructor
    • 66
    • Unused open! statement
    • A
    • all warnings
    • C
    • warnings 1, 2.
    • D
    • Alias for warning 3.
    • E
    • Alias for warning 4.
    • F
    • Alias for warning 5.
    • K
    • warnings 32, 33, 34, 35, 36, 37, 38, 39.
    • L
    • Alias for warning 6.
    • M
    • Alias for warning 7.
    • P
    • Alias for warning 8.
    • R
    • Alias for warning 9.
    • S
    • Alias for warning 10.
    • U
    • warnings 11, 12.
    • V
    • Alias for warning 13.
    • X
    • warnings 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 30.
    • Y
    • Alias for warning 26.
    • Z
    • Alias for warning 27.The default setting is -w +a-4-6-7-9-27-29-32..42-44-45-48-50-60.It is displayed by -help.Note that warnings 5 and 10 are not always triggered, depending onthe internals of the type checker.
  • -warn-errorwarning-list

  • Mark as fatal the warnings specified in the argument warning-list.The compiler will stop with an error when one of these warnings isemitted. The warning-list has the same meaning as forthe -w option: a + sign (or an uppercase letter) marks thecorresponding warnings as fatal, a -sign (or a lowercase letter) turns them back into non-fatal warnings,and a @ sign both enables and marks as fatal the correspondingwarnings.Note: it is not recommended to use warning sets (i.e. letters) asarguments to -warn-errorin production code, because this can break your build when future versionsof OCaml add some new warnings.

The default setting is -warn-error -a+31 (only warning 31 is fatal).

  • -warn-help
  • Show the description of all available warning numbers.
  • -file
  • Use file as a script file name, even when it starts with ahyphen (-).
  • -help or —help
  • Display a short usage summary and exit.
Unix:The following environment variables are also consulted:
OCAMLTOP_INCLUDE_PATH
Additional directories to search for compiledobject code files (.cmi, .cmo and .cma). The specified directories areconsidered from left to right, after the include directories specified on thecommand line via -I have been searched. Available since OCaml 4.08.
OCAMLTOP_UTF_8
When printing string values, non-ascii bytes( > \0x7E ) are printed as decimal escape sequence if OCAMLTOP_UTF_8 isset to false. Otherwise, they are printed unescaped.
TERM
When printing error messages, the toplevel systemattempts to underline visually the location of the error. Itconsults the TERM variable to determines the type of output terminaland look up its capabilities in the terminal database.
HOME
Directory where the .ocamlinit file is searched.

10.2 Toplevel directives

The following directives control the toplevel behavior, load files inmemory, 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 typeif 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 forsource and compiled files.
    • remove_directory "dir-name";;

    • Remove the given directory from the list of directories searched forsource and compiled files. Do nothing if the list does not containthe 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 moduleswhich have not been loaded yet, the .cmo files for these modulesare searched and loaded as well, recursively. The loading orderis not specified.
    • use "file-name";;

    • Read, compile and execute source phrases from the given file.This is textual inclusion: phrases are processed just as ifthey were typed on standard input. The reading of the file stops atthe first error encountered.
    • mod_use "file-name";;

    • Similar to #use but also wrap the code into a top-level module of thesame name as capitalized file name without extensions, followingsemantics of the compiler.For directives that take file names as arguments, if the given filename specifies no directory, the file is searched in the followingdirectories:

    • In script mode, the directory containing the script currentlyexecuting; in interactive mode, the current working directory.

    • Directories added with the #directory directive.
    • Directories given on the command line with -I options.
    • The standard library directory.
  • 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 theabove categories.
  • Pretty-printing
    • install_printer printer-name;;

    • This directive registers the function named printer-name (avalue path) as a printer for values whose types match the argumenttype of the function. That is, the toplevel loop will callprinter-name when it has such a value to print.The printing function printer-name should have typeFormat.formatter->t->unit, where t is thetype for the values to be printed, and should output its textualrepresentation for the value of type t on the given formatter,using the functions provided by the Format library. For backwardcompatibility, printer-name can also have typet->unit and should then output on the standardformatter, 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 namedfunction-name will be “traced”. That is, the argument and theresult are displayed for each call, as well as the exceptions escapingout of the function, raised either by the function itself or byanother function it calls. If the function is curried, each argumentis 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 backto default behaviour (commuting style) if argument is true.
    • ppx "file-name";;

    • After parsing, pipe the abstract syntax tree through the preprocessorcommand.
    • principal bool;;

    • If the argument is true, check information paths duringtype-checking, to make sure that all types are derived in a principalway. If the argument is false, do not check information paths.
    • rectypes;;

    • Allow arbitrary recursive types during type-checking. Note: onceenabled, this option cannot be disabled because that would lead tounsoundness of the type system.
    • warn_error "warning-list";;

    • Treat as errors the warnings enabled by the argument and as normalwarnings the warnings disabled by the argument.
    • warnings "warning-list";;

    • Enable or disable warnings according to the argument.

10.3 The toplevel and the module system

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

However, before referencing another compilation unit, animplementation of that unit must be present in memory.At start-up, the toplevel system contains implementations for all themodules in the the standard library. Implementations for user modulescan be entered with the #load directive described above. Referencinga unit for which no implementation has been providedresults in the error Reference to undefined global `…'.

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

10.4 Common errors

This section describes and explains the most frequently encounterederror messages.

  • Cannot find file filename
  • The named file could not be found in the current directory, nor in thedirectories of the search path.If filename has the format mod.cmi, thismeans you have referenced the compilation unit mod, but itscompiled interface could not be found. Fix: compile mod.mli ormod.ml first, to create the compiled interface mod.cmi.

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

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

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

10.5 Building custom toplevel systems: ocamlmktop

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

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

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

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

  1. ./mytoplevel

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

  1. #load "foo.cmo";;
  2. #load "bar.cmo";;
  3. #load "gee.cmo";;

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

  1. open Foo;;

yourself, if this is what you wish.

10.5.1 Options

The following command-line options are recognized by ocamlmktop.

  • -ccliblibname
  • Pass the -llibname option to the C linker when linking in“custom runtime” mode. See the corresponding option forocamlc, in chapter 9.
  • -ccoptoption
  • Pass the given option to the C compiler and linker, when linking in“custom runtime” mode. See the corresponding option forocamlc, in chapter 9.
  • -custom
  • Link in “custom runtime” mode. See the corresponding option forocamlc, in chapter 9.
  • -Idirectory
  • Add the given directory to the list of directories searched forcompiled object code files (.cmo and .cma).
  • -oexec-file
  • Specify the name of the toplevel file produced by the linker.The default is a.out.

10.6 The native toplevel: ocamlnat (experimental)

This section describes a tool that is not yet officially supported but may be found useful.

OCaml code executing in the traditional toplevel system uses the bytecodeinterpreter. When increased performance is required, or for testingprograms that will only execute correctly when compiled to native code,the native toplevel may be used instead.

For the majority of installations the native toplevel will not have beeninstalled along with the rest of the OCaml toolchain. In such circumstancesit will be necessary to build the OCaml distribution from source.From the built source tree of the distribution you may usemake natruntop to build and execute a native toplevel. (Alternativelymake ocamlnat can be used, which just performs the build step.)

If the make install command is run after having built the nativetoplevel then the ocamlnat program (either from the source or theinstallation directory) may be invoked directly rather than usingmake natruntop.