aboutsummaryrefslogtreecommitdiffhomepage
path: root/kernel/declareops.ml
blob: e597ea9a91d607fb6f6ac84cda7ced1d3b60fd85 (plain)
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
(************************************************************************)
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
(* <O___,, *   INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2012     *)
(*   \VV/  **************************************************************)
(*    //   *      This file is distributed under the terms of the       *)
(*         *       GNU Lesser General Public License Version 2.1        *)
(************************************************************************)

open Declarations
open Mod_subst
open Lazyconstr
open Util

(** Operations concernings types in [Declarations] :
    [constant_body], [mutual_inductive_body], [module_body] ... *)

(** Constants *)

let body_of_constant cb = match cb.const_body with
  | Undef _ -> None
  | Def c -> Some (Lazyconstr.force c)
  | OpaqueDef lc -> Some (Lazyconstr.force_opaque (Future.force lc))

let constant_has_body cb = match cb.const_body with
  | Undef _ -> false
  | Def _ | OpaqueDef _ -> true

let is_opaque cb = match cb.const_body with
  | OpaqueDef _ -> true
  | Undef _ | Def _ -> false

(** Constant substitutions *)

let subst_rel_declaration sub (id,copt,t as x) =
  let copt' = Option.smartmap (subst_mps sub) copt in
  let t' = subst_mps sub t in
  if copt == copt' & t == t' then x else (id,copt',t')

let subst_rel_context sub = List.smartmap (subst_rel_declaration sub)

(* TODO: these substitution functions could avoid duplicating things
   when the substitution have preserved all the fields *)

let subst_const_type sub arity =
  if is_empty_subst sub then arity
  else match arity with
    | NonPolymorphicType s -> NonPolymorphicType (subst_mps sub s)
    | PolymorphicArity (ctx,s) -> PolymorphicArity (subst_rel_context sub ctx,s)

let subst_const_def sub = function
  | Undef inl -> Undef inl
  | Def c -> Def (subst_constr_subst sub c)
  | OpaqueDef lc ->
      OpaqueDef (Future.chain ~pure:true lc (subst_lazy_constr sub))

let subst_const_body sub cb = {
  const_hyps = (match cb.const_hyps with [] -> [] | _ -> assert false);
  const_body = subst_const_def sub cb.const_body;
  const_type = subst_const_type sub cb.const_type;
  const_body_code = Cemitcodes.subst_to_patch_subst sub cb.const_body_code;
  const_constraints = cb.const_constraints;
  const_native_name = ref NotLinked;
  const_inline_code = cb.const_inline_code }

(** Hash-consing of constants *)

let hcons_rel_decl ((n,oc,t) as d) =
  let n' = Names.Name.hcons n
  and oc' = Option.smartmap Term.hcons_constr oc
  and t' = Term.hcons_types t
  in if n' == n && oc' == oc && t' == t then d else (n',oc',t')

let hcons_rel_context l = List.smartmap hcons_rel_decl l

let hcons_polyarity ar =
  { poly_param_levels =
      List.smartmap (Option.smartmap Univ.hcons_univ) ar.poly_param_levels;
    poly_level = Univ.hcons_univ ar.poly_level }

let hcons_const_type = function
  | NonPolymorphicType t ->
    NonPolymorphicType (Term.hcons_constr t)
  | PolymorphicArity (ctx,s) ->
    PolymorphicArity (hcons_rel_context ctx, hcons_polyarity s)

let hcons_const_def = function
  | Undef inl -> Undef inl
  | Def l_constr ->
    let constr = force l_constr in
    Def (from_val (Term.hcons_constr constr))
  | OpaqueDef lc ->
    if Future.is_val lc then
      let constr = force_opaque (Future.force lc) in
      OpaqueDef (Future.from_val (opaque_from_val (Term.hcons_constr constr)))
    else OpaqueDef lc

let hcons_const_body cb =
  { cb with
    const_body = hcons_const_def cb.const_body;
    const_type = hcons_const_type cb.const_type;
    const_constraints =
      if Future.is_val cb.const_constraints then
        Future.from_val
          (Univ.hcons_constraints (Future.force cb.const_constraints))
      else cb.const_constraints }

(** Inductive types *)

let eq_recarg r1 r2 = match r1, r2 with
| Norec, Norec -> true
| Mrec i1, Mrec i2 -> Names.eq_ind i1 i2
| Imbr i1, Imbr i2 -> Names.eq_ind i1 i2
| _ -> false

let subst_recarg sub r = match r with
  | Norec -> r
  | Mrec (kn,i) -> let kn' = subst_ind sub kn in
      if kn==kn' then r else Mrec (kn',i)
  | Imbr (kn,i) -> let kn' = subst_ind sub kn in
      if kn==kn' then r else Imbr (kn',i)

