从OCaml编译器中打开模块而不构建自定义顶级

从OCaml编译器中打开模块而不构建自定义顶级,ocaml,Ocaml,我希望在OCaml输入文件的开头有几行代码,以便toplevel始终记住最后键入的表达式,名称为it。也就是说,我想要: # 3 + 4;; val it : int = 7 # it;; val it : int = 7 # let foo = 42;; val foo : int = 42 # it + 130;; val it : int = 137 # 但我不想建立一个定制的顶级,也不想使用camlp5或任何类似的东西 我目前所做的工作(在OCaml版本4.02.3中,我不知道为什么会

我希望在OCaml输入文件的开头有几行代码,以便toplevel始终记住最后键入的表达式,名称为
it
。也就是说,我想要:

# 3 + 4;;
val it : int = 7
# it;;
val it : int = 7
# let foo = 42;;
val foo : int = 42
# it + 130;;
val it : int = 137
#
但我不想建立一个定制的顶级,也不想使用
camlp5
或任何类似的东西

我目前所做的工作(在OCaml版本4.02.3中,我不知道为什么会有那个版本;但我希望确切的版本不重要?)如下所示:

#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);;
这样的工作

我的问题是:如果我只做
#directory“+编译器libs”东西,我可以访问
Toploop
Parsetree
模块,但我不能访问
位置
模块!原因是什么?我发现必须从源目录加载
.cmo
文件非常不吸引人

那么,有没有一种方法可以在不需要源代码树的情况下实现我想要的呢


或者,换句话说:
Toploop
Location
之间的区别在这方面是什么?

简而言之,您应该加载的不是单个
.cmo
文件,而是

#load "ocamlcommon.cma";;
它位于
+编译器libs
目录中

Parsetree
Toploop
Location
之间的差异很微妙

在OCaml中,数据类型及其构造函数只有通过将其目录添加到加载路径(通过
#directory”“
)才能访问。无需为其加载目标代码(通过
#load

Parsetree
被称为“仅mli模块”:它只有数据类型定义,没有定义值。因此,
Parsetree
中的所有内容只有通过将其放入加载路径才能访问

位置
定义类型和值。其数据类型和构造函数无需加载对象文件即可访问,但值需要加载。在这种情况下,对象
location.cmo
在加载归档它的
ocamlcomon.cma
时被加载


Toploop
是一个棘手的问题。即使不加载
Toploop.cmo
,您也可以访问
Toploop
的值,因为
Toploop
已链接并已在OCaml toplevel中可用。

感谢您的精彩回答!这完全解决了我的问题。我的困惑是,作为一个Coq用户,我认为构造函数和函数是同一种东西,并且允许使用
Parsetree.Ptop_def
。这就是为什么我忽略了
Toploop
Parsetree
之间的区别。再次感谢您的回答和进一步的澄清。