如何遍历OCaml编译器中的类型化抽象语法树

时间:2015-02-08 01:26:39

标签: compiler-construction ocaml abstract-syntax-tree ocamlbuild

我正在尝试转储OCaml项目中所有标识符的类型信息,基本上它与遍历类型化的抽象语法树(https://github.com/ocaml/ocaml/blob/trunk/typing/typedtree.mli)相同。由于我是OCaml编译器代码库的新手,我不确定编译器是否提供了apis所以我们可以轻松编写插件来完成这项工作,或者我们必须破解编译器代码?这又如何与OCamlbuild互动?感谢任何提示或建议。

2 个答案:

答案 0 :(得分:4)

假设您已经以某种方式获得了类型为structure的AST。

经典的方法就是编写一个大的递归函数来自己遍历AST。

但是现在OCaml编译器源代码中提供了模块TypedtreeIter,它被公开给compiler-libs。对于简单的遍历,这非常方便。

TypedtreeIter提供了一个函子来构建自己的类型化ASTs迭代器。下面是一个非常简单的示例,用于打印所有模式标识符及其类型:

(* ocamlfind ocamlc -package compiler-libs.common -c example.ml *)
open Typedtree
open TypedtreeIter

module MyIteratorArgument = struct
  include DefaultIteratorArgument

  let enter_pattern p = match p.pat_desc with
    | Tpat_var (id, _) ->
        Format.printf "@[<2>%s@ : %a@]@."
          (Ident.name id)
          Printtyp.type_scheme p.pat_type
    | _ -> ()
end

module Iterator = TypedtreeIter.MakeIterator(MyIteratorArgument)

模块类型TypedtreeIter.IteratorArgument用于指定迭代器为每个AST构造执行的操作。你有两个点来执行你的工作:当遍历进入一个结构并从它退出时。例如,对于pattern,您有enter_patternexit_pattern。您不必担心递归遍历本身:它是仿函数MakeIterator的工作。给一个IteratorArgument模块递归连接所有enter_*exit_*并返回一个带有一堆迭代器的模块。

通常,您只对AST的某些部分感兴趣,并希望跳过其他部分。 DefaultIteratorArgumententer_*exit_*无效的模块。您的IteratorArgument模块应包含DefaultIteratorArgument以继承此默认行为,然后仅实现执行特殊操作的部分。

如果您不仅要遍历类型化的AST,还要修改其中的某些部分,请使用TypedtreeMap代替TypedtreeIter。在https://bitbucket.org/camlspotter/compiler-libs-hack/src/340072a7c14cbce624b98a57bf8c4c6509c40a31/overload/mod.ml?at=default处有一个TypedtreeMap的小例子。

(我不使用ocamlbuild,所以我不能帮助那一点。)

答案 1 :(得分:3)

OCaml提供自己的编译器作为名为compiler-libs的库。它包含了所有内容,允许用户从具体语法转向可执行文件,所有中间步骤都在您的控制之下,当然包括typedtree。

坏消息是没有记录。我建议您使用utopmerlin来探索此库。

使用compiler-libs ocamlbuild不需要任何特殊操作,它是一个常规库。