此代码可以正常工作:
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
我不知道为什么在这种情况下同样的方法会失败,谢谢!
答案 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