Skip to content

Commit 982cfee

Browse files
authored
Merge pull request #4471 from BuckleScript/remove_pparse
use our own front-end driver instead of pparse
2 parents 8834a45 + 6316346 commit 982cfee

27 files changed

+475
-1987
lines changed

jscomp/common/ml_binary.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,10 @@ let write_ast (type t) (kind : t kind)
4848
| Mli -> Config.ast_intf_magic_number in
4949
output_string oc magic ;
5050
output_value oc fname;
51-
output_value oc pt
51+
output_value oc pt
52+
53+
let magic_of_kind : type a . a kind -> string = function
54+
| Ml -> Config.ast_impl_magic_number
55+
| Mli -> Config.ast_intf_magic_number
56+
57+

jscomp/common/ml_binary.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ type _ kind =
3232
val read_ast : 'a kind -> in_channel -> 'a
3333

3434
val write_ast :
35-
'a kind -> string -> 'a -> out_channel -> unit
35+
'a kind -> string -> 'a -> out_channel -> unit
36+
37+
val magic_of_kind : 'a kind -> string

jscomp/core/cmd_ast_exception.ml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
type error =
2+
| CannotRun of string
3+
| WrongMagic of string
4+
5+
exception Error of error
6+
7+
8+
let report_error ppf = function
9+
| CannotRun cmd ->
10+
Format.fprintf ppf "Error while running external preprocessor@.\
11+
Command line: %s@." cmd
12+
| WrongMagic cmd ->
13+
Format.fprintf ppf "External preprocessor does not produce a valid file@.\
14+
Command line: %s@." cmd
15+
16+
let () =
17+
Location.register_error_of_exn
18+
(function
19+
| Error err -> Some (Location.error_of_printer_file report_error err)
20+
| _ -> None
21+
)
22+
23+
let cannot_run comm =
24+
raise (Error (CannotRun comm))
25+
26+
let wrong_magic magic =
27+
raise (Error (WrongMagic magic))

jscomp/core/cmd_ppx_apply.ml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
3+
(* Note: some of the functions here should go to Ast_mapper instead,
4+
which would encapsulate the "binary AST" protocol. *)
5+
6+
let write_ast (type a) (kind : a Ml_binary.kind) fn (ast : a) =
7+
let oc = open_out_bin fn in
8+
output_string oc (Ml_binary.magic_of_kind kind);
9+
output_value oc (!Location.input_name : string);
10+
output_value oc (ast : a);
11+
close_out oc
12+
13+
let apply_rewriter kind fn_in ppx =
14+
let magic = Ml_binary.magic_of_kind kind in
15+
let fn_out = Filename.temp_file "camlppx" "" in
16+
let comm =
17+
Printf.sprintf "%s %s %s" ppx (Filename.quote fn_in) (Filename.quote fn_out)
18+
in
19+
let ok = Ccomp.command comm = 0 in
20+
Misc.remove_file fn_in;
21+
if not ok then begin
22+
Misc.remove_file fn_out;
23+
Cmd_ast_exception.cannot_run comm
24+
end;
25+
if not (Sys.file_exists fn_out) then
26+
Cmd_ast_exception.cannot_run comm;
27+
(* check magic before passing to the next ppx *)
28+
let ic = open_in_bin fn_out in
29+
let buffer =
30+
try really_input_string ic (String.length magic) with End_of_file -> "" in
31+
close_in ic;
32+
if buffer <> magic then begin
33+
Misc.remove_file fn_out;
34+
Cmd_ast_exception.wrong_magic buffer;
35+
end;
36+
fn_out
37+
38+
let read_ast (type a) (kind : a Ml_binary.kind) fn : a =
39+
let ic = open_in_bin fn in
40+
try
41+
let magic = Ml_binary.magic_of_kind kind in
42+
let buffer = really_input_string ic (String.length magic) in
43+
assert(buffer = magic); (* already checked by apply_rewriter *)
44+
Location.set_input_name @@ (input_value ic : string);
45+
let ast = (input_value ic : a) in
46+
close_in ic;
47+
Misc.remove_file fn;
48+
ast
49+
with exn ->
50+
close_in ic;
51+
Misc.remove_file fn;
52+
raise exn
53+
let rewrite kind ppxs ast =
54+
let fn = Filename.temp_file "camlppx" "" in
55+
write_ast kind fn ast;
56+
let fn = List.fold_left (apply_rewriter kind) fn (List.rev ppxs) in
57+
read_ast kind fn
58+
59+
let apply_rewriters_str ?(restore = true) ~tool_name ast =
60+
match !Clflags.all_ppx with
61+
| [] -> ast
62+
| ppxs ->
63+
ast
64+
|> Ast_mapper.add_ppx_context_str ~tool_name
65+
|> rewrite Ml ppxs
66+
|> Ast_mapper.drop_ppx_context_str ~restore
67+
68+
let apply_rewriters_sig ?(restore = true) ~tool_name ast =
69+
match !Clflags.all_ppx with
70+
| [] -> ast
71+
| ppxs ->
72+
ast
73+
|> Ast_mapper.add_ppx_context_sig ~tool_name
74+
|> rewrite Mli ppxs
75+
|> Ast_mapper.drop_ppx_context_sig ~restore
76+
77+
let apply_rewriters ?restore ~tool_name
78+
(type a) (kind : a Ml_binary.kind) (ast : a) : a =
79+
match kind with
80+
| Ml_binary.Ml ->
81+
apply_rewriters_str ?restore ~tool_name ast
82+
| Ml_binary.Mli ->
83+
apply_rewriters_sig ?restore ~tool_name ast

