如何遍历OCaml编译器中的类型化抽象语法树 [英] How to traverse typed abstract syntax tree in OCaml compiler

查看:357
本文介绍了如何遍历OCaml编译器中的类型化抽象语法树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

假设你已经有类型结构的类型AST 。



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



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



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

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

模块MyIteratorArgument = struct
include DefaultIteratorArgument

让enter_pattern p =匹配p.pat_desc与
| Tpat_var(id,_) - >
Format.printf@ [< 2>%s @:%a @] @。
(Ident.name id)
Printtyp.type_scheme p.pat_type
| _ - > ()
end

模块Iterator = TypedtreeIter.MakeIterator(MyIteratorArgument)

模块类型 TypedtreeIter.IteratorArgument 是指定您的迭代器对每个AST结构执行的操作。你有两个点来执行你的工作:当遍历进入一个构造,当它从它退出。例如,对于 pattern ,您有 enter_pattern exit_pattern 。你不需要担心递归遍历本身:它是函子 MakeIterator 的工作。给出一个 IteratorArgument 模块它连接所有输入_ * exit _ * 递归并返回一个模块与一堆的迭代器。



通常你只对AST的一部分感兴趣,想跳过其他。 DefaultIteratorArgument 输入_ * exit _ * do没有。您的 IteratorArgument 模块应包含 DefaultIteratorArgument 以继承此默认行为,然后仅实现特殊的部分。 p>

如果你不仅要遍历输入的AST,而且要修改它们的某些部分,请使用 TypedtreeMap c $ c> TypedtreeIter 。在 TypedtreeMap 的一个小例子。 ml?at = defaultrel =nofollow> https://bitbucket.org/camlspotter/compiler-libs-hack/src/340072a7c14cbce624b98a57bf8c4c6509c40a31/overload/mod.ml?at=default



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


I'm trying to dump type information of all identifiers in an OCaml project, basically it's the same as traversing the typed abstract syntax tree(https://github.com/ocaml/ocaml/blob/trunk/typing/typedtree.mli). Since I'm new to OCaml compiler's codebase, I'm not sure whether the Compiler has provided apis so we could easily write a plugin to do the job or we have to hack the compiler code? Also how does this interact with OCamlbuild? Thanks for any hints or advices.

解决方案

Assuming you have already got a typed AST of type structure somehow.

The classic way is simply to write a big recursive function to traverse the AST by yourself.

But now there is module TypedtreeIter available in OCaml compiler source code and it is exposed to compiler-libs. For simple traversal, this is very handy.

TypedtreeIter provides a functor to build your own iterator over typed ASTs. Here is a very simple example to print all the pattern identifiers with their types:

(* 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)

Module type TypedtreeIter.IteratorArgument is to specify what your iterator does for each AST construct. You have two points to execute your job: when the traversal enters a construct and when it exits from it. For pattern, for example, you have enter_pattern and exit_pattern. You do not need to worry about the recursion traversal itself: it is the job of the functor MakeIterator. Giving an IteratorArgument module it wires up all the enter_* and exit_* recursively and returns a module with bunch of iterators.

Normally you are interested only in some part of AST and want to skip the others. DefaultIteratorArgument is a module whose enter_* and exit_* do nothing. Your IteratorArgument module should include DefaultIteratorArgument to inherit this default behaviour, then implement only the parts which do something special.

If you want not only to traverse typed ASTs but also to modify some part of them, use TypedtreeMap instead of TypedtreeIter. There is a small example of TypedtreeMap at https://bitbucket.org/camlspotter/compiler-libs-hack/src/340072a7c14cbce624b98a57bf8c4c6509c40a31/overload/mod.ml?at=default.

(I do not use ocamlbuild, so I cannot help that point.)

这篇关于如何遍历OCaml编译器中的类型化抽象语法树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