forked from MetaRocq/metarocq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin_core.ml
304 lines (264 loc) · 12.5 KB
/
plugin_core.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
(* this file is the interface that extracted plugins will use.
*)
type ident = Names.Id.t (* Template.BasicAst.ident *)
type qualid = Libnames.qualid (* Template.BasicAst.qualid *)
type kername = Names.KerName.t (* Template.BasicAst.kername *)
type reduction_strategy = Redexpr.red_expr (* Template.TemplateMonad.Common.reductionStrategy *)
type global_reference = Names.GlobRef.t (* Template.Ast.global_reference *)
type term = Constr.t (* Template.Ast.term *)
type mutual_inductive_body = Declarations.mutual_inductive_body (* Template.Ast.mutual_inductive_body *)
type constant_body = Declarations.constant_body
type constant_entry = Entries.constant_entry (* Template.Ast.constant_entry *)
type mutual_inductive_entry = Entries.mutual_inductive_entry (* Template.Ast.mutual_inductive_entry *)
let default_flags = Redops.make_red_flag Genredexpr.[FBeta;FMatch;FFix;FCofix;FZeta;FDeltaBut []]
let rs_cbv = Genredexpr.Cbv default_flags
let rs_cbn = Genredexpr.Cbn default_flags
let rs_hnf = Genredexpr.Hnf
let rs_all = Genredexpr.Cbv Redops.all_flags
let rs_lazy = Genredexpr.Cbv Redops.all_flags
let rs_unfold (env : Environ.env) (gr : global_reference) =
try
Genredexpr.Unfold [Locus.AllOccurrences,
Tacred.evaluable_of_global_reference env gr]
with
| _ -> CErrors.user_err
Pp.(str "Constant not found or not a constant: " ++ Printer.pr_global gr)
(* Coq state related to vernaculars, needed to declare constants,
could be a good idea to add the evar_map / env here as a record *)
type coq_state = Declare.OblState.t
type 'a cont = st:coq_state -> Environ.env -> Evd.evar_map -> 'a -> coq_state
type 'a tm =
st:coq_state -> Environ.env -> Evd.evar_map
-> 'a cont -> (st:coq_state -> Pp.t -> coq_state) -> coq_state
let run ~st (c : 'a tm) env evm (k : st:coq_state -> Environ.env -> Evd.evar_map -> 'a -> coq_state) : coq_state =
c ~st env evm k (fun ~st x -> CErrors.user_err x)
let run_vernac ~st (c : 'a tm) : coq_state =
let env = Global.env () in
let evm = Evd.from_env env in
run ~st c env evm (fun ~st _ _ _ -> st)
let with_env_evm (c : Environ.env -> Evd.evar_map -> 'a tm) : 'a tm =
fun ~st env evm success fail -> c ~st env evm env evm success fail
let tmReturn (x : 'a) : 'a tm =
fun ~st env evd k _fail -> k ~st env evd x
let tmBind (x : 'a tm) (k : 'a -> 'b tm) : 'b tm =
fun ~st env evd success fail ->
x ~st env evd (fun ~st env evd v -> k v ~st env evd success fail) fail
let tmMap (f : 'a -> 'b) (x : 'a tm) : 'b tm =
fun ~st env evd success fail ->
x ~st env evd (fun ~st env evd v -> success ~st env evd (f v)) fail
let tmPrint (t : term) : unit tm =
fun ~st env evd success _fail ->
let _ = Feedback.msg_info (Printer.pr_constr_env env evd t) in
success ~st env evd ()
let tmMsg (s : string) : unit tm =
fun ~st env evd success _fail ->
let _ = Feedback.msg_info (Pp.str s) in
success ~st env evd ()
let tmFail (s : Pp.t) : 'a tm =
fun ~st _ _ _ fail -> fail ~st s
let tmFailString (s : string) : 'a tm =
tmFail Pp.(str s)
let reduce env evm red trm =
let red, _ = Redexpr.reduction_of_red_expr env red in
let evm, red = red env evm (EConstr.of_constr trm) in
(evm, EConstr.to_constr evm red)
let tmEval (rd : reduction_strategy) (t : term) : term tm =
fun ~st env evd k _fail ->
let evd,t' = reduce env evd rd t in
k ~st env evd t'
let tmDefinition (nm : ident) ?poly:(poly=false) ?opaque:(opaque=false) (typ : term option) (body : term) : kername tm =
fun ~st env evm success _fail ->
let cinfo = Declare.CInfo.make ~name:nm ~typ:(Option.map EConstr.of_constr typ) () in
let info = Declare.Info.make ~poly ~kind:(Decls.(IsDefinition Definition)) () in
let n = Declare.declare_definition ~cinfo ~info ~opaque ~body:(EConstr.of_constr body) evm in
let env = Global.env () in
let evm = Evd.from_env env in
success ~st env evm (Names.Constant.canonical (Globnames.destConstRef n))
let tmAxiom (nm : ident) ?poly:(poly=false) (typ : term) : kername tm =
fun ~st env evm success _fail ->
let univs = Evd.univ_entry ~poly evm in
let param =
let entry = Declare.parameter_entry ~univs typ in
Declare.ParameterEntry entry
in
let n =
Declare.declare_constant ~name:nm
~kind:(Decls.IsDefinition Decls.Definition)
param
in
success ~st (Global.env ()) evm (Names.Constant.canonical n)
(* this generates a lemma leaving a hole *)
let tmLemma (nm : ident) ?poly:(poly=false)(ty : term) : kername tm =
fun ~st env evm success _fail ->
let kind = Decls.(IsDefinition Definition) in
let hole = CAst.make (Constrexpr.CHole (Some Evar_kinds.(GQuestionMark default_question_mark))) in
Feedback.msg_debug (Pp.str "interp_casted called");
let evm, (c, _) =
try Constrintern.interp_casted_constr_evars_impls ~program_mode:true env evm hole (EConstr.of_constr ty)
with e -> Feedback.msg_debug (Pp.str "interp_casted raised"); raise e in
RetrieveObl.check_evars env evm;
let obls, _, c, cty = RetrieveObl.retrieve_obligations env nm evm 0 c (EConstr.of_constr ty) in
(* let evm = Evd.minimize_universes evm in *)
let ctx = Evd.evar_universe_context evm in
let obl_hook = Declare.Hook.make_g (fun { Declare.Hook.S.dref = gr } pm ->
let env = Global.env () in
let evm = Evd.from_env env in
let evm, t = Evd.fresh_global env evm gr in
match Constr.kind (EConstr.to_constr evm t) with
| Constr.Const (tm, _) ->
success ~st:pm env evm (Names.Constant.canonical tm)
| _ -> failwith "Evd.fresh_global did not return a Const") in
let cinfo = Declare.CInfo.make ~name:nm ~typ:cty () in
let info = Declare.Info.make ~poly ~kind () in
(* This should register properly with the interpretation extension *)
let pm, _ = Declare.Obls.add_definition ~pm:st ~cinfo ~info ~body:c ~uctx:ctx ~obl_hook ~opaque:false obls in
pm
let tmFreshName (nm : ident) : ident tm =
fun ~st env evd success _fail ->
let name' =
Namegen.next_ident_away_from nm (fun id -> Nametab.exists_cci (Lib.make_path id))
in success ~st env evd name'
let tmLocate (qualid : qualid) : global_reference list tm =
fun ~st env evd success _fail ->
let grs = Nametab.locate_all qualid in success ~st env evd grs
let tmLocateModule (qualid : qualid) : Names.ModPath.t list tm =
fun ~st env evd success _fail ->
let mps = Nametab.locate_extended_all_module qualid in success ~st env evd mps
let tmLocateModType (qualid : qualid) : Names.ModPath.t list tm =
fun ~st env evd success _fail ->
let mps = Nametab.locate_extended_all_modtype qualid in success ~st env evd mps
let tmLocateString (s : string) : global_reference list tm =
let id = Libnames.qualid_of_string s in
tmLocate id
let tmLocateModuleString (s : string) : Names.ModPath.t list tm =
let id = Libnames.qualid_of_string s in
tmLocateModule id
let tmLocateModTypeString (s : string) : Names.ModPath.t list tm =
let id = Libnames.qualid_of_string s in
tmLocateModType id
let tmCurrentModPath : Names.ModPath.t tm =
fun ~st env evd success _fail ->
let mp = Lib.current_mp () in success ~st env evd mp
let tmQuoteInductive (kn : kername) : (Names.MutInd.t * mutual_inductive_body) option tm =
fun ~st env evm success _fail ->
try
let mi = Names.MutInd.make1 kn in
let mind = Environ.lookup_mind mi env in
success ~st env evm (Some (mi, mind))
with
Not_found -> success ~st env evm None
let tmQuoteUniverses : UGraph.t tm =
fun ~st env evm success _fail ->
success ~st env evm (Environ.universes env)
let quote_module ~(include_functor : bool) ~(include_submodule : bool) ~(include_submodtype : bool) (qualid : qualid) : global_reference list =
let mp = Nametab.locate_module qualid in
let mb = Global.lookup_module mp in
let open Declarations in
let open Mod_declarations in
let rec aux mb mp =
let rec aux' mt mp =
match mt with
| MoreFunctor (_, _, body) -> if include_functor then aux' body mp else []
| NoFunctor body ->
let get_ref (label, field) =
let open Names in
match field with
| SFBconst _ -> [GlobRef.ConstRef (Constant.make2 mp label)]
| SFBmind _ -> [GlobRef.IndRef (MutInd.make2 mp label, 0)]
| SFBrules _ -> failwith "Rewrite rules are not supported by TemplateCoq"
| SFBmodule mb -> if include_submodule then aux (mod_type mb) (MPdot (mp, label)) else []
| SFBmodtype mtb -> if include_submodtype then aux (mod_type mtb) (MPdot (mp, label)) else []
in
CList.map_append get_ref body
in aux' mb mp
in aux (mod_type mb) mp
let tmQuoteModule (qualid : qualid) : global_reference list tm =
fun ~st env evd success _fail ->
let include_functor = false in
let include_submodule = true in
let include_submodtype = false in
success ~st env evd (quote_module ~include_functor ~include_submodule ~include_submodtype qualid)
let tmQuoteModFunctor (qualid : qualid) : global_reference list tm =
fun ~st env evd success _fail ->
let include_functor = true in
let include_submodule = true in
let include_submodtype = false in
success ~st env evd (quote_module ~include_functor ~include_submodule ~include_submodtype qualid)
let tmQuoteModType (qualid : qualid) : global_reference list tm =
fun ~st env evd success _fail ->
let include_functor = true in
let include_submodule = true in
let include_submodtype = true in
success ~st env evd (quote_module ~include_functor ~include_submodule ~include_submodtype qualid)
(*let universes_entry_of_decl ?withctx d =
let open Declarations in
let open Entries in
match d with
| Monomorphic ctx ->
(match withctx with
| Some ctx' -> Monomorphic_entry (Univ.ContextSet.union ctx ctx')
| None -> Monomorphic_entry ctx)
| Polymorphic ctx ->
assert(Option.is_empty withctx);
Polymorphic_entry (Univ.AUContext.names ctx, Univ.AUContext.repr ctx)*)
(*
let _constant_entry_of_cb (cb : Declarations.constant_body) =
let open Declarations in
let open Entries in
let secctx = match cb.const_hyps with [] -> None | l -> Some l in
let with_body_opaque b ?withctx opaque =
Entries.{ const_entry_secctx = secctx;
const_entry_feedback = None;
const_entry_type = Some cb.const_type;
const_entry_body = Future.from_val ((b, Univ.ContextSet.empty), Safe_typing.empty_private_constants);
const_entry_universes = universes_entry_of_decl ?withctx cb.const_universes;
const_entry_opaque = opaque;
const_entry_inline_code = cb.const_inline_code }
in
let parameter inline = { parameter_entry_secctx = secctx;
parameter_entry_type = cb.const_type;
parameter_entry_universes = universes_entry_of_decl cb.const_universes;
parameter_entry_inline_code = inline }
in
match cb.const_body with
| Def b -> DefinitionEntry (with_body_opaque (Mod_subst.force_constr b) false)
| Undef inline -> ParameterEntry (parameter inline)
| OpaqueDef pr ->
let opaquetab = Global.opaque_tables () in
let proof = Opaqueproof.force_proof opaquetab pr in
let ctx = Opaqueproof.force_constraints opaquetab pr in
DefinitionEntry (with_body_opaque proof ~withctx:ctx true)
| Primitive _ -> failwith "Primitives not supported by TemplateCoq"
*)
(* get the definition associated to a kername *)
let tmQuoteConstant (kn : kername) (bypass : bool) : Declarations.constant_body tm =
fun ~st env evd success fail ->
(* todo(gmm): there is a bug here *)
try
let cnst = Environ.lookup_constant (Names.Constant.make1 kn) env in
success ~st env evd cnst
with
Not_found -> fail ~st Pp.(str "constant not found " ++ Names.KerName.print kn)
let tmInductive (infer_univs : bool) (mie : mutual_inductive_entry) : unit tm =
fun ~st env evd success _fail ->
let mie =
if infer_univs then
let evm = Evd.from_env env in
let ctx, mie = Tm_util.RetypeMindEntry.infer_mentry_univs env evm mie in
Global.push_context_set ctx; mie
else mie
in
let names = (UState.Monomorphic_entry Univ.ContextSet.empty, UnivNames.empty_binders) in
ignore (DeclareInd.declare_mutual_inductive_with_eliminations mie names []) ;
success ~st (Global.env ()) evd ()
let tmExistingInstance (locality : Hints.hint_locality) (gr : Names.GlobRef.t) : unit tm =
fun ~st env evd success _fail ->
Classes.existing_instance locality gr None;
success ~st env evd ()
let tmInferInstance (typ : term) : term option tm =
fun ~st env evm success fail ->
try
let (evm,t) = Typeclasses.resolve_one_typeclass env evm (EConstr.of_constr typ) in
success ~st env evm (Some (EConstr.to_constr evm t))
with
Not_found -> success ~st env evm None