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



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

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

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

但现在OCaml编译器源代码中有模块TypedtreeIter可用,并且它暴露在compiler-libs中。对于简单的遍历,这是非常方便的。

TypedtreeIter提供了一个函数,用于在类型化的AST上构建自己的迭代器。这里有一个非常简单的例子来打印所有的模式标识符及其类型:

(* 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的某些部分感兴趣,并希望跳过其他部分。CCD_ 13是CCD_ 14和CCD_。您的IteratorArgument模块应该包括DefaultIteratorArgument以继承此默认行为,然后只实现执行特殊操作的部分。

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

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

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

坏消息是,它没有记录在案。我建议你使用utopmerlin来探索这个库。

使用compiler-libs不需要与ocamlbuild有任何特殊关系,它是一个常规库。

最新更新