]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_refiner/nCicRefiner.ml
1cd2e54b96614a37ae097022799f109a964d7765
[helm.git] / helm / software / components / ng_refiner / nCicRefiner.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.      
9      \ /   This software is distributed as is, NO WARRANTY.     
10       V_______________________________________________________________ *)
11
12 (* $Id$ *)
13
14 exception RefineFailure of (Stdpp.location * string) Lazy.t;;
15 exception Uncertain of (Stdpp.location * string) Lazy.t;;
16 exception AssertFailure of string Lazy.t;;
17
18 module C = NCic
19 module Ref = NReference
20
21 let indent = ref "";;
22 let inside c = indent := !indent ^ String.make 1 c;;
23 let outside () = indent := String.sub !indent 0 (String.length !indent -1);;
24
25
26 let pp s = 
27   prerr_endline (Printf.sprintf "%-20s" !indent ^ " " ^ Lazy.force s)
28 ;;  
29
30 let pp _ = ();;
31
32 let wrap_exc msg = function
33   | NCicUnification.Uncertain _ -> Uncertain msg
34   | NCicUnification.UnificationFailure _ -> RefineFailure msg
35   | NCicTypeChecker.TypeCheckerFailure _ -> RefineFailure msg
36   | e -> raise e
37 ;;
38
39 let exp_implicit metasenv context expty =
40  let foo x = match expty with Some t -> `WithType t | None -> x in
41  function      
42   | `Closed -> NCicMetaSubst.mk_meta metasenv [] (foo `Term)
43   | `Type -> NCicMetaSubst.mk_meta metasenv context (foo `Type)
44   | `Term -> NCicMetaSubst.mk_meta metasenv context (foo `Term)
45   | _ -> assert false
46 ;;
47
48
49 let check_allowed_sort_elimination hdb localise r orig =
50    let mkapp he arg =
51      match he with
52      | C.Appl l -> C.Appl (l @ [arg])
53      | t -> C.Appl [t;arg] in
54    (* ctx, ind_type @ lefts, sort_of_ind_ty@lefts, outsort *)
55    let rec aux metasenv subst context ind arity1 arity2 =
56      (*D*)inside 'S'; try let rc = 
57      let arity1 = NCicReduction.whd ~subst context arity1 in
58      pp (lazy(NCicPp.ppterm ~subst ~metasenv ~context arity1 ^ "   elimsto   " ^
59         NCicPp.ppterm ~subst ~metasenv ~context arity2 ^ "\nMENV:\n"^
60         NCicPp.ppmetasenv ~subst metasenv));
61      match arity1 with
62      | C.Prod (name,so1,de1) (* , t ==?== C.Prod _ *) ->
63         let metasenv, meta, _ = 
64           NCicMetaSubst.mk_meta metasenv ((name,C.Decl so1)::context) `Type 
65         in
66         let metasenv, subst = 
67           try NCicUnification.unify hdb metasenv subst context 
68                 arity2 (C.Prod (name, so1, meta)) 
69           with exc -> raise (wrap_exc (lazy (localise orig, Printf.sprintf
70             "expected %s, found %s" (* XXX localizzare meglio *)
71             (NCicPp.ppterm ~subst ~metasenv ~context (C.Prod (name, so1, meta)))
72             (NCicPp.ppterm ~subst ~metasenv ~context arity2))) exc)
73         in
74         aux metasenv subst ((name, C.Decl so1)::context)
75          (mkapp (NCicSubstitution.lift 1 ind) (C.Rel 1)) de1 meta
76      | C.Sort _ (* , t ==?== C.Prod _ *) ->
77         let metasenv, meta, _ = NCicMetaSubst.mk_meta metasenv [] `Type in
78         let metasenv, subst = 
79           try NCicUnification.unify hdb metasenv subst context 
80                 arity2 (C.Prod ("_", ind, meta)) 
81           with exc -> raise (wrap_exc (lazy (localise orig, Printf.sprintf
82             "expected %s, found %s" (* XXX localizzare meglio *)
83             (NCicPp.ppterm ~subst ~metasenv ~context (C.Prod ("_", ind, meta)))
84             (NCicPp.ppterm ~subst ~metasenv ~context arity2))) exc)
85         in
86         (try NCicTypeChecker.check_allowed_sort_elimination
87             ~metasenv ~subst r context ind arity1 arity2; 
88             metasenv, subst
89         with exc -> raise (wrap_exc (lazy (localise orig, 
90           "Sort elimination not allowed ")) exc))
91      | _ -> assert false
92      (*D*)in outside(); rc with exc -> outside (); raise exc
93    in
94     aux
95 ;;
96
97 let rec typeof hdb 
98   ?(localise=fun _ -> Stdpp.dummy_loc) 
99   ~look_for_coercion metasenv subst context term expty 
100 =
101   let force_ty skip_lambda metasenv subst context orig t infty expty =
102     (*D*)inside 'F'; try let rc = 
103     match expty with
104     | Some expty ->
105        (match t with
106        | C.Implicit _ -> assert false
107        | C.Lambda _ when skip_lambda -> metasenv, subst, t, expty
108        | _ ->
109           pp (lazy (
110           (NCicPp.ppterm ~metasenv ~subst ~context infty) ^  " === " ^
111           (NCicPp.ppterm ~metasenv ~subst:[] ~context expty)));
112            try 
113              let metasenv, subst =
114                NCicUnification.unify hdb metasenv subst context infty expty 
115              in
116              metasenv, subst, t, expty
117            with exc -> 
118              try_coercions hdb ~look_for_coercion ~localise 
119                metasenv subst context t orig infty expty true exc)
120     | None -> metasenv, subst, t, infty
121     (*D*)in outside(); rc with exc -> outside (); raise exc
122   in
123   let rec typeof_aux metasenv subst context expty = 
124     fun t as orig -> 
125     (*D*)inside 'R'; try let rc = 
126     pp (lazy (NCicPp.ppterm ~metasenv ~subst ~context t));
127     pp (lazy (if expty = None then "NONE" else "SOME"));
128     if (List.exists (fun (i,_) -> i=29) subst) then 
129       pp (lazy (NCicPp.ppsubst ~metasenv subst));
130     let metasenv, subst, t, infty = 
131     match t with
132     | C.Rel n ->
133         let infty = 
134          (try
135            match List.nth context (n - 1) with
136            | (_,C.Decl ty) -> NCicSubstitution.lift n ty
137            | (_,C.Def (_,ty)) -> NCicSubstitution.lift n ty
138          with Failure _ -> 
139            raise (RefineFailure (lazy (localise t,"unbound variable"))))
140         in
141         metasenv, subst, t, infty
142     | C.Sort (C.Type [false,u]) -> metasenv,subst,t,(C.Sort (C.Type [true, u]))
143     | C.Sort (C.Type _) -> 
144         raise (AssertFailure (lazy ("Cannot type an inferred type: "^
145           NCicPp.ppterm ~subst ~metasenv ~context t)))
146     | C.Sort _ -> metasenv,subst,t,(C.Sort (C.Type NCicEnvironment.type0))
147     | C.Implicit infos -> 
148          let metasenv,t,ty = exp_implicit metasenv context expty infos in
149          metasenv, subst, t, ty 
150     | C.Meta (n,l) as t -> 
151        let ty =
152         try
153          let _,_,_,ty = NCicUtils.lookup_subst n subst in ty 
154         with NCicUtils.Subst_not_found _ -> try
155          let _,_,ty = NCicUtils.lookup_meta n metasenv in 
156          match ty with C.Implicit _ -> assert false | _ -> ty 
157         with NCicUtils.Meta_not_found _ ->
158          raise (AssertFailure (lazy (Printf.sprintf
159           "%s not found" (NCicPp.ppterm ~subst ~metasenv ~context t))))
160        in
161        metasenv, subst, t, NCicSubstitution.subst_meta l ty
162     | C.Const _ -> 
163        metasenv, subst, t, NCicTypeChecker.typeof ~subst ~metasenv context t
164     | C.Prod (name,(s as orig_s),(t as orig_t)) ->
165        let metasenv, subst, s, s1 = typeof_aux metasenv subst context None s in
166        let metasenv, subst, s, s1 = 
167          force_to_sort hdb ~look_for_coercion
168            metasenv subst context s orig_s localise s1 in
169        let context1 = (name,(C.Decl s))::context in
170        let metasenv, subst, t, s2 = typeof_aux metasenv subst context1 None t in
171        let metasenv, subst, t, s2 = 
172          force_to_sort hdb ~look_for_coercion
173            metasenv subst context1 t orig_t localise s2 in
174        let metasenv, subst, s, t, ty = 
175          sort_of_prod localise metasenv subst 
176            context orig_s orig_t (name,s) t (s1,s2)
177        in
178        metasenv, subst, NCic.Prod(name,s,t), ty
179     | C.Lambda (n,(s as orig_s),t) as orig ->
180        let exp_s, exp_ty_t, force_after =
181          match expty with
182          | None -> None, None, false
183          | Some expty -> 
184              match NCicReduction.whd ~subst context expty with
185              | C.Prod (_,s,t) -> Some s, Some t, false
186              | _ -> None, None, true 
187        in
188        let metasenv, subst, s, ty_s = 
189          typeof_aux metasenv subst context None s in
190        let metasenv, subst, s, _ = 
191          force_to_sort hdb ~look_for_coercion
192            metasenv subst context s orig_s localise ty_s in
193        let (metasenv,subst), exp_ty_t = 
194          match exp_s with 
195          | Some exp_s -> 
196              (try NCicUnification.unify hdb metasenv subst context s exp_s,exp_ty_t
197              with exc -> raise (wrap_exc (lazy (localise orig_s, Printf.sprintf
198                "Source type %s was expected to be %s" (NCicPp.ppterm ~metasenv
199                ~subst ~context s) (NCicPp.ppterm ~metasenv ~subst ~context
200                exp_s))) exc))
201          | None -> (metasenv, subst), None
202        in
203        let context_for_t = (n,C.Decl s) :: context in
204        let metasenv, subst, t, ty_t = 
205          typeof_aux metasenv subst context_for_t exp_ty_t t 
206        in
207        if force_after then
208          force_ty false metasenv subst context orig 
209            (C.Lambda(n,s,t)) (C.Prod (n,s,ty_t)) expty
210        else 
211          metasenv, subst, C.Lambda(n,s,t), C.Prod (n,s,ty_t)
212     | C.LetIn (n,(ty as orig_ty),t,bo) ->
213        let metasenv, subst, ty, ty_ty = 
214          typeof_aux metasenv subst context None ty in
215        let metasenv, subst, ty, _ = 
216          force_to_sort hdb ~look_for_coercion
217            metasenv subst context ty orig_ty localise ty_ty in
218        let metasenv, subst, t, _ = 
219          typeof_aux metasenv subst context (Some ty) t in
220        let context1 = (n, C.Def (t,ty)) :: context in
221        let metasenv, subst, bo, bo_ty = 
222          typeof_aux metasenv subst context1 None bo 
223        in
224        let bo_ty = NCicSubstitution.subst ~avoid_beta_redexes:true t bo_ty in
225        metasenv, subst, C.LetIn (n, ty, t, bo), bo_ty
226     | C.Appl ((he as orig_he)::(_::_ as args)) ->
227        let upto = 
228          match orig_he with C.Meta _ -> List.length args | _ -> 0
229        in
230        let metasenv, subst, he, ty_he = 
231          typeof_aux metasenv subst context None he in
232        let metasenv, subst, t, ty = 
233          eat_prods hdb ~localise ~look_for_coercion 
234            metasenv subst context orig_he he ty_he args
235        in
236        let t = if upto > 0 then NCicReduction.head_beta_reduce ~upto t else t in
237        metasenv, subst, t, ty
238    | C.Appl _ -> raise (AssertFailure (lazy "Appl of length < 2"))
239    | C.Match (Ref.Ref (_,Ref.Ind (_,tyno,_)) as r,
240           outtype,(term as orig_term),pl) as orig ->
241       let _, leftno, itl, _, _ = NCicEnvironment.get_checked_indtys r in
242       let _, _, arity, cl = List.nth itl tyno in
243       let constructorsno = List.length cl in
244       let _, metasenv, args = 
245         NCicMetaSubst.saturate metasenv subst context arity 0 in
246       let ind = if args = [] then C.Const r else C.Appl (C.Const r::args) in
247       let metasenv, subst, term, _ = 
248         typeof_aux metasenv subst context (Some ind) term in
249       let parameters, arguments = HExtlib.split_nth leftno args in
250       let outtype =  
251         match outtype with
252         | C.Implicit _ as ot -> 
253              let rec aux = function
254                | [] -> NCic.Lambda ("_",NCic.Implicit `Type,ot)
255                | _::tl -> NCic.Lambda ("_",NCic.Implicit `Type,aux tl)
256              in
257                aux arguments
258         | _ -> outtype
259       in 
260       let metasenv, subst, outtype, outsort = 
261         typeof_aux metasenv subst context None outtype in
262       (* let's control if the sort elimination is allowed: [(I q1 ... qr)|B] *)
263       let ind =
264         if parameters = [] then C.Const r
265         else C.Appl ((C.Const r)::parameters) in
266       let metasenv, subst, ind, ind_ty = 
267         typeof_aux metasenv subst context None ind in
268       let metasenv, subst = 
269          check_allowed_sort_elimination hdb localise r orig_term metasenv subst 
270            context ind ind_ty outsort 
271       in
272       (* let's check if the type of branches are right *)
273       if List.length pl <> constructorsno then
274        raise (RefineFailure (lazy (localise orig, 
275          "Wrong number of cases in a match")));
276 (*
277       let metasenv, subst =
278         match expty with
279         | None -> metasenv, subst
280         | Some expty -> 
281            NCicUnification.unify hdb metasenv subst context resty expty 
282       in
283 *)
284       let _, metasenv, subst, pl_rev =
285         List.fold_left
286           (fun (j, metasenv, subst, branches) p ->
287               let cons = 
288                 let cons = Ref.mk_constructor j r in
289                 if parameters = [] then C.Const cons
290                 else C.Appl (C.Const cons::parameters)
291               in
292               let metasenv, subst, cons, ty_cons = 
293                 typeof_aux metasenv subst context None cons in
294               let ty_branch = 
295                 NCicTypeChecker.type_of_branch 
296                   ~subst context leftno outtype cons ty_cons in
297               pp (lazy ("TYPEOFBRANCH: " ^
298                NCicPp.ppterm ~metasenv ~subst ~context p ^ " ::: " ^
299                NCicPp.ppterm ~metasenv ~subst ~context ty_branch ));
300               let metasenv, subst, p, _ = 
301                 typeof_aux metasenv subst context (Some ty_branch) p in
302               j+1, metasenv, subst, p :: branches)
303           (1, metasenv, subst, []) pl
304       in
305       let resty = C.Appl (outtype::arguments@[term]) in
306       let resty = NCicReduction.head_beta_reduce ~subst resty in
307       metasenv, subst, C.Match (r, outtype, term, List.rev pl_rev),resty
308     | C.Match _ as orig -> assert false
309     in
310     pp (lazy (NCicPp.ppterm ~metasenv ~subst ~context t ^ " :: "^
311          NCicPp.ppterm ~metasenv ~subst ~context infty ));
312       force_ty true metasenv subst context orig t infty expty
313     (*D*)in outside(); rc with exc -> outside (); raise exc
314   in
315     typeof_aux metasenv subst context expty term
316
317 and try_coercions hdb 
318   ~localise ~look_for_coercion 
319   metasenv subst context t orig_t infty expty perform_unification exc 
320 =
321   (* we try with a coercion *)
322   let rec first exc = function
323   | [] ->         
324       raise (wrap_exc (lazy (localise orig_t, Printf.sprintf
325         "The term %s has type %s but is here used with type %s"
326         (NCicPp.ppterm ~metasenv ~subst ~context t)
327         (NCicPp.ppterm ~metasenv ~subst ~context infty)
328         (NCicPp.ppterm ~metasenv ~subst ~context expty))) exc)
329   | (metasenv, newterm, newtype, meta)::tl ->
330       try 
331           pp (lazy ( "UNIFICATION in CTX:\n"^ 
332             NCicPp.ppcontext ~metasenv ~subst context
333             ^ "\nMENV: " ^
334             NCicPp.ppmetasenv metasenv ~subst
335             ^ "\nOF: " ^
336             NCicPp.ppterm ~metasenv ~subst ~context meta ^  " === " ^
337             NCicPp.ppterm ~metasenv ~subst ~context t ^ "\n"));
338         let metasenv, subst = 
339           NCicUnification.unify hdb metasenv subst context meta t
340         in
341           pp (lazy ( "UNIFICATION in CTX:\n"^ 
342             NCicPp.ppcontext ~metasenv ~subst context
343             ^ "\nMENV: " ^
344             NCicPp.ppmetasenv metasenv ~subst
345             ^ "\nOF: " ^
346             NCicPp.ppterm ~metasenv ~subst ~context newtype ^  " === " ^
347             NCicPp.ppterm ~metasenv ~subst ~context expty ^ "\n"));
348         let metasenv, subst = 
349           if perform_unification then
350             NCicUnification.unify hdb metasenv subst context newtype expty
351           else metasenv, subst
352         in
353         metasenv, subst, newterm, newtype
354       with 
355       | NCicUnification.UnificationFailure _ -> first exc tl
356       | NCicUnification.Uncertain _ as exc -> first exc tl
357   in 
358     first exc
359       (look_for_coercion metasenv subst context infty expty)
360
361 and force_to_sort hdb 
362   ~look_for_coercion metasenv subst context t orig_t localise ty 
363 =
364   match NCicReduction.whd ~subst context ty with
365   | C.Meta (_,(0,(C.Irl 0 | C.Ctx []))) as ty -> 
366      metasenv, subst, t, ty
367   | C.Meta (i,(_,(C.Irl 0 | C.Ctx []))) -> 
368      metasenv, subst, t, C.Meta(i,(0,C.Irl 0))
369   | C.Meta (i,(_,lc)) ->
370      let len = match lc with C.Irl len->len | C.Ctx l->List.length l in
371      let metasenv, subst, newmeta = 
372        if len > 0 then
373          NCicMetaSubst.restrict metasenv subst i (HExtlib.list_seq 1 (len+1)) 
374        else metasenv, subst, i
375      in
376      metasenv, subst, t, C.Meta (newmeta,(0,C.Irl 0))
377   | C.Sort _ as ty -> metasenv, subst, t, ty 
378   | ty -> 
379       try_coercions hdb ~localise ~look_for_coercion metasenv subst context
380         t orig_t ty (NCic.Sort (NCic.Type NCicEnvironment.type0)) false 
381          (Uncertain (lazy (localise orig_t, 
382          "The type of " ^ NCicPp.ppterm ~metasenv ~subst ~context t
383          ^ " is not a sort: " ^ NCicPp.ppterm ~metasenv ~subst ~context ty)))
384
385 and sort_of_prod 
386   localise metasenv subst context orig_s orig_t (name,s) t (t1, t2) 
387 =
388    (* force to sort is done in the Prod case in typeof *)
389    match t1, t2 with
390    | C.Sort _, C.Sort C.Prop -> metasenv, subst, s, t, t2
391    | C.Sort (C.Type u1), C.Sort (C.Type u2) ->
392         metasenv, subst, s, t, C.Sort (C.Type (NCicEnvironment.max u1 u2)) 
393    | C.Sort C.Prop,C.Sort (C.Type _) -> metasenv, subst, s, t, t2
394    | C.Meta _, C.Sort _ 
395    | C.Meta _, C.Meta (_,(_,_))
396    | C.Sort _, C.Meta (_,(_,_)) -> metasenv, subst, s, t, t2 
397    | x, (C.Sort _ | C.Meta _) | _, x -> 
398       let y, context, orig = 
399         if x == t1 then s, context, orig_s 
400         else t, ((name,C.Decl s)::context), orig_t
401       in
402       raise (RefineFailure (lazy (localise orig,Printf.sprintf
403         "%s is expected to be a type, but its type is %s that is not a sort" 
404          (NCicPp.ppterm ~subst ~metasenv ~context y) 
405          (NCicPp.ppterm ~subst ~metasenv ~context x))))
406
407 and eat_prods hdb
408   ~localise ~look_for_coercion metasenv subst context orig_he he ty_he args 
409 =
410   (*D*)inside 'E'; try let rc = 
411   let rec aux metasenv subst args_so_far he ty_he = function 
412   | []->metasenv, subst, NCicUntrusted.mk_appl he (List.rev args_so_far), ty_he
413   | arg::tl ->
414       match NCicReduction.whd ~subst context ty_he with 
415       | C.Prod (_,s,t) ->
416           let metasenv, subst, arg, _ = 
417             typeof hdb ~look_for_coercion ~localise 
418               metasenv subst context arg (Some s) in
419           let t = NCicSubstitution.subst ~avoid_beta_redexes:true arg t in
420           aux metasenv subst (arg :: args_so_far) he t tl
421       | C.Meta _
422       | C.Appl (C.Meta _ :: _) as t ->
423           let metasenv, subst, arg, ty_arg = 
424             typeof hdb ~look_for_coercion ~localise 
425               metasenv subst context arg None in
426           let metasenv, meta, _ = 
427             NCicMetaSubst.mk_meta metasenv 
428               (("_",C.Decl ty_arg) :: context) `Type
429           in
430           let flex_prod = C.Prod ("_", ty_arg, meta) in
431           (* next line grants that ty_args is a type *)
432           let metasenv,subst, flex_prod, _ =
433            typeof hdb ~look_for_coercion ~localise metasenv subst
434             context flex_prod None in
435           pp (lazy ( "UNIFICATION in CTX:\n"^ 
436             NCicPp.ppcontext ~metasenv ~subst context
437             ^ "\nOF: " ^
438             NCicPp.ppterm ~metasenv ~subst ~context t ^  " === " ^
439             NCicPp.ppterm ~metasenv ~subst ~context flex_prod ^ "\n"));
440           let metasenv, subst = 
441              try NCicUnification.unify hdb metasenv subst context t flex_prod 
442              with exc -> raise (wrap_exc (lazy (localise orig_he, Printf.sprintf
443               ("The term %s has an inferred type %s, but is applied to the" ^^
444                " argument %s of type %s")
445               (NCicPp.ppterm ~metasenv ~subst ~context he)
446               (NCicPp.ppterm ~metasenv ~subst ~context t)
447               (NCicPp.ppterm ~metasenv ~subst ~context arg)
448               (NCicPp.ppterm ~metasenv ~subst ~context ty_arg))) exc)
449               (* XXX coerce to funclass *)
450           in
451           let meta = NCicSubstitution.subst ~avoid_beta_redexes:true arg meta in
452           aux metasenv subst (arg :: args_so_far) he meta tl
453       | C.Match (_,_,C.Meta _,_) 
454       | C.Match (_,_,C.Appl (C.Meta _ :: _),_) 
455       | C.Appl (C.Const (NReference.Ref (_, NReference.Fix _)) :: _) ->
456           raise (Uncertain (lazy (localise orig_he, Printf.sprintf
457             ("The term %s is here applied to %d arguments but expects " ^^
458             "only %d arguments") (NCicPp.ppterm ~metasenv ~subst ~context he)
459             (List.length args) (List.length args_so_far))))
460       | ty ->
461           let metasenv, subst, newhead, newheadty = 
462             try_coercions hdb ~localise ~look_for_coercion metasenv subst context
463               (NCicUntrusted.mk_appl he (List.rev args_so_far)) orig_he ty
464               (NCic.Prod ("_",NCic.Implicit `Term,NCic.Implicit `Term))
465               false
466               (RefineFailure (lazy (localise orig_he, Printf.sprintf
467                ("The term %s is here applied to %d arguments but expects " ^^
468                "only %d arguments") (NCicPp.ppterm ~metasenv ~subst ~context he)
469                (List.length args) (List.length args_so_far))))
470           in
471           aux metasenv subst [] newhead newheadty (arg :: tl)
472   in
473    aux metasenv subst [] he ty_he args
474   (*D*)in outside(); rc with exc -> outside (); raise exc
475 ;;
476
477 let rec first f l1 l2 =
478   match l1,l2 with
479   | x1::tl1, x2::tl2 -> 
480       (try f x1 x2 with Not_found -> first f tl1 tl2)
481   | _ -> raise Not_found
482 ;;
483
484 let rec find add dt t =
485   if dt == add then t
486   else
487     let dl, l = 
488       match dt, t with
489       | C.Meta (_,(_,C.Ctx dl)), C.Meta (_,(_,C.Ctx l))
490       | C.Appl dl,C.Appl l -> dl,l
491       | C.Lambda (_,ds,dt), C.Lambda (_,s,t) 
492       | C.Prod (_,ds,dt), C.Prod (_,s,t) -> [ds;dt],[s;t]
493       | C.LetIn (_,ds,db,dt), C.LetIn (_,s,b,t) -> [ds;db;dt],[s;b;t] 
494       | C.Match (_,dot,dt,dl),  C.Match (_,ot,t,l) -> (dot::dt::dl),(ot::t::l)
495       | _ -> raise Not_found
496     in
497       first (find add) dl l
498 ;;
499
500 let relocalise old_localise dt t add = 
501   old_localise 
502     (try find add dt t with Not_found -> assert false)
503 ;;
504
505 let undebruijnate inductive ref t rev_fl =
506   NCicSubstitution.psubst (fun x -> x) 
507     (HExtlib.list_mapi 
508       (fun (_,_,rno,_,_,_) i -> 
509          NCic.Const 
510            (if inductive then NReference.mk_fix i rno ref
511             else NReference.mk_cofix i ref))
512       rev_fl)
513     t
514 ;; 
515
516
517 let typeof_obj hdb 
518   ?(localise=fun _ -> Stdpp.dummy_loc) 
519   ~look_for_coercion (uri,height,metasenv,subst, obj)
520
521   let check_type metasenv subst (ty as orig_ty) =  (* XXX fattorizza *)
522     let metasenv, subst, ty, sort = 
523       typeof hdb ~localise ~look_for_coercion metasenv subst [] ty None
524     in
525     let metasenv, subst, ty, _ = 
526       force_to_sort hdb ~look_for_coercion 
527         metasenv subst [] ty orig_ty localise sort
528     in
529       metasenv, subst, ty
530   in
531   match obj with 
532   | C.Constant (relevance, name, bo, ty , attr) ->
533        let metasenv, subst, ty = check_type metasenv subst ty in
534        let metasenv, subst, bo, ty, height = 
535          match bo with
536          | Some bo ->
537              let metasenv, subst, bo, ty = 
538                typeof hdb ~localise ~look_for_coercion 
539                  metasenv subst [] bo (Some ty)
540              in
541              let height = (* XXX recalculate *) height in
542                metasenv, subst, Some bo, ty, height
543          | None -> metasenv, subst, None, ty, 0
544        in
545        uri, height, metasenv, subst, 
546          C.Constant (relevance, name, bo, ty, attr)
547   | C.Fixpoint (inductive, fl, attr) -> 
548       let len = List.length fl in
549       let types, metasenv, subst, rev_fl =
550         List.fold_left
551          (fun (types, metasenv, subst, fl) (relevance,name,k,ty,bo) ->
552            let metasenv, subst, ty = check_type metasenv subst ty in
553            let dbo = NCicTypeChecker.debruijn uri len [] bo in
554            let localise = relocalise localise dbo bo in
555             (name,C.Decl ty)::types,
556               metasenv, subst, (relevance,name,k,ty,dbo,localise)::fl
557          ) ([], metasenv, subst, []) fl (* XXX kl rimosso nel nucleo *)
558       in
559       let metasenv, subst, fl = 
560         List.fold_left 
561           (fun (metasenv,subst,fl) (relevance,name,k,ty,dbo,localise) ->
562             let metasenv, subst, dbo, ty = 
563               typeof hdb ~localise ~look_for_coercion 
564                 metasenv subst types dbo (Some ty)
565             in
566             metasenv, subst, (relevance,name,k,ty,dbo)::fl)
567           (metasenv, subst, []) rev_fl
568       in
569       let height = (* XXX recalculate *) height in
570       let fl =
571         List.map 
572           (fun (relevance,name,k,ty,dbo) ->
573             let bo = 
574               undebruijnate inductive 
575                (NReference.reference_of_spec uri 
576                  (if inductive then NReference.Fix (0,k,0) 
577                   else NReference.CoFix 0)) dbo rev_fl
578             in
579               relevance,name,k,ty,bo)
580           fl
581       in
582        uri, height, metasenv, subst, 
583          C.Fixpoint (inductive, fl, attr)
584
585   | C.Inductive (ind, leftno, itl, attr) ->  assert false
586 (*
587   (* let's check if the arity of the inductive types are well formed *)
588   List.iter (fun (_,_,x,_) -> ignore (typeof ~subst ~metasenv [] x)) tyl;
589   (* let's check if the types of the inductive constructors are well formed. *)
590   let len = List.length tyl in
591   let tys = List.rev_map (fun (_,n,ty,_) -> (n,(C.Decl ty))) tyl in
592   ignore
593    (List.fold_right
594     (fun (it_relev,_,ty,cl) i ->
595        let context,ty_sort = split_prods ~subst [] ~-1 ty in
596        let sx_context_ty_rev,_ = HExtlib.split_nth leftno (List.rev context) in
597        List.iter
598          (fun (k_relev,_,te) ->
599            let _,k_relev = HExtlib.split_nth leftno k_relev in
600            let te = debruijn uri len [] te in
601            let context,te = split_prods ~subst tys leftno te in
602            let _,chopped_context_rev =
603             HExtlib.split_nth (List.length tys) (List.rev context) in
604            let sx_context_te_rev,_ =
605             HExtlib.split_nth leftno chopped_context_rev in
606            (try
607              ignore (List.fold_left2
608               (fun context item1 item2 ->
609                 let convertible =
610                  match item1,item2 with
611                    (n1,C.Decl ty1),(n2,C.Decl ty2) ->
612                      n1 = n2 && 
613                      R.are_convertible ~metasenv ~subst context ty1 ty2
614                  | (n1,C.Def (bo1,ty1)),(n2,C.Def (bo2,ty2)) ->
615                      n1 = n2
616                      && R.are_convertible ~metasenv ~subst context ty1 ty2
617                      && R.are_convertible ~metasenv ~subst context bo1 bo2
618                  | _,_ -> false
619                 in
620                  if not convertible then
621                   raise (TypeCheckerFailure (lazy
622                    ("Mismatch between the left parameters of the constructor " ^
623                     "and those of its inductive type")))
624                  else
625                   item1::context
626               ) [] sx_context_ty_rev sx_context_te_rev)
627             with Invalid_argument "List.fold_left2" -> assert false);
628            let con_sort = typeof ~subst ~metasenv context te in
629            (match R.whd ~subst context con_sort, R.whd ~subst [] ty_sort with
630                (C.Sort (C.Type u1) as s1), (C.Sort (C.Type u2) as s2) ->
631                 if not (E.universe_leq u1 u2) then
632                  raise
633                   (TypeCheckerFailure
634                     (lazy ("The type " ^ PP.ppterm ~metasenv ~subst ~context s1^
635                       " of the constructor is not included in the inductive" ^
636                       " type sort " ^ PP.ppterm ~metasenv ~subst ~context s2)))
637              | C.Sort _, C.Sort C.Prop
638              | C.Sort _, C.Sort C.Type _ -> ()
639              | _, _ ->
640                 raise
641                  (TypeCheckerFailure
642                    (lazy ("Wrong constructor or inductive arity shape"))));
643            (* let's check also the positivity conditions *)
644            if 
645              not
646                (are_all_occurrences_positive ~subst context uri leftno
647                  (i+leftno) leftno (len+leftno) te) 
648            then
649              raise
650                (TypeCheckerFailure
651                  (lazy ("Non positive occurence in "^NUri.string_of_uri
652                  uri)))
653            else check_relevance ~subst ~metasenv context k_relev te) 
654          cl;
655         check_relevance ~subst ~metasenv [] it_relev ty;
656         i+1)
657     tyl 1)
658 *)
659
660
661 ;;
662
663
664
665 (* vim:set foldmethod=marker: *)