~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to contrib/subtac/subtac_cases.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(* -*- compile-command: "make -C ../.. bin/coqtop.byte" -*- *)
 
2
(************************************************************************)
 
3
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
4
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
5
(*   \VV/  **************************************************************)
 
6
(*    //   *      This file is distributed under the terms of the       *)
 
7
(*         *       GNU Lesser General Public License Version 2.1        *)
 
8
(************************************************************************)
 
9
 
 
10
(* $Id: subtac_cases.ml 12194 2009-06-17 16:38:09Z msozeau $ *)
 
11
 
 
12
open Cases
 
13
open Util
 
14
open Names
 
15
open Nameops
 
16
open Term
 
17
open Termops
 
18
open Declarations
 
19
open Inductiveops
 
20
open Environ
 
21
open Sign
 
22
open Reductionops
 
23
open Typeops
 
24
open Type_errors
 
25
 
 
26
open Rawterm
 
27
open Retyping
 
28
open Pretype_errors
 
29
open Evarutil
 
30
open Evarconv
 
31
 
 
32
open Subtac_utils
 
33
 
 
34
(************************************************************************)
 
35
(*            Pattern-matching compilation (Cases)                      *)
 
36
(************************************************************************)
 
37
 
 
38
(************************************************************************)
 
39
(* Configuration, errors and warnings *)
 
40
 
 
41
open Pp
 
42
 
 
43
let mssg_may_need_inversion () =
 
44
  str "Found a matching with no clauses on a term unknown to have an empty inductive type"
 
45
 
 
46
(* Utils *)
 
47
let make_anonymous_patvars =
 
48
  list_tabulate (fun _ -> PatVar (dummy_loc,Anonymous)) 
 
49
 
 
50
(* Environment management *)
 
51
let push_rels vars env = List.fold_right push_rel vars env
 
52
 
 
53
let push_rel_defs =
 
54
  List.fold_right (fun (x,d,t) e -> push_rel (x,Some d,t) e)
 
55
 
 
56
(* We have x1:t1...xn:tn,xi':ti,y1..yk |- c and re-generalize
 
57
   over xi:ti to get x1:t1...xn:tn,xi':ti,y1..yk |- c[xi:=xi'] *)
 
58
 
 
59
let regeneralize_rel i k j = if j = i+k then k else if j < i+k then j else j
 
60
 
 
61
let rec regeneralize_index i k t = match kind_of_term t with
 
62
  | Rel j when j = i+k -> mkRel (k+1)
 
63
  | Rel j when j < i+k -> t
 
64
  | Rel j when j > i+k -> t
 
65
  | _ -> map_constr_with_binders succ (regeneralize_index i) k t
 
66
 
 
67
type alias_constr =
 
68
  | DepAlias
 
69
  | NonDepAlias
 
70
 
 
71
let mkSpecialLetInJudge j (na,(deppat,nondeppat,d,t)) =
 
72
  { uj_val =
 
73
      (match d with
 
74
        | DepAlias -> mkLetIn (na,deppat,t,j.uj_val)
 
75
        | NonDepAlias ->
 
76
            if (not (dependent (mkRel 1) j.uj_type))
 
77
              or (* A leaf: *) isRel deppat
 
78
            then 
 
79
              (* The body of pat is not needed to type j - see *)
 
80
              (* insert_aliases - and both deppat and nondeppat have the *)
 
81
              (* same type, then one can freely substitute one by the other *)
 
82
              subst1 nondeppat j.uj_val
 
83
            else
 
84
              (* The body of pat is not needed to type j but its value *)
 
85
              (* is dependent in the type of j; our choice is to *)
 
86
              (* enforce this dependency *)
 
87
              mkLetIn (na,deppat,t,j.uj_val));
 
88
    uj_type = subst1 deppat j.uj_type }
 
89
 
 
90
(**********************************************************************)
 
91
(* Structures used in compiling pattern-matching *)
 
92
 
 
93
type rhs =
 
94
    { rhs_env    : env;
 
95
      avoid_ids  : identifier list;
 
96
      it         : rawconstr;
 
97
    }
 
98
 
 
99
type equation =
 
100
    { patterns     : cases_pattern list; 
 
101
      rhs          : rhs;
 
102
      alias_stack  : name list;
 
103
      eqn_loc      : loc;
 
104
      used         : bool ref }
 
105
 
 
106
type matrix = equation list
 
107
 
 
108
(* 1st argument of IsInd is the original ind before extracting the summary *)
 
109
type tomatch_type =
 
110
  | IsInd of types * inductive_type
 
111
  | NotInd of constr option * types
 
112
 
 
113
type tomatch_status =
 
114
  | Pushed of ((constr * tomatch_type) * int list)
 
115
  | Alias of (constr * constr * alias_constr * constr)
 
116
  | Abstract of rel_declaration
 
117
 
 
118
type tomatch_stack = tomatch_status list
 
119
 
 
120
(* The type [predicate_signature] types the terms to match and the rhs:
 
121
 
 
122
   - [PrLetIn (names,dep,pred)] types a pushed term ([Pushed]),
 
123
     if dep<>Anonymous, the term is dependent, let n=|names|, if
 
124
     n<>0 then the type of the pushed term is necessarily an
 
125
     inductive with n real arguments. Otherwise, it may be
 
126
     non inductive, or inductive without real arguments, or inductive
 
127
     originating from a subterm in which case real args are not dependent;
 
128
     it accounts for n+1 binders if dep or n binders if not dep
 
129
   - [PrProd] types abstracted term ([Abstract]); it accounts for one binder
 
130
   - [PrCcl] types the right-hand-side
 
131
   - Aliases [Alias] have no trace in [predicate_signature]
 
132
*)
 
133
 
 
134
type predicate_signature =
 
135
  | PrLetIn of (name list * name) * predicate_signature
 
136
  | PrProd of predicate_signature
 
137
  | PrCcl of constr
 
138
 
 
139
(* We keep a constr for aliases and a cases_pattern for error message *)
 
140
 
 
141
type alias_builder =
 
142
  | AliasLeaf
 
143
  | AliasConstructor of constructor
 
144
 
 
145
type pattern_history =
 
146
  | Top
 
147
  | MakeAlias of alias_builder * pattern_continuation
 
148
 
 
149
and pattern_continuation =
 
150
  | Continuation of int * cases_pattern list * pattern_history
 
151
  | Result of cases_pattern list
 
152
 
 
153
let start_history n = Continuation (n, [], Top)
 
154
 
 
155
let initial_history = function Continuation (_,[],Top) -> true | _ -> false
 
156
 
 
157
let feed_history arg = function
 
158
  | Continuation (n, l, h) when n>=1 ->
 
159
      Continuation (n-1, arg :: l, h)
 
160
  | Continuation (n, _, _) ->
 
161
      anomaly ("Bad number of expected remaining patterns: "^(string_of_int n))
 
162
  | Result _ -> 
 
163
      anomaly "Exhausted pattern history"
 
164
 
 
165
(* This is for non exhaustive error message *)
 
166
 
 
167
let rec rawpattern_of_partial_history args2 = function
 
168
  | Continuation (n, args1, h) ->
 
169
      let args3 = make_anonymous_patvars (n - (List.length args2)) in
 
170
      build_rawpattern (List.rev_append args1 (args2@args3)) h
 
171
  | Result pl -> pl
 
172
 
 
173
and build_rawpattern args = function
 
174
  | Top -> args
 
175
  | MakeAlias (AliasLeaf, rh) ->
 
176
      assert (args = []);
 
177
      rawpattern_of_partial_history [PatVar (dummy_loc, Anonymous)] rh
 
178
  | MakeAlias (AliasConstructor pci, rh) ->
 
179
      rawpattern_of_partial_history
 
180
        [PatCstr (dummy_loc, pci, args, Anonymous)] rh
 
181
 
 
182
let complete_history = rawpattern_of_partial_history []
 
183
 
 
184
(* This is to build glued pattern-matching history and alias bodies *)
 
185
 
 
186
let rec simplify_history = function
 
187
  | Continuation (0, l, Top) -> Result (List.rev l)
 
188
  | Continuation (0, l, MakeAlias (f, rh)) ->
 
189
      let pargs = List.rev l in
 
190
      let pat = match f with
 
191
        | AliasConstructor pci ->
 
192
            PatCstr (dummy_loc,pci,pargs,Anonymous)
 
193
        | AliasLeaf -> 
 
194
            assert (l = []);
 
195
            PatVar (dummy_loc, Anonymous) in
 
196
      feed_history pat rh
 
197
  | h -> h
 
198
 
 
199
(* Builds a continuation expecting [n] arguments and building [ci] applied
 
200
   to this [n] arguments *)
 
201
 
 
202
let push_history_pattern n current cont =
 
203
  Continuation (n, [], MakeAlias (current, cont))
 
204
 
 
205
(* A pattern-matching problem has the following form:
 
206
 
 
207
   env, isevars |- <pred> Cases tomatch of mat end
 
208
 
 
209
  where tomatch is some sequence of "instructions" (t1  ... tn)
 
210
 
 
211
  and mat is some matrix 
 
212
   (p11 ... p1n -> rhs1)
 
213
   (    ...            )
 
214
   (pm1 ... pmn -> rhsm)
 
215
 
 
216
  Terms to match: there are 3 kinds of instructions
 
217
 
 
218
  - "Pushed" terms to match are typed in [env]; these are usually just
 
219
    Rel(n) except for the initial terms given by user and typed in [env]
 
220
  - "Abstract" instructions means an abstraction has to be inserted in the
 
221
    current branch to build (this means a pattern has been detected dependent
 
222
    in another one and generalisation is necessary to ensure well-typing)
 
223
  - "Alias" instructions means an alias has to be inserted (this alias
 
224
    is usually removed at the end, except when its type is not the
 
225
    same as the type of the matched term from which it comes -
 
226
    typically because the inductive types are "real" parameters)
 
227
 
 
228
  Right-hand-sides:
 
229
 
 
230
  They consist of a raw term to type in an environment specific to the
 
231
  clause they belong to: the names of declarations are those of the
 
232
  variables present in the patterns. Therefore, they come with their
 
233
  own [rhs_env] (actually it is the same as [env] except for the names
 
234
  of variables).
 
235
 
 
236
*)
 
237
type pattern_matching_problem =
 
238
    { env      : env;
 
239
      isevars  : Evd.evar_defs ref;
 
240
      pred     : predicate_signature option;
 
241
      tomatch  : tomatch_stack;
 
242
      history  : pattern_continuation;
 
243
      mat      : matrix;
 
244
      caseloc  : loc;
 
245
      casestyle: case_style;
 
246
      typing_function: type_constraint -> env -> rawconstr -> unsafe_judgment }
 
247
 
 
248
(*--------------------------------------------------------------------------*
 
249
 * A few functions to infer the inductive type from the patterns instead of *
 
250
 * checking that the patterns correspond to the ind. type of the            *
 
251
 * destructurated object. Allows type inference of examples like            *
 
252
 *  match n with O => true | _ => false end                                 *
 
253
 *  match x in I with C => true | _ => false end                            *
 
254
 *--------------------------------------------------------------------------*)
 
255
 
 
256
(* Computing the inductive type from the matrix of patterns *)
 
257
 
 
258
(* We use the "in I" clause to coerce the terms to match and otherwise
 
259
   use the constructor to know in which type is the matching problem
 
260
 
 
261
   Note that insertion of coercions inside nested patterns is done
 
262
   each time the matrix is expanded *)
 
263
 
 
264
let rec find_row_ind = function
 
265
    [] -> None
 
266
  | PatVar _ :: l -> find_row_ind l
 
267
  | PatCstr(loc,c,_,_) :: _ -> Some (loc,c)
 
268
 
 
269
let inductive_template isevars env tmloc ind =
 
270
  let arsign = get_full_arity_sign env ind in
 
271
  let hole_source = match tmloc with 
 
272
    | Some loc -> fun i -> (loc, Evd.TomatchTypeParameter (ind,i))
 
273
    | None -> fun _ -> (dummy_loc, Evd.InternalHole) in
 
274
   let (_,evarl,_) =
 
275
    List.fold_right
 
276
      (fun (na,b,ty) (subst,evarl,n) ->
 
277
        match b with
 
278
        | None ->
 
279
            let ty' = substl subst ty in
 
280
            let e = e_new_evar isevars env ~src:(hole_source n) ty' in
 
281
            (e::subst,e::evarl,n+1) 
 
282
        | Some b ->
 
283
            (b::subst,evarl,n+1))
 
284
      arsign ([],[],1) in
 
285
   applist (mkInd ind,List.rev evarl)
 
286
 
 
287
 
 
288
(************************************************************************)
 
289
(* Utils *)
 
290
 
 
291
let mkExistential env ?(src=(dummy_loc,Evd.InternalHole)) isevars =
 
292
  e_new_evar isevars env ~src:src (new_Type ())
 
293
 
 
294
let evd_comb2 f isevars x y =
 