let mk_norec = Rtree.mk_node Norec [||]

let mk_paths r recargs =
  Rtree.mk_node r
    (Array.map (fun l -> Rtree.mk_node Norec (Array.of_list l)) recargs)

let dest_recarg p = fst (Rtree.dest_node p)

(* dest_subterms returns the sizes of each argument of each constructor of
   an inductive object of size [p]. This should never be done for Norec,
   because the number of sons does not correspond to the number of
   constructors.
 *)
let dest_subterms p =
  let (ra,cstrs) = Rtree.dest_node p in
  assert (match ra with Norec -> false | _ -> true);
  Array.map (fun t -> Array.to_list (snd (Rtree.dest_node t))) cstrs

let recarg_length p j =
  let (_,cstrs) = Rtree.dest_node p in
  Array.length (snd (Rtree.dest_node cstrs.(j-1)))

let subst_wf_paths sub p = Rtree.smartmap (subst_recarg sub) p

(** Substitution of inductive declarations *)

let subst_indarity sub = function
| Monomorphic s ->
    Monomorphic {
      mind_user_arity = subst_mps sub s.mind_user_arity;
      mind_sort = s.mind_sort;
    }
| Polymorphic s as x -> x

let subst_mind_packet sub mbp =
  { mind_consnames = mbp.mind_consnames;
    mind_consnrealdecls = mbp.mind_consnrealdecls;
    mind_typename = mbp.mind_typename;
    mind_nf_lc = Array.smartmap (subst_mps sub) mbp.mind_nf_lc;
    mind_arity_ctxt = subst_rel_context sub mbp.mind_arity_ctxt;
    mind_arity = subst_indarity sub mbp.mind_arity;
    mind_user_lc = Array.smartmap (subst_mps sub) mbp.mind_user_lc;
    mind_nrealargs = mbp.mind_nrealargs;
    mind_nrealargs_ctxt = mbp.mind_nrealargs_ctxt;
    mind_kelim = mbp.mind_kelim;
    mind_recargs = subst_wf_paths sub mbp.mind_recargs (*wf_paths*);
    mind_nb_constant = mbp.mind_nb_constant;
    mind_nb_args = mbp.mind_nb_args;
    mind_reloc_tbl = mbp.mind_reloc_tbl }

let subst_mind sub mib =
  { mind_record = mib.mind_record ;
    mind_finite = mib.mind_finite ;
    mind_ntypes = mib.mind_ntypes ;
    mind_hyps = (match mib.mind_hyps with [] -> [] | _ -> assert false);
    mind_nparams = mib.mind_nparams;
    mind_nparams_rec = mib.mind_nparams_rec;
    mind_params_ctxt =
      Context.map_rel_context (subst_mps sub) mib.mind_params_ctxt;
    mind_packets = Array.smartmap (subst_mind_packet sub) mib.mind_packets ;
    mind_constraints = mib.mind_constraints;
    mind_native_name = ref NotLinked }

(** Hash-consing of inductive declarations *)

let hcons_indarity = function
  | Monomorphic a ->
    Monomorphic { mind_user_arity = Term.hcons_constr a.mind_user_arity;
		  mind_sort = Term.hcons_sorts a.mind_sort }
  | Polymorphic a -> Polymorphic (hcons_polyarity a)

let hcons_mind_packet oib =
 { oib with
   mind_typename = Names.Id.hcons oib.mind_typename;
   mind_arity_ctxt = hcons_rel_context oib.mind_arity_ctxt;
   mind_arity = hcons_indarity oib.mind_arity;
   mind_consnames = Array.smartmap Names.Id.hcons oib.mind_consnames;
   mind_user_lc = Array.smartmap Term.hcons_types oib.mind_user_lc;
   mind_nf_lc = Array.smartmap Term.hcons_types oib.mind_nf_lc }

let hcons_mind mib =
  { mib with
    mind_packets = Array.smartmap hcons_mind_packet mib.mind_packets;
    mind_params_ctxt = hcons_rel_context mib.mind_params_ctxt;
    mind_constraints = Univ.hcons_constraints mib.mind_constraints }

let join_constant_body cb =
  ignore(Future.join cb.const_constraints);
  match cb.const_body with
  | OpaqueDef d -> ignore(Future.join d)
  | _ -> ()

let string_of_side_effect = function
  | NewConstant (c,_) -> Names.string_of_con c
type side_effects = side_effect list
let no_seff = ([] : side_effects)
let iter_side_effects f l = List.iter f l
let fold_side_effects f a l = List.fold_left f a l
let uniquize_side_effects l = List.uniquize l
let union_side_effects l1 l2 = l1 @ l2
let flatten_side_effects l = List.flatten l
let side_effects_of_list l = l
let cons_side_effects x l = x :: l