]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/ng_kernel/nCicTypeChecker.ml
Bug fixed: the debrujinate function (hence the one to compute objects height)
[helm.git] / helm / software / components / ng_kernel / nCicTypeChecker.ml
index da130c55574c07a501db14f6cd73ef0d676f0588..c4c2af477d3a510e33846f2bec5f827635a16ef3 100644 (file)
@@ -96,23 +96,22 @@ let fixed_args bos j n nn =
    (let rec f = function 0 -> [] | n -> true :: f (n-1) in f j) bos
 ;;
 
-(* if n < 0, then splits all prods from an arity, returning a sort *)
-let rec split_prods ~subst context n te =
-  match (n, R.whd ~subst context te) with
-   | (0, _) -> context,te
-   | (n, C.Sort _) when n <= 0 -> context,te
-   | (n, C.Prod (name,so,ta)) ->
-       split_prods ~subst ((name,(C.Decl so))::context) (n - 1) ta
-   | (_, _) -> raise (AssertFailure (lazy "split_prods"))
-;;
-
-let debruijn uri number_of_types context = 
+let debruijn uri number_of_types ~subst context = 
+(* manca la subst! *)
  let rec aux k t =
   match t with
-   | C.Meta (i,(s,C.Ctx l)) ->
-      let l1 = HExtlib.sharing_map (aux (k-s)) l in
-      if l1 == l then t else C.Meta (i,(s,C.Ctx l1))
-   | C.Meta _ -> t
+   | C.Meta (i,(s,l)) ->
+      (try
+        let _,_,term,_ = U.lookup_subst i subst in
+        let ts = S.subst_meta (0,l) term in
+        let ts' = aux (k-s) ts in
+         if ts == ts' then t else ts'
+       with U.Subst_not_found _ ->
+        match l with
+           C.Ctx l ->
+            let l1 = HExtlib.sharing_map (aux (k-s)) l in
+            if l1 == l then t else C.Meta (i,(s,C.Ctx l1))
+         | _ -> t)
    | C.Const (Ref.Ref (uri1,(Ref.Fix (no,_,_) | Ref.CoFix no))) 
    | C.Const (Ref.Ref (uri1,Ref.Ind (_,no,_))) when NUri.eq uri uri1 ->
       C.Rel (k + number_of_types - no)
@@ -126,7 +125,8 @@ let sort_of_prod ~metasenv ~subst context (name,s) t (t1, t2) =
    let t2 = R.whd ~subst ((name,C.Decl s)::context) t2 in
    match t1, t2 with
    | C.Sort _, C.Sort C.Prop -> t2
-   | C.Sort (C.Type u1), C.Sort (C.Type u2) -> C.Sort (C.Type (u1@u2)) 
+   | C.Sort (C.Type u1), C.Sort (C.Type u2) ->
+      C.Sort (C.Type (NCicEnvironment.max u1 u2))
    | C.Sort C.Prop,C.Sort (C.Type _) -> t2
    | C.Meta (_,(_,(C.Irl 0 | C.Ctx []))), C.Sort _ -> t2
    | C.Meta (_,(_,(C.Irl 0 | C.Ctx []))), C.Meta (i,(_,(C.Irl 0 | C.Ctx [])))
@@ -175,7 +175,7 @@ let specialize_and_abstract_constrs ~subst r_uri r_len context ty_term =
     | _ -> assert false
   in
   context_dcl,
-  List.map (fun (_,id,ty) -> id, debruijn r_uri r_len context ty) cl,
+  List.map (fun (_,id,ty) -> id, debruijn r_uri r_len ~subst context ty) cl,
   len, len + r_len
 ;;
 
