-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathcompile_common.ml
138 lines (124 loc) · 4.99 KB
/
compile_common.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 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. *)
(* *)
(**************************************************************************)
open Misc
type info = {
source_file : string;
module_name : Compilation_unit.t;
output_prefix : string;
env : Env.t;
ppf_dump : Format.formatter;
tool_name : string;
native : bool;
}
let cmx i = i.output_prefix ^ ".cmx"
let obj i = i.output_prefix ^ Config.ext_obj
let cmo i = i.output_prefix ^ ".cmo"
let annot i = i.output_prefix ^ ".annot"
let with_info ~native ~tool_name ~source_file ~output_prefix ~dump_ext k =
Compmisc.init_path ();
let module_name = Compenv.module_of_filename source_file output_prefix in
let for_pack_prefix = Compilation_unit.Prefix.from_clflags () in
let compilation_unit =
Compilation_unit.create for_pack_prefix
(module_name |> Compilation_unit.Name.of_string)
in
Compilation_unit.set_current (Some compilation_unit);
let env = Compmisc.initial_env() in
let dump_file = String.concat "." [output_prefix; dump_ext] in
Compmisc.with_ppf_dump ~file_prefix:dump_file (fun ppf_dump ->
k {
module_name = compilation_unit;
output_prefix;
env;
source_file;
ppf_dump;
tool_name;
native;
})
(** Compile a .mli file *)
let parse_intf i =
Pparse.parse_interface ~tool_name:i.tool_name i.source_file
|> print_if i.ppf_dump Clflags.dump_parsetree Printast.interface
|> print_if i.ppf_dump Clflags.dump_source Pprintast.signature
let typecheck_intf info ast =
Profile.(record_call typing) @@ fun () ->
let tsg =
ast
|> Typemod.type_interface info.env
|> print_if info.ppf_dump Clflags.dump_typedtree Printtyped.interface
in
let sg = tsg.Typedtree.sig_type in
if !Clflags.print_types then
Printtyp.wrap_printing_env ~error:false info.env (fun () ->
Format.(fprintf std_formatter) "%a@."
(Printtyp.printed_signature info.source_file)
sg);
ignore (Includemod.signatures info.env ~mark:Mark_both sg sg);
Typecore.force_delayed_checks ();
Builtin_attributes.warn_unused ();
Warnings.check_fatal ();
tsg
let emit_signature info ast tsg =
let sg =
let alerts = Builtin_attributes.alerts_of_sig ast in
Env.save_signature ~alerts tsg.Typedtree.sig_type
info.module_name (info.output_prefix ^ ".cmi")
in
Typemod.save_signature info.module_name tsg
info.output_prefix info.source_file info.env sg
let interface ~hook_parse_tree ~hook_typed_tree info =
Profile.record_call info.source_file @@ fun () ->
let ast = parse_intf info in
hook_parse_tree ast;
if Clflags.(should_stop_after Compiler_pass.Parsing) then () else begin
let tsg = typecheck_intf info ast in
hook_typed_tree tsg;
if not !Clflags.print_types then begin
emit_signature info ast tsg
end
end
(** Frontend for a .ml file *)
let parse_impl i =
Pparse.parse_implementation ~tool_name:i.tool_name i.source_file
|> print_if i.ppf_dump Clflags.dump_parsetree Printast.implementation
|> print_if i.ppf_dump Clflags.dump_source Pprintast.structure
let typecheck_impl i parsetree =
parsetree
|> Profile.(record typing)
(Typemod.type_implementation
i.source_file i.output_prefix i.module_name i.env)
|> print_if i.ppf_dump Clflags.dump_typedtree
Printtyped.implementation_with_coercion
|> print_if i.ppf_dump Clflags.dump_shape
(fun fmt {Typedtree.shape; _} -> Shape.print fmt shape)
let implementation ~hook_parse_tree ~hook_typed_tree info ~backend =
Profile.record_call info.source_file @@ fun () ->
let exceptionally () =
let sufs = if info.native then [ cmx; obj ] else [ cmo ] in
List.iter (fun suf -> remove_file (suf info)) sufs;
in
Misc.try_finally ?always:None ~exceptionally (fun () ->
let parsed = parse_impl info in
hook_parse_tree parsed;
if Clflags.(should_stop_after Compiler_pass.Parsing) then () else begin
let typed = typecheck_impl info parsed in
hook_typed_tree typed;
if Clflags.(should_stop_after Compiler_pass.Typing) then () else begin
backend info typed
end;
end;
Builtin_attributes.warn_unused ();
Warnings.check_fatal ();
)