Camel spotter: Oh, it was extremely interesting, very, very - quite... it was dull; dull, dull, dull, oh God it was dull. Sitting in the Waterloo waiting room. ...
from You're No Fun Anymore, Monty Python's Flying Circus
OCaml module language is powerful. So extremely powerful that you can be lost yourself easily inside huge OCaml projects with tons of modules. Spotting the definition of a variable is sometimes
"extremely interesting". Let's see such a dull example:
include M
open N
open O
let _ = f 1
Suppose you are not familiar with the function f and want to spot its definition. Where to find it? Just from the code you are looking at, it is not sure: if you are enough lucky it may be f in m.ml, n.ml or o.ml. Otherwise, it may be O.f in n.ml. Or probably N.O.f in m.ml. More over, there can be complex module operations in m.ml (i.e includes, functor applications) and in such cases the definition may be found somewhere completely unexpected. Module packing, module load paths and library installation without .ml files complicate the situation even worse.
In you first days after joining a large OCaml project, you should be busy for this kind of manual value definition spotting with find + grep. Yes, actually it is very educational: you can learn a lot about the project struggling in the source tree (only if your collegues have organized things very well :-P), but it is dull job too, if they use too many "open M" in it.
To say short, OCamlSpotter is a program which does this dull job automatically for you and permits investing your energy for something more
"interesting" like
Yeti spotting:
- The -annot option of ocamlc and ocamlopt is extended and creates <module>.spot files, which record the localtion information of the values defined and used in the module.
- A small application ocamlspot provides automatic where-about spotting of the definition of the variable you are interested in.
- ocamlspot.el provides interactive ocaml-spotting of definition locations in emacs.
- Interfaces for other editors such as vi can be built easily. But I am an emacs user.
Download
Mercurial repository
Recently I have moved almost of all my development repos to bitbucket (
https://bitbucket.org/camlspotter/).
Older versions
- versions for ocaml 3.12.0
OCamlSpotter development is now in OCamlForge. The latest source code
for OCaml 3.12.0 is available at OCamlForge's mercurial repository:
hg clone http://hg.ocamlcore.org/cgi-bin/hgwebdir.cgi/ocamlspotter/ocamlspotter/ -r <tag>
Use one of the following release tags for <tag> above:
- ocamlspot-1.2.0-for-3.12.0 version 1.2.0 for ocaml 3.12.0
- ocamlspot-1.2.0-for-3.12.0+rc1 version 1.2.0 for ocaml 3.12.0+rc1 release candidate
- versions for ocaml 3.12.0 branch for the latest development for ocaml 3.12.0
- version 1.1 for ocaml 3.11.2
- added -n option which does not analyze definition position.
- supports a new position format l<line>c<column in bytes>
- supports a new query file:kind:path
- more spots are saved
- Work around for ocamlbuild. If .ocamlspot file with the text build_dir=dirname is placed in a directory $DIR, then spot files of source files under $DIR ex. $DIR/subdir/source.ml is searched in $DIR/dirname/subdir/. See an example at camlp4/.ocamlspot
- ocamlspot.el
- various elisp bug fixes
- multi-byte character support in emacs
- ocamlspot-type function is added for type query
- ocamlspot-use function is added for use query
- version 1.05 for ocaml 3.11.1
FAQ and NAQ(Never Asked Questions actually)
Why have you chosen another file format (.spot, .spit) instead of .annot?
.annot files are in a text format. .spot and .spit are OCaml's marshaled value files. There are several reasons why I did not extend .annot file for ocamlspotter but choose to use different format:
- .annot file tends to become very huge (more than 10Mbytes for some big .ml source). .spot files are usually 40% smaller than the corresponding .annot files.
- I do not see any advantage to have text based interoperability like HTML and XML for this kind of OCaml specific information. Printing and parsing back of .annot files are meaningless overheaded.
- .annot file's textual information loses important information for ocamlspotter: type sharings and ident stamp numbers.
Is the patched compiler incompatible with the original one?
Generally, no. They should produce the same object files and executable binaries. From version 1.2, a small script VERIFY.sh is available to check this by compiling the ocaml compiler source code both by the original and patched compilers.
- You can use the libraries compiled by the original compiler with the conjunction of the patched compiler. Of course such libraries have no .spot files and therefore code browsing is not available.
- Unfortunately, CamlP4 parser extension object files (aka pa_*.cmo) created by the original compiler may not be linked with patched CamlP4. There is a simple workaround, however. Use the orignal CamlP4 tools (camlp*) with the other patched tools (ocamlc, ocamlc.opt, ocamlopt, ocamlopt.opt and other ocaml*). You can achieve this by creating a new directory which contains patched ocaml* binaries (and not camlp*), and put the directory at the top of your PATH.
- OCamlFind users can instruct it to override the compilers (ocamlc and ocamlopt) by editing findlib.conf
Strange source location information
OCamlSpotter does not work well if a source file is preprocessed by CamlP4 and its extension modules (pa_*.cmo) if they have bugs around source location handling. There is no cure in OCamlSpotter side. Fix the location bugs of CamlP4 or pa_*.cmo.
Tutorial video
Some of the confusing points in the above document might be explained in the following video:
Acknowledgment
I thank my ex-colleagues of Jane Street who have provided valuable feed back and patches for this software.