@@ -235,7 +235,7 @@ let check_homogeneous_call ~subst context indparamsno n uri reduct tl =
    (fun k x ->
      if k = 0 then 0
      else
-      match R.whd context x with
+      match R.whd ~subst context x with
       | C.Rel m when m = n - (indparamsno - k) -> k - 1
       | _ -> raise (TypeCheckerFailure (lazy 
          ("Argument "^string_of_int (indparamsno - k + 1) ^ " (of " ^
@@ -268,7 +268,7 @@ let rec weakly_positive ~subst context n nn uri indparamsno posuri te =
      are skipped because we already know that are_all_occurrences_positive
      of uri in te. *)
   let rec aux context n nn te =
-    match R.whd context te with
+    match R.whd ~subst context te with
      | t when t = dummy -> true
      | C.Appl (te::rargs) when te = dummy ->
         List.for_all (does_not_occur ~subst context n nn) rargs
@@ -286,7 +286,7 @@ let rec weakly_positive ~subst context n nn uri indparamsno posuri te =
      aux context n nn (subst_inductive_type_with_dummy () te)
 
 and strictly_positive ~subst context n nn indparamsno posuri te =
-  match R.whd context te with
+  match R.whd ~subst context te with
    | t when does_not_occur ~subst context n nn t -> true
    | C.Rel _ when indparamsno = 0 -> true
    | C.Appl ((C.Rel m)::tl) as reduct when m > n && m <= nn ->
@@ -314,7 +314,7 @@ and strictly_positive ~subst context n nn indparamsno posuri te =
        
 (* the inductive type indexes are s.t. n < x <= nn *)
 and are_all_occurrences_positive ~subst context uri indparamsno i n nn te =
-  match R.whd context te with
+  match R.whd ~subst context te with
   |  C.Appl ((C.Rel m)::tl) as reduct when m = i ->
       check_homogeneous_call ~subst context indparamsno n uri reduct tl;
       List.for_all (does_not_occur ~subst context n nn) tl
@@ -359,7 +359,9 @@ let type_of_branch ~subst context leftno outty cons tycons =
         | t -> C.Appl [t ; C.Rel 1]
        in
         C.Prod (name,so, aux (liftno+1) ((name,(C.Decl so))::context) cons de)
-   | _ -> raise (AssertFailure (lazy "type_of_branch"))
+   | t -> raise (AssertFailure 
+      (lazy ("type_of_branch, the contructor has type: " ^ NCicPp.ppterm
+       ~metasenv:[] ~context:[] ~subst:[] t)))
  in
   aux 0 context cons tycons
 ;;
@@ -374,7 +376,9 @@ let rec typeof ~subst ~metasenv context term =
          match List.nth context (n - 1) with
          | (_,C.Decl ty) -> S.lift n ty
          | (_,C.Def (_,ty)) -> S.lift n ty
-        with Failure _ -> raise (TypeCheckerFailure (lazy "unbound variable")))
+        with Failure _ -> 
+          raise (TypeCheckerFailure (lazy ("unbound variable " ^ string_of_int n
+            ^" under: " ^ NCicPp.ppcontext ~metasenv ~subst context))))
     | C.Sort (C.Type [false,u]) -> C.Sort (C.Type [true, u])
     | C.Sort (C.Type _) -> 
         raise (AssertFailure (lazy ("Cannot type an inferred type: "^
@@ -677,7 +681,7 @@ and eat_prods ~subst ~metasenv context he ty_he args_with_ty =
             raise 
               (TypeCheckerFailure 
                 (lazy (Printf.sprintf
-                  ("Appl: wrong application of %s: the parameter %s has type"^^
+                  ("Appl: wrong application of %s: the argument %s has type"^^
                    "\n%s\nbut it should have type \n%s\nContext:\n%s\n")
                   (PP.ppterm ~subst ~metasenv ~context he)
                   (PP.ppterm ~subst ~metasenv ~context arg)
@@ -700,7 +704,7 @@ and eat_prods ~subst ~metasenv context he ty_he args_with_ty =
 
 and is_non_recursive_singleton ~subst (Ref.Ref (uri,_)) iname ity cty =
      let ctx = [iname, C.Decl ity] in
-     let cty = debruijn uri 1 [] cty in
+     let cty = debruijn uri 1 [] ~subst cty in
      let len = List.length ctx in
      let rec aux ctx n nn t =
        match R.whd ~subst ctx t with
@@ -714,12 +718,12 @@ and is_non_recursive_singleton ~subst (Ref.Ref (uri,_)) iname ity cty =
 
 and is_non_informative ~metasenv ~subst paramsno c =
  let rec aux context c =
-   match R.whd context c with
+   match R.whd ~subst context c with
     | C.Prod (n,so,de) ->
        let s = typeof ~metasenv ~subst context so in
        s = C.Sort C.Prop && aux ((n,(C.Decl so))::context) de
     | _ -> true in
- let context',dx = split_prods ~subst [] paramsno c in
+ let context',dx = NCicReduction.split_prods ~subst [] paramsno c in
   aux context' dx
 
 and check_mutual_inductive_defs uri ~metasenv ~subst leftno tyl = 
@@ -731,13 +735,15 @@ and check_mutual_inductive_defs uri ~metasenv ~subst leftno tyl =
   ignore
    (List.fold_right
     (fun (it_relev,_,ty,cl) i ->
-       let context,ty_sort = split_prods ~subst [] ~-1 ty in
+       let context,ty_sort = NCicReduction.split_prods ~subst [] ~-1 ty in
        let sx_context_ty_rev,_ = HExtlib.split_nth leftno (List.rev context) in
        List.iter
          (fun (k_relev,_,te) ->
-          let _,k_relev = HExtlib.split_nth leftno k_relev in
-           let te = debruijn uri len [] te in
-           let context,te = split_prods ~subst tys leftno te in
+          let k_relev =
+            try snd (HExtlib.split_nth leftno k_relev)
+            with Failure _ -> k_relev in
+           let te = debruijn uri len [] ~subst te in
+           let context,te = NCicReduction.split_prods ~subst tys leftno te in
            let _,chopped_context_rev =
             HExtlib.split_nth (List.length tys) (List.rev context) in
            let sx_context_te_rev,_ =
@@ -747,13 +753,11 @@ and check_mutual_inductive_defs uri ~metasenv ~subst leftno tyl =
               (fun context item1 item2 ->
                 let convertible =
                  match item1,item2 with
-                   (n1,C.Decl ty1),(n2,C.Decl ty2) ->
-                     n1 = n2 && 
+                   (_,C.Decl ty1),(_,C.Decl ty2) ->
                      R.are_convertible ~metasenv ~subst context ty1 ty2
-                 | (n1,C.Def (bo1,ty1)),(n2,C.Def (bo2,ty2)) ->
-                     n1 = n2
-                     && R.are_convertible ~metasenv ~subst context ty1 ty2
-                     && R.are_convertible ~metasenv ~subst context bo1 bo2
+                 | (_,C.Def (bo1,ty1)),(_,C.Def (bo2,ty2)) ->
+                     R.are_convertible ~metasenv ~subst context ty1 ty2 &&
+                      R.are_convertible ~metasenv ~subst context bo1 bo2
                  | _,_ -> false
                 in
                  if not convertible then
@@ -869,7 +873,7 @@ and guarded_by_destructors r_uri r_len ~subst ~metasenv context recfuns t =
         List.split (List.map (fun (_,name,_,ty,bo) -> (name, C.Decl ty), bo) fl)
       in
       let fl_len = List.length fl in
-      let bos = List.map (debruijn uri fl_len context) bos in
+      let bos = List.map (debruijn uri fl_len context ~subst) bos in
       let j = List.fold_left min max_int (List.map (fun (_,_,i,_,_)->i) fl) in
       let ctx_len = List.length context in
         (* we may look for fixed params not only up to j ... *)
@@ -1001,7 +1005,7 @@ and guarded_by_constructors ~subst ~metasenv context t indURI indlen nn =
    aux context 0 nn false t
                                                                       
 and recursive_args ~subst ~metasenv context n nn te =
-  match R.whd context te with
+  match R.whd ~subst context te with
   | C.Rel _ | C.Appl _ | C.Const _ -> []
   | C.Prod (name,so,de) ->
      (not (does_not_occur ~subst context n nn so)) ::
@@ -1082,11 +1086,14 @@ and type_of_constant ((Ref.Ref (uri,_)) as ref) =
       let _,_,recno1,arity,_ = List.nth fl i in
       if h1 <> h2 || recno1 <> recno2 then error ();
       arity
-  | (_,_,_,_,C.Constant (_,_,_,ty,_)), Ref.Ref (_,Ref.Decl) -> ty
-  | (_,h1,_,_,C.Constant (_,_,_,ty,_)), Ref.Ref (_,Ref.Def h2) ->
+  | (_,_,_,_,C.Constant (_,_,None,ty,_)), Ref.Ref (_,Ref.Decl) -> ty
+  | (_,h1,_,_,C.Constant (_,_,Some _,ty,_)), Ref.Ref (_,Ref.Def h2) ->
      if h1 <> h2 then error ();
      ty
-  | _ -> raise (AssertFailure (lazy "type_of_constant: environment/reference"))
+  | _ ->
+    raise (AssertFailure
+     (lazy ("type_of_constant: environment/reference: " ^
+       Ref.string_of_reference ref)))
 
 and get_relevance ~metasenv ~subst context t args = 
    let ty = typeof ~subst ~metasenv context t in
@@ -1183,9 +1190,52 @@ let typecheck_subst ~metasenv subst =
     ) [] subst)
 ;;
 
+let height_of_term tl =
+ let h = ref 0 in
+ let get_height (NReference.Ref (uri,_)) =
+  let _,height,_,_,_ = NCicEnvironment.get_checked_obj uri in
+   height in
+ let rec aux =
+  function
+     NCic.Meta (_,(_,NCic.Ctx l)) -> List.iter aux l
+   | NCic.Meta _ -> ()
+   | NCic.Rel _
+   | NCic.Sort _ -> ()
+   | NCic.Implicit _ -> assert false
+   | NCic.Const nref -> h := max !h (get_height nref)
+   | NCic.Prod (_,t1,t2)
+   | NCic.Lambda (_,t1,t2) -> aux t1; aux t2
+   | NCic.LetIn (_,s,ty,t) -> aux s; aux ty; aux t
+   | NCic.Appl l -> List.iter aux l
+   | NCic.Match (_,outty,t,pl) -> aux outty; aux t; List.iter aux pl
+ in
+  List.iter aux tl;
+  1 + !h
+;;
+
+let height_of_obj_kind uri ~subst =
+ function
+    NCic.Inductive _
+  | NCic.Constant (_,_,None,_,_)
+  | NCic.Fixpoint (false,_,_) -> 0
+  | NCic.Fixpoint (true,ifl,_) ->
+     let iflno = List.length ifl in
+      height_of_term
+       (List.fold_left
+        (fun l (_,_,_,ty,bo) ->
+          let bo = debruijn uri iflno [] ~subst bo in
+           ty::bo::l
+       ) [] ifl)
+  | NCic.Constant (_,_,Some bo,ty,_) -> height_of_term [bo;ty]
+;;
 
-let typecheck_obj (uri,_height,metasenv,subst,kind) =
- (* height is not checked since it is only used to implement an optimization *)
+let typecheck_obj (uri,height,metasenv,subst,kind) =
+(*height must be checked since it is not only an optimization during reduction*)
+ let iheight = height_of_obj_kind uri ~subst kind in
+ if height <> iheight then
+  raise (TypeCheckerFailure (lazy (Printf.sprintf
+   "the declared object height (%d) is not the inferred one (%d)"
+   height iheight)));
  typecheck_metasenv metasenv;
  typecheck_subst ~metasenv subst;
  match kind with
@@ -1218,7 +1268,7 @@ let typecheck_obj (uri,_height,metasenv,subst,kind) =
       let dfl, kl =   
         List.split (List.map2 
           (fun (_,_,_,_,bo) rno -> 
-             let dbo = debruijn uri len [] bo in
+             let dbo = debruijn uri len [] ~subst bo in
              dbo, Evil rno)
           fl kl)
       in
@@ -1302,4 +1352,31 @@ E.set_typecheck_obj
 
 let _ = NCicReduction.set_get_relevance get_relevance;;
 
+
+let indent = ref 0;;
+let debug = true;;
+let logger =
+    let do_indent () = String.make !indent ' ' in  
+    (function 
+      | `Start_type_checking s ->
+          if debug then
+           prerr_endline (do_indent () ^ "Start: " ^ NUri.string_of_uri s); 
+          incr indent
+      | `Type_checking_completed s ->
+          decr indent;
+          if debug then
+           prerr_endline (do_indent () ^ "End: " ^ NUri.string_of_uri s)
+      | `Type_checking_interrupted s ->
+          decr indent;
+          if debug then
+           prerr_endline (do_indent () ^ "Break: " ^ NUri.string_of_uri s)
+      | `Type_checking_failed s ->
+          decr indent;
+          if debug then
+           prerr_endline (do_indent () ^ "Fail: " ^ NUri.string_of_uri s)
+      | `Trust_obj s ->
+          if debug then
+           prerr_endline (do_indent () ^ "Trust: " ^ NUri.string_of_uri s))
+;;
+(* let _ = set_logger logger ;; *)
 (* EOF *)