]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/cic_unification/cicRefine.ml
new tacticals
[helm.git] / helm / ocaml / cic_unification / cicRefine.ml
index f216b3c5c03429324561f49e8a89e770246063e1..120fdceaa1b5a08452ff30c4398a0d0cad76bebd 100644 (file)
 
 open Printf
 
-exception RefineFailure of string;;
-exception Uncertain of string;;
-exception AssertFailure of string;;
+exception RefineFailure of string Lazy.t;;
+exception Uncertain of string Lazy.t;;
+exception AssertFailure of string Lazy.t;;
 
 let debug_print = fun _ -> ()
 
+let profiler = HExtlib.profile "CicRefine.fo_unif"
+
 let fo_unif_subst subst context metasenv t1 t2 ugraph =
   try
+let foo () =
     CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
+in profiler.HExtlib.profile foo ()
   with
       (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
     | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
 ;;
-
+                       
 let rec split l n =
  match (l,n) with
     (l,0) -> ([], l)
   | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
-  | (_,_) -> raise (AssertFailure "split: list too short")
+  | (_,_) -> raise (AssertFailure (lazy "split: list too short"))
 ;;
 
 let rec type_of_constant uri ugraph =
@@ -61,7 +65,7 @@ let rec type_of_constant uri ugraph =
     | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
     | _ ->
        raise
-        (RefineFailure ("Unknown constant definition " ^  U.string_of_uri uri))
+        (RefineFailure (lazy ("Unknown constant definition " ^  U.string_of_uri uri)))
 
 and type_of_variable uri ugraph =
   let module C = Cic in
@@ -78,7 +82,7 @@ and type_of_variable uri ugraph =
     | _ ->
         raise
          (RefineFailure
-          ("Unknown variable definition " ^ UriManager.string_of_uri uri))
+          (lazy ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
 
 and type_of_mutual_inductive_defs uri i ugraph =
   let module C = Cic in
@@ -97,7 +101,7 @@ and type_of_mutual_inductive_defs uri i ugraph =
     | _ ->
        raise
         (RefineFailure
-         ("Unknown mutual inductive definition " ^ U.string_of_uri uri))
+         (lazy ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
 
 and type_of_mutual_inductive_constr uri i j ugraph =
   let module C = Cic in
@@ -117,7 +121,7 @@ and type_of_mutual_inductive_constr uri i j ugraph =
       | _ ->
          raise
            (RefineFailure
-               ("Unkown mutual inductive definition " ^ U.string_of_uri uri))
+               (lazy ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
 
 
 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
@@ -156,8 +160,8 @@ and check_branch n context metasenv subst left_args_no actualtype term expectedt
                   check_branch (n+1) 
                      ((Some (name,(C.Decl so)))::context) 
                        metasenv subst left_args_no de' term' de ugraph1
-             | _ -> raise (AssertFailure "Wrong number of arguments"))
-      | _ -> raise (AssertFailure "Prod or MutInd expected")
+             | _ -> raise (AssertFailure (lazy "Wrong number of arguments")))
+      | _ -> raise (AssertFailure (lazy "Prod or MutInd expected"))
 
 and type_of_aux' metasenv context t ugraph =
   let rec type_of_aux subst metasenv context t ugraph =
@@ -180,9 +184,9 @@ and type_of_aux' metasenv context t ugraph =
                        (S.lift n bo) ugraph 
                      in
                       t,ty,subst,metasenv,ugraph
-                | None -> raise (RefineFailure "Rel to hidden hypothesis")
+                | None -> raise (RefineFailure (lazy "Rel to hidden hypothesis"))
              with
-                _ -> raise (RefineFailure "Not a close term")
+                _ -> raise (RefineFailure (lazy "Not a close term"))
            )
        | C.Var (uri,exp_named_subst) ->
            let exp_named_subst',subst',metasenv',ugraph1 =
@@ -222,7 +226,7 @@ and type_of_aux' metasenv context t ugraph =
              t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
        | C.Sort _ -> 
             t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
-       | C.Implicit _ -> raise (AssertFailure "21")
+       | C.Implicit _ -> raise (AssertFailure (lazy "21"))
        | C.Cast (te,ty) ->
            let ty',_,subst',metasenv',ugraph1 =
               type_of_aux subst metasenv context ty ugraph 
@@ -237,7 +241,7 @@ and type_of_aux' metasenv context t ugraph =
                 in
                   C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
                with
-                  _ -> raise (RefineFailure "Cast"))
+                  _ -> raise (RefineFailure (lazy "Cast")))
        | C.Prod (name,s,t) ->
            let s',sort1,subst',metasenv',ugraph1 = 
               type_of_aux subst metasenv context s ugraph 
