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

Compiler construction 如何在OCaml编译器中遍历类型化抽象语法树,compiler-construction,ocaml,abstract-syntax-tree,ocamlbuild,Compiler Construction,Ocaml,Abstract Syntax Tree,Ocamlbuild,我试图在OCaml项目中转储所有标识符的类型信息,基本上与遍历类型化抽象语法树()相同。由于我是OCaml编译器代码库的新手,我不确定编译器是否提供了API,以便我们可以轻松编写插件来完成这项工作,或者我们必须破解编译器代码?这又是如何与OCamlbuild交互的?谢谢你的任何提示或建议 OCaml以名为compiler libs的库的形式提供了自己的编译器。它拥有一切,允许从具体的语法转向可执行的,所有中间步骤都在您的控制之下,当然包括typedtree 坏消息是它没有记录在案。我建议您使用u

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

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

坏消息是它没有记录在案。我建议您使用
utop
merlin
来探索这个库


要使用
编译器libs
,您不需要对ocamlbuild做任何特殊的处理,它是一个常规库。

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

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

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

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)
(*ocamlfind ocamlc-package compiler-libs.common-c example.ml*)
开放式树
开式伸缩器
模块MyIteratorArgument=struct
包括DefaultIteratorArgument
让输入模式p=将p.pat\u desc与匹配
|Tpat_变量(id)->
Format.printf“@[%s@:%a@.”
(识别名称id)
打印类型\方案p.pat\类型
| _ -> ()
结束
模块迭代器=TypedTreiter.MakeIterator(MyIteratorArgument)
模块类型
TypedtreeIter.IteratorArgument
用于指定迭代器对每个AST构造执行的操作。执行作业有两点:遍历进入构造和退出构造。例如,对于
模式
,您有
输入模式
退出模式
。您不必担心递归遍历本身:它是函子
MakeIterator
的工作。给出一个
IteratorArgument
模块,它递归地连接所有
enter*
exit*
,并返回一个包含一组迭代器的模块

通常你只对AST的一部分感兴趣,而想跳过其他部分
DefaultIteratorArgument
是一个模块,其
enter*
exit*
不执行任何操作。您的
IteratorArgument
模块应该包括
DefaultIteratorArgument
以继承此默认行为,然后仅实现执行特殊操作的部分

如果不仅要遍历类型化的AST,还要修改其中的某些部分,请使用
TypedtreeMap
而不是
TypedtreeIter
。有一个小例子是
TypedtreeMap
at


(我不使用ocamlbuild,所以我无法帮助解决这个问题。)

Hi,@ivg感谢您的回复。在深入研究源代码之前,一个简单的问题是,这个库是否公开了整个OCaml项目处理的API?或者由于OCaml对单独编译的强大支持,键入整个项目的问题会减少到逐个键入每个文件?谢谢。据我所知,它只公开了编译器部分,这样您就可以使用这些库构建自己的驱动程序了。如果您真的需要使用ocaml项目,并使用自己经过调整的编译器编译它,那么只需调整编译器就更容易了。但对于测试和调查来说,编译器仍然是一个不错的选择。嗨,@camlsporter,谢谢你提供了一个很好的例子!
TypedtreeIter
很整洁!有一件事我认为是缺少了迭代器函子,它没有提供我们所处的当前
Env
。因此,我们可能无法跟踪变量的定义站点。您以前是否遇到过此问题,并且知道代码库中的其他实用程序函数可以解决此问题?每个类型化AST节点都具有用于构建节点的类型环境。