2016-02-18 07:11:59 -08:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* OCaml *)
|
|
|
|
(* *)
|
|
|
|
(* Damien Doligez, projet Moscova, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
|
|
|
(* Copyright 2003 Institut National de Recherche en Informatique et *)
|
|
|
|
(* en Automatique. *)
|
|
|
|
(* *)
|
|
|
|
(* All rights reserved. This file is distributed under the terms of *)
|
|
|
|
(* the GNU Lesser General Public License version 2.1, with the *)
|
|
|
|
(* special exception on linking described in the file LICENSE. *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
2003-04-01 17:32:09 -08:00
|
|
|
|
|
|
|
(* Recording and dumping (partial) type information *)
|
|
|
|
|
|
|
|
(*
|
|
|
|
We record all types in a list as they are created.
|
|
|
|
This means we can dump type information even if type inference fails,
|
|
|
|
which is extremely important, since type information is most
|
|
|
|
interesting in case of errors.
|
|
|
|
*)
|
|
|
|
|
2007-05-16 01:21:41 -07:00
|
|
|
open Annot;;
|
2003-04-01 17:32:09 -08:00
|
|
|
open Lexing;;
|
|
|
|
open Location;;
|
2003-04-01 22:57:15 -08:00
|
|
|
open Typedtree;;
|
2003-04-01 17:32:09 -08:00
|
|
|
|
2018-08-30 10:15:32 -07:00
|
|
|
let output_int oc i = output_string oc (Int.to_string i)
|
2012-11-07 02:14:02 -08:00
|
|
|
|
2007-05-16 01:21:41 -07:00
|
|
|
type annotation =
|
2019-09-20 06:23:07 -07:00
|
|
|
| Ti_pat : 'k pattern_category * 'k general_pattern -> annotation
|
2003-04-01 22:57:15 -08:00
|
|
|
| Ti_expr of expression
|
|
|
|
| Ti_class of class_expr
|
|
|
|
| Ti_mod of module_expr
|
2007-05-16 01:21:41 -07:00
|
|
|
| An_call of Location.t * Annot.call
|
2008-07-29 08:42:44 -07:00
|
|
|
| An_ident of Location.t * string * Annot.ident
|
2003-04-01 22:57:15 -08:00
|
|
|
;;
|
|
|
|
|
|
|
|
let get_location ti =
|
|
|
|
match ti with
|
2019-09-20 06:23:07 -07:00
|
|
|
| Ti_pat (_, p) -> p.pat_loc
|
2003-04-01 22:57:15 -08:00
|
|
|
| Ti_expr e -> e.exp_loc
|
|
|
|
| Ti_class c -> c.cl_loc
|
|
|
|
| Ti_mod m -> m.mod_loc
|
2016-03-09 02:40:16 -08:00
|
|
|
| An_call (l, _k) -> l
|
|
|
|
| An_ident (l, _s, _k) -> l
|
2003-04-01 22:57:15 -08:00
|
|
|
;;
|
|
|
|
|
2007-05-16 01:21:41 -07:00
|
|
|
let annotations = ref ([] : annotation list);;
|
2003-07-23 09:52:41 -07:00
|
|
|
let phrases = ref ([] : Location.t list);;
|
2003-04-01 17:32:09 -08:00
|
|
|
|
2003-04-01 22:57:15 -08:00
|
|
|
let record ti =
|
2007-05-16 01:21:41 -07:00
|
|
|
if !Clflags.annotations && not (get_location ti).Location.loc_ghost then
|
|
|
|
annotations := ti :: !annotations
|
2003-04-01 17:32:09 -08:00
|
|
|
;;
|
|
|
|
|
2003-07-23 09:52:41 -07:00
|
|
|
let record_phrase loc =
|
2007-05-16 01:21:41 -07:00
|
|
|
if !Clflags.annotations then phrases := loc :: !phrases;
|
2003-07-23 09:52:41 -07:00
|
|
|
;;
|
|
|
|
|
2003-07-25 11:00:40 -07:00
|
|
|
(* comparison order:
|
|
|
|
the intervals are sorted by order of increasing upper bound
|
|
|
|
same upper bound -> sorted by decreasing lower bound
|
|
|
|
*)
|
|
|
|
let cmp_loc_inner_first loc1 loc2 =
|
|
|
|
match compare loc1.loc_end.pos_cnum loc2.loc_end.pos_cnum with
|
|
|
|
| 0 -> compare loc2.loc_start.pos_cnum loc1.loc_start.pos_cnum
|
2003-04-01 17:32:09 -08:00
|
|
|
| x -> x
|
|
|
|
;;
|
2003-07-25 11:00:40 -07:00
|
|
|
let cmp_ti_inner_first ti1 ti2 =
|
|
|
|
cmp_loc_inner_first (get_location ti1) (get_location ti2)
|
|
|
|
;;
|
2003-04-01 17:32:09 -08:00
|
|
|
|
|
|
|
let print_position pp pos =
|
2007-05-16 01:21:41 -07:00
|
|
|
if pos = dummy_pos then
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "--"
|
2012-11-06 10:25:47 -08:00
|
|
|
else begin
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp '\"';
|
|
|
|
output_string pp (String.escaped pos.pos_fname);
|
|
|
|
output_string pp "\" ";
|
|
|
|
output_int pp pos.pos_lnum;
|
|
|
|
output_char pp ' ';
|
|
|
|
output_int pp pos.pos_bol;
|
|
|
|
output_char pp ' ';
|
|
|
|
output_int pp pos.pos_cnum;
|
2012-11-06 10:25:47 -08:00
|
|
|
end
|
2007-05-16 01:21:41 -07:00
|
|
|
;;
|
|
|
|
|
|
|
|
let print_location pp loc =
|
|
|
|
print_position pp loc.loc_start;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp ' ';
|
2007-05-16 01:21:41 -07:00
|
|
|
print_position pp loc.loc_end;
|
2003-04-01 17:32:09 -08:00
|
|
|
;;
|
|
|
|
|
2003-07-23 09:52:41 -07:00
|
|
|
let sort_filter_phrases () =
|
2003-07-25 11:00:40 -07:00
|
|
|
let ph = List.sort (fun x y -> cmp_loc_inner_first y x) !phrases in
|
2003-07-23 09:52:41 -07:00
|
|
|
let rec loop accu cur l =
|
|
|
|
match l with
|
|
|
|
| [] -> accu
|
|
|
|
| loc :: t ->
|
2003-07-25 11:00:40 -07:00
|
|
|
if cur.loc_start.pos_cnum <= loc.loc_start.pos_cnum
|
|
|
|
&& cur.loc_end.pos_cnum >= loc.loc_end.pos_cnum
|
2003-07-23 09:52:41 -07:00
|
|
|
then loop accu cur t
|
|
|
|
else loop (loc :: accu) loc t
|
|
|
|
in
|
|
|
|
phrases := loop [] Location.none ph;
|
|
|
|
;;
|
|
|
|
|
|
|
|
let rec printtyp_reset_maybe loc =
|
|
|
|
match !phrases with
|
2003-07-25 11:00:40 -07:00
|
|
|
| cur :: t when cur.loc_start.pos_cnum <= loc.loc_start.pos_cnum ->
|
|
|
|
Printtyp.reset ();
|
|
|
|
phrases := t;
|
|
|
|
printtyp_reset_maybe loc;
|
|
|
|
| _ -> ()
|
2003-07-23 09:52:41 -07:00
|
|
|
;;
|
|
|
|
|
2007-05-16 01:21:41 -07:00
|
|
|
let call_kind_string k =
|
|
|
|
match k with
|
|
|
|
| Tail -> "tail"
|
|
|
|
| Stack -> "stack"
|
|
|
|
| Inline -> "inline"
|
|
|
|
;;
|
|
|
|
|
2008-07-29 08:42:44 -07:00
|
|
|
let print_ident_annot pp str k =
|
2007-05-16 01:21:41 -07:00
|
|
|
match k with
|
2012-11-06 10:25:47 -08:00
|
|
|
| Idef l ->
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "def ";
|
|
|
|
output_string pp str;
|
|
|
|
output_char pp ' ';
|
2012-11-06 10:25:47 -08:00
|
|
|
print_location pp l;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp '\n'
|
2012-11-06 10:25:47 -08:00
|
|
|
| Iref_internal l ->
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "int_ref ";
|
|
|
|
output_string pp str;
|
|
|
|
output_char pp ' ';
|
2012-11-06 10:25:47 -08:00
|
|
|
print_location pp l;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp '\n'
|
2012-11-06 10:25:47 -08:00
|
|
|
| Iref_external ->
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "ext_ref ";
|
|
|
|
output_string pp str;
|
|
|
|
output_char pp '\n'
|
2007-05-16 01:21:41 -07:00
|
|
|
;;
|
2003-07-23 09:52:41 -07:00
|
|
|
|
2003-06-12 05:52:17 -07:00
|
|
|
(* The format of the annotation file is documented in emacs/caml-types.el. *)
|
|
|
|
|
2013-06-04 06:46:48 -07:00
|
|
|
let print_info pp prev_loc ti =
|
2003-04-01 22:57:15 -08:00
|
|
|
match ti with
|
2007-05-16 01:21:41 -07:00
|
|
|
| Ti_class _ | Ti_mod _ -> prev_loc
|
2019-09-20 06:23:07 -07:00
|
|
|
| Ti_pat (_, {pat_loc = loc; pat_type = typ; pat_env = env})
|
|
|
|
| Ti_expr {exp_loc = loc; exp_type = typ; exp_env = env} ->
|
2012-11-06 10:25:47 -08:00
|
|
|
if loc <> prev_loc then begin
|
|
|
|
print_location pp loc;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp '\n'
|
2012-11-06 10:25:47 -08:00
|
|
|
end;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "type(\n";
|
2003-07-23 09:52:41 -07:00
|
|
|
printtyp_reset_maybe loc;
|
|
|
|
Printtyp.mark_loops typ;
|
2013-06-04 06:46:48 -07:00
|
|
|
Format.pp_print_string Format.str_formatter " ";
|
2018-03-26 17:25:28 -07:00
|
|
|
Printtyp.wrap_printing_env ~error:false env
|
2013-09-04 08:12:37 -07:00
|
|
|
(fun () -> Printtyp.type_sch Format.str_formatter typ);
|
2013-06-04 06:46:48 -07:00
|
|
|
Format.pp_print_newline Format.str_formatter ();
|
|
|
|
let s = Format.flush_str_formatter () in
|
|
|
|
output_string pp s;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp ")\n";
|
2007-05-16 01:21:41 -07:00
|
|
|
loc
|
|
|
|
| An_call (loc, k) ->
|
2012-11-06 10:25:47 -08:00
|
|
|
if loc <> prev_loc then begin
|
|
|
|
print_location pp loc;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp '\n'
|
2012-11-06 10:25:47 -08:00
|
|
|
end;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "call(\n ";
|
|
|
|
output_string pp (call_kind_string k);
|
|
|
|
output_string pp "\n)\n";
|
2007-05-16 01:21:41 -07:00
|
|
|
loc
|
2008-07-29 08:42:44 -07:00
|
|
|
| An_ident (loc, str, k) ->
|
2012-11-06 10:25:47 -08:00
|
|
|
if loc <> prev_loc then begin
|
|
|
|
print_location pp loc;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_char pp '\n'
|
2012-11-06 10:25:47 -08:00
|
|
|
end;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp "ident(\n ";
|
2008-07-29 08:42:44 -07:00
|
|
|
print_ident_annot pp str k;
|
2012-11-07 02:14:02 -08:00
|
|
|
output_string pp ")\n";
|
2007-05-16 01:21:41 -07:00
|
|
|
loc
|
2003-04-01 17:32:09 -08:00
|
|
|
;;
|
|
|
|
|
2003-04-01 22:57:15 -08:00
|
|
|
let get_info () =
|
2007-05-16 01:21:41 -07:00
|
|
|
let info = List.fast_sort cmp_ti_inner_first !annotations in
|
|
|
|
annotations := [];
|
2003-04-01 22:57:15 -08:00
|
|
|
info
|
2003-07-23 09:52:41 -07:00
|
|
|
;;
|
2003-04-01 22:57:15 -08:00
|
|
|
|
|
|
|
let dump filename =
|
2007-05-16 01:21:41 -07:00
|
|
|
if !Clflags.annotations then begin
|
2017-09-06 11:01:15 -07:00
|
|
|
let do_dump _temp_filename pp =
|
|
|
|
let info = get_info () in
|
|
|
|
sort_filter_phrases ();
|
|
|
|
ignore (List.fold_left (print_info pp) Location.none info) in
|
2014-10-29 14:18:14 -07:00
|
|
|
begin match filename with
|
2017-09-06 11:01:15 -07:00
|
|
|
| None -> do_dump "" stdout
|
|
|
|
| Some filename ->
|
|
|
|
Misc.output_to_file_via_temporary ~mode:[Open_text] filename do_dump
|
2014-10-29 14:18:14 -07:00
|
|
|
end;
|
2003-07-23 09:52:41 -07:00
|
|
|
phrases := [];
|
2003-07-25 11:00:40 -07:00
|
|
|
end else begin
|
2007-05-16 01:21:41 -07:00
|
|
|
annotations := [];
|
2003-04-01 17:32:09 -08:00
|
|
|
end;
|
|
|
|
;;
|