295
  let (evd',y) = f !isevars x y in
 
296
  isevars := evd';
 
297
  y
 
298
 
 
299
 
 
300
module Cases_F(Coercion : Coercion.S) : S = struct
 
301
 
 
302
let inh_coerce_to_ind isevars env ty tyi =
 
303
  let expected_typ = inductive_template isevars env None tyi in
 
304
     (* devrait être indifférent d'exiger leq ou pas puisque pour 
 
305
        un inductif cela doit être égal *)
 
306
  let _ = e_cumul env isevars expected_typ ty in ()
 
307
 
 
308
let unify_tomatch_with_patterns isevars env loc typ pats =
 
309
  match find_row_ind pats with
 
310
    | None -> NotInd (None,typ)
 
311
    | Some (_,(ind,_)) ->
 
312
        inh_coerce_to_ind isevars env typ ind;
 
313
        try IsInd (typ,find_rectype env (Evd.evars_of !isevars) typ)
 
314
        with Not_found -> NotInd (None,typ)
 
315
 
 
316
let find_tomatch_tycon isevars env loc = function
 
317
  (* Try if some 'in I ...' is present and can be used as a constraint *)
 
318
  | Some (_,ind,_,_) -> mk_tycon (inductive_template isevars env loc ind)
 
319
  | None -> empty_tycon
 
320
 
 
321
let coerce_row typing_fun isevars env pats (tomatch,(_,indopt)) =
 
322
  let loc = Some (loc_of_rawconstr tomatch) in
 
323
  let tycon = find_tomatch_tycon isevars env loc indopt in
 
324
  let j = typing_fun tycon env tomatch in
 
325
  let evd, j = Coercion.inh_coerce_to_base (loc_of_rawconstr tomatch) env !isevars j in
 
326
  isevars := evd;
 
327
  let typ = nf_evar (Evd.evars_of !isevars) j.uj_type in
 
328
  let t =
 
329
    try IsInd (typ,find_rectype env (Evd.evars_of !isevars) typ)
 
330
    with Not_found ->
 
331
      unify_tomatch_with_patterns isevars env loc typ pats in
 
332
  (j.uj_val,t)
 
333
 
 
334
let coerce_to_indtype typing_fun isevars env matx tomatchl =
 
335
  let pats = List.map (fun r ->  r.patterns) matx in
 
336
  let matx' = match matrix_transpose pats with
 
337
    | [] -> List.map (fun _ -> []) tomatchl (* no patterns at all *)
 
338
    | m -> m in
 
339
  List.map2 (coerce_row typing_fun isevars env) matx' tomatchl
 
340
 
 
341
 
 
342
 
 
343
let adjust_tomatch_to_pattern pb ((current,typ),deps) =
 
344
  (* Ideally, we could find a common inductive type to which both the
 
345
     term to match and the patterns coerce *)
 
346
  (* In practice, we coerce the term to match if it is not already an
 
347
     inductive type and it is not dependent; moreover, we use only 
 
348
     the first pattern type and forget about the others *)
 
349
  let typ = match typ with IsInd (t,_) -> t | NotInd (_,t) -> t in
 
350
  let typ =
 
351
    try IsInd (typ,find_rectype pb.env (Evd.evars_of !(pb.isevars)) typ)
 
352
    with Not_found -> NotInd (None,typ) in
 
353
  let tomatch = ((current,typ),deps) in
 
354
  match typ with
 
355
  | NotInd (None,typ) ->
 
356
      let tm1 = List.map (fun eqn -> List.hd eqn.patterns) pb.mat in
 
357
      (match find_row_ind tm1 with
 
358
        | None -> tomatch
 
359
        | Some (_,(ind,_)) ->
 
360
            let indt = inductive_template pb.isevars pb.env None ind in
 
361
            let current =
 
362
              if deps = [] & isEvar typ then
 
363
              (* Don't insert coercions if dependent; only solve evars *)
 
364
                let _ = e_cumul pb.env pb.isevars indt typ in
 
365
                current
 
366
              else
 
367
                (evd_comb2 (Coercion.inh_conv_coerce_to dummy_loc pb.env)
 
368
                  pb.isevars (make_judge current typ) (mk_tycon_type indt)).uj_val in
 
369
            let sigma = Evd.evars_of !(pb.isevars) in
 
370
            let typ = IsInd (indt,find_rectype pb.env sigma indt) in
 
371
            ((current,typ),deps))
 
372
  | _ -> tomatch
 
373
 
 
374
   (* extract some ind from [t], possibly coercing from constructors in [tm] *)
 
375
let to_mutind env isevars tm c t =
 
376
(*  match c with
 
377
    | Some body -> *) NotInd (c,t)
 
378
(*    | None -> unify_tomatch_with_patterns isevars env t tm*)
 
379
 
 
380
let type_of_tomatch = function
 
381
  | IsInd (t,_) -> t
 
382
  | NotInd (_,t) -> t
 
383
 
 
384
let mkDeclTomatch na = function
 
385
  | IsInd (t,_) -> (na,None,t)
 
386
  | NotInd (c,t) -> (na,c,t)
 
387
 
 
388
let map_tomatch_type f = function
 
389
  | IsInd (t,ind) -> IsInd (f t,map_inductive_type f ind)
 
390
  | NotInd (c,t) -> NotInd (Option.map f c, f t)
 
391
 
 
392
let liftn_tomatch_type n depth = map_tomatch_type (liftn n depth)
 
393
let lift_tomatch_type n = liftn_tomatch_type n 1
 
394
 
 
395
let lift_tomatch n ((current,typ),info) =
 
396
  ((lift n current,lift_tomatch_type n typ),info)
 
397
 
 
398
(**********************************************************************)
 
399
(* Utilities on patterns *)
 
400
 
 
401
let current_pattern eqn =
 
402
  match eqn.patterns with
 
403
    | pat::_ -> pat
 
404
    | [] -> anomaly "Empty list of patterns"
 
405
 
 
406
let alias_of_pat = function
 
407
  | PatVar (_,name) -> name
 
408
  | PatCstr(_,_,_,name) -> name
 
409
 
 
410
let unalias_pat = function
 
411
  | PatVar (c,name) as p ->
 
412
      if name = Anonymous then p else PatVar (c,Anonymous)
 
413
  | PatCstr(a,b,c,name) as p ->
 
414
      if name = Anonymous then p else PatCstr (a,b,c,Anonymous)
 
415
 
 
416
let remove_current_pattern eqn =
 
417
  match eqn.patterns with
 
418
    | pat::pats ->
 
419
        { eqn with
 
420
            patterns = pats;
 
421
            alias_stack = alias_of_pat pat :: eqn.alias_stack }
 
422
    | [] -> anomaly "Empty list of patterns"
 
423
 
 
424
let prepend_pattern tms eqn = {eqn with patterns = tms@eqn.patterns }
 
425
 
 
426
(**********************************************************************)
 
427
(* Well-formedness tests *)
 
428
(* Partial check on patterns *)
 
429
 
 
430
exception NotAdjustable
 
431
 
 
432
let rec adjust_local_defs loc = function
 
433
  | (pat :: pats, (_,None,_) :: decls) ->
 
434
      pat :: adjust_local_defs loc (pats,decls)
 
435
  | (pats, (_,Some _,_) :: decls) ->
 
436
      PatVar (loc, Anonymous) :: adjust_local_defs loc (pats,decls)
 
437
  | [], [] -> []
 
438
  | _ -> raise NotAdjustable
 
439
 
 
440
let check_and_adjust_constructor env ind cstrs = function 
 
441
  | PatVar _ as pat -> pat
 
442
  | PatCstr (loc,((_,i) as cstr),args,alias) as pat ->
 
443
      (* Check it is constructor of the right type *)
 
444
      let ind' = inductive_of_constructor cstr in
 
445
      if Closure.mind_equiv env ind' ind then
 
446
        (* Check the constructor has the right number of args *)
 
447
        let ci = cstrs.(i-1) in
 
448
        let nb_args_constr = ci.cs_nargs in
 
449
        if List.length args = nb_args_constr then pat
 
450
        else
 
451
          try 
 
452
            let args' = adjust_local_defs loc (args, List.rev ci.cs_args)
 
453
            in PatCstr (loc, cstr, args', alias)
 
454
          with NotAdjustable ->
 
455
            error_wrong_numarg_constructor_loc loc (Global.env())
 
456
              cstr nb_args_constr
 
457
      else
 
458
        (* Try to insert a coercion *)
 
459
        try
 
460
          Coercion.inh_pattern_coerce_to loc pat ind' ind
 
461
        with Not_found -> 
 
462
          error_bad_constructor_loc loc cstr ind
 
463
 
 
464
let check_all_variables typ mat =
 
465
  List.iter
 
466
    (fun eqn -> match current_pattern eqn with
 
467
       | PatVar (_,id) -> ()
 
468
       | PatCstr (loc,cstr_sp,_,_) ->
 
469
           error_bad_pattern_loc loc cstr_sp typ)
 
470
    mat
 
471
 
 
472
let check_unused_pattern env eqn =
 
473
  if not !(eqn.used) then 
 
474
    raise_pattern_matching_error
 
475
      (eqn.eqn_loc, env, UnusedClause eqn.patterns)
 
476
 
 
477
let set_used_pattern eqn = eqn.used := true
 
478
 
 
479
let extract_rhs pb =
 
480
  match pb.mat with 
 
481
    | [] -> errorlabstrm "build_leaf" (mssg_may_need_inversion())
 
482
    | eqn::_ ->
 
483
        set_used_pattern eqn;
 
484
        eqn.rhs
 
485
 
 
486
(**********************************************************************)
 
487
(* Functions to deal with matrix factorization *)
 
488
 
 
489
let occur_in_rhs na rhs =
 
490
  match na with
 
491
    | Anonymous -> false
 
492
    | Name id -> occur_rawconstr id rhs.it
 
493
 
 
494
let is_dep_patt eqn = function
 
495
  | PatVar (_,name) -> occur_in_rhs name eqn.rhs
 
496
  | PatCstr _ -> true
 
497
 
 
498
let dependencies_in_rhs nargs eqns =
 
499
  if eqns = [] then list_tabulate (fun _ -> false) nargs (* Only "_" patts *)
 
500
  else
 
501
  let deps = List.map (fun (tms,eqn) -> List.map (is_dep_patt eqn) tms) eqns in
 
502
  let columns = matrix_transpose deps in
 
503
  List.map (List.exists ((=) true)) columns
 
504
 
 
505
let dependent_decl a = function
 
506
  | (na,None,t) -> dependent a t
 
507
  | (na,Some c,t) -> dependent a t || dependent a c
 
508
 
 
509
(* Computing the matrix of dependencies *)
 
510
 
 
511
(* We are in context d1...dn |- and [find_dependencies k 1 nextlist]
 
512
   computes for declaration [k+1] in which of declarations in
 
513
   [nextlist] (which corresponds to d(k+2)...dn) it depends;
 
514
   declarations are expressed by index, e.g. in dependency list
 
515
   [n-2;1], [1] points to [dn] and [n-2] to [d3] *)
 
516
 
 
517
let rec find_dependency_list k n = function
 
518
  | [] -> []
 
519
  | (used,tdeps,d)::rest -> 
 
520
      let deps = find_dependency_list k (n+1) rest in
 
521
      if used && dependent_decl (mkRel n) d
 
522
      then list_add_set (List.length rest + 1) (list_union deps tdeps)
 
523
      else deps
 
524
 
 
525
let find_dependencies is_dep_or_cstr_in_rhs d (k,nextlist) =
 
526
  let deps = find_dependency_list k 1 nextlist in
 
527
  if is_dep_or_cstr_in_rhs || deps <> []
 
528
  then (k-1,(true ,deps,d)::nextlist)
 
529
  else (k-1,(false,[]  ,d)::nextlist)
 
530
 
 
531
let find_dependencies_signature deps_in_rhs typs =
 
532
  let k = List.length deps_in_rhs in
 
533
  let _,l = List.fold_right2 find_dependencies deps_in_rhs typs (k,[]) in
 
534
  List.map (fun (_,deps,_) -> deps) l
 
535
 
 
536
(******)
 
537
 
 
538
(* A Pushed term to match has just been substituted by some
 
539
   constructor t = (ci x1...xn) and the terms x1 ... xn have been added to
 
540
   match 
 
541
 
 
542
   - all terms to match and to push (dependent on t by definition)
 
543
     must have (Rel depth) substituted by t and Rel's>depth lifted by n
 
544
   - all pushed terms to match (non dependent on t by definition) must
 
545
     be lifted by n
 
546
 
 
547
  We start with depth=1
 
548
*)
 
549
 
 
550
let regeneralize_index_tomatch n =
 
551
  let rec genrec depth = function
 
552
  | [] -> []
 
553
  | Pushed ((c,tm),l)::rest ->
 
554
      let c = regeneralize_index n depth c in
 
555
      let tm = map_tomatch_type (regeneralize_index n depth) tm in
 
556
      let l = List.map (regeneralize_rel n depth) l in
 
557
      Pushed ((c,tm),l)::(genrec depth rest)
 
558
  | Alias (c1,c2,d,t)::rest ->
 
559
      Alias (regeneralize_index n depth c1,c2,d,t)::(genrec depth rest)
 
560
  | Abstract d::rest ->
 
561
      Abstract (map_rel_declaration (regeneralize_index n depth) d)
 
562
      ::(genrec (depth+1) rest) in
 
563
  genrec 0
 
564
 
 
565
let rec replace_term n c k t = 
 
566
  if t = mkRel (n+k) then lift k c
 
567
  else map_constr_with_binders succ (replace_term n c) k t
 
568
 
 
569
let replace_tomatch n c =
 
570
  let rec replrec depth = function
 
571
  | [] -> []
 
572
  | Pushed ((b,tm),l)::rest ->
 
573
      let b = replace_term n c depth b in
 
574
      let tm = map_tomatch_type (replace_term n c depth) tm in
 
575
      List.iter (fun i -> if i=n+depth then anomaly "replace_tomatch") l;
 
576
      Pushed ((b,tm),l)::(replrec depth rest)
 
577
  | Alias (c1,c2,d,t)::rest ->
 
578
      Alias (replace_term n c depth c1,c2,d,t)::(replrec depth rest)
 
579
  | Abstract d::rest ->
 
580
      Abstract (map_rel_declaration (replace_term n c depth) d)
 
581
      ::(replrec (depth+1) rest) in
 
582
  replrec 0
 
583
 
 
584
let liftn_rel_declaration n k = map_rel_declaration (liftn n k)
 
585
let substnl_rel_declaration sigma k = map_rel_declaration (substnl sigma k)
 
586
 
 
587
let rec liftn_tomatch_stack n depth = function
 
588
  | [] -> []
 
589
  | Pushed ((c,tm),l)::rest ->
 
590
      let c = liftn n depth c in
 
591
      let tm = liftn_tomatch_type n depth tm in
 
592
      let l = List.map (fun i -> if i<depth then i else i+n) l in
 
593
      Pushed ((c,tm),l)::(liftn_tomatch_stack n depth rest)
 
594
  | Alias (c1,c2,d,t)::rest ->
 
595
      Alias (liftn n depth c1,liftn n depth c2,d,liftn n depth t)
 
596
      ::(liftn_tomatch_stack n depth rest)
 
597
  | Abstract d::rest ->
 
598
      Abstract (map_rel_declaration (liftn n depth) d)
 
599
      ::(liftn_tomatch_stack n (depth+1) rest)
 
600
 
 
601
 
 
602
let lift_tomatch_stack n = liftn_tomatch_stack n 1
 
603
 
 
604
(* if [current] has type [I(p1...pn u1...um)] and we consider the case
 
605
   of constructor [ci] of type [I(p1...pn u'1...u'm)], then the
 
606
   default variable [name] is expected to have which type?
 
607
   Rem: [current] is [(Rel i)] except perhaps for initial terms to match *)
 
608
 
 
609
(************************************************************************)
 
610
(* Some heuristics to get names for variables pushed in pb environment *)
 
611
(* Typical requirement:
 
612
 
 
613
   [match y with (S (S x)) => x | x => x end] should be compiled into
 
614
   [match y with O => y | (S n) => match n with O => y | (S x) => x end end]
 
615
 
 
616
   and [match y with (S (S n)) => n | n => n end] into 
 
617
   [match y with O => y | (S n0) => match n0 with O => y | (S n) => n end end]
 
618
 
 
619
  i.e. user names should be preserved and created names should not
 
620
  interfere with user names *)
 
621
 
 
622
let merge_name get_name obj = function
 
623
  | Anonymous -> get_name obj
 
624
  | na -> na
 
625
 
 
626
let merge_names get_name = List.map2 (merge_name get_name)
 
627
 
 
628
let get_names env sign eqns =
 
629
  let names1 = list_tabulate (fun _ -> Anonymous) (List.length sign) in
 
630
  (* If any, we prefer names used in pats, from top to bottom *)
 
631
  let names2 = 
 
632
    List.fold_right
 
633
      (fun (pats,eqn) names -> merge_names alias_of_pat pats names)
 
634
      eqns names1 in
 
635
  (* Otherwise, we take names from the parameters of the constructor but
 
636
     avoiding conflicts with user ids *)
 
637
  let allvars =
 
638
    List.fold_left (fun l (_,eqn) -> list_union l eqn.rhs.avoid_ids) [] eqns in
 
639
  let names4,_ =
 
640
    List.fold_left2
 
641
      (fun (l,avoid) d na ->
 
642
         let na =
 
643
           merge_name
 
644
             (fun (na,_,t) -> Name (next_name_away (named_hd env t na) avoid))
 
645
             d na 
 
646
         in
 
647
         (na::l,(out_name na)::avoid))
 
648
      ([],allvars) (List.rev sign) names2 in
 
649
  names4
 
650
 
 
651
(************************************************************************)
 
652
(* Recovering names for variables pushed to the rhs' environment *)
 
653
 
 
654
let recover_alias_names get_name = List.map2 (fun x (_,c,t) ->(get_name x,c,t))
 
655
 
 
656
let all_name sign = List.map (fun (n, b, t) -> let n = match n with Name _ -> n | Anonymous -> Name (id_of_string "Anonymous") in
 
657
                                (n, b, t)) sign
 
658
 
 
659
let push_rels_eqn sign eqn =
 
660
  let sign = all_name sign in
 
661
    {eqn with rhs = {eqn.rhs with rhs_env = push_rels sign eqn.rhs.rhs_env; } }
 
662
 
 
663
let push_rels_eqn_with_names sign eqn =
 
664
  let pats = List.rev (list_firstn (List.length sign) eqn.patterns) in
 
665
  let sign = recover_alias_names alias_of_pat pats sign in
 
666
  push_rels_eqn sign eqn
 
667
 
 
668
let build_aliases_context env sigma names allpats pats =
 
669
  (* pats is the list of bodies to push as an alias *)
 
670
  (* They all are defined in env and we turn them into a sign *)
 
671
  (* cuts in sign need to be done in allpats *)
 
672
  let rec insert env sign1 sign2 n newallpats oldallpats = function
 
673
    | (deppat,_,_,_)::pats, Anonymous::names when not (isRel deppat) ->
 
674
        (* Anonymous leaves must be considered named and treated in the *)
 
675
        (* next clause because they may occur in implicit arguments *)
 
676
        insert env sign1 sign2
 
677
          n newallpats (List.map List.tl oldallpats) (pats,names)
 
678
    | (deppat,nondeppat,d,t)::pats, na::names ->
 
679
        let nondeppat = lift n nondeppat in
 
680
        let deppat = lift n deppat in
 
681
        let newallpats =
 
682
          List.map2 (fun l1 l2 -> List.hd l2::l1) newallpats oldallpats in
 
683
        let oldallpats = List.map List.tl oldallpats in
 
684
        let decl = (na,Some deppat,t) in
 
685
        let a = (deppat,nondeppat,d,t) in
 
686
        insert (push_rel decl env) (decl::sign1) ((na,a)::sign2) (n+1) 
 
687
          newallpats oldallpats (pats,names)
 
688
    | [], [] -> newallpats, sign1, sign2, env
 
689
    | _ -> anomaly "Inconsistent alias and name lists" in
 
690
  let allpats = List.map (fun x -> [x]) allpats
 
691
  in insert env [] [] 0 (List.map (fun _ -> []) allpats) allpats (pats, names)
 
692
 
 
693
let insert_aliases_eqn sign eqnnames alias_rest eqn =
 
694
  let thissign = List.map2 (fun na (_,c,t) -> (na,c,t)) eqnnames sign in
 
695
    push_rels_eqn thissign { eqn with  alias_stack = alias_rest; }
 
696
            
 
697
 
 
698
let insert_aliases env sigma alias eqns =
 
699
  (* Là, y a une faiblesse, si un alias est utilisé dans un cas par *)
 
700
  (* défaut présent mais inutile, ce qui est le cas général, l'alias *)
 
701
  (* est introduit même s'il n'est pas utilisé dans les cas réguliers *)
 
702
  let eqnsnames = List.map (fun eqn -> List.hd eqn.alias_stack) eqns in
 
703
  let alias_rests = List.map (fun eqn -> List.tl eqn.alias_stack) eqns in
 
704
  (* names2 takes the meet of all needed aliases *)
 
705
  let names2 = 
 
706
    List.fold_right (merge_name (fun x -> x)) eqnsnames Anonymous in
 
707
  (* Only needed aliases are kept by build_aliases_context *)
 
708
  let eqnsnames, sign1, sign2, env =
 
709
    build_aliases_context env sigma [names2] eqnsnames [alias] in
 
710
  let eqns = list_map3 (insert_aliases_eqn sign1) eqnsnames alias_rests eqns in
 
711
  sign2, env, eqns
 
712
 
 
713
(**********************************************************************)
 
714
(* Functions to deal with elimination predicate *)
 
715
 
 
716
exception Occur
 
717
let noccur_between_without_evar n m term = 
 
718
  let rec occur_rec n c = match kind_of_term c with
 
719
    | Rel p       -> if n<=p && p<n+m then raise Occur
 
720
    | Evar (_,cl) -> ()
 
721
    | _             -> iter_constr_with_binders succ occur_rec n c
 
722
  in 
 
723
  try occur_rec n term; true with Occur -> false
 
724
 
 
725
(* Inferring the predicate *)
 
726
let prepare_unif_pb typ cs =
 
727
  let n = List.length (assums_of_rel_context cs.cs_args) in
 
728
 
 
729
  (* We may need to invert ci if its parameters occur in typ *)
 
730
  let typ' =
 
731
    if noccur_between_without_evar 1 n typ then lift (-n) typ
 
732
    else (* TODO4-1 *)
 
733
      error "Unable to infer return clause of this pattern-matching problem" in
 
734
  let args = extended_rel_list (-n) cs.cs_args in
 
735
  let ci = applist (mkConstruct cs.cs_cstr, cs.cs_params@args) in
 
736
 
 
737
  (* This is the problem: finding P s.t. cs_args |- (P realargs ci) = typ' *)
 
738
  (Array.map (lift (-n)) cs.cs_concl_realargs, ci, typ')
 
739
 
 
740
 
 
741
(* Infering the predicate *)
 
742
(*
 
743
The problem to solve is the following:
 
744
 
 
745
We match Gamma |- t : I(u01..u0q) against the following constructors:
 
746
 
 
747
  Gamma, x11...x1p1 |- C1(x11..x1p1) : I(u11..u1q)
 
748
   ...
 
749
  Gamma, xn1...xnpn |- Cn(xn1..xnp1) : I(un1..unq)
 
750
 
 
751
Assume the types in the branches are the following
 
752
 
 
753
  Gamma, x11...x1p1 |- branch1 : T1
 
754
   ...
 
755
  Gamma, xn1...xnpn |- branchn : Tn
 
756
 
 
757
Assume the type of the global case expression is Gamma |- T
 
758
 
 
759
The predicate has the form phi = [y1..yq][z:I(y1..yq)]? and must satisfy
 
760
the following n+1 equations:
 
761
 
 
762
  Gamma, x11...x1p1 |- (phi u11..u1q (C1 x11..x1p1))  =  T1
 
763
   ...
 
764
  Gamma, xn1...xnpn |- (phi un1..unq (Cn xn1..xnpn))  =  Tn
 
765
  Gamma             |- (phi u01..u0q t)               =  T
 
766
 
 
767
Some hints:
 
768
 
 
769
- Clearly, if xij occurs in Ti, then, a "match z with (Ci xi1..xipi) => ..."
 
770
  should be inserted somewhere in Ti.
 
771
 
 
772
- If T is undefined, an easy solution is to insert a "match z with (Ci
 
773
  xi1..xipi) => ..." in front of each Ti
 
774
 
 
775
- Otherwise, T1..Tn and T must be step by step unified, if some of them
 
776
  diverge, then try to replace the diverging subterm by one of y1..yq or z.
 
777
 
 
778
- The main problem is what to do when an existential variables is encountered
 
779
 
 
780
let prepare_unif_pb typ cs =
 
781
  let n = cs.cs_nargs in
 
782
  let _,p = decompose_prod_n n typ in
 
783
  let ci = build_dependent_constructor cs in
 
784
  (* This is the problem: finding P s.t. cs_args |- (P realargs ci) = p *)
 
785
  (n, cs.cs_concl_realargs, ci, p)
 
786
 
 
787
let eq_operator_lift k (n,n') = function
 
788
  | OpRel p, OpRel p' when p > k & p' > k ->
 
789
      if p < k+n or p' < k+n' then false else p - n = p' - n'
 
790
  | op, op' -> op = op'
 
791
 
 
792
let rec transpose_args n =
 
793
  if n=0 then []
 
794
  else
 
795
    (Array.map (fun l -> List.hd l) lv)::
 
796
    (transpose_args (m-1) (Array.init (fun l -> List.tl l)))
 
797
 
 
798
let shift_operator k = function OpLambda _ | OpProd _ -> k+1 | _ -> k
 
799
 
 
800
let reloc_operator (k,n) = function OpRel p when p > k -> 
 
801
let rec unify_clauses k pv =
 
802
  let pv'= Array.map (fun (n,sign,_,p) -> n,splay_constr (whd_betaiotaevar (push_rels (List.rev sign) env) (Evd.evars_of isevars)) p) pv in
 
803
  let n1,op1 = let (n1,(op1,args1)) = pv'.(0) in n1,op1 in
 
804
  if Array.for_all (fun (ni,(opi,_)) -> eq_operator_lift k (n1,ni) (op1,opi)) pv'
 
805
  then
 
806
    let argvl = transpose_args (List.length args1) pv' in
 
807
    let k' = shift_operator k op1 in
 
808
    let argl = List.map (unify_clauses k') argvl in
 
809
    gather_constr (reloc_operator (k,n1) op1) argl
 
810
*)
 
811
 
 
812
let abstract_conclusion typ cs =
 
813
  let n = List.length (assums_of_rel_context cs.cs_args) in
 
814
  let (sign,p) = decompose_prod_n n typ in
 
815
  lam_it p sign
 
816
 
 
817
let infer_predicate loc env isevars typs cstrs indf =
 
818
  (* Il faudra substituer les isevars a un certain moment *)
 
819
  if Array.length cstrs = 0 then (* "TODO4-3" *)
 
820
    error "Inference of annotation for empty inductive types not implemented"
 
821
  else
 
822
    (* Empiric normalization: p may depend in a irrelevant way on args of the*)
 
823
    (* cstr as in [c:{_:Alpha & Beta}] match c with (existS a b)=>(a,b) end *)
 
824
    let typs =
 
825
      Array.map (local_strong whd_beta (Evd.evars_of !isevars)) typs
 
826
    in
 
827
    let eqns = array_map2 prepare_unif_pb typs cstrs in
 
828
    (* First strategy: no dependencies at all *)
 
829
(*
 
830
    let (mis,_) = dest_ind_family indf in
 
831
    let (cclargs,_,typn) = eqns.(mis_nconstr mis -1) in
 
832
*)
 
833
    let (sign,_) = get_arity env indf in
 
834
    let mtyp =
 
835
      if array_exists is_Type typs then
 
836
        (* Heuristic to avoid comparison between non-variables algebric univs*)
 
837
        new_Type ()
 
838
      else
 
839
        mkExistential env ~src:(loc, Evd.CasesType) isevars
 
840
    in
 
841
    if array_for_all (fun (_,_,typ) -> e_cumul env isevars typ mtyp) eqns
 
842
    then
 
843
      (* Non dependent case -> turn it into a (dummy) dependent one *)
 
844
      let sign = (Anonymous,None,build_dependent_inductive env indf)::sign in
 
845
      let pred = it_mkLambda_or_LetIn (lift (List.length sign) mtyp) sign in
 
846
      (true,pred) (* true = dependent -- par défaut *)
 
847
    else
 
848
(*
 
849
      let s = get_sort_of env (evars_of isevars) typs.(0) in
 
850
      let predpred = it_mkLambda_or_LetIn (mkSort s) sign in
 
851
      let caseinfo = make_default_case_info mis in
 
852
      let brs = array_map2 abstract_conclusion typs cstrs in
 
853
      let predbody = mkCase (caseinfo, (nf_betaiota predpred), mkRel 1, brs) in
 
854
      let pred = it_mkLambda_or_LetIn (lift (List.length sign) mtyp) sign in
 
855
*)
 
856
      (* "TODO4-2" *)
 
857
      (* We skip parameters *)
 
858
      let cis = 
 
859
        Array.map
 
860
          (fun cs ->
 
861
             applist (mkConstruct cs.cs_cstr, extended_rel_list 0 cs.cs_args))
 
862
          cstrs in
 
863
      let ct = array_map2 (fun ci (_,_,t) -> (ci,t)) cis eqns in
 
864
      raise_pattern_matching_error (loc,env, CannotInferPredicate ct)
 
865
(*
 
866
      (true,pred)
 
867
*)
 
868
 
 
869
(* Propagation of user-provided predicate through compilation steps *)
 
870
 
 
871
let rec map_predicate f k = function
 
872
  | PrCcl ccl -> PrCcl (f k ccl)
 
873
  | PrProd pred ->
 
874
      PrProd (map_predicate f (k+1) pred)
 
875
  | PrLetIn ((names,dep as tm),pred) ->
 
876
      let k' = List.length names + (if dep<>Anonymous then 1 else 0) in
 
877
      PrLetIn (tm, map_predicate f (k+k') pred)
 
878
 
 
879
let rec noccurn_predicate k = function
 
880
  | PrCcl ccl -> noccurn k ccl
 
881
  | PrProd pred -> noccurn_predicate (k+1) pred
 
882
  | PrLetIn ((names,dep),pred) ->
 
883
      let k' = List.length names + (if dep<>Anonymous then 1 else 0) in
 
884
      noccurn_predicate (k+k') pred
 
885
 
 
886
let liftn_predicate n = map_predicate (liftn n)
 
887
 
 
888
let lift_predicate n = liftn_predicate n 1
 
889
 
 
890
let regeneralize_index_predicate n = map_predicate (regeneralize_index n) 0
 
891
 
 
892
let substnl_predicate sigma = map_predicate (substnl sigma)
 
893
 
 
894
(* This is parallel bindings *)
 
895
let subst_predicate (args,copt) pred =
 
896
  let sigma = match copt with
 
897
    | None -> List.rev args
 
898
    | Some c -> c::(List.rev args) in
 
899
  substnl_predicate sigma 0 pred
 
900
 
 
901
let specialize_predicate_var (cur,typ) = function
 
902
  | PrProd _ | PrCcl _ ->
 
903
     anomaly "specialize_predicate_var: a pattern-variable must be pushed"
 
904
  | PrLetIn (([],dep),pred) ->
 
905
      subst_predicate ([],if dep<>Anonymous then Some cur else None) pred
 
906
  | PrLetIn ((_,dep),pred) ->
 
907
      (match typ with
 
908
        | IsInd (_,IndType (_,realargs)) ->
 
909
           subst_predicate (realargs,if dep<>Anonymous then Some cur else None) pred
 
910
        | _ -> anomaly "specialize_predicate_var")
 
911
 
 
912
let ungeneralize_predicate = function
 
913
  | PrLetIn _ | PrCcl _ -> anomaly "ungeneralize_predicate: expects a product"
 
914
  | PrProd pred -> pred
 
915
 
 
916
(*****************************************************************************)
 
917
(* We have pred = [X:=realargs;x:=c]P typed in Gamma1, x:I(realargs), Gamma2 *)
 
918
(* and we want to abstract P over y:t(x) typed in the same context to get    *)
 
919
(*                                                                           *)
 
920
(*    pred' = [X:=realargs;x':=c](y':t(x'))P[y:=y']                          *)
 
921
(*                                                                           *)
 
922
(* We first need to lift t(x) s.t. it is typed in Gamma, X:=rargs, x'        *)
 
923
(* then we have to replace x by x' in t(x) and y by y' in P                  *)
 
924
(*****************************************************************************)
 
925
let generalize_predicate ny d = function
 
926
  | PrLetIn ((names,dep as tm),pred) ->
 
927
      if dep=Anonymous then anomaly "Undetected dependency";
 
928
      let p = List.length names + 1 in
 
929
      let pred = lift_predicate 1 pred in
 
930
      let pred = regeneralize_index_predicate (ny+p+1) pred in
 
931
      PrLetIn (tm, PrProd pred)
 
932
  | PrProd _ | PrCcl _ ->
 
933
      anomaly "generalize_predicate: expects a non trivial pattern"
 
934
 
 
935
let rec extract_predicate l = function
 
936
  | pred, Alias (deppat,nondeppat,_,_)::tms ->
 
937
      let tms' = match kind_of_term nondeppat with
 
938
        | Rel i -> replace_tomatch i deppat tms
 
939
        | _ -> (* initial terms are not dependent *) tms in
 
940
      extract_predicate l (pred,tms')
 
941
  | PrProd pred, Abstract d'::tms ->
 
942
      let d' = map_rel_declaration (lift (List.length l)) d' in
 
943
      substl l (mkProd_or_LetIn d' (extract_predicate [] (pred,tms)))
 
944
  | PrLetIn (([],dep),pred), Pushed ((cur,_),_)::tms ->
 
945
      extract_predicate (if dep<>Anonymous then cur::l else l) (pred,tms)
 
946
  | PrLetIn ((_,dep),pred), Pushed ((cur,IsInd (_,(IndType(_,realargs)))),_)::tms ->
 
947
      let l = List.rev realargs@l in
 
948
      extract_predicate (if dep<>Anonymous then cur::l else l) (pred,tms)
 
949
  | PrCcl ccl, [] ->
 
950
      substl l ccl
 
951
  | _ -> anomaly"extract_predicate: predicate inconsistent with terms to match"
 
952
 
 
953
let abstract_predicate env sigma indf cur tms = function
 
954
  | (PrProd _ | PrCcl _) -> anomaly "abstract_predicate: must be some LetIn"
 
955
  | PrLetIn ((names,dep),pred) ->
 
956
      let sign = make_arity_signature env true indf in
 
957
      (* n is the number of real args + 1 *)
 
958
      let n = List.length sign in
 
959
      let tms = lift_tomatch_stack n tms in
 
960
      let tms =
 
961
        match kind_of_term cur with
 
962
          | Rel i -> regeneralize_index_tomatch (i+n) tms
 
963
          | _ -> (* Initial case *) tms in
 
964
      (* Depending on whether the predicate is dependent or not, and has real
 
965
         args or not, we lift it to make room for [sign] *)
 
966
      (* Even if not intrinsically dep, we move the predicate into a dep one *)
 
967
      let sign,k =
 
968
        if names = [] & n <> 1 then
 
969
          (* Real args were not considered *)
 
970
          (if dep<>Anonymous then
 
971
            ((let (_,c,t) = List.hd sign in (dep,c,t)::List.tl sign),n-1)
 
972
          else
 
973
            (sign,n))
 
974
        else
 
975
          (* Real args are OK *)
 
976
          (List.map2 (fun na (_,c,t) -> (na,c,t)) (dep::names) sign,
 
977
           if dep<>Anonymous then 0 else 1) in
 
978
      let pred = lift_predicate k pred in
 
979
      let pred = extract_predicate [] (pred,tms) in
 
980
      (true, it_mkLambda_or_LetIn_name env pred sign)
 
981
 
 
982
let rec known_dependent = function
 
983
  | None -> false
 
984
  | Some (PrLetIn ((_,dep),_)) -> dep<>Anonymous
 
985
  | Some (PrCcl _) -> false
 
986
  | Some (PrProd _) ->
 
987
      anomaly "known_dependent: can only be used when patterns remain"
 
988
 
 
989
(* [expand_arg] is used by [specialize_predicate]
 
990
   it replaces gamma, x1...xn, x1...xk |- pred
 
991
   by gamma, x1...xn, x1...xk-1 |- [X=realargs,xk=xk]pred (if dep) or
 
992
   by gamma, x1...xn, x1...xk-1 |- [X=realargs]pred (if not dep) *)
 
993
 
 
994
let expand_arg n alreadydep (na,t) deps (k,pred) =
 
995
  (* current can occur in pred even if the original problem is not dependent *)
 
996
  let dep =
 
997
    if alreadydep<>Anonymous then alreadydep
 
998
    else if deps = [] && noccurn_predicate 1 pred then Anonymous
 
999
    else Name (id_of_string "x") in
 
1000
  let pred = if dep<>Anonymous then pred else lift_predicate (-1) pred in
 
1001
  (* There is no dependency in realargs for subpattern *)
 
1002
  (k-1, PrLetIn (([],dep), pred))
 
1003
 
 
1004
 
 
1005
(*****************************************************************************)
 
1006
(* pred = [X:=realargs;x:=c]P types the following problem:                   *)
 
1007
(*                                                                           *)
 
1008
(*  Gamma |- match Pushed(c:I(realargs)) rest with...end: pred               *)
 
1009
(*                                                                           *)
 
1010
(* where the branch with constructor Ci:(x1:T1)...(xn:Tn)->I(realargsi)      *)
 
1011
(* is considered. Assume each Ti is some Ii(argsi).                          *)
 
1012
(* We let e=Ci(x1,...,xn) and replace pred by                                *)
 
1013
(*                                                                           *)
 
1014
(* pred' = [X1:=rargs1,x1:=x1']...[Xn:=rargsn,xn:=xn'](P[X:=realargsi;x:=e]) *)
 
1015
(*                                                                           *)
 
1016
(* s.t Gamma,x1'..xn' |- match Pushed(x1')..Pushed(xn') rest with..end :pred'*)
 
1017
(*                                                                           *)
 
1018
(*****************************************************************************)
 
1019
let specialize_predicate tomatchs deps cs = function
 
1020
  | (PrProd _ | PrCcl _) ->
 
1021
      anomaly "specialize_predicate: a matched pattern must be pushed"
 
1022
  | PrLetIn ((names,isdep),pred) ->
 
1023
      (* Assume some gamma st: gamma, (X,x:=realargs,copt) |- pred *)
 
1024
      let nrealargs = List.length names in
 
1025
      let k = nrealargs + (if isdep<>Anonymous then 1 else 0) in
 
1026
      (* We adjust pred st: gamma, x1..xn, (X,x:=realargs,copt) |- pred' *)
 
1027
      let n = cs.cs_nargs in
 
1028
      let pred' = liftn_predicate n (k+1) pred in
 
1029
      let argsi = if nrealargs <> 0 then Array.to_list cs.cs_concl_realargs else [] in
 
1030
      let copti = if isdep<>Anonymous then Some (build_dependent_constructor cs) else None in
 
1031
      (* The substituends argsi, copti are all defined in gamma, x1...xn *)
 
1032
      (* We need _parallel_ bindings to get gamma, x1...xn |- pred'' *)
 
1033
      let pred'' = subst_predicate (argsi, copti) pred' in
 
1034
      (* We adjust pred st: gamma, x1..xn, x1..xn |- pred'' *)
 
1035
      let pred''' = liftn_predicate n (n+1) pred'' in
 
1036
      (* We finally get gamma,x1..xn |- [X1,x1:=R1,x1]..[Xn,xn:=Rn,xn]pred'''*)
 
1037
      snd (List.fold_right2 (expand_arg n isdep) tomatchs deps (n,pred'''))
 
1038
 
 
1039
let find_predicate loc env isevars p typs cstrs current
 
1040
  (IndType (indf,realargs)) tms =
 
1041
  let (dep,pred) =
 
1042
    match p with
 
1043
      | Some p -> abstract_predicate env (Evd.evars_of !isevars) indf current tms p
 
1044
      | None -> infer_predicate loc env isevars typs cstrs indf in
 
1045
  let typ = whd_beta (Evd.evars_of !isevars) (applist (pred, realargs)) in
 
1046
  if dep then
 
1047
    (pred, whd_beta (Evd.evars_of !isevars) (applist (typ, [current])),
 
1048
     new_Type ())
 
1049
  else
 
1050
    (pred, typ, new_Type ())
 
1051
 
 
1052
(************************************************************************)
 
1053
(* Sorting equations by constructor *)
 
1054
 
 
1055
type inversion_problem =
 
1056
  (* the discriminating arg in some Ind and its order in Ind *)
 
1057
  | Incompatible of int * (int * int)
 
1058
  | Constraints of (int * constr) list
 
1059
 
 
1060
let solve_constraints constr_info indt =
 
1061
  (* TODO *)
 
1062
  Constraints []
 
1063
 
 
1064
let rec irrefutable env = function
 
1065
  | PatVar (_,name) -> true
 
1066
  | PatCstr (_,cstr,args,_) ->
 
1067
      let ind = inductive_of_constructor cstr in
 
1068
      let (_,mip) = Inductive.lookup_mind_specif env ind in
 
1069
      let one_constr = Array.length mip.mind_user_lc = 1 in
 
1070
      one_constr & List.for_all (irrefutable env) args
 
1071
 
 
1072
let first_clause_irrefutable env = function
 
1073
  | eqn::mat -> List.for_all (irrefutable env) eqn.patterns
 
1074
  | _ -> false
 
1075
 
 
1076
let group_equations pb ind current cstrs mat =
 
1077
  let mat =
 
1078
    if first_clause_irrefutable pb.env mat then [List.hd mat] else mat in
 
1079
  let brs = Array.create (Array.length cstrs) [] in
 
1080
  let only_default = ref true in
 
1081
  let _ =
 
1082
    List.fold_right (* To be sure it's from bottom to top *)
 
1083
      (fun eqn () ->
 
1084
         let rest = remove_current_pattern eqn in
 
1085
         let pat = current_pattern eqn in
 
1086
         match check_and_adjust_constructor pb.env ind cstrs pat with 
 
1087
           | PatVar (_,name) -> 
 
1088
               (* This is a default clause that we expand *)
 
1089
               for i=1 to Array.length cstrs do
 
1090
                 let n = cstrs.(i-1).cs_nargs in
 
1091
                 let args = make_anonymous_patvars n in
 
1092
                 brs.(i-1) <- (args, rest) :: brs.(i-1)
 
1093
               done
 
1094
           | PatCstr (loc,((_,i)),args,_) ->
 
1095
               (* This is a regular clause *)
 
1096
               only_default := false;
 
1097
               brs.(i-1) <- (args,rest) :: brs.(i-1)) mat () in
 
1098
  (brs,!only_default)
 
1099
 
 
1100
(************************************************************************)
 
1101
(* Here starts the pattern-matching compilation algorithm *)
 
1102
 
 
1103
(* Abstracting over dependent subterms to match *)
 
1104
let rec generalize_problem pb = function
 
1105
  | [] -> pb
 
1106
  | i::l ->
 
1107
      let d = map_rel_declaration (lift i) (Environ.lookup_rel i pb.env) in
 
1108
      let pb' = generalize_problem pb l in
 
1109
      let tomatch = lift_tomatch_stack 1 pb'.tomatch in
 
1110
      let tomatch = regeneralize_index_tomatch (i+1) tomatch in
 
1111
      { pb with
 
1112
          tomatch = Abstract d :: tomatch;
 
1113
          pred = Option.map (generalize_predicate i d) pb'.pred }
 
1114
 
 
1115
(* No more patterns: typing the right-hand-side of equations *)
 
1116
let build_leaf pb =
 
1117
  let rhs = extract_rhs pb in
 
1118
  let tycon = match pb.pred with
 
1119
    | None -> anomaly "Predicate not found"
 
1120
    | Some (PrCcl typ) -> mk_tycon typ
 
1121
    | Some _ -> anomaly "not all parameters of pred have been consumed" in
 
1122
    pb.typing_function tycon rhs.rhs_env rhs.it
 
1123
 
 
1124
(* Building the sub-problem when all patterns are variables *)
 
1125
let shift_problem (current,t) pb =
 
1126
  {pb with
 
1127
     tomatch = Alias (current,current,NonDepAlias,type_of_tomatch t)::pb.tomatch;
 
1128
     pred = Option.map (specialize_predicate_var (current,t)) pb.pred;
 
1129
     history = push_history_pattern 0 AliasLeaf pb.history;
 
1130
     mat = List.map remove_current_pattern pb.mat }
 
1131
 
 
1132
(* Building the sub-pattern-matching problem for a given branch *)
 
1133
let build_branch current deps pb eqns const_info =
 
1134
  (* We remember that we descend through a constructor *)
 
1135
  let alias_type =
 
1136
    if Array.length const_info.cs_concl_realargs = 0
 
1137
      & not (known_dependent pb.pred) & deps = []
 
1138
    then
 
1139
      NonDepAlias
 
1140
    else 
 
1141
      DepAlias
 
1142
  in
 
1143
  let history = 
 
1144
    push_history_pattern const_info.cs_nargs
 
1145
      (AliasConstructor const_info.cs_cstr)
 
1146
      pb.history in
 
1147
 
 
1148
  (* We find matching clauses *)
 
1149
  let cs_args = (*assums_of_rel_context*) const_info.cs_args in
 
1150
  let names = get_names pb.env cs_args eqns in
 
1151
  let submat = List.map (fun (tms,eqn) -> prepend_pattern tms eqn) eqns in
 
1152
  if submat = [] then
 
1153
    raise_pattern_matching_error
 
1154
      (dummy_loc, pb.env, NonExhaustive (complete_history history));
 
1155
  let typs = List.map2 (fun (_,c,t) na -> (na,c,t)) cs_args names in
 
1156
  let _,typs',_ =
 
1157
    List.fold_right
 
1158
      (fun (na,c,t as d) (env,typs,tms) ->
 
1159
         let tm1 = List.map List.hd tms in
 
1160
         let tms = List.map List.tl tms in
 
1161
         (push_rel d env, (na,to_mutind env pb.isevars tm1 c t)::typs,tms))
 
1162
      typs (pb.env,[],List.map fst eqns) in
 
1163
 
 
1164
  let dep_sign =
 
1165
    find_dependencies_signature
 
1166
      (dependencies_in_rhs const_info.cs_nargs eqns) (List.rev typs) in
 
1167
 
 
1168
  (* The dependent term to subst in the types of the remaining UnPushed 
 
1169
     terms is relative to the current context enriched by topushs *)
 
1170
  let ci = build_dependent_constructor const_info in
 
1171
 
 
1172
  (* We replace [(mkRel 1)] by its expansion [ci] *)
 
1173
  (* and context "Gamma = Gamma1, current, Gamma2" by "Gamma;typs;curalias" *)
 
1174
  (* This is done in two steps : first from "Gamma |- tms" *)
 
1175
  (* into  "Gamma; typs; curalias |- tms" *)
 
1176
  let tomatch = lift_tomatch_stack const_info.cs_nargs pb.tomatch in
 
1177
 
 
1178
  let currents =
 
1179
    list_map2_i
 
1180
      (fun i (na,t) deps -> Pushed ((mkRel i, lift_tomatch_type i t), deps))
 
1181
      1 typs' (List.rev dep_sign) in
 
1182
 
 
1183
  let sign = List.map (fun (na,t) -> mkDeclTomatch na t) typs' in
 
1184
  let ind =
 
1185
    appvect (
 
1186
      applist (mkInd (inductive_of_constructor const_info.cs_cstr),
 
1187
      List.map (lift const_info.cs_nargs) const_info.cs_params),
 
1188
      const_info.cs_concl_realargs) in
 
1189
 
 
1190
  let cur_alias = lift (List.length sign) current in
 
1191
  let currents = Alias (ci,cur_alias,alias_type,ind) :: currents in
 
1192
  let env' = push_rels sign pb.env in
 
1193
  let pred' = Option.map (specialize_predicate (List.rev typs') dep_sign const_info) pb.pred in
 
1194
    sign,
 
1195
  { pb with
 
1196
      env = env';
 
1197
      tomatch = List.rev_append currents tomatch;
 
1198
      pred = pred';
 
1199
      history = history;
 
1200
      mat = List.map (push_rels_eqn_with_names sign) submat }
 
1201
 
 
1202
(**********************************************************************
 
1203
 INVARIANT:
 
1204
 
 
1205
  pb = { env, subst, tomatch, mat, ...}
 
1206
  tomatch = list of Pushed (c:T) or Abstract (na:T) or Alias (c:T)
 
1207
 
 
1208
  "Pushed" terms and types are relative to env
 
1209
  "Abstract" types are relative to env enriched by the previous terms to match
 
1210
 
 
1211
*)
 
1212
 
 
1213
(**********************************************************************)
 
1214
(* Main compiling descent *)
 
1215
let rec compile pb =
 
1216
  match pb.tomatch with
 
1217
    | (Pushed cur)::rest -> match_current { pb with tomatch = rest } cur
 
1218
    | (Alias x)::rest -> compile_alias pb x rest
 
1219
    | (Abstract d)::rest -> compile_generalization pb d rest
 
1220
    | [] -> build_leaf pb
 
1221
 
 
1222
and match_current pb tomatch =
 
1223
  let ((current,typ as ct),deps) = adjust_tomatch_to_pattern pb tomatch in
 
1224
  match typ with
 
1225
    | NotInd (_,typ) ->
 
1226
        check_all_variables typ pb.mat;
 
1227
        compile (shift_problem ct pb)
 
1228
    | IsInd (_,(IndType(indf,realargs) as indt)) ->
 
1229
        let mind,_ = dest_ind_family indf in
 
1230
        let cstrs = get_constructors pb.env indf in
 
1231
        let eqns,onlydflt = group_equations pb mind current cstrs pb.mat in
 
1232
        if (Array.length cstrs <> 0 or pb.mat <> []) & onlydflt  then
 
1233
          compile (shift_problem ct pb)
 
1234
        else
 
1235
          let _constraints = Array.map (solve_constraints indt) cstrs in
 
1236
 
 
1237
          (* We generalize over terms depending on current term to match *)
 
1238
          let pb = generalize_problem pb deps in
 
1239
 
 
1240
          (* We compile branches *)
 
1241
          let brs = array_map2 (compile_branch current deps pb) eqns cstrs in
 
1242
 
 
1243
          (* We build the (elementary) case analysis *)
 
1244
          let brvals = Array.map (fun (v,_) -> v) brs in
 
1245
          let brtyps = Array.map (fun (_,t) -> t) brs in
 
1246
          let (pred,typ,s) =
 
1247
            find_predicate pb.caseloc pb.env pb.isevars 
 
1248
              pb.pred brtyps cstrs current indt pb.tomatch in
 
1249
          let ci = make_case_info pb.env mind pb.casestyle in
 
1250
          let case = mkCase (ci,nf_betaiota Evd.empty pred,current,brvals) in
 
1251
          let inst = List.map mkRel deps in
 
1252
          { uj_val = applist (case, inst);
 
1253
            uj_type = substl inst typ }
 
1254
 
 
1255
and compile_branch current deps pb eqn cstr =
 
1256
  let sign, pb = build_branch current deps pb eqn cstr in
 
1257
  let j = compile pb in
 
1258
  (it_mkLambda_or_LetIn j.uj_val sign, j.uj_type)
 
1259
 
 
1260
and compile_generalization pb d rest =
 
1261
  let pb =
 
1262
    { pb with
 
1263
       env = push_rel d pb.env;
 
1264
       tomatch = rest;
 
1265
       pred = Option.map ungeneralize_predicate pb.pred;
 
1266
       mat = List.map (push_rels_eqn [d]) pb.mat } in
 
1267
  let j = compile pb in
 
1268
  { uj_val = mkLambda_or_LetIn d j.uj_val;
 
1269
    uj_type = mkProd_or_LetIn d j.uj_type }
 
1270
 
 
1271
and compile_alias pb (deppat,nondeppat,d,t) rest =
 
1272
  let history = simplify_history pb.history in
 
1273
  let sign, newenv, mat =
 
1274
    insert_aliases pb.env (Evd.evars_of !(pb.isevars)) (deppat,nondeppat,d,t) pb.mat in
 
1275
  let n = List.length sign in
 
1276
 
 
1277
  (* We had Gamma1; x:current; Gamma2 |- tomatch(x) and we rebind x to get *)
 
1278
  (* Gamma1; x:current; Gamma2; typs; x':=curalias |- tomatch(x') *)
 
1279
  let tomatch = lift_tomatch_stack n rest in
 
1280
  let tomatch = match kind_of_term nondeppat with
 
1281
    | Rel i ->
 
1282
        if n = 1 then regeneralize_index_tomatch (i+n) tomatch
 
1283
        else replace_tomatch i deppat tomatch
 
1284
    | _ -> (* initial terms are not dependent *) tomatch in
 
1285
 
 
1286
  let pb =
 
1287
    {pb with
 
1288
       env = newenv;
 
1289
       tomatch = tomatch;
 
1290
       pred = Option.map (lift_predicate n) pb.pred;
 
1291
       history = history;
 
1292
       mat = mat } in
 
1293
  let j = compile pb in
 
1294
  List.fold_left mkSpecialLetInJudge j sign
 
1295
 
 
1296
(* pour les alias des initiaux, enrichir les env de ce qu'il faut et
 
1297
substituer après par les initiaux *)
 
1298
 
 
1299
(**************************************************************************)
 
1300
(* Preparation of the pattern-matching problem                            *)
 
1301
 
 
1302
(* builds the matrix of equations testing that each eqn has n patterns
 
1303
 * and linearizing the _ patterns.
 
1304
 * Syntactic correctness has already been done in astterm *)
 
1305
let matx_of_eqns env eqns =
 
1306
  let build_eqn (loc,ids,lpat,rhs) =
 
1307
    let rhs =
 
1308
      { rhs_env = env;
 
1309
        avoid_ids = ids@(ids_of_named_context (named_context env));
 
1310
        it = rhs;
 
1311
      } in
 
1312
    { patterns = lpat;
 
1313
      alias_stack = [];
 
1314
      eqn_loc = loc;
 
1315
      used = ref false;
 
1316
      rhs = rhs }
 
1317
  in List.map build_eqn eqns
 
1318
 
 
1319
(************************************************************************)
 
1320
(* preparing the elimination predicate if any                          *)
 
1321
 
 
1322
let oldprepare_predicate_from_tycon loc dep env isevars tomatchs sign c =
 
1323
  let cook (n, l, env, signs) = function
 
1324
    | c,IsInd (_,IndType(indf,realargs)) ->
 
1325
        let indf' = lift_inductive_family n indf in
 
1326
        let sign = make_arity_signature env dep indf' in
 
1327
        let p = List.length realargs in
 
1328
        if dep then
 
1329
          (n + p + 1, c::(List.rev realargs)@l, push_rels sign env,sign::signs)
 
1330
        else
 
1331
          (n + p, (List.rev realargs)@l, push_rels sign env,sign::signs)
 
1332
    | c,NotInd _ ->
 
1333
        (n, l, env, []::signs) in
 
1334
  let n, allargs, env, signs = List.fold_left cook (0, [], env, []) tomatchs in
 
1335
  let names = List.rev (List.map (List.map pi1) signs) in
 
1336
  let allargs =
 
1337
    List.map (fun c -> lift n (nf_betadeltaiota env (Evd.evars_of !isevars) c)) allargs in
 
1338
  let rec build_skeleton env c =
 
1339
    (* Don't put into normal form, it has effects on the synthesis of evars *)
 
1340
 (* let c = whd_betadeltaiota env (evars_of isevars) c in *)
 
1341
    (* We turn all subterms possibly dependent into an evar with maximum ctxt*)
 
1342
    if isEvar c or List.exists (eq_constr c) allargs then
 
1343
      e_new_evar isevars env  ~src:(loc, Evd.CasesType)
 
1344
        (Retyping.get_type_of env (Evd.evars_of !isevars) c)
 
1345
    else
 
1346
      map_constr_with_full_binders push_rel build_skeleton env c 
 
1347
  in
 
1348
    names, build_skeleton env (lift n c)
 
1349
  
 
1350
(* Here, [pred] is assumed to be in the context built from all *)
 
1351
(* realargs and terms to match *)
 
1352
let build_initial_predicate isdep allnames pred =
 
1353
  let nar = List.fold_left (fun n names -> List.length names + n) 0 allnames in
 
1354
  let rec buildrec n pred = function
 
1355
    | [] -> PrCcl pred
 
1356
    | names::lnames ->
 
1357
        let names' = if isdep then List.tl names else names in
 
1358
        let n' = n + List.length names' in
 
1359
        let pred, p, user_p =
 
1360
          if isdep then 
 
1361
            if dependent (mkRel (nar-n')) pred then pred, 1, 1
 
1362
            else liftn (-1) (nar-n') pred, 0, 1
 
1363
          else pred, 0, 0 in
 
1364
        let na =
 
1365
          if p=1 then
 
1366
            let na = List.hd names in
 
1367
            if na = Anonymous then
 
1368
              (* peut arriver en raison des evars *)
 
1369
              Name (id_of_string "x") (*Hum*)
 
1370
            else na
 
1371
          else Anonymous in
 
1372
        PrLetIn ((names',na), buildrec (n'+user_p) pred lnames)
 
1373
  in buildrec 0 pred allnames
 
1374
 
 
1375
let extract_arity_signature env0 tomatchl tmsign =
 
1376
  let get_one_sign n tm (na,t) =
 
1377
    match tm with
 
1378
      | NotInd (bo,typ) -> 
 
1379
          (match t with
 
1380
            | None -> [na,Option.map (lift n) bo,lift n typ]
 
1381
            | Some (loc,_,_,_) -> 
 
1382
            user_err_loc (loc,"",
 
1383
            str "Unexpected type annotation for a term of non inductive type"))
 
1384
      | IsInd (_,IndType(indf,realargs)) ->
 
1385
          let indf' = lift_inductive_family n indf in
 
1386
          let (ind,params) = dest_ind_family indf' in
 
1387
          let nrealargs = List.length realargs in
 
1388
          let realnal =
 
1389
            match t with
 
1390
              | Some (loc,ind',nparams,realnal) ->
 
1391
                  if ind <> ind' then
 
1392
                    user_err_loc (loc,"",str "Wrong inductive type");
 
1393
                  if List.length params <> nparams
 
1394
                    or nrealargs <> List.length realnal then
 
1395
                      anomaly "Ill-formed 'in' clause in cases";
 
1396
                  List.rev realnal
 
1397
              | None -> list_tabulate (fun _ -> Anonymous) nrealargs in
 
1398
          let arsign = fst (get_arity env0 indf') in
 
1399
          (na,None,build_dependent_inductive env0 indf')
 
1400
          ::(List.map2 (fun x (_,c,t) ->(x,c,t)) realnal arsign) in
 
1401
  let rec buildrec n = function
 
1402
    | [],[] -> []
 
1403
    | (_,tm)::ltm, x::tmsign ->
 
1404
        let l = get_one_sign n tm x in
 
1405
        l :: buildrec (n + List.length l) (ltm,tmsign)
 
1406
    | _ -> assert false
 
1407
  in List.rev (buildrec 0 (tomatchl,tmsign))
 
1408
 
 
1409
let extract_arity_signatures env0 tomatchl tmsign =
 
1410
  let get_one_sign tm (na,t) =
 
1411
    match tm with
 
1412
      | NotInd (bo,typ) -> 
 
1413
          (match t with
 
1414
            | None -> [na,bo,typ]
 
1415
            | Some (loc,_,_,_) -> 
 
1416
            user_err_loc (loc,"",
 
1417
            str "Unexpected type annotation for a term of non inductive type"))
 
1418
      | IsInd (_,IndType(indf,realargs)) ->
 
1419
          let (ind,params) = dest_ind_family indf in
 
1420
          let nrealargs = List.length realargs in
 
1421
          let realnal =
 
1422
            match t with
 
1423
              | Some (loc,ind',nparams,realnal) ->
 
1424
                  if ind <> ind' then
 
1425
                    user_err_loc (loc,"",str "Wrong inductive type");
 
1426
                  if List.length params <> nparams
 
1427
                    or nrealargs <> List.length realnal then
 
1428
                      anomaly "Ill-formed 'in' clause in cases";
 
1429
                  List.rev realnal
 
1430
              | None -> list_tabulate (fun _ -> Anonymous) nrealargs in
 
1431
          let arsign = fst (get_arity env0 indf) in
 
1432
            (na,None,build_dependent_inductive env0 indf)
 
1433
            ::(try List.map2 (fun x (_,c,t) ->(x,c,t)) realnal arsign with _ -> assert false) in
 
1434
  let rec buildrec = function
 
1435
    | [],[] -> []
 
1436
    | (_,tm)::ltm, x::tmsign ->
 
1437
        let l = get_one_sign tm x in
 
1438
          l :: buildrec (ltm,tmsign)
 
1439
    | _ -> assert false
 
1440
  in List.rev (buildrec (tomatchl,tmsign))
 
1441
 
 
1442
let inh_conv_coerce_to_tycon loc env isevars j tycon =
 
1443
  match tycon with
 
1444
    | Some p ->
 
1445
        let (evd',j) = Coercion.inh_conv_coerce_to loc env !isevars j p in
 
1446
          isevars := evd';
 
1447
          j
 
1448
    | None -> j
 
1449
 
 
1450
let out_ind = function IsInd (_, IndType(x, y)) -> (x, y) | _ -> assert(false)
 
1451
               
 
1452
let string_of_name name = 
 
1453
  match name with
 
1454
    | Anonymous -> "anonymous"
 
1455
    | Name n -> string_of_id n
 
1456
        
 
1457
let id_of_name n = id_of_string (string_of_name n)
 
1458
 
 
1459
let make_prime_id name = 
 
1460
  let str = string_of_name name in
 
1461
    id_of_string str, id_of_string (str ^ "'")
 
1462
 
 
1463
let prime avoid name = 
 
1464
  let previd, id = make_prime_id name in
 
1465
    previd, next_ident_away_from id avoid
 
1466
 
 
1467
let make_prime avoid prevname =
 
1468
  let previd, id = prime !avoid prevname in
 
1469
    avoid := id :: !avoid;
 
1470
    previd, id
 
1471
 
 
1472
let eq_id avoid id = 
 
1473
  let hid = id_of_string ("Heq_" ^ string_of_id id) in
 
1474
  let hid' = next_ident_away_from hid avoid in
 
1475
    hid'
 
1476
 
 
1477
let mk_eq typ x y = mkApp (Lazy.force eq_ind, [| typ; x ; y |])
 
1478
let mk_eq_refl typ x = mkApp (Lazy.force eq_refl, [| typ; x |])
 
1479
    
 
1480
let hole = RHole (dummy_loc, Evd.QuestionMark (Evd.Define true))
 
1481
 
 
1482
let context_of_arsign l =
 
1483
  let (x, _) = List.fold_right
 
1484
    (fun c (x, n) -> 
 
1485
      (lift_rel_context n c @ x, List.length c + n))
 
1486
    l ([], 0)
 
1487
  in x
 
1488
 
 
1489
let constr_of_pat env isevars arsign pat avoid = 
 
1490
  let rec typ env (ty, realargs) pat avoid = 
 
1491
    match pat with
 
1492
    | PatVar (l,name) -> 
 
1493
        let name, avoid = match name with
 
1494
            Name n -> name, avoid
 
1495
          | Anonymous -> 
 
1496
              let previd, id = prime avoid (Name (id_of_string "wildcard")) in
 
1497
                Name id, id :: avoid 
 
1498
        in
 
1499
          PatVar (l, name), [name, None, ty] @ realargs, mkRel 1, ty, (List.map (fun x -> mkRel 1) realargs), 1, avoid
 
1500
    | PatCstr (l,((_, i) as cstr),args,alias) ->
 
1501
        let cind = inductive_of_constructor cstr in
 
1502
        let IndType (indf, _) = find_rectype env (Evd.evars_of !isevars) (lift (-(List.length realargs)) ty) in
 
1503
        let ind, params = dest_ind_family indf in
 
1504
        if ind <> cind then error_bad_constructor_loc l cstr ind;
 
1505
        let cstrs = get_constructors env indf in
 
1506
        let ci = cstrs.(i-1) in
 
1507
        let nb_args_constr = ci.cs_nargs in
 
1508
        assert(nb_args_constr = List.length args);
 
1509
        let patargs, args, sign, env, n, m, avoid = 
 
1510
          List.fold_right2
 
1511
            (fun (na, c, t) ua (patargs, args, sign, env, n, m, avoid)  ->
 
1512
               let pat', sign', arg', typ', argtypargs, n', avoid = 
 
1513
                 typ env (lift (n - m) t, []) ua avoid 
 
1514
               in
 
1515
               let args' = arg' :: List.map (lift n') args in
 
1516
               let env' = push_rels sign' env in
 
1517
                 (pat' :: patargs, args', sign' @ sign, env', n' + n, succ m, avoid))
 
1518
            ci.cs_args (List.rev args) ([], [], [], env, 0, 0, avoid)
 
1519
        in
 
1520
        let args = List.rev args in
 
1521
        let patargs = List.rev patargs in
 
1522
        let pat' = PatCstr (l, cstr, patargs, alias) in
 
1523
        let cstr = mkConstruct ci.cs_cstr in
 
1524
        let app = applistc cstr (List.map (lift (List.length sign)) params) in
 
1525
        let app = applistc app args in
 
1526
        let apptype = Retyping.get_type_of env (Evd.evars_of !isevars) app in   
 
1527
        let IndType (indf, realargs) = find_rectype env (Evd.evars_of !isevars) apptype in
 
1528
          match alias with
 
1529
              Anonymous ->
 
1530
                pat', sign, app, apptype, realargs, n, avoid
 
1531
            | Name id ->
 
1532
                let sign = (alias, None, lift m ty) :: sign in
 
1533
                let avoid = id :: avoid in
 
1534
                let sign, i, avoid =
 
1535
                  try
 
1536
                    let env = push_rels sign env in
 
1537
                    isevars := the_conv_x_leq (push_rels sign env) (lift (succ m) ty) (lift 1 apptype) !isevars;
 
1538
                    let eq_t = mk_eq (lift (succ m) ty)
 
1539
                      (mkRel 1) (* alias *)
 
1540
                      (lift 1 app) (* aliased term *)
 
1541
                    in 
 
1542
                    let neq = eq_id avoid id in
 
1543
                      (Name neq, Some (mkRel 0), eq_t) :: sign, 2, neq :: avoid
 
1544
                  with Reduction.NotConvertible -> sign, 1, avoid
 
1545
                in
 
1546
                  (* Mark the equality as a hole *)
 
1547
                  pat', sign, lift i app, lift i apptype, realargs, n + i, avoid
 
1548
  in 
 
1549
  let pat', sign, patc, patty, args, z, avoid = typ env (pi3 (List.hd arsign), List.tl arsign) pat avoid in 
 
1550
    pat', (sign, patc, (pi3 (List.hd arsign), args), pat'), avoid
 
1551
 
 
1552
 
 
1553
(* shadows functional version *)
 
1554
let eq_id avoid id = 
 
1555
  let hid = id_of_string ("Heq_" ^ string_of_id id) in
 
1556
  let hid' = next_ident_away_from hid !avoid in
 
1557
    avoid := hid' :: !avoid;
 
1558
    hid'
 
1559
 
 
1560
let rels_of_patsign = 
 
1561
  List.map (fun ((na, b, t) as x) -> 
 
1562
    match b with 
 
1563
      | Some t' when kind_of_term t' = Rel 0 -> (na, None, t)
 
1564
      | _ -> x)
 
1565
 
 
1566
let vars_of_ctx ctx = 
 
1567
  let _, y =
 
1568
    List.fold_right (fun (na, b, t)  (prev, vars) -> 
 
1569
      match b with 
 
1570
        | Some t' when kind_of_term t' = Rel 0 -> 
 
1571
            prev, 
 
1572
            (RApp (dummy_loc, 
 
1573
                (RRef (dummy_loc, Lazy.force refl_ref)), [hole; RVar (dummy_loc, prev)])) :: vars
 
1574
        | _ ->
 
1575
            match na with
 
1576
                Anonymous -> raise (Invalid_argument "vars_of_ctx")
 
1577
              | Name n -> n, RVar (dummy_loc, n) :: vars)
 
1578
      ctx (id_of_string "vars_of_ctx_error", [])
 
1579
  in List.rev y
 
1580
 
 
1581
let rec is_included x y = 
 
1582
  match x, y with
 
1583
    | PatVar _, _ -> true
 
1584
    | _, PatVar _ -> true
 
1585
    | PatCstr (l, (_, i), args, alias), PatCstr (l', (_, i'), args', alias')  ->
 
1586
        if i = i' then List.for_all2 is_included args args'
 
1587
        else false
 
1588
 
 
1589
(* liftsign is the current pattern's complete signature length. Hence pats is already typed in its
 
1590
   full signature. However prevpatterns are in the original one signature per pattern form.
 
1591
 *)
 
1592
let build_ineqs prevpatterns pats liftsign =
 
1593
  let _tomatchs = List.length pats in
 
1594
  let diffs = 
 
1595
    List.fold_left 
 
1596
      (fun c eqnpats -> 
 
1597
          let acc = List.fold_left2
 
1598
            (* ppat is the pattern we are discriminating against, curpat is the current one. *)
 
1599
            (fun acc (ppat_sign, ppat_c, (ppat_ty, ppat_tyargs), ppat) 
 
1600
              (curpat_sign, curpat_c, (curpat_ty, curpat_tyargs), curpat) ->
 
1601
              match acc with
 
1602
                  None -> None
 
1603
                | Some (sign, len, n, c) -> (* FixMe: do not work with ppat_args *)
 
1604
                    if is_included curpat ppat then
 
1605
                      (* Length of previous pattern's signature *)
 
1606
                      let lens = List.length ppat_sign in
 
1607
                      (* Accumulated length of previous pattern's signatures *)
 
1608
                      let len' = lens + len in
 
1609
                      let acc = 
 
1610
                        ((* Jump over previous prevpat signs *)
 
1611
                          lift_rel_context len ppat_sign @ sign, 
 
1612
                          len',
 
1613
                          succ n, (* nth pattern *)
 
1614
                          mkApp (Lazy.force eq_ind,
 
1615
                                [| lift (len' + liftsign) curpat_ty;
 
1616
                                   liftn (len + liftsign) (succ lens) ppat_c ;
 
1617
                                   lift len' curpat_c |]) :: 
 
1618
                            List.map (lift lens (* Jump over this prevpat signature *)) c)
 
1619
                      in Some acc
 
1620
                    else None)
 
1621
           (Some ([], 0, 0, [])) eqnpats pats
 
1622
         in match acc with 
 
1623
             None -> c
 
1624
           | Some (sign, len, _, c') ->
 
1625
               let conj = it_mkProd_or_LetIn (mk_not (mk_conj c')) 
 
1626
                 (lift_rel_context liftsign sign) 
 
1627
               in
 
1628
                 conj :: c)
 
1629
      [] prevpatterns
 
1630
  in match diffs with [] -> None
 
1631
    | _ -> Some (mk_conj diffs)
 
1632
        
 
1633
let subst_rel_context k ctx subst =
 
1634
  let (_, ctx') =
 
1635
    List.fold_right 
 
1636
      (fun (n, b, t) (k, acc) ->
 
1637
         (succ k, (n, Option.map (substnl subst k) b, substnl subst k t) :: acc))
 
1638
      ctx (k, [])
 
1639
  in ctx'
 
1640
 
 
1641
let lift_rel_contextn n k sign =
 
1642
  let rec liftrec k = function
 
1643
    | (na,c,t)::sign ->
 
1644
        (na,Option.map (liftn n k) c,liftn n k t)::(liftrec (k-1) sign)
 
1645
    | [] -> []
 
1646
  in
 
1647
  liftrec (rel_context_length sign + k) sign
 
1648
 
 
1649
let constrs_of_pats typing_fun env isevars eqns tomatchs sign neqs arity =
 
1650
  let i = ref 0 in
 
1651
  let (x, y, z) = 
 
1652
    List.fold_left
 
1653
      (fun (branches, eqns, prevpatterns) eqn ->
 
1654
         let _, newpatterns, pats = 
 
1655
           List.fold_left2
 
1656
             (fun (idents, newpatterns, pats) pat arsign -> 
 
1657
                let pat', cpat, idents = constr_of_pat env isevars arsign pat idents in
 
1658
                  (idents, pat' :: newpatterns, cpat :: pats))
 
1659
              ([], [], []) eqn.patterns sign
 
1660
         in
 
1661
         let newpatterns = List.rev newpatterns and opats = List.rev pats in
 
1662
         let rhs_rels, pats, signlen = 
 
1663
           List.fold_left 
 
1664
             (fun (renv, pats, n) (sign,c, (s, args), p) -> 
 
1665
               (* Recombine signatures and terms of all of the row's patterns *)
 
1666
               let sign' = lift_rel_context n sign in
 
1667
               let len = List.length sign' in
 
1668
                 (sign' @ renv, 
 
1669
                 (* lift to get outside of previous pattern's signatures. *)
 
1670
                 (sign', liftn n (succ len) c, (s, List.map (liftn n (succ len)) args), p) :: pats,
 
1671
                 len + n))
 
1672
             ([], [], 0) opats in
 
1673
         let pats, _ = List.fold_left 
 
1674
           (* lift to get outside of past patterns to get terms in the combined environment. *)
 
1675
           (fun (pats, n) (sign, c, (s, args), p) ->
 
1676
             let len = List.length sign in
 
1677
               ((rels_of_patsign sign, lift n c, (s, List.map (lift n) args), p) :: pats, len + n))
 
1678
           ([], 0) pats
 
1679
         in
 
1680
         let ineqs = build_ineqs prevpatterns pats signlen in
 
1681
         let rhs_rels' = rels_of_patsign rhs_rels in
 
1682
         let _signenv = push_rel_context rhs_rels' env in
 
1683
         let arity =
 
1684
           let args, nargs = 
 
1685
             List.fold_right (fun (sign, c, (_, args), _) (allargs,n) ->
 
1686
               (args @ c :: allargs, List.length args + succ n))
 
1687
               pats ([], 0)
 
1688
           in
 
1689
           let args = List.rev args in
 
1690
             substl args (liftn signlen (succ nargs) arity)
 
1691
         in
 
1692
         let rhs_rels', tycon = 
 
1693
           let neqs_rels, arity =
 
1694
             match ineqs with
 
1695
             | None -> [], arity
 
1696
             | Some ineqs ->
 
1697
                 [Anonymous, None, ineqs], lift 1 arity
 
1698
           in
 
1699
           let eqs_rels, arity = decompose_prod_n_assum neqs arity in
 
1700
             eqs_rels @ neqs_rels @ rhs_rels', arity
 
1701
         in
 
1702
         let rhs_env = push_rels rhs_rels' env in
 
1703
         let j = typing_fun (mk_tycon tycon) rhs_env eqn.rhs.it in
 
1704
         let bbody = it_mkLambda_or_LetIn j.uj_val rhs_rels'
 
1705
         and btype = it_mkProd_or_LetIn j.uj_type rhs_rels' in
 
1706
         let branch_name = id_of_string ("branch_" ^ (string_of_int !i)) in
 
1707
         let branch_decl = (Name branch_name, Some (lift !i bbody), (lift !i btype)) in
 
1708
         let branch = 
 
1709
           let bref = RVar (dummy_loc, branch_name) in
 
1710
             match vars_of_ctx rhs_rels with
 
1711
                 [] -> bref
 
1712
               | l -> RApp (dummy_loc, bref, l)
 
1713
         in
 
1714
         let branch = match ineqs with
 
1715
             Some _ -> RApp (dummy_loc, branch, [ hole ])
 
1716
           | None -> branch
 
1717
         in
 
1718
         incr i;
 
1719
         let rhs = { eqn.rhs with it = branch } in
 
1720
           (branch_decl :: branches,
 
1721
           { eqn with patterns = newpatterns; rhs = rhs } :: eqns,
 
1722
           opats :: prevpatterns))
 
1723
      ([], [], []) eqns
 
1724
  in x, y
 
1725
 
 
1726
(* Builds the predicate. If the predicate is dependent, its context is
 
1727
 * made of 1+nrealargs assumptions for each matched term in an inductive
 
1728
 * type and 1 assumption for each term not _syntactically_ in an
 
1729
 * inductive type.
 
1730
 
 
1731
 * Each matched terms are independently considered dependent or not.
 
1732
 
 
1733
 * A type constraint but no annotation case: it is assumed non dependent.
 
1734
 *)
 
1735
  
 
1736
let lift_ctx n ctx = 
 
1737
  let ctx', _ =
 
1738
    List.fold_right (fun (c, t) (ctx, n') -> (liftn n n' c, liftn_tomatch_type n n' t) :: ctx, succ n') ctx ([], 0)
 
1739
  in ctx'
 
1740
 
 
1741
(* Turn matched terms into variables. *)
 
1742
let abstract_tomatch env tomatchs =
 
1743
  let prev, ctx, names = 
 
1744
    List.fold_left
 
1745
      (fun (prev, ctx, names) (c, t) ->
 
1746
         let lenctx =  List.length ctx in
 
1747
         match kind_of_term c with
 
1748
             Rel n -> (lift lenctx c, lift_tomatch_type lenctx t) :: prev, ctx, names
 
1749
           | _ -> 
 
1750
               let name = next_ident_away_from (id_of_string "filtered_var") names in
 
1751
                 (mkRel 1, lift_tomatch_type (succ lenctx) t) :: lift_ctx 1 prev, 
 
1752
               (Name name, Some (lift lenctx c), lift lenctx $ type_of_tomatch t) :: ctx, 
 
1753
               name :: names)
 
1754
      ([], [], []) tomatchs
 
1755
  in List.rev prev, ctx
 
1756
    
 
1757
let is_dependent_ind = function
 
1758
    IsInd (_, IndType (indf, args)) when List.length args > 0 -> true
 
1759
  | _ -> false
 
1760
 
 
1761
let build_dependent_signature env evars avoid tomatchs arsign =
 
1762
  let avoid = ref avoid in
 
1763
  let arsign = List.rev arsign in
 
1764
  let allnames = List.rev (List.map (List.map pi1) arsign) in
 
1765
  let nar = List.fold_left (fun n names -> List.length names + n) 0 allnames in
 
1766
  let eqs, neqs, refls, slift, arsign' = 
 
1767
    List.fold_left2 
 
1768
      (fun (eqs, neqs, refl_args, slift, arsigns) (tm, ty) arsign -> 
 
1769
         (* The accumulator:
 
1770
            previous eqs, 
 
1771
            number of previous eqs, 
 
1772
            lift to get outside eqs and in the introduced variables ('as' and 'in'), 
 
1773
            new arity signatures
 
1774
         *)
 
1775
         match ty with
 
1776
             IsInd (ty, IndType (indf, args)) when List.length args > 0 ->
 
1777
               (* Build the arity signature following the names in matched terms as much as possible *)
 
1778
               let argsign = List.tl arsign in (* arguments in inverse application order *)
 
1779
               let (appn, appb, appt) as _appsign = List.hd arsign in (* The matched argument *)
 
1780
               let argsign = List.rev argsign in (* arguments in application order *)
 
1781
               let env', nargeqs, argeqs, refl_args, slift, argsign' =
 
1782
                 List.fold_left2
 
1783
                   (fun (env, nargeqs, argeqs, refl_args, slift, argsign') arg (name, b, t) ->
 
1784
                      let argt = Retyping.get_type_of env evars arg in
 
1785
                      let eq, refl_arg = 
 
1786
                        if Reductionops.is_conv env evars argt t then
 
1787
                          (mk_eq (lift (nargeqs + slift) argt)
 
1788
                             (mkRel (nargeqs + slift))
 
1789
                             (lift (nargeqs + nar) arg),
 
1790
                           mk_eq_refl argt arg)
 
1791
                        else
 
1792
                          (mk_JMeq (lift (nargeqs + slift) t)
 
1793
                             (mkRel (nargeqs + slift))
 
1794
                             (lift (nargeqs + nar) argt)
 
1795
                             (lift (nargeqs + nar) arg),
 
1796
                           mk_JMeq_refl argt arg)
 
1797
                      in
 
1798
                      let previd, id = 
 
1799
                        let name = 
 
1800
                          match kind_of_term arg with 
 
1801
                              Rel n -> pi1 (Environ.lookup_rel n env)
 
1802
                            | _ -> name
 
1803
                        in
 
1804
                          make_prime avoid name 
 
1805
                      in
 
1806
                        (env, succ nargeqs, 
 
1807
                         (Name (eq_id avoid previd), None, eq) :: argeqs, 
 
1808
                         refl_arg :: refl_args,
 
1809
                         pred slift,
 
1810
                         (Name id, b, t) :: argsign'))
 
1811
                   (env, 0, [], [], slift, []) args argsign
 
1812
               in
 
1813
               let eq = mk_JMeq 
 
1814
                 (lift (nargeqs + slift) appt)
 
1815
                 (mkRel (nargeqs + slift))
 
1816
                 (lift (nargeqs + nar) ty) 
 
1817
                 (lift (nargeqs + nar) tm) 
 
1818
               in
 
1819
               let refl_eq = mk_JMeq_refl ty tm in
 
1820
               let previd, id = make_prime avoid appn in
 
1821
                 (((Name (eq_id avoid previd), None, eq) :: argeqs) :: eqs, 
 
1822
                 succ nargeqs, 
 
1823
                 refl_eq :: refl_args,
 
1824
                 pred slift, 
 
1825
                 (((Name id, appb, appt) :: argsign') :: arsigns))
 
1826
                   
 
1827
           | _ -> 
 
1828
               (* Non dependent inductive or not inductive, just use a regular equality *)
 
1829
               let (name, b, typ) = match arsign with [x] -> x | _ -> assert(false) in
 
1830
               let previd, id = make_prime avoid name in
 
1831
               let arsign' = (Name id, b, typ) in
 
1832
               let tomatch_ty = type_of_tomatch ty in
 
1833
               let eq = 
 
1834
                 mk_eq (lift nar tomatch_ty)
 
1835
                   (mkRel slift) (lift nar tm)
 
1836
               in
 
1837
                 ([(Name (eq_id avoid previd), None, eq)] :: eqs, succ neqs, 
 
1838
                  (mk_eq_refl tomatch_ty tm) :: refl_args,
 
1839
                  pred slift, (arsign' :: []) :: arsigns))
 
1840
      ([], 0, [], nar, []) tomatchs arsign
 
1841
  in 
 
1842
  let arsign'' = List.rev arsign' in
 
1843
    assert(slift = 0); (* we must have folded over all elements of the arity signature *)
 
1844
    arsign'', allnames, nar, eqs, neqs, refls
 
1845
 
 
1846
(**************************************************************************)
 
1847
(* Main entry of the matching compilation                                 *)
 
1848
  
 
1849
let liftn_rel_context n k sign =  
 
1850
  let rec liftrec k = function
 
1851
    | (na,c,t)::sign ->
 
1852
        (na,Option.map (liftn n k) c,liftn n k t)::(liftrec (k-1) sign)
 
1853
    | [] -> []
 
1854
  in
 
1855
    liftrec (k + rel_context_length sign) sign
 
1856
 
 
1857
let nf_evars_env evar_defs (env : env) : env = 
 
1858
  let nf t = nf_isevar evar_defs t in
 
1859
  let env0 : env = reset_context env in 
 
1860
  let f e (na, b, t) e' : env =
 
1861
    Environ.push_named (na, Option.map nf b, nf t) e'
 
1862
  in
 
1863
  let env' = Environ.fold_named_context f ~init:env0 env in
 
1864
    Environ.fold_rel_context (fun e (na, b, t) e' -> Environ.push_rel (na, Option.map nf b, nf t) e')
 
1865
     ~init:env' env
 
1866
      
 
1867
(* We put the tycon inside the arity signature, possibly discovering dependencies. *)
 
1868
 
 
1869
let prepare_predicate_from_arsign_tycon loc env evm tomatchs arsign c =
 
1870
  let nar = List.fold_left (fun n sign -> List.length sign + n) 0 arsign in
 
1871
  let subst, len = 
 
1872
    List.fold_left2 (fun (subst, len) (tm, tmtype) sign ->
 
1873
      let signlen = List.length sign in
 
1874
        match kind_of_term tm with
 
1875
          | Rel n when dependent tm c 
 
1876
                && signlen = 1 (* The term to match is not of a dependent type itself *) ->
 
1877
              ((n, len) :: subst, len - signlen)
 
1878
          | Rel _ when not (dependent tm c)
 
1879
                && signlen > 1 (* The term is of a dependent type but does not appear in 
 
1880
                                  the tycon, maybe some variable in its type does. *) ->
 
1881
              (match tmtype with
 
1882
                  NotInd _ -> (* len - signlen, subst*) assert false (* signlen > 1 *)
 
1883
                | IsInd (_, IndType(indf,realargs)) ->
 
1884
                    List.fold_left
 
1885
                      (fun (subst, len) arg -> 
 
1886
                        match kind_of_term arg with
 
1887
                          | Rel n when dependent arg c ->
 
1888
                              ((n, len) :: subst, pred len)
 
1889
                          | _ -> (subst, pred len))
 
1890
                      (subst, len) realargs)
 
1891
          | _ -> (subst, len - signlen))
 
1892
      ([], nar) tomatchs arsign
 
1893
  in
 
1894
  let rec predicate lift c =
 
1895
    match kind_of_term c with
 
1896
      | Rel n when n > lift -> 
 
1897
          (try 
 
1898
              (* Make the predicate dependent on the matched variable *)
 
1899
              let idx = List.assoc (n - lift) subst in
 
1900
                mkRel (idx + lift)
 
1901
            with Not_found -> 
 
1902
              (* A variable that is not matched, lift over the arsign. *)
 
1903
              mkRel (n + nar))
 
1904
      | _ ->
 
1905
          map_constr_with_binders succ predicate lift c 
 
1906
  in
 
1907
    try 
 
1908
      (* The tycon may be ill-typed after abstraction. *)
 
1909
      let pred = predicate 0 c in
 
1910
      let env' = push_rel_context (context_of_arsign arsign) env in
 
1911
        ignore(Typing.sort_of env' evm pred); pred
 
1912
    with _ -> lift nar c
 
1913
 
 
1914
 
 
1915
let prepare_predicate_from_rettyp loc typing_fun isevars env tomatchs sign tycon rtntyp =
 
1916
  (* We extract the signature of the arity *)
 
1917
  let arsign = extract_arity_signature env tomatchs sign in
 
1918
  let newenv = List.fold_right push_rels arsign env in
 
1919
  let allnames = List.rev (List.map (List.map pi1) arsign) in
 
1920
    match rtntyp with
 
1921
      | Some rtntyp ->
 
1922
          let predcclj = typing_fun (mk_tycon (new_Type ())) newenv rtntyp in
 
1923
          let predccl = (j_nf_isevar !isevars predcclj).uj_val in      
 
1924
            Some (build_initial_predicate true allnames predccl)
 
1925
      | None -> 
 
1926
          match valcon_of_tycon tycon with
 
1927
            | Some ty -> 
 
1928
                let pred = 
 
1929
                  prepare_predicate_from_arsign_tycon loc env (Evd.evars_of !isevars) tomatchs arsign ty
 
1930
                in Some (build_initial_predicate true allnames pred)
 
1931
            | None -> None
 
1932
 
 
1933
let compile_cases loc style (typing_fun, isevars) (tycon : Evarutil.type_constraint) env (predopt, tomatchl, eqns) =
 
1934
 
 
1935
  let typing_fun tycon env = typing_fun tycon env isevars in
 
1936
 
 
1937
  (* We build the matrix of patterns and right-hand-side *)
 
1938
  let matx = matx_of_eqns env eqns in
 
1939
     
 
1940
  (* We build the vector of terms to match consistently with the *)
 
1941
  (* constructors found in patterns *)
 
1942
  let tomatchs = coerce_to_indtype typing_fun isevars env matx tomatchl in
 
1943
  let _isdep = List.exists (fun (x, y) -> is_dependent_ind y) tomatchs in
 
1944
    if predopt = None then
 
1945
      let tomatchs, tomatchs_lets = abstract_tomatch env tomatchs in
 
1946
      let tomatchs_len = List.length tomatchs_lets in
 
1947
      let env = push_rel_context tomatchs_lets env in
 
1948
      let len = List.length eqns in 
 
1949
      let sign, allnames, signlen, eqs, neqs, args = 
 
1950
        (* The arity signature *)
 
1951
        let arsign = extract_arity_signatures env tomatchs (List.map snd tomatchl) in
 
1952
          (* Build the dependent arity signature, the equalities which makes
 
1953
             the first part of the predicate and their instantiations. *)
 
1954
        let avoid = [] in
 
1955
          build_dependent_signature env (Evd.evars_of !isevars) avoid tomatchs arsign
 
1956
 
 
1957
      in
 
1958
      let tycon, arity = 
 
1959
        match valcon_of_tycon tycon with
 
1960
        | None -> let ev = mkExistential env isevars in ev, ev
 
1961
        | Some t -> 
 
1962
            t, prepare_predicate_from_arsign_tycon loc env (Evd.evars_of !isevars)
 
1963
              tomatchs sign (lift tomatchs_len t)
 
1964
      in
 
1965
      let neqs, arity = 
 
1966
        let ctx = context_of_arsign eqs in
 
1967
        let neqs = List.length ctx in
 
1968
          neqs, it_mkProd_or_LetIn (lift neqs arity) ctx
 
1969
      in
 
1970
      let lets, matx = 
 
1971
        (* Type the rhs under the assumption of equations *)
 
1972
        constrs_of_pats typing_fun env isevars matx tomatchs sign neqs arity 
 
1973
      in
 
1974
      let matx = List.rev matx in
 
1975
      let _ = assert(len = List.length lets) in
 
1976
      let env = push_rels lets env in
 
1977
      let matx = List.map (fun eqn -> { eqn with rhs = { eqn.rhs with rhs_env = env } }) matx in
 
1978
      let tomatchs = List.map (fun (x, y) -> lift len x, lift_tomatch_type len y) tomatchs in
 
1979
      let args = List.rev_map (lift len) args in
 
1980
      let pred = liftn len (succ signlen) arity in
 
1981
      let pred = build_initial_predicate true allnames pred in
 
1982
 
 
1983
      (* We push the initial terms to match and push their alias to rhs' envs *)
 
1984
      (* names of aliases will be recovered from patterns (hence Anonymous here) *)
 
1985
      let initial_pushed = List.map (fun tm -> Pushed (tm,[])) tomatchs in
 
1986
        
 
1987
      let pb =
 
1988
        { env      = env;
 
1989
          isevars  = isevars;
 
1990
          pred     = Some pred;
 
1991
          tomatch  = initial_pushed;
 
1992
          history  = start_history (List.length initial_pushed);
 
1993
          mat      = matx;
 
1994
          caseloc  = loc;
 
1995
          casestyle= style;
 
1996
          typing_function = typing_fun } in
 
1997
        
 
1998
      let j = compile pb in
 
1999
        (* We check for unused patterns *)
 
2000
        List.iter (check_unused_pattern env) matx;
 
2001
        let body = it_mkLambda_or_LetIn (applistc j.uj_val args) lets in
 
2002
        let j = 
 
2003
          { uj_val = it_mkLambda_or_LetIn body tomatchs_lets;
 
2004
            uj_type = nf_isevar !isevars tycon; }
 
2005
        in j
 
2006
    else
 
2007
      (* We build the elimination predicate if any and check its consistency *)
 
2008
      (* with the type of arguments to match *)
 
2009
      let tmsign = List.map snd tomatchl in
 
2010
      let pred = prepare_predicate_from_rettyp loc typing_fun isevars env tomatchs tmsign tycon predopt in
 
2011
 
 
2012
      (* We push the initial terms to match and push their alias to rhs' envs *)
 
2013
      (* names of aliases will be recovered from patterns (hence Anonymous here) *)
 
2014
      let initial_pushed = List.map (fun tm -> Pushed (tm,[])) tomatchs in
 
2015
      let pb =
 
2016
        { env      = env;
 
2017
          isevars  = isevars;
 
2018
          pred     = pred;
 
2019
          tomatch  = initial_pushed;
 
2020
          history  = start_history (List.length initial_pushed);
 
2021
          mat      = matx;
 
2022
          caseloc  = loc;
 
2023
          casestyle= style;
 
2024
          typing_function = typing_fun } in
 
2025
        
 
2026
      let j = compile pb in
 
2027
        (* We check for unused patterns *)
 
2028
        List.iter (check_unused_pattern env) matx;
 
2029
        inh_conv_coerce_to_tycon loc env isevars j tycon          
 
2030
          
 
2031
end
 
2032