All Projects → johnwhitington → Ocamli

johnwhitington / Ocamli

Licence: bsd-3-clause
OCaml interpreter

Programming Languages

ocaml
1615 projects

OCamli

OCamli is a proof-of-concept step-by-step interpreter for OCaml programs intended for teaching purposes and, eventually, as a debugger. It works by reading an OCaml program into an abstract syntax tree, then interpreting the AST one reduction at a time, optionally displaying each reduction and underlining the reducible expression. For example:

showall

With just -show instead:

show

Running the classic factorial program, using a set of options to elide parts of the output (there are too many options, and the interface will be improved):

factorial

Mutable code

Some of ocamli's output is a little low-level for now, but it's important to emulate what OCaml itself does by making the actual calls to primitives like %setfield0:

mutable

Input/Output

Sometimes the approach of printing everything gets far too much. We will need methods for hiding this internal detail by default:

printint

Standard Library Functions

You should be able to use some or most of the Standard Library functions. Presently Printf and Scanf are not loaded due to bugs.

listmap

Searching

"I want to see the last few steps before factorial (4 - 1)":

search

Examples

The directory examples contains a number of little programs written for development.

The directory OCaml from the Very Beginning contains all the examples and exercises from the beginner's OCaml textbook.

Paper

The eventual use of ocamli as a debugger is sketched in the position paper "Visualizing the Evaluation of Functional Programs for Debugging", given at SLATE'17 in June.

Selected command line options

eval <filename | -e program> [-- arg1 arg2 ...]

Loading and runnning programs:

  • -e <string> Evaluate the program text given
  • -show Print the final result of the program
  • -show-all Print steps of evaluation
  • -e-name <string> Set the module name for the next -e instance
  • -no-stdlib Don't load the standard library (for speed)

Multiple files and -e options may be given, and will be treated as zero or more modules followed by one main program.

Searching:

  • -search <search-term> Show only matching evaluation steps
  • -regexp Search terms are regular expressions rather than the built-in system
  • -invert-search Invert the search, showing non-matching steps
  • -highlight Highlight the matching part of each matched step.
  • -n <integer> Show only results
  • -until <search-term> show only until this matches a printed step
  • -after <search-term> show only after this matches a printed step
  • -until-any <search-term> show only until this matches any step
  • -after-any <search-term> show only after this matches any step
  • -invert-after invert the after condition
  • -invert-until invert the until condition
  • -stop stop computation after final search results
  • -repeat allow the after...until result to be repeated.
  • -upto <n> show n lines up to each result line
  • -times <n> Do many times

Interaction:

  • -prompt Require enter after each step but last
  • -step / Wait a number of seconds after each step but last

Elision:

  • -remove-rec <string> Do not print the given recursive function
  • -remove-rec-all Do not print any recursive functions
  • -show-pervasives Show Pervasives such as :=
  • -fast-curry Apply all curried arguments at once.
  • -show-stdlib-init Show initialisation of standard library
  • -no-arith Ellide simple arithmetic
  • -no-if-bool Don't show if false, if true stage
  • -no-var-lookup Don't show stage immediately after variable lookup
  • -side-lets Show value-lets at the side

Configuration:

  • -pp Set the prettyprinter "normal" or "simple" (default)
  • -width Set the output width
  • -top Do nothing, exit cleanly (for top level)
  • -dtiny Show Tinyocaml representation
  • -dpp Show the pretty-printed program
  • -debug Debug (for OCAMLRUNPARAM=b)
  • -no-syntax Don't use syntax highlighting
  • -no-typecheck Don't typecheck
  • -no-collect Don't collect unused lets
  • -otherlibs Location of OCaml otherlibs folder (Unix, Bigarray, Str)

Implementation

The ocamli interpreter requires no patches to the OCaml compiler; it is implemented entirely using compiler-libs.

The OCaml program is lexed and parsed by compiler-libs, typechecked, then the parse tree is converted to a simpler, more direct datatype, called Tinyocaml.

The Tinyocaml representation is then interpreted step-by-step, optionally printing each stage out. We use a custom prettyprinter, but hope to eventually contribute back to the standard one.

Keeping ocamli in sync with OCaml will involve updating it to reflect any changes in the compiler-libs API and adding any new features added to the OCaml languages. So, we will have ocamli 4.05 for OCaml 4.05 and so on.

The ocamli facilities for conversing with C code (such as OCaml %external declarations) are based on reading and writing OCaml heap values. The interpreter and the interpreted program and the compiled parts live in the same process with the same OCaml runtime.

Use at runtime

The interpreter can be used at runtime, and the resulting value bought back into the caller:

# let x : int list * int list =
  Tinyocaml.to_ocaml_value
    (Runeval.eval_string "List.split [(1, 2); (3, 4)]");;
val x : int list * int list = ([1; 3], [2; 4])

Support for this is very rudimentary at the moment.

PPX_eval

Writing

let compiler_command = [%compiletimestr "Sys.argv.(0)"])

in a normal compiled OCaml program with PPX_eval generates

let compiler_command = "ocamlopt"

Status

The ocamli interpreter is a proof-of-concept. Do not expect it to run your larger programs!

It supports just enough of the language to load (and run the module initialisation of) most of the OCaml Standard Library. This is quite a large number of constructs, though, including functors, first class modules and so on.

The ocamli interpreter can run almost all the programs in the OCaml from the Very Beginning textbook. The examples are included in the download.

The ocamli interpreter currently makes no guarantee of computational complexity, even when the steps of evaluation are not shown. The extent to which such a guarantee can be given is an open research question.

Future

In short, make it more than a proof-of-concept:

  • Extend it to the full language
  • Better pretty-printing
  • Make it fast enough for general use
  • Easy invocation as a debugger regardless of build system or source structure
  • Better tools for searching and eliding
  • Allow interpretation of just one module -- other modules run at full speed
  • An interactive interface

Building

Make sure to download from tag "OCaml17". Should work on all platforms with OCaml 4.05. To build, run the build script. You will need ocamlfind and ppx_tools installed, both of which are available on OPAM.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].