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

时间:2018-09-21 09:51:03

标签: compiler-construction ocaml

此代码可以正常工作:

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.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

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

1 个答案:

答案 0 :(得分:2)

首先,我是否建议您不要通过查看编译器代码库来学习OCaml?编译器代码库充满了旧的习惯用法,微妙的不变式,经过高度优化的算法,并且对于初学者而言,文档不足。因此,如果您正在使用OCaml挣扎,通常不是学习的好地方。

对于您眼前的错误,问题在于foreach的结果不是parse_fun lexbuf,而是局部抽象类型structure。这种局部抽象的类型受a的{​​{1}}参数的约束。 kind的类型为file_aux,它是一种通用抽象数据类型(又称为GADT),定义为

kind

因此a ast_kind可以是结构也可以是签名。这些都是列表,但是您需要将此事实暴露给类型检查器,以便能够计算列表长度:

type 'a ast_kind =
| Structure: structure ast_kind
| Signature: signature ast_kind