Зачем выводить число ошибок Parsetree.implementation в исходном коде компилятора ocaml? - PullRequest
0 голосов
/ 21 сентября 2018

Этот код работает нормально:

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, который представляет собой «список struct_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 голосов
/ 21 сентября 2018

Во-первых, могу ли я предложить вам не изучать OCaml, взглянув на базу кода компилятора?Кодовая база компилятора полна старых идиом, тонких инвариантов, сильно оптимизированных алгоритмов и совершенно недокументирована для начинающих.Таким образом, в общем случае не стоит учиться, если вы боретесь с OCaml.

Из-за вашей ошибки проблема в том, что результатом parse_fun lexbuf является не structure, алокально абстрактный тип a.Этот локально абстрактный тип ограничен аргументом kind file_aux.Тип 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
...