从OCaml编译器打开模块,无需构建自定义顶层

时间:2016-05-20 21:38:34

标签: ocaml

我想在我的OCaml输入文件的开头有几行代码,以便在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 "+compiler-libs";;项操作,我可以访问ToploopParsetree模块,但我无法访问Location模块!这是什么原因?我发现必须从我的源目录加载.cmo文件非常缺乏吸引力。

那么有没有办法在没有源树可用的情况下做我想做的事情?

或者换句话说:为什么ToploopLocation之间存在差异?

1 个答案:

答案 0 :(得分:8)

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

#load "ocamlcommon.cma";;

位于+compiler-libs目录中。

ParsetreeToploopLocation之间的差异很微妙......

在OCaml中,只有将其目录添加到加载路径(#directory "<dir>"),才能访问数据类型及其构造函数。

,无需加载对象代码(#load)。

Parsetree被称为&#34; mli only module&#34;:它只有数据类型定义,没有定义任何值。因此,Parsetree中的所有内容只能通过将其放入加载路径来访问。

Location定义类型和值。可以在不加载目标文件的情况下访问其数据类型和构造函数,但值需要加载。在这种情况下,加载location.cmo时会加载对象ocamlcommon.cma

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