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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
open Pp
open CErrors
open Util
open Vernacexpr
open Vernacprop
let checknav { CAst.loc; v = { expr } } =
if is_navigation_vernac expr && not (is_reset expr) then
CErrors.user_err ?loc (str "Navigation commands forbidden in files.")
let vernac_echo ?loc in_chan = let open Loc in
Option.iter (fun loc ->
let len = loc.ep - loc.bp in
seek_in in_chan loc.bp;
Feedback.msg_notice @@ str @@ really_input_string in_chan len
) loc
module State = struct
type t = {
doc : Stm.doc;
sid : Stateid.t;
proof : Proof.t option;
time : bool;
}
end
let interp_vernac ~check ~interactive ~state ({CAst.loc;_} as com) =
let open State in
try
let com = if state.time
then begin
CAst.map (fun cmd -> { cmd with control = ControlTime state.time :: cmd.control }) com
end else com in
let doc, nsid, ntip = Stm.add ~doc:state.doc ~ontop:state.sid (not !Flags.quiet) com in
if ntip <> Stm.NewAddTip then
anomaly (str "vernac.ml: We got an unfocus operation on the toplevel!");
let ndoc = if check then Stm.observe ~doc nsid else doc in
let new_proof = Vernacstate.Declare.give_me_the_proof_opt () [@ocaml.warning "-3"] in
{ state with doc = ndoc; sid = nsid; proof = new_proof; }
with reraise ->
let (reraise, info) = Exninfo.capture reraise in
if interactive then ignore(Stm.edit_at ~doc:state.doc state.sid);
let info = begin
match Loc.get_loc info with
| None -> Option.cata (Loc.add_loc info) info loc
| Some _ -> info
end in
Exninfo.iraise (reraise, info)
let load_vernac_core ~echo ~check ~interactive ~state ?ldir file =
let in_chan = open_utf8_file_in file in
let in_echo = if echo then Some (open_utf8_file_in file) else None in
let input_cleanup () = close_in in_chan; Option.iter close_in in_echo in
let dirpath = Option.cata (fun ldir -> Some Names.DirPath.(to_string ldir))
None ldir in
let in_pa = Pcoq.Parsable.make ~loc:Loc.(initial (InFile {dirpath; file}))
(Stream.of_channel in_chan) in
let open State in
let rec loop state ids =
match
Stm.parse_sentence
~doc:state.doc ~entry:Pvernac.main_entry state.sid in_pa
with
| None ->
input_cleanup ();
state, ids, Pcoq.Parsable.comments in_pa
| Some ast ->
Option.iter (vernac_echo ?loc:ast.CAst.loc) in_echo;
checknav ast;
let state =
Flags.silently (interp_vernac ~check ~interactive ~state) ast in
(loop [@ocaml.tailcall]) state (state.sid :: ids)
in
try loop state []
with any ->
let (e, info) = Exninfo.capture any in
input_cleanup ();
Exninfo.iraise (e, info)
let process_expr ~state loc_ast =
interp_vernac ~interactive:true ~check:true ~state loc_ast
let beautify_suffix = ".beautified"
let set_formatter_translator ch =
let out s b e = output_substring ch s b e in
let ft = Format.make_formatter out (fun () -> flush ch) in
Format.pp_set_max_boxes ft max_int;
ft
let pr_new_syntax ?loc ft_beautify ocom =
let loc = Option.cata Loc.unloc (0,0) loc in
let before = comment (Pputils.extract_comments (fst loc)) in
let com = Option.cata Ppvernac.pr_vernac (mt ()) ocom in
let after = comment (Pputils.extract_comments (snd loc)) in
if !Flags.beautify_file then
(Pp.pp_with ft_beautify (hov 0 (before ++ com ++ after));
Format.pp_print_flush ft_beautify ())
else
Feedback.msg_info (hov 4 (str"New Syntax:" ++ fnl() ++ (hov 0 com)))
let beautify_pass ~doc ~ ~ids ~filename =
let ft_beautify, close_beautify =
if !Flags.beautify_file then
let chan_beautify = open_out (filename^beautify_suffix) in
set_formatter_translator chan_beautify, fun () -> close_out chan_beautify;
else
!Topfmt.std_ft, fun () -> ()
in
Pputils.beautify_comments := comments;
List.iter (fun id -> pr_new_syntax ft_beautify (Stm.get_ast ~doc id)) ids;
pr_new_syntax ~loc:(Loc.make_loc (max_int,max_int)) ft_beautify None;
close_beautify ()
let load_vernac ~echo ~check ~interactive ~state ?ldir filename =
let ostate, ids, = load_vernac_core ~echo ~check ~interactive ~state ?ldir filename in
if !Flags.beautify then beautify_pass ~doc:ostate.State.doc ~comments ~ids:(List.rev ids) ~filename;
ostate