jscomp/core/js_implementation.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ let after_parsing_sig ppf outputprefix ast =
103103

104104
let interface ppf fname outputprefix =
105105
Compmisc.init_path false;
106-
Pparse.parse_interface ~tool_name:Js_config.tool_name ppf fname
106+
Pparse_driver.parse_interface ppf fname
107+
|> Cmd_ppx_apply.apply_rewriters ~restore:false ~tool_name:Js_config.tool_name Mli
107108
|> Ppx_entry.rewrite_signature
108109
|> print_if_pipe ppf Clflags.dump_parsetree Printast.interface
109110
|> print_if_pipe ppf Clflags.dump_source Pprintast.signature
@@ -200,8 +201,9 @@ let after_parsing_impl ppf outputprefix (ast : Parsetree.structure) =
200201
process_with_gentype (outputprefix ^ ".cmt")
201202
end
202203
let implementation ppf fname outputprefix =
203-
Compmisc.init_path false;
204-
Pparse.parse_implementation ~tool_name:Js_config.tool_name ppf fname
204+
Compmisc.init_path false;
205+
Pparse_driver.parse_implementation ppf fname
206+
|> Cmd_ppx_apply.apply_rewriters ~restore:false ~tool_name:Js_config.tool_name Ml
205207
|> Ppx_entry.rewrite_implementation
206208
|> print_if_pipe ppf Clflags.dump_parsetree Printast.implementation
207209
|> print_if_pipe ppf Clflags.dump_source Pprintast.structure

jscomp/core/pparse_driver.ml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
2+
3+
4+
(* Optionally preprocess a source file *)
5+
6+
let call_external_preprocessor sourcefile pp =
7+
let tmpfile = Filename.temp_file "ocamlpp" "" in
8+
let comm = Printf.sprintf "%s %s > %s"
9+
pp (Filename.quote sourcefile) tmpfile
10+
in
11+
if Ccomp.command comm <> 0 then begin
12+
Misc.remove_file tmpfile;
13+
Cmd_ast_exception.cannot_run comm
14+
end;
15+
tmpfile
16+
17+
let preprocess sourcefile =
18+
match !Clflags.preprocessor with
19+
None -> sourcefile
20+
| Some pp ->
21+
call_external_preprocessor sourcefile pp
22+
23+
24+
let remove_preprocessed inputfile =
25+
match !Clflags.preprocessor with
26+
None -> ()
27+
| Some _ -> Misc.remove_file inputfile
28+
29+
30+
31+
32+
33+
34+
(* Parse a file or get a dumped syntax tree from it *)
35+
36+
let parse (type a) (kind : a Ml_binary.kind) lexbuf : a =
37+
match kind with
38+
| Ml_binary.Ml -> Parse.implementation lexbuf
39+
| Ml_binary.Mli -> Parse.interface lexbuf
40+
41+
let file_aux ppf inputfile (type a) (parse_fun : _ -> a)
42+
(kind : a Ml_binary.kind) : a =
43+
let ast_magic = Ml_binary.magic_of_kind kind in
44+
let ic = open_in_bin inputfile in
45+
let is_ast_file =
46+
match really_input_string ic (String.length ast_magic) with
47+
| exception _ -> false
48+
| buffer ->
49+
if buffer = ast_magic then true
50+
else if Ext_string.starts_with buffer "Caml1999" then
51+
Cmd_ast_exception.wrong_magic buffer
52+
else false in
53+
let ast =
54+
try
55+
if is_ast_file then begin
56+
if !Clflags.fast then
57+
(* FIXME make this a proper warning *)
58+
Format.fprintf ppf "@[Warning: %s@]@."
59+
"option -unsafe used with a preprocessor returning a syntax tree";
60+
Location.set_input_name (input_value ic : string);
61+
(input_value ic : a)
62+
end else begin
63+
seek_in ic 0;
64+
let lexbuf = Lexing.from_channel ic in
65+
Location.init lexbuf inputfile;
66+
parse_fun lexbuf
67+
end
68+
with x -> close_in ic; raise x
69+
in
70+
close_in ic; ast
71+
72+
73+
74+
75+
76+
let parse_file (type a) (kind : a Ml_binary.kind) (ppf : Format.formatter) (sourcefile : string) : a =
77+
Location.set_input_name sourcefile;
78+
let inputfile = preprocess sourcefile in
79+
let ast =
80+
try
81+
(file_aux ppf inputfile (parse kind) kind)
82+
with exn ->
83+
remove_preprocessed inputfile;
84+
raise exn
85+
in
86+
remove_preprocessed inputfile;
87+
ast
88+
89+
90+
91+
let parse_implementation ppf sourcefile =
92+
(parse_file
93+
Ml ppf sourcefile)
94+
95+
let parse_interface ppf sourcefile =
96+
parse_file Mli ppf sourcefile

jscomp/core/pparse_driver.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
3+
val parse_implementation:
4+
Format.formatter ->
5+
string -> Parsetree.structure
6+
7+
8+
val parse_interface:
9+
Format.formatter ->
10+
11+
string -> Parsetree.signature

0 commit comments

Comments
 (0)