Reputation: 511
I would like to have a few lines of code at the start of my OCaml input file to have toplevel remember the last expression typed all the time, under the name of it
. I.e., I want to have:
# 3 + 4;;
val it : int = 7
# it;;
val it : int = 7
# let foo = 42;;
val foo : int = 42
# it + 130;;
val it : int = 137
#
But I don't want to build a custom toplevel or use camlp5
or anything fancy like that.
What I currently do (in OCaml version 4.02.3, I don't know why I have that version; but I hope the exact version doesn't matter?) is the following:
#directory "+compiler-libs";;
#load "/opt/src/ocaml-4.02.3/utils/warnings.cmo";;
#load "/opt/src/ocaml-4.02.3/parsing/location.cmo";;
let convert_phrase x =
match x with
| Parsetree.Ptop_def
[{Parsetree.pstr_desc = Parsetree.Pstr_eval (e, a)}] ->
Parsetree.Ptop_def
([{Parsetree.pstr_desc =
Parsetree.Pstr_value (Asttypes.Nonrecursive,
[{Parsetree.pvb_pat =
{Parsetree.ppat_desc =
Parsetree.Ppat_var (Location.mknoloc "it");
Parsetree.ppat_loc = Location.none;
Parsetree.ppat_attributes = []};
Parsetree.pvb_expr = e;
Parsetree.pvb_attributes = a;
Parsetree.pvb_loc = Location.none}]);
Parsetree.pstr_loc = Location.none}])
| x -> x;;
Toploop.parse_toplevel_phrase :=
let parse_toplevel_phrase = !Toploop.parse_toplevel_phrase in
fun x -> convert_phrase (parse_toplevel_phrase x);;
And that kind of works.
My question: if I just do the #directory "+compiler-libs";;
thing, I can access the Toploop
and Parsetree
modules, but I cannot access the Location
module! What is the reason for that? I find having to load .cmo
files from my source directories very unattractive.
So is there a way to do what I want without having to have a source tree available?
Or, in other words: why the difference between Toploop
and Location
, in this respect?
Upvotes: 3
Views: 281
Reputation: 9040
In short, what you should load is not individual .cmo
files but
#load "ocamlcommon.cma";;
which is in +compiler-libs
directory.
The differences between Parsetree
, Toploop
and Location
are subtle...
In OCaml, data types and their constructors become accessible only with adding its directory to the load path (by #directory "<dir>"
). No object code loading (by #load
) is required for them.
Parsetree
is so called "mli only module": it has only data type definitions and no values are defined. Therefore everything in Parsetree
is accessible only by putting it into the load path.
Location
defines types and values. Its data types and constructors are accessible without loading the object file but values require the loading. In this case, the object location.cmo
is loaded when you load ocamlcommon.cma
which archives it.
Toploop
is a tricky one. You can access the values of Toploop
even without loading toploop.cmo
, since Toploop
is linked and already available in OCaml toplevel.
Upvotes: 8