Source file vernacinterp.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
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
open Vernacexpr
open Synterp
let vernac_pperr_endline = CDebug.create ~name:"vernacinterp" ()
let real_error_loc ~cmdloc ~eloc =
if Loc.finer eloc cmdloc then eloc
else cmdloc
let locate_if_not_already ?loc (e, info) =
(e, Option.cata (Loc.add_loc info) info (real_error_loc ~cmdloc:loc ~eloc:(Loc.get_loc info)))
let with_interp_state ~unfreeze_transient st =
let with_local_state synterp_st f =
unfreeze_transient synterp_st;
let v = f () in
Vernacstate.Interp.invalidate_cache ();
Vernacstate.unfreeze_full_state st;
(), v
in
{ VernacControl.with_local_state }
let interp_control_gen ~loc ~st ~unfreeze_transient control f =
let noop = st.Vernacstate.interp.lemmas, st.Vernacstate.interp.program in
let control, res =
VernacControl.under_control ~loc
~with_local_state:(with_interp_state ~unfreeze_transient st)
control
~noop
f
in
if VernacControl.after_last_phase ~loc control
then noop
else res
let rec interp_expr ?loc ~st cmd =
let before_univs = Global.universes () in
let pstack, pm = with_generic_atts ~check:false cmd.attrs (fun ~atts ->
interp_expr_core ?loc ~atts ~st cmd.expr)
in
let after_univs = Global.universes () in
if before_univs == after_univs then pstack, pm
else
let f = Declare.Proof.update_sigma_univs after_univs in
Option.map (Vernacstate.LemmaStack.map ~f) pstack, pm
and interp_expr_core ?loc ~atts ~st c =
match c with
| VernacSynPure VernacAbortAll -> CErrors.user_err (Pp.str "AbortAll cannot be used through the Load command")
| VernacSynPure VernacRestart -> CErrors.user_err (Pp.str "Restart cannot be used through the Load command")
| VernacSynPure VernacUndo _ -> CErrors.user_err (Pp.str "Undo cannot be used through the Load command")
| VernacSynPure VernacUndoTo _ -> CErrors.user_err (Pp.str "UndoTo cannot be used through the Load command")
| VernacSynPure VernacResetName _ -> CErrors.anomaly (Pp.str "VernacResetName not handled by Stm.")
| VernacSynPure VernacResetInitial -> CErrors.anomaly (Pp.str "VernacResetInitial not handled by Stm.")
| VernacSynPure VernacBack _ -> CErrors.anomaly (Pp.str "VernacBack not handled by Stm.")
| VernacSynterp EVernacLoad (verbosely, fname) ->
Attributes.unsupported_attributes atts;
vernac_load ~verbosely fname
| v ->
let fv = Vernacentries.translate_vernac ?loc ~atts v in
let stack = st.Vernacstate.interp.lemmas in
let program = st.Vernacstate.interp.program in
let {Vernactypes.prog; proof; opaque_access=(); }, () = Vernactypes.run fv {
prog=program;
proof=stack;
opaque_access=();
}
in
proof, prog
and vernac_load ~verbosely entries =
let st = Vernacstate.freeze_full_state () in
let v_mod = if verbosely then Flags.verbosely else Flags.silently in
let interp_entry (stack, pm) (CAst.{ loc; v = cmd }, synterp_st) =
Vernacstate.Synterp.unfreeze synterp_st;
let st = Vernacstate.{ synterp = synterp_st; interp = { st.interp with Interp.lemmas = stack; program = pm }} in
v_mod (interp_control ~st) (CAst.make ?loc cmd)
in
let pm = st.Vernacstate.interp.program in
let stack = st.Vernacstate.interp.lemmas in
let stack, pm =
Dumpglob.with_glob_output Dumpglob.NoGlob
(fun () -> List.fold_left interp_entry (stack, pm) entries) ()
in
if Option.has_some stack then
CErrors.user_err Pp.(str "Files processed by Load cannot leave open proofs.");
stack, pm
and interp_control ~st ({ CAst.v = cmd; loc }) =
Util.try_finally (fun () ->
Loc.set_current_command_loc loc;
interp_control_gen ~loc ~st cmd.control
~unfreeze_transient:Vernacstate.Synterp.unfreeze
(fun () -> interp_expr ?loc ~st cmd))
()
(fun () -> Loc.set_current_command_loc None)
()
let interp_qed_delayed ~proof ~st pe =
let stack = st.Vernacstate.interp.lemmas in
let pm = st.Vernacstate.interp.program in
let stack = Option.cata (fun stack -> snd @@ Vernacstate.LemmaStack.pop stack) None stack in
let pm = NeList.map_head (fun pm -> match pe with
| Admitted ->
Declare.Proof.save_lemma_admitted_delayed ~pm ~proof
| Proved (_,idopt) ->
let pm = Declare.Proof.save_lemma_proved_delayed ~pm ~proof ~idopt in
pm)
pm
in
stack, pm
let interp_qed_delayed_control ~proof ~st ~control { CAst.loc; v=pe } =
interp_control_gen ~loc ~st control
~unfreeze_transient:(fun () -> ())
(fun () -> interp_qed_delayed ~proof ~st pe)
let interp_gen ~verbosely ~st ~interp_fn cmd =
try
let v_mod = if verbosely then Flags.verbosely else Flags.silently in
let ontop = v_mod (interp_fn ~st) cmd in
Vernacstate.Declare.set ontop [@ocaml.warning "-3"];
Vernacstate.Interp.freeze_interp_state ()
with exn ->
let exn = Exninfo.capture exn in
let exn = locate_if_not_already ?loc:cmd.CAst.loc exn in
Vernacstate.Interp.invalidate_cache ();
Exninfo.iraise exn
let interp ~intern ?(verbosely=true) ~st cmd =
Vernacstate.unfreeze_full_state st;
vernac_pperr_endline Pp.(fun () -> str "interpreting: " ++ Ppvernac.pr_vernac_expr cmd.CAst.v.expr);
let entry = NewProfile.profile "synterp" (fun () -> Synterp.synterp_control ~intern cmd) () in
let interp = NewProfile.profile "interp" (fun () -> interp_gen ~verbosely ~st ~interp_fn:interp_control entry) () in
Vernacstate.{ synterp = Vernacstate.Synterp.freeze (); interp }
let interp_entry ?(verbosely=true) ~st entry =
Vernacstate.unfreeze_full_state st;
interp_gen ~verbosely ~st ~interp_fn:interp_control entry
module Intern = struct
let fs_intern dp =
match Loadpath.locate_absolute_library dp with
| Ok file ->
Feedback.feedback @@ Feedback.FileDependency (Some file, Names.DirPath.to_string dp);
let res, provenance = Library.intern_from_file file in
Result.iter (fun _ ->
Feedback.feedback @@ Feedback.FileLoaded (Names.DirPath.to_string dp, file)) res;
res, provenance
| Error e ->
Loadpath.Error.raise dp e
end
let fs_intern = Intern.fs_intern
let interp_qed_delayed_proof ~proof ~st ~control (CAst.{loc; v = pe } as e) : Vernacstate.Interp.t =
NewProfile.profile "interp-delayed-qed" (fun () ->
interp_gen ~verbosely:false ~st
~interp_fn:(interp_qed_delayed_control ~proof ~control) e)
()