-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdefutils.ml
121 lines (104 loc) · 4.36 KB
/
defutils.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
(*
* Utilities for defining terms
*)
open Constr
open Names
open Evd
open Decl_kinds
open Recordops
open Constrexpr
open Constrextern
(* --- Defining Coq terms --- *)
(* https://github.com/ybertot/plugin_tutorials/blob/master/tuto1/src/simple_declare.ml
TODO do we need to return the updated evar_map? *)
let edeclare ident (_, poly, _ as k) ~opaque sigma udecl body tyopt imps hook refresh =
let open EConstr in
(* XXX: "Standard" term construction combinators such as `mkApp`
don't add any universe constraints that may be needed later for
the kernel to check that the term is correct.
We could manually call `Evd.add_universe_constraints`
[high-level] or `Evd.add_constraints` [low-level]; however, that
turns out to be a bit heavyweight.
Instead, we call type inference on the manually-built term which
will happily infer the constraint for us, even if that's way more
costly in term of CPU cycles.
Beware that `type_of` will perform full type inference including
canonical structure resolution and what not.
*)
let env = Global.env () in
let sigma =
if refresh then
fst (Typing.type_of ~refresh:false env sigma body)
else
sigma
in
let sigma =
if Option.has_some tyopt && refresh then
fst (Typing.type_of ~refresh:false env sigma (Option.get tyopt))
else
sigma
in
let sigma = Evd.minimize_universes sigma in
let body = to_constr sigma body in
let tyopt = Option.map (to_constr sigma) tyopt in
let uvars_fold uvars c =
Univ.LSet.union uvars (Univops.universes_of_constr c) in
let uvars = List.fold_left uvars_fold Univ.LSet.empty
(Option.List.cons tyopt [body]) in
let sigma = Evd.restrict_universe_context sigma uvars in
let univs = Evd.check_univ_decl ~poly sigma udecl in
let ubinders = Evd.universe_binders sigma in
let ce = Declare.definition_entry ?types:tyopt ~univs body in
DeclareDef.declare_definition ident k ce ubinders imps hook
(* Define a new Coq term *)
let define_term ?typ (n : Id.t) (evm : evar_map) (trm : types) (refresh : bool) =
let k = (Global, Flags.is_universe_polymorphism(), Definition) in
let udecl = UState.default_univ_decl in
let nohook = Lemmas.mk_hook (fun _ x -> x) in
let etrm = EConstr.of_constr trm in
let etyp = Option.map EConstr.of_constr typ in
edeclare n k ~opaque:false evm udecl etrm etyp [] nohook refresh
(* Define a Canonical Structure *)
let define_canonical ?typ (n : Id.t) (evm : evar_map) (trm : types) (refresh : bool) =
let k = (Global, Flags.is_universe_polymorphism (), CanonicalStructure) in
let udecl = UState.default_univ_decl in
let hook = Lemmas.mk_hook (fun _ x -> declare_canonical_structure x; x) in
let etrm = EConstr.of_constr trm in
let etyp = Option.map EConstr.of_constr typ in
edeclare n k ~opaque:false evm udecl etrm etyp [] hook refresh
(* --- Converting between representations --- *)
(*
* See defutils.mli for explanations of these representations.
*)
(* Intern a term (for now, ignore the resulting evar_map) *)
let intern env sigma t : evar_map * types =
let (sigma, trm) = Constrintern.interp_constr_evars env sigma t in
sigma, EConstr.to_constr sigma trm
(* Extern a term *)
let extern env sigma t : constr_expr =
Constrextern.extern_constr true env sigma (EConstr.of_constr t)
(* Construct the external expression for a definition *)
let expr_of_global (g : global_reference) : constr_expr =
let r = extern_reference Id.Set.empty g in
CAst.make @@ (CAppExpl ((None, r, None), []))
(* Convert a term into a global reference with universes (or raise Not_found) *)
let pglobal_of_constr term =
match Constr.kind term with
| Const (const, univs) -> Globnames.ConstRef const, univs
| Ind (ind, univs) -> IndRef ind, univs
| Construct (cons, univs) -> ConstructRef cons, univs
| Var id -> VarRef id, Univ.Instance.empty
| _ -> raise Not_found
(* Convert a global reference with universes into a term *)
let constr_of_pglobal (glob, univs) =
match glob with
| Globnames.ConstRef const -> mkConstU (const, univs)
| IndRef ind -> mkIndU (ind, univs)
| ConstructRef cons -> mkConstructU (cons, univs)
| VarRef id -> mkVar id
(* Safely instantiate a global reference, with proper universe handling *)
let new_global sigma gref =
let sigma_ref = ref sigma in
let glob = Evarutil.e_new_global sigma_ref gref in
let sigma = ! sigma_ref in
sigma, EConstr.to_constr sigma glob