@@ -246,11 +250,61 @@ and type_of_aux' metasenv context t ugraph =
               type_of_aux subst' metasenv' 
                 ((Some (name,(C.Decl s')))::context) t ugraph1
            in
-            let sop,subst''',metasenv''',ugraph3 =
-              sort_of_prod subst'' metasenv'' 
-                context (name,s') (sort1,sort2) ugraph2
-            in
-              C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
+            (try
+              let sop,subst''',metasenv''',ugraph3 =
+                sort_of_prod subst'' metasenv'' 
+                  context (name,s') (sort1,sort2) ugraph2
+              in
+                C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
+            with
+            | RefineFailure _ as exn ->
+                (* given [t] of type [type_to_coerce] returns
+                 * a term that has type [tgt_sort] eventually 
+                 * derived from (coercion [t]) *)
+                let refined_target = t' in
+                let sort_of_refined_target = sort2 in
+                let carr t subst context = CicMetaSubst.apply_subst subst t in
+                let coerce_to_sort tgt_sort t type_to_coerce subst ctx =
+                  match type_to_coerce with
+                  | Cic.Sort _ -> t
+                  | term -> 
+                      let coercion_src = carr type_to_coerce subst ctx in
+                      let coercion_tgt = carr (Cic.Sort tgt_sort) subst ctx in
+                      let search = CoercGraph.look_for_coercion in
+                      (match search coercion_src coercion_tgt with
+                      | CoercGraph.NoCoercion 
+                      | CoercGraph.NotHandled _ -> raise exn
+                      | CoercGraph.NotMetaClosed -> 
+                          raise (Uncertain (lazy "Coercions on metas"))
+                      | CoercGraph.SomeCoercion c -> Cic.Appl [c;t])
+                in
+                (* this is probably not the best... *)
+                let tgt_sort_for_pi_source = Cic.Type(CicUniv.fresh()) in
+                let tgt_sort_for_pi_target = Cic.Type(CicUniv.fresh()) in
+                let new_src = 
+                  coerce_to_sort tgt_sort_for_pi_source s sort1 subst context 
+                in
+                let context_with_new_src = 
+                  ((Some (name,(C.Decl new_src)))::context) 
+                in
+                let new_tgt = 
+                  coerce_to_sort 
+                    tgt_sort_for_pi_target 
+                    refined_target sort_of_refined_target
+                    subst context_with_new_src
+                in
+                let newprod = C.Prod (name,new_src,new_tgt) in
+                let _,sort_of_refined_prod,subst,metasenv,ugraph3 =
+                  type_of_aux subst metasenv context newprod ugraph2
+                in
+                (* this if for a coercion on the tail of the arrow *)
+                let new_target = 
+                  match sort_of_refined_target with
+                  | Cic.Sort _ -> refined_target
+                  | _ -> new_tgt
+                in
+                C.Prod(name,new_src,new_target),
+                sort_of_refined_prod,subst,metasenv,ugraph3) 
        | C.Lambda (n,s,t) ->
            let s',sort1,subst',metasenv',ugraph1 = 
              type_of_aux subst metasenv context s ugraph
@@ -259,10 +313,10 @@ and type_of_aux' metasenv context t ugraph =
                   C.Meta _
                 | C.Sort _ -> ()
                 | _ ->
-                    raise (RefineFailure (sprintf
+                    raise (RefineFailure (lazy (sprintf
                                             "Not well-typed lambda-abstraction: the source %s should be a type;
              instead it is a term of type %s" (CicPp.ppterm s)
-                                            (CicPp.ppterm sort1)))
+                                            (CicPp.ppterm sort1))))
              ) ;
              let t',type2,subst'',metasenv'',ugraph2 =
                type_of_aux subst' metasenv' 
@@ -303,7 +357,7 @@ and type_of_aux' metasenv context t ugraph =
                 hetype tlbody_and_type ugraph2
             in
               C.Appl (he'::tl'), applty,subst''',metasenv''',ugraph3
-       | C.Appl _ -> raise (RefineFailure "Appl: no arguments")
+       | C.Appl _ -> raise (RefineFailure (lazy "Appl: no arguments"))
        | C.Const (uri,exp_named_subst) ->
            let exp_named_subst',subst',metasenv',ugraph1 =
              check_exp_named_subst subst metasenv context 
@@ -347,8 +401,8 @@ and type_of_aux' metasenv context t ugraph =
                | _ ->
                    raise
                      (RefineFailure
-                        ("Unkown mutual inductive definition " ^ 
-                         U.string_of_uri uri)) 
+                        (lazy ("Unkown mutual inductive definition " ^ 
+                         U.string_of_uri uri)))
            in
           let rec count_prod t =
              match CicReduction.whd ~subst context t with
@@ -550,7 +604,7 @@ and type_of_aux' metasenv context t ugraph =
                        None,ugraph4,metasenv,subst
                in
                match candidate with
-               | None -> raise (Uncertain "can't solve an higher order unification problem") 
+               | None -> raise (Uncertain (lazy "can't solve an higher order unification problem"))
                | Some candidate ->
                    let subst,metasenv,ugraph = 
                      fo_unif_subst subst context metasenv 
@@ -706,7 +760,7 @@ and type_of_aux' metasenv context t ugraph =
                    let subst',metasenv',ugraph' = 
                   (try
                      fo_unif_subst subst context metasenv t ct ugraph
-                   with e -> raise (RefineFailure (sprintf "The local context is not consistent with the canonical context, since %s cannot be unified with %s. Reason: %s" (CicMetaSubst.ppterm subst t) (CicMetaSubst.ppterm subst ct) (match e with AssertFailure msg -> msg | _ -> (Printexc.to_string e)))))
+                   with e -> raise (RefineFailure (lazy (sprintf "The local context is not consistent with the canonical context, since %s cannot be unified with %s. Reason: %s" (CicMetaSubst.ppterm subst t) (CicMetaSubst.ppterm subst ct) (match e with AssertFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
                    in
                      l @ [Some t],subst',metasenv',ugraph'
                | Some t,Some (_,C.Decl ct) ->
@@ -717,23 +771,23 @@ and type_of_aux' metasenv context t ugraph =
                     (try
                        fo_unif_subst
                          subst' context metasenv' inferredty ct ugraph1
-                     with e -> raise (RefineFailure (sprintf "The local context is not consistent with the canonical context, since the type %s of %s cannot be unified with the expected type %s. Reason: %s" (CicMetaSubst.ppterm subst' inferredty) (CicMetaSubst.ppterm subst' t) (CicMetaSubst.ppterm subst' ct) (match e with AssertFailure msg -> msg | _ -> (Printexc.to_string e)))))
+                     with e -> raise (RefineFailure (lazy (sprintf "The local context is not consistent with the canonical context, since the type %s of %s cannot be unified with the expected type %s. Reason: %s" (CicMetaSubst.ppterm subst' inferredty) (CicMetaSubst.ppterm subst' t) (CicMetaSubst.ppterm subst' ct) (match e with AssertFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
                    in
                      l @ [Some t'], subst'',metasenv'',ugraph2
                | None, Some _  ->
-                  raise (RefineFailure (sprintf
+                  raise (RefineFailure (lazy (sprintf
                                           "Not well typed metavariable instance %s: the local context does not instantiate an hypothesis even if the hypothesis is not restricted in the canonical context %s"
                                           (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
-                                          (CicMetaSubst.ppcontext subst canonical_context)))
+                                          (CicMetaSubst.ppcontext subst canonical_context))))
          ) ([],subst,metasenv,ugraph) l lifted_canonical_context 
       with
          Invalid_argument _ ->
            raise
            (RefineFailure
-               (sprintf
+               (lazy (sprintf
                  "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
                  (CicMetaSubst.ppterm subst (Cic.Meta (metano, l)))
-                 (CicMetaSubst.ppcontext subst canonical_context)))
+                 (CicMetaSubst.ppcontext subst canonical_context))))
 
   and check_exp_named_subst metasubst metasenv context tl ugraph =
     let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph  =
@@ -747,13 +801,13 @@ and type_of_aux' metasenv context t ugraph =
                 (match CicEnvironment.get_cooked_obj ~trust:false uri with
                 Cic.Variable (_,Some bo,_,_) ->
                 raise
-                (RefineFailure
-                "A variable with a body can not be explicit substituted")
+                (RefineFailure (Reason
+                "A variable with a body can not be explicit substituted"))
                 | Cic.Variable (_,None,_,_) -> ()
                 | _ ->
                 raise
-                (RefineFailure
-                ("Unkown variable definition " ^ UriManager.string_of_uri uri))
+                (RefineFailure (Reason
+                ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
                 ) ;
              *)
            let t',typeoft,metasubst',metasenv',ugraph2 =
@@ -764,11 +818,11 @@ and type_of_aux' metasenv context t ugraph =
                fo_unif_subst 
                   metasubst' context metasenv' typeoft typeofvar ugraph2
               with _ ->
-               raise (RefineFailure
+               raise (RefineFailure (lazy
                         ("Wrong Explicit Named Substitution: " ^ 
                            CicMetaSubst.ppterm metasubst' typeoft ^
                          " not unifiable with " ^ 
-                          CicMetaSubst.ppterm metasubst' typeofvar))
+                          CicMetaSubst.ppterm metasubst' typeofvar)))
             in
             (* FIXME: no mere tail recursive! *)
             let exp_name_subst, metasubst''', metasenv''', ugraph4 = 
@@ -787,35 +841,39 @@ and type_of_aux' metasenv context t ugraph =
     let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
       match (t1'', t2'') with
          (C.Sort s1, C.Sort s2)
-            when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) -> (* different than Coq manual!!! *)
+            when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) -> 
+              (* different than Coq manual!!! *)
               C.Sort s2,subst,metasenv,ugraph
        | (C.Sort (C.Type t1), C.Sort (C.Type t2)) -> 
-           (* TASSI: CONSRTAINTS: the same in cictypechecker, doubletypeinference *)
            let t' = CicUniv.fresh() in 
            let ugraph1 = CicUniv.add_ge t' t1 ugraph in
            let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
              C.Sort (C.Type t'),subst,metasenv,ugraph2
        | (C.Sort _,C.Sort (C.Type t1)) -> 
-           (* TASSI: CONSRTAINTS: the same in cictypechecker, doubletypeinference *)
            C.Sort (C.Type t1),subst,metasenv,ugraph
        | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
        | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
             (* TODO how can we force the meta to become a sort? If we don't we
              * brake the invariant that refine produce only well typed terms *)
-            (* TODO if we check the non meta term and if it is a sort then we are
-             * likely to know the exact value of the result e.g. if the rhs is a
-             * Sort (Prop | Set | CProp) then the result is the rhs *)
+            (* TODO if we check the non meta term and if it is a sort then we
+             * are likely to know the exact value of the result e.g. if the rhs
+             * is a Sort (Prop | Set | CProp) then the result is the rhs *)
             let (metasenv,idx) =
               CicMkImplicit.mk_implicit_sort metasenv subst in
             let (subst, metasenv,ugraph1) =
-              fo_unif_subst subst context_for_t2 metasenv (C.Meta (idx,[])) t2'' ugraph
+              fo_unif_subst subst context_for_t2 metasenv 
+                (C.Meta (idx,[])) t2'' ugraph
             in
               t2'',subst,metasenv,ugraph1
-       | (_,_) ->
-            raise (RefineFailure (sprintf
-                                   "Two sorts were expected, found %s (that reduces to %s) and %s (that reduces to %s)"
-                                   (CicPp.ppterm t1) (CicPp.ppterm t1'') (CicPp.ppterm t2)
-                                   (CicPp.ppterm t2'')))
+        | _,_ -> 
+            raise 
+              (RefineFailure 
+                (lazy 
+                  (sprintf
+                    ("Two sorts were expected, found %s " ^^ 
+                     "(that reduces to %s) and %s (that reduces to %s)")
+                (CicPp.ppterm t1) (CicPp.ppterm t1'') (CicPp.ppterm t2)
+                (CicPp.ppterm t2''))))
 
   and eat_prods subst metasenv context hetype tlbody_and_type ugraph =
     let rec mk_prod metasenv context =
@@ -864,11 +922,11 @@ and type_of_aux' metasenv context t ugraph =
       try
        fo_unif_subst subst context metasenv hetype hetype' ugraph
       with exn ->
-       debug_print (Printf.sprintf "hetype=%s\nhetype'=%s\nmetasenv=%s\nsubst=%s"
+       debug_print (lazy (Printf.sprintf "hetype=%s\nhetype'=%s\nmetasenv=%s\nsubst=%s"
                         (CicPp.ppterm hetype)
                         (CicPp.ppterm hetype')
-                        (CicMetaSubst.ppmetasenv metasenv [])
-                        (CicMetaSubst.ppsubst subst));
+                         (CicMetaSubst.ppmetasenv [] metasenv)
+                        (CicMetaSubst.ppsubst subst)));
        raise exn
 
     in
@@ -886,13 +944,20 @@ and type_of_aux' metasenv context t ugraph =
                          hete,subst,metasenv,ugraph1
                     with exn ->
                        (* we search a coercion from hety to s *)
-                       let coer = CoercGraph.look_for_coercion 
-                         (CicMetaSubst.apply_subst subst hety) 
-                         (CicMetaSubst.apply_subst subst s) 
+                       let coer = 
+                         let carr t subst context = 
+                           CicMetaSubst.apply_subst subst t 
+                         in
+                         let c_hety = carr hety subst context in
+                         let c_s = carr s subst context in 
+                         CoercGraph.look_for_coercion c_hety c_s
                        in
                        match coer with
-                       | None -> raise exn
-                       | Some c -> 
+                       | CoercGraph.NoCoercion 
+                       | CoercGraph.NotHandled _ -> raise exn
+                       | CoercGraph.NotMetaClosed -> 
+                           raise (Uncertain (lazy "Coercions on meta"))
+                       | CoercGraph.SomeCoercion c -> 
                            (Cic.Appl [ c ; hete ]), subst, metasenv, ugraph
                   in
                    let coerced_args,metasenv',subst',t',ugraph2 =
@@ -961,7 +1026,7 @@ let type_of_aux' metasenv context term ugraph =
   try 
     type_of_aux' metasenv context term ugraph
   with 
-    CicUniv.UniverseInconsistency msg -> raise (RefineFailure msg)
+    CicUniv.UniverseInconsistency msg -> raise (RefineFailure (lazy msg))
 
 (*CSC: this is a very very rough approximation; to be finished *)
 let are_all_occurrences_positive uri =
@@ -971,7 +1036,7 @@ let are_all_occurrences_positive uri =
      Cic.Appl (Cic.MutInd (uri',_,_)::_) when uri = uri' -> ()
    | Cic.MutInd (uri',_,_) when uri = uri' -> ()
    | Cic.Prod (_,_,t) -> aux t
-   | _ -> raise (RefineFailure "not well formed constructor type")
+   | _ -> raise (RefineFailure (lazy "not well formed constructor type"))
  in
   aux
     
@@ -1000,7 +1065,7 @@ let typecheck metasenv uri obj =
        (* instead of raising Uncertain, let's hope that the meta will become
           a sort *)
        | Cic.Meta _ -> ()
-       | _ -> raise (RefineFailure "The term provided is not a type")
+       | _ -> raise (RefineFailure (lazy "The term provided is not a type"))
      end;
      let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
      let bo' = CicMetaSubst.apply_subst subst bo' in
@@ -1061,16 +1126,24 @@ let type_of_aux' metasenv context term =
  try
   let (t,ty,m) = 
       type_of_aux' metasenv context term in
-    debug_print
-     ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty);
-   debug_print
-    ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []);
+    debug_print (lazy
+     ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
+   debug_print (lazy
+    ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
    (t,ty,m)
  with
  | RefineFailure msg as e ->
-     debug_print ("@@@ REFINE FAILED: " ^ msg);
+     debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
      raise e
  | Uncertain msg as e ->
-     debug_print ("@@@ REFINE UNCERTAIN: " ^ msg);
+     debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
      raise e
 ;; *)
+
+let profiler2 = HExtlib.profile "CicRefine"
+
+let type_of_aux' metasenv context term ugraph =
+ profiler2.HExtlib.profile (type_of_aux' metasenv context term) ugraph
+
+let typecheck metasenv uri obj =
+ profiler2.HExtlib.profile (typecheck metasenv uri) obj