为什么在 ocaml 编译器源代码中打印 Parsetree.implementation 的数量失败?

Why print the number of Parsetree.implementation fail at ocaml compiler source code?

这段代码工作正常:

let ()=
 let filename = "/home/wk/prog/LocationTest/b.ml" in
 Location.input_name := filename ;
 let readhandle = open_in filename in
 let buf = Lexing.from_channel readhandle in
 Location.init buf filename ;
 let ast = Parse.implementation buf in
 Printf.printf "%d" (List.length ast) ;

ast 的类型是 Parsetree.structure 即 "structure_item list",所以我可以使用 List.length 得到它的长度

我用同样的方法调试ocaml 4.07编译器源码:

我更改ocaml 4.07编译器源代码/driver/pparse.ml 181-183:

let lexbuf = Lexing.from_channel ic in
Location.init lexbuf inputfile;
Profile.record_call "parser" (fun () -> parse_fun lexbuf)

对此:

let lexbuf = Lexing.from_channel ic in
Location.init lexbuf inputfile;
let xx=parse_fun lexbuf in
Printf.printf "%d" (List.length xx);
Profile.record_call "parser" (fun () -> xx)

parse_fun是Parse.implementation,然后是"make world",得到错误:

Error: This expression has type 'a list
   but an expression was expected of type a

我不知道为什么同样的方法在这种情况下失败了,谢谢!

首先,我是否建议您不要通过查看编译器代码库来学习 OCaml?编译器代码库充满了陈旧的习语、微妙的不变量、高度优化的算法,而且对于初学者来说文档不足。因此,如果您正在努力学习 OCaml,它通常不是一个学习的好地方。

对于您手头的错误,问题是 parse_fun lexbuf 的结果不是 structure,而是局部抽象类型 a。此局部抽象类型受 file_auxkind 参数约束。 kind 的类型是 a ast_kind,它是定义为

的通用抽象数据类型(又名 GADT)
type 'a ast_kind =
| Structure: structure ast_kind
| Signature: signature ast_kind

因此a可能是结构或签名。这些都是列表,但您需要将此事实公开给类型检查器才能计算列表长度:

let len (type a) (kind:a ast_kind) (l:a) = match kind with
| Signature -> List.length l
| Structure -> List.length l