Source file comDefinition.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
open Pp
open Util
open Redexpr
open Constrintern
let red_constant_body red_opt env sigma body = match red_opt with
| None -> sigma, body
| Some red ->
let red, _ = reduction_of_red_expr env red in
red env sigma body
let warn_implicits_in_term =
CWarnings.create ~name:"implicits-in-term" ~category:CWarnings.CoreCategories.implicits
(fun () ->
strbrk "Implicit arguments declaration relies on type." ++ spc () ++
strbrk "Discarding incompatible declaration in term.")
let check_imps ~impsty ~impsbody =
let rec aux impsty impsbody =
match impsty, impsbody with
| a1 :: impsty, a2 :: impsbody ->
let () = match a1.CAst.v, a2.CAst.v with
| None , None | Some _, None -> ()
| Some (_,b1) , Some (_,b2) ->
if not ((b1:bool) = b2) then warn_implicits_in_term ?loc:a2.CAst.loc ()
| None, Some _ -> warn_implicits_in_term ?loc:a2.CAst.loc ()
in
aux impsty impsbody
| _ :: _, [] | [], _ :: _ -> ()
| [], [] -> () in
aux impsty impsbody
let protect_pattern_in_binder bl c ctypopt =
if List.exists (function Constrexpr.CLocalPattern _ -> true | _ -> false) bl
then
let t = match ctypopt with
| None -> CAst.make ?loc:c.CAst.loc (Constrexpr.CHole (None))
| Some t -> t in
let loc = Loc.merge_opt c.CAst.loc t.CAst.loc in
let c = CAst.make ?loc @@ Constrexpr.CCast (c, Some Constr.DEFAULTcast, t) in
let loc = match List.hd bl with
| Constrexpr.CLocalAssum (a::_,_,_,_) | Constrexpr.CLocalDef (a,_,_,_) -> a.CAst.loc
| Constrexpr.CLocalPattern {CAst.loc} -> loc
| Constrexpr.CLocalAssum ([],_,_,_) -> assert false in
let apply_under_binders f env evd c =
let rec aux env evd c =
let open Constr in
let open EConstr in
let open Context.Rel.Declaration in
match kind evd c with
| Lambda (x,t,c) ->
let evd,c = aux (push_rel (LocalAssum (x,t)) env) evd c in
evd, mkLambda (x,t,c)
| LetIn (x,b,t,c) ->
let evd,c = aux (push_rel (LocalDef (x,b,t)) env) evd c in
evd, mkLetIn (x,t,b,c)
| Case (ci,u,pms,p,iv,a,bl) ->
let (ci, p, iv, a, bl) = EConstr.expand_case env evd (ci, u, pms, p, iv, a, bl) in
let evd,bl = Array.fold_left_map (aux env) evd bl in
evd, mkCase (EConstr.contract_case env evd (ci, p, iv, a, bl))
| Cast (c,_,_) -> f env evd c
| _ -> (evd,c) in
aux env evd c in
([], Constrexpr_ops.mkLambdaCN ?loc:(Loc.merge_opt loc c.CAst.loc) bl c, None, apply_under_binders)
else
(bl, c, ctypopt, fun f env evd c -> f env evd c)
let interp_definition ~program_mode env evd impl_env bl red_option c ctypopt =
let flags = Pretyping.{ all_no_fail_flags with program_mode } in
let (bl, c, ctypopt, apply_under_binders) = protect_pattern_in_binder bl c ctypopt in
let evd, (impls, ((env_bl, ctx), imps1)) = interp_context_evars ~program_mode ~impl_env env evd bl in
let evd, tyopt = Option.fold_left_map
(interp_type_evars_impls ~flags ~impls env_bl)
evd ctypopt
in
let evd, c, imps, tyopt =
match tyopt with
| None ->
let evd, (c, impsbody) = interp_constr_evars_impls ~program_mode ~impls env_bl evd c in
evd, c, imps1@impsbody, None
| Some (ty, impsty) ->
let evd, (c, impsbody) = interp_casted_constr_evars_impls ~program_mode ~impls env_bl evd c ty in
check_imps ~impsty ~impsbody;
evd, c, imps1@impsty, Some ty
in
let evd, c = apply_under_binders (red_constant_body red_option) env_bl evd c in
let c = EConstr.it_mkLambda_or_LetIn c ctx in
let tyopt = Option.map (fun ty -> EConstr.it_mkProd_or_LetIn ty ctx) tyopt in
evd, (c, tyopt), imps
let do_definition ?hook ~name ?scope ?clearbody ~poly ?typing_flags ~kind ?using ?user_warns udecl bl red_option c ctypopt =
let program_mode = false in
let env = Global.env() in
let env = Environ.update_typing_flags ?typing_flags env in
let evd, udecl = interp_univ_decl_opt env udecl in
let evd, (body, types), impargs =
interp_definition ~program_mode env evd empty_internalization_env bl red_option c ctypopt
in
let kind = Decls.IsDefinition kind in
let cinfo = Declare.CInfo.make ~name ~impargs ~typ:types () in
let info = Declare.Info.make ?scope ?clearbody ~kind ?hook ~udecl ~poly ?typing_flags ?user_warns () in
let _ : Names.GlobRef.t =
Declare.declare_definition ~info ~cinfo ~opaque:false ~body ?using evd
in ()
let do_definition_program ?hook ~pm ~name ~scope ?clearbody ~poly ?typing_flags ~kind ?using ?user_warns udecl bl red_option c ctypopt =
let () = if not poly then udecl |> Option.iter (fun udecl ->
if not udecl.UState.univdecl_extensible_instance
|| not udecl.UState.univdecl_extensible_constraints
then
CErrors.user_err
Pp.(str "Non extensible universe declaration not supported \
with monomorphic Program Definition."))
in
let env = Global.env() in
let env = Environ.update_typing_flags ?typing_flags env in
let evd, udecl = interp_univ_decl_opt env udecl in
let evd, (body, types), impargs =
interp_definition ~program_mode:true env evd empty_internalization_env bl red_option c ctypopt
in
let body, typ, uctx, _, obls = Declare.Obls.prepare_obligations ~name ~body ?types env evd in
let pm, _ =
let cinfo = Declare.CInfo.make ~name ~typ ~impargs () in
let info = Declare.Info.make ~udecl ~scope ?clearbody ~poly ~kind ?hook ?typing_flags ?user_warns () in
Declare.Obls.add_definition ~pm ~info ~cinfo ~opaque:false ~body ~uctx ?using obls
in pm