]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/ng_kernel/nCicTypeChecker.ml
guarded by has a nice error message
[helm.git] / helm / software / components / ng_kernel / nCicTypeChecker.ml
index 7ba5ab15219d435aa3be7011fd3086c0086f15ff..7e9cd70b206dcde2d7fe22ab6fb4044b775c7ca5 100644 (file)
@@ -608,6 +608,11 @@ let eat_prods ~subst ~metasenv context ty_he args_with_ty =
   | (arg, ty_arg)::tl ->
       (match R.whd ~subst context ty_he with 
       | C.Prod (n,s,t) ->
+(*
+          prerr_endline (NCicPp.ppterm ~context s ^ " - Vs - " ^ NCicPp.ppterm
+          ~context ty_arg);
+          prerr_endline (NCicPp.ppterm ~context (S.subst ~avoid_beta_redexes:true arg t));
+*)
           if R.are_convertible ~subst ~metasenv context ty_arg s then
             aux (S.subst ~avoid_beta_redexes:true arg t) tl
           else
@@ -664,10 +669,12 @@ let does_not_occur ~subst context n nn t =
    with DoesOccur -> false
 ;;
 
-exception NotGuarded;;
+exception NotGuarded of string Lazy.t;;
 
 let rec typeof ~subst ~metasenv context term =
-  let rec typeof_aux context = function
+  let rec typeof_aux context = 
+    fun t -> (*prerr_endline (NCicPp.ppterm ~context t); *)
+    match t with
     | C.Rel n ->
        (try
          match List.nth context (n - 1) with
@@ -720,9 +727,16 @@ let rec typeof ~subst ~metasenv context term =
     | C.Appl (he::(_::_ as args)) ->
        let ty_he = typeof_aux context he in
        let args_with_ty = List.map (fun t -> t, typeof_aux context t) args in
+(*
+       prerr_endline ("HEAD: " ^ NCicPp.ppterm ~context ty_he);
+       prerr_endline ("TARGS: " ^ String.concat " | " (List.map (NCicPp.ppterm
+       ~context) (List.map snd args_with_ty)));
+       prerr_endline ("ARGS: " ^ String.concat " | " (List.map (NCicPp.ppterm
+       ~context) (List.map fst args_with_ty)));
+*)
        eat_prods ~subst ~metasenv context ty_he args_with_ty
    | C.Appl _ -> raise (AssertFailure (lazy "Appl of length < 2"))
-   | C.Match (Ref.Ref (dummy_depth,uri,Ref.Ind tyno) as r,outtype,term,pl) ->
+   | C.Match (Ref.Ref (_,_,Ref.Ind tyno) as r,outtype,term,pl) ->
       let outsort = typeof_aux context outtype in
       let leftno = E.get_indty_leftno r in
       let parameters, arguments =
@@ -765,32 +779,36 @@ let rec typeof ~subst ~metasenv context term =
       in
       if List.length pl <> constructorsno then
        raise (TypeCheckerFailure (lazy ("Wrong number of cases in a match")));
-      let j,branches_ok =
+      let j,branches_ok,p_ty, exp_p_ty =
         List.fold_left
-          (fun (j,b) p ->
+          (fun (j,b,old_p_ty,old_exp_p_ty) p ->
             if b then
               let cons = 
-                let cons = Ref.Ref (dummy_depth, uri, Ref.Con (tyno, j)) in
+                let cons = Ref.mk_constructor j r in
                 if parameters = [] then C.Const cons
                 else C.Appl (C.Const cons::parameters)
               in
               let ty_p = typeof_aux context p in
               let ty_cons = typeof_aux context cons in
               let ty_branch = 
-                type_of_branch ~subst context leftno outtype cons ty_cons 0 in
-              j+1, R.are_convertible ~subst ~metasenv context ty_p ty_branch 
+                type_of_branch ~subst context leftno outtype cons ty_cons 0 
+              in
+              j+1, R.are_convertible ~subst ~metasenv context ty_p ty_branch,
+              ty_p, ty_branch
             else
-              j,false
-          ) (1,true) pl
-         in
-          if not branches_ok then
-           raise
-            (TypeCheckerFailure 
-              (lazy (Printf.sprintf "Branch for constructor %s has wrong type"
-              (NCicPp.ppterm (C.Const 
-                (Ref.Ref (dummy_depth, uri, Ref.Con (tyno, j)))))))); 
-          let res = outtype::arguments@[term] in
-          R.head_beta_reduce (C.Appl res)
+              j,false,old_p_ty,old_exp_p_ty
+          ) (1,true,C.Sort C.Prop,C.Sort C.Prop) pl
+      in
+      if not branches_ok then
+        raise
+         (TypeCheckerFailure 
+          (lazy (Printf.sprintf ("Branch for constructor %s :=\n%s\n"^^
+          "has type %s\nnot convertible with %s") (NCicPp.ppterm (C.Const 
+          (Ref.mk_constructor j r)))
+          (NCicPp.ppterm ~context (List.nth pl (j-1)))
+          (NCicPp.ppterm ~context p_ty) (NCicPp.ppterm ~context exp_p_ty)))); 
+      let res = outtype::arguments@[term] in
+      R.head_beta_reduce (C.Appl res)
     | C.Match _ -> assert false
 
   and type_of_branch ~subst context leftno outty cons tycons liftno = 
@@ -953,7 +971,7 @@ let rec typeof ~subst ~metasenv context term =
  in 
    typeof_aux context term
 
-and check_mutual_inductive_defs _ = assert false
+and check_mutual_inductive_defs _ = ()
 
 and eat_lambdas ~subst context n te =
   match (n, R.whd ~subst context te) with
@@ -967,19 +985,24 @@ and eat_lambdas ~subst context n te =
 and guarded_by_destructors ~subst context recfuns t = 
  let recursor f k t = NCicUtils.fold shift_k k (fun k () -> f k) () t in
  let rec aux (context, recfuns, x, safes as k) = function
-  | C.Rel m when List.mem_assoc m recfuns -> raise NotGuarded 
+  | C.Rel m as t when List.mem_assoc m recfuns -> 
+      raise (NotGuarded (lazy (NCicPp.ppterm ~context t ^ " passed around")))
   | C.Rel m ->
      (match List.nth context (m-1) with 
      | _,C.Decl _ -> ()
      | _,C.Def (bo,_) -> aux (context, recfuns, x, safes) (S.lift m bo))
   | C.Meta _ -> ()
-  | C.Appl ((C.Rel m)::tl) when List.mem_assoc m recfuns ->
+  | C.Appl ((C.Rel m)::tl) as t when List.mem_assoc m recfuns ->
      let rec_no = List.assoc m recfuns in
-     if not (List.length tl > rec_no) then raise NotGuarded
+     if not (List.length tl > rec_no) then 
+       raise (NotGuarded (lazy 
+         (NCicPp.ppterm ~context ~subst t ^ 
+         " is a partial application of a fix")))
      else
        let rec_arg = List.nth tl rec_no in
-       if not (is_really_smaller ~subst k rec_arg) then raise
-       NotGuarded;
+       if not (is_really_smaller ~subst k rec_arg) then 
+         raise (NotGuarded (lazy 
+           (NCicPp.ppterm ~context ~subst rec_arg ^ " not smaller")));
        List.iter (aux k) tl
   | C.Match (Ref.Ref (_,uri,_) as ref,outtype,term,pl) as t ->
      (match R.whd ~subst context term with
@@ -1000,8 +1023,8 @@ and guarded_by_destructors ~subst context recfuns t =
      | _ -> recursor aux k t)
   | t -> recursor aux k t
  in
-  try aux (context, recfuns, 1, []) t;true
-  with NotGuarded -> false
+  try aux (context, recfuns, 1, []) t
+  with NotGuarded s -> raise (TypeCheckerFailure s)
 
 (*
  | C.Fix (_, fl) ->
@@ -1150,7 +1173,7 @@ and type_of_constant ((Ref.Ref (_,uri,_)) as ref) =
       let _,_,arity,_ = List.nth tl i in arity
   | (_,_,_,_,C.Inductive (_,_,tl,_)), Ref.Ref (_,_,Ref.Con (i,j))  ->
       let _,_,_,cl = List.nth tl i in 
-      let _,_,arity = List.nth cl j in 
+      let _,_,arity = List.nth cl (j-1) in 
       arity
   | (_,_,_,_,C.Fixpoint (_,fl,_)), Ref.Ref (_,_,(Ref.Fix (i,_)|Ref.CoFix i)) ->
       let _,_,_,arity,_ = List.nth fl i in
@@ -1163,14 +1186,17 @@ and check_obj_well_typed (uri,height,metasenv,subst,kind) =
  assert (metasenv = [] && subst = []);
  match kind with
    | C.Constant (_,_,Some te,ty,_) ->
+      prerr_endline ("TY: " ^ NCicPp.ppterm ty);
+      prerr_endline ("BO: " ^ NCicPp.ppterm te);
       let _ = typeof ~subst ~metasenv [] ty in
       let ty_te = typeof ~subst ~metasenv [] te in
+      prerr_endline "XXXX";
       if not (R.are_convertible ~subst ~metasenv [] ty_te ty) then
        raise (TypeCheckerFailure (lazy (Printf.sprintf
         "the type of the body is not the one expected:\n%s\nvs\n%s"
         (NCicPp.ppterm ty_te) (NCicPp.ppterm ty))))
    | C.Constant (_,_,None,ty,_) -> ignore (typeof ~subst ~metasenv [] ty)
-   | C.Inductive _ as obj -> check_mutual_inductive_defs uri obj
+   | C.Inductive _ as obj -> check_mutual_inductive_defs obj
    | C.Fixpoint (inductive,fl,_) ->
       let types,kl,len =
         List.fold_left
@@ -1180,6 +1206,7 @@ and check_obj_well_typed (uri,height,metasenv,subst,kind) =
          ) ([],[],0) fl
       in
         List.iter (fun (_,name,x,ty,bo) ->
+         let bo = debruijn uri len bo in
          let ty_bo = typeof ~subst ~metasenv types bo in
          if not (R.are_convertible ~subst ~metasenv types ty_bo (S.lift len ty))
          then raise (TypeCheckerFailure (lazy ("(Co)Fix: ill-typed bodies")))
@@ -1190,9 +1217,7 @@ and check_obj_well_typed (uri,height,metasenv,subst,kind) =
             let rec enum_from k = 
               function [] -> [] | v::tl -> (k,v)::enum_from (k+1) tl 
             in
-            if not (guarded_by_destructors 
-                      ~subst context (enum_from (x+1) kl) m) then
-              raise(TypeCheckerFailure(lazy("Fix: not guarded by destructors")))
+            guarded_by_destructors ~subst context (enum_from (x+1) kl) m;
           end else
            match returns_a_coinductive ~subst [] ty with
             | None ->