]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/cic_unification/cicRefine.ml
This commit was manufactured by cvs2svn to create branch 'moogle'.
[helm.git] / helm / ocaml / cic_unification / cicRefine.ml
diff --git a/helm/ocaml/cic_unification/cicRefine.ml b/helm/ocaml/cic_unification/cicRefine.ml
deleted file mode 100644 (file)
index b3525d3..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-(* Copyright (C) 2000, HELM Team.
- * 
- * This file is part of HELM, an Hypertextual, Electronic
- * Library of Mathematics, developed at the Computer Science
- * Department, University of Bologna, Italy.
- * 
- * HELM is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * HELM is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HELM; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA  02111-1307, USA.
- * 
- * For details, see the HELM World-Wide-Web page,
- * http://cs.unibo.it/helm/.
- *)
-
-open Printf
-
-exception RefineFailure of string;;
-exception Uncertain of string;;
-exception AssertFailure of string;;
-
-let debug_print = prerr_endline
-
-let fo_unif_subst subst context metasenv t1 t2 =
- try
-  CicUnification.fo_unif_subst subst context metasenv t1 t2
- 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")
-;;
-
-let rec type_of_constant uri =
- let module C = Cic in
- let module R = CicReduction in
- let module U = UriManager in
-  match CicEnvironment.get_cooked_obj uri with
-     C.Constant (_,_,ty,_) -> ty
-   | C.CurrentProof (_,_,_,ty,_) -> ty
-   | _ ->
-     raise
-      (RefineFailure ("Unknown constant definition " ^  U.string_of_uri uri))
-
-and type_of_variable uri =
- let module C = Cic in
- let module R = CicReduction in
- let module U = UriManager in
-  match CicEnvironment.get_cooked_obj uri with
-     C.Variable (_,_,ty,_) -> ty
-   |  _ ->
-      raise
-       (RefineFailure
-         ("Unknown variable definition " ^ UriManager.string_of_uri uri))
-
-and type_of_mutual_inductive_defs uri i =
- let module C = Cic in
- let module R = CicReduction in
- let module U = UriManager in
-  match CicEnvironment.get_cooked_obj uri with
-     C.InductiveDefinition (dl,_,_) ->
-      let (_,_,arity,_) = List.nth dl i in
-       arity
-   | _ ->
-     raise
-      (RefineFailure
-        ("Unknown mutual inductive definition " ^ U.string_of_uri uri))
-
-and type_of_mutual_inductive_constr uri i j =
- let module C = Cic in
- let module R = CicReduction in
- let module U = UriManager in
-  match CicEnvironment.get_cooked_obj uri with
-      C.InductiveDefinition (dl,_,_) ->
-       let (_,_,_,cl) = List.nth dl i in
-        let (_,ty) = List.nth cl (j-1) in
-         ty
-   | _ ->
-     raise
-      (RefineFailure
-        ("Unkown mutual inductive definition " ^ U.string_of_uri uri))
-
-(* type_of_aux' is just another name (with a different scope) for type_of_aux *)
-
-(* the check_branch function checks if a branch of a case is refinable. 
-   It returns a pair (outype_instance,args), a subst and a metasenv.
-   outype_instance is the expected result of applying the case outtype 
-   to args. 
-   The problem is that outype is in general unknown, and we should
-   try to synthesize it from the above information, that is in general
-   a second order unification problem. *)
-and check_branch n context metasenv subst left_args_no actualtype term expectedtype =
-  let module C = Cic in
-  let module R = CicMetaSubst in
-  match R.whd subst context expectedtype with
-     C.MutInd (_,_,_) ->
-       (n,context,actualtype, [term]), subst, metasenv
-   | C.Appl (C.MutInd (_,_,_)::tl) ->
-       let (_,arguments) = split tl left_args_no in
-       (n,context,actualtype, arguments@[term]), subst, metasenv
-   | C.Prod (name,so,de) ->
-      (* we expect that the actual type of the branch has the due 
-         number of Prod *)
-      (match R.whd subst context actualtype with
-           C.Prod (name',so',de') ->
-             let subst, metasenv = 
-               fo_unif_subst subst context metasenv so so' in
-             let term' =
-               (match CicSubstitution.lift 1 term with
-                   C.Appl l -> C.Appl (l@[C.Rel 1])
-                 | t -> C.Appl [t ; C.Rel 1]) in
-             (* we should also check that the name variable is anonymous in
-             the actual type de' ?? *)
-             check_branch (n+1) ((Some (name,(C.Decl so)))::context) metasenv subst left_args_no de' term' de 
-        | _ -> raise (AssertFailure "Wrong number of arguments"))
-   | _ -> raise (AssertFailure "Prod or MutInd expected")
-
-and type_of_aux' metasenv context t =
- let rec type_of_aux subst metasenv context =
-  let module C = Cic in
-  let module S = CicSubstitution in
-  let module U = UriManager in
-   function
-      C.Rel n ->
-       (try
-         match List.nth context (n - 1) with
-            Some (_,C.Decl t) -> S.lift n t,subst,metasenv
-          | Some (_,C.Def (_,Some ty)) -> S.lift n ty,subst,metasenv
-          | Some (_,C.Def (bo,None)) ->
-             type_of_aux subst metasenv context (S.lift n bo)
-          | None -> raise (RefineFailure "Rel to hidden hypothesis")
-        with
-         _ -> raise (RefineFailure "Not a close term")
-       )
-    | C.Var (uri,exp_named_subst) ->
-      let subst',metasenv' =
-       check_exp_named_subst subst metasenv context exp_named_subst in
-      let ty =
-       CicSubstitution.subst_vars exp_named_subst (type_of_variable uri)
-      in
-       ty,subst',metasenv'
-    | C.Meta (n,l) -> 
-       let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
-        let subst',metasenv' =
-         check_metasenv_consistency n subst metasenv context canonical_context l
-        in
-        CicSubstitution.lift_meta l ty, subst', metasenv'
-     (* TASSI: CONSTRAINT *)
-    | C.Sort (C.Type t) ->
-        let t' = CicUniv.fresh() in
-        if not (CicUniv.add_gt t' t ) then
-         assert false (* t' is fresh! an error in CicUniv *)
-       else
-          C.Sort (C.Type t'),subst,metasenv
-     (* TASSI: CONSTRAINT *)
-    | C.Sort _ -> C.Sort (C.Type (CicUniv.fresh())),subst,metasenv
-    | C.Implicit _ -> raise (AssertFailure "21")
-    | C.Cast (te,ty) ->
-       let _,subst',metasenv' =
-        type_of_aux subst metasenv context ty in
-       let inferredty,subst'',metasenv'' =
-        type_of_aux subst' metasenv' context te
-       in
-        (try
-          let subst''',metasenv''' =
-           fo_unif_subst subst'' context metasenv'' inferredty ty
-          in
-           ty,subst''',metasenv'''
-         with
-          _ -> raise (RefineFailure "Cast"))
-    | C.Prod (name,s,t) ->
-       let sort1,subst',metasenv' = type_of_aux subst metasenv context s in
-       let sort2,subst'',metasenv'' =
-        type_of_aux subst' metasenv' ((Some (name,(C.Decl s)))::context) t
-       in
-        sort_of_prod subst'' metasenv'' context (name,s) (sort1,sort2)
-   | C.Lambda (n,s,t) ->
-       let sort1,subst',metasenv' = type_of_aux subst metasenv context s in
-       (match CicMetaSubst.whd subst' context sort1 with
-           C.Meta _
-         | C.Sort _ -> ()
-         | _ ->
-           raise (RefineFailure (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)))
-       ) ;
-       let type2,subst'',metasenv'' =
-        type_of_aux subst' metasenv' ((Some (n,(C.Decl s)))::context) t
-       in
-          C.Prod (n,s,type2),subst'',metasenv''
-   | C.LetIn (n,s,t) ->
-      (* only to check if s is well-typed *)
-      let ty,subst',metasenv' = type_of_aux subst metasenv context s in
-      let inferredty,subst'',metasenv'' =
-       type_of_aux subst' metasenv' ((Some (n,(C.Def (s,Some ty))))::context) t
-      in
-       (* One-step LetIn reduction. Even faster than the previous solution.
-          Moreover the inferred type is closer to the expected one. *)
-       CicSubstitution.subst s inferredty,subst',metasenv'
-   | C.Appl (he::tl) when List.length tl > 0 ->
-      let hetype,subst',metasenv' = type_of_aux subst metasenv context he in
-      let tlbody_and_type,subst'',metasenv'' =
-       List.fold_right
-        (fun x (res,subst,metasenv) ->
-          let ty,subst',metasenv' =
-           type_of_aux subst metasenv context x
-          in
-           (x, ty)::res,subst',metasenv'
-        ) tl ([],subst',metasenv')
-      in
-       eat_prods subst'' metasenv'' context hetype tlbody_and_type
-   | C.Appl _ -> raise (RefineFailure "Appl: no arguments")
-   | C.Const (uri,exp_named_subst) ->
-      let subst',metasenv' =
-       check_exp_named_subst subst metasenv context exp_named_subst in
-      let cty =
-       CicSubstitution.subst_vars exp_named_subst (type_of_constant uri)
-      in
-       cty,subst',metasenv'
-   | C.MutInd (uri,i,exp_named_subst) ->
-      let subst',metasenv' =
-       check_exp_named_subst subst metasenv context exp_named_subst in
-      let cty =
-       CicSubstitution.subst_vars exp_named_subst
-        (type_of_mutual_inductive_defs uri i)
-      in
-       cty,subst',metasenv'
-   | C.MutConstruct (uri,i,j,exp_named_subst) ->
-      let subst',metasenv' =
-       check_exp_named_subst subst metasenv context exp_named_subst in
-      let cty =
-       CicSubstitution.subst_vars exp_named_subst
-        (type_of_mutual_inductive_constr uri i j)
-      in
-       cty,subst',metasenv'
-   | C.MutCase (uri, i, outtype, term, pl) ->
-       (* first, get the inductive type (and noparams) in the environment  *)
-       let (_,b,arity,constructors), expl_params, no_left_params =
-         match CicEnvironment.get_cooked_obj ~trust:true uri with
-            C.InductiveDefinition (l,expl_params,parsno) -> 
-              List.nth l i , expl_params, parsno
-          | _ ->
-            raise
-             (RefineFailure
-              ("Unkown mutual inductive definition " ^ U.string_of_uri uri)) in
-       let rec count_prod t =
-         match CicMetaSubst.whd subst context t with
-             C.Prod (_, _, t) -> 1 + (count_prod t)
-           | _ -> 0 in 
-       let no_args = count_prod arity in
-       (* now, create a "generic" MutInd *)
-       let metasenv,left_args = 
-         CicMkImplicit.n_fresh_metas metasenv context no_left_params in
-       let metasenv,right_args = 
-         let no_right_params = no_args - no_left_params in
-         if no_right_params < 0 then assert false
-         else CicMkImplicit.n_fresh_metas metasenv context no_right_params in
-       let metasenv,exp_named_subst = 
-         CicMkImplicit.fresh_subst metasenv context expl_params in
-       let expected_type = 
-         if no_args = 0 then 
-           C.MutInd (uri,i,exp_named_subst)
-         else
-          C.Appl (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
-       in
-       (* check consistency with the actual type of term *)
-       let actual_type,subst,metasenv = 
-         type_of_aux subst metasenv context term in
-       let _, subst, metasenv =
-         type_of_aux subst metasenv context expected_type
-       in
-       let actual_type = CicMetaSubst.whd subst context actual_type in
-       let subst,metasenv =
-         fo_unif_subst subst context metasenv expected_type actual_type
-       in
-       (* TODO: check if the sort elimination is allowed: [(I q1 ... qr)|B] *)
-       let (_,outtypeinstances,subst,metasenv) =
-          List.fold_left
-           (fun (j,outtypeinstances,subst,metasenv) p ->
-             let constructor =
-              if left_args = [] then
-               (C.MutConstruct (uri,i,j,exp_named_subst))
-              else
-               (C.Appl (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
-             in
-             let actual_type,subst,metasenv = 
-               type_of_aux subst metasenv context p in
-             let expected_type, subst, metasenv = 
-               type_of_aux subst metasenv context constructor in
-             let outtypeinstance,subst,metasenv =
-               check_branch 
-                0 context metasenv subst 
-                no_left_params actual_type constructor expected_type in
-             (j+1,outtypeinstance::outtypeinstances,subst,metasenv))
-            (1,[],subst,metasenv) pl in
-        (* we are left to check that the outype matches his instances.
-           The easy case is when the outype is specified, that amount
-           to a trivial check. Otherwise, we should guess a type from
-           its instances *)
-
-        (* easy case *)
-        let _, subst, metasenv =
-          type_of_aux subst metasenv context
-            (C.Appl ((outtype :: right_args) @ [term]))
-        in
-        let (subst,metasenv) = 
-          List.fold_left
-            (fun (subst,metasenv) (constructor_args_no,context,instance,args) ->
-              let instance' = 
-                let appl =
-                  let outtype' =
-                    CicSubstitution.lift constructor_args_no outtype
-                  in
-                  C.Appl (outtype'::args)
-                in
-(*
-                (* if appl is not well typed then the type_of below solves the
-                 * problem *)
-                let (_, subst, metasenv) =
-                  type_of_aux subst metasenv context appl
-                in
-*)
-                CicMetaSubst.whd subst context appl
-              in
-               fo_unif_subst subst context metasenv instance instance')
-             (subst,metasenv) outtypeinstances in
-        CicMetaSubst.whd subst
-          context (C.Appl(outtype::right_args@[term])),subst,metasenv
-   | C.Fix (i,fl) ->
-      let subst,metasenv,types =
-       List.fold_left
-        (fun (subst,metasenv,types) (n,_,ty,_) ->
-          let _,subst',metasenv' = type_of_aux subst metasenv context ty in
-           subst',metasenv', Some (C.Name n,(C.Decl ty)) :: types
-        ) (subst,metasenv,[]) fl
-      in
-       let len = List.length types in
-       let context' = types@context in
-       let subst,metasenv =
-        List.fold_left
-         (fun (subst,metasenv) (name,x,ty,bo) ->
-           let ty_of_bo,subst,metasenv =
-            type_of_aux subst metasenv context' bo
-           in
-            fo_unif_subst subst context' metasenv
-              ty_of_bo (CicMetaSubst.lift subst len ty)
-         ) (subst,metasenv) fl in
-        let (_,_,ty,_) = List.nth fl i in
-         ty,subst,metasenv
-   | C.CoFix (i,fl) ->
-      let subst,metasenv,types =
-       List.fold_left
-        (fun (subst,metasenv,types) (n,ty,_) ->
-          let _,subst',metasenv' = type_of_aux subst metasenv context ty in
-           subst',metasenv', Some (C.Name n,(C.Decl ty)) :: types
-        ) (subst,metasenv,[]) fl
-      in
-       let len = List.length types in
-       let context' = types@context in
-       let subst,metasenv =
-        List.fold_left
-         (fun (subst,metasenv) (name,ty,bo) ->
-           let ty_of_bo,subst,metasenv =
-            type_of_aux subst metasenv context' bo
-           in
-            fo_unif_subst subst context' metasenv
-              ty_of_bo (CicMetaSubst.lift subst len ty)
-         ) (subst,metasenv) fl in
-      
-        let (_,ty,_) = List.nth fl i in
-         ty,subst,metasenv
-
- (* check_metasenv_consistency checks that the "canonical" context of a
- metavariable is consitent - up to relocation via the relocation list l -
- with the actual context *)
- and check_metasenv_consistency
-  metano subst metasenv context canonical_context l
- =
-   let module C = Cic in
-   let module R = CicReduction in
-   let module S = CicSubstitution in
-    let lifted_canonical_context = 
-     let rec aux i =
-      function
-         [] -> []
-       | (Some (n,C.Decl t))::tl ->
-          (Some (n,C.Decl (S.lift_meta l (S.lift i t))))::(aux (i+1) tl)
-       | (Some (n,C.Def (t,None)))::tl ->
-          (Some (n,C.Def ((S.lift_meta l (S.lift i t)),None)))::(aux (i+1) tl)
-       | None::tl -> None::(aux (i+1) tl)
-       | (Some (n,C.Def (t,Some ty)))::tl ->
-           (Some (n,
-            C.Def ((S.lift_meta l (S.lift i t)),
-              Some (S.lift_meta l (S.lift i ty))))) :: (aux (i+1) tl)
-     in
-      aux 1 canonical_context
-    in
-    try
-     List.fold_left2 
-      (fun (subst,metasenv) t ct -> 
-        match (t,ct) with
-           _,None ->
-             subst,metasenv
-         | Some t,Some (_,C.Def (ct,_)) ->
-            (try
-              fo_unif_subst subst context metasenv t ct
-             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)))))
-         | Some t,Some (_,C.Decl ct) ->
-            let inferredty,subst',metasenv' =
-             type_of_aux subst metasenv context t
-            in
-             (try
-               fo_unif_subst
-                subst' context metasenv' inferredty ct
-             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)))))
-         | None, Some _  ->
-             raise (RefineFailure (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)))
-      ) (subst,metasenv) l lifted_canonical_context 
-    with
-     Invalid_argument _ ->
-      raise
-       (RefineFailure
-         (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)))
-
- and check_exp_named_subst metasubst metasenv context =
-  let rec check_exp_named_subst_aux metasubst metasenv substs =
-   function
-      [] -> metasubst,metasenv
-    | ((uri,t) as subst)::tl ->
-       let typeofvar =
-        CicSubstitution.subst_vars substs (type_of_variable uri) in
-       (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")
-         | Cic.Variable (_,None,_,_) -> ()
-         | _ ->
-           raise
-            (RefineFailure
-             ("Unkown variable definition " ^ UriManager.string_of_uri uri))
-       ) ;
-       let typeoft,metasubst',metasenv' =
-        type_of_aux metasubst metasenv context t
-       in
-        try
-         let metasubst'',metasenv'' =
-          fo_unif_subst metasubst' context metasenv' typeoft typeofvar
-         in
-          check_exp_named_subst_aux metasubst'' metasenv'' (substs@[subst]) tl
-        with _ ->
-         raise (RefineFailure "Wrong Explicit Named Substitution")
-  in
-   check_exp_named_subst_aux metasubst metasenv []
-
- and sort_of_prod subst metasenv context (name,s) (t1, t2) =
-  let module C = Cic in
-    let context_for_t2 = (Some (name,C.Decl s))::context in
-    let t1'' = CicMetaSubst.whd subst context t1 in
-    let t2'' = CicMetaSubst.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!!! *)
-          C.Sort s2,subst,metasenv
-     | (C.Sort (C.Type t1), C.Sort (C.Type t2)) -> 
-       (* TASSI: CONSRTAINTS: the same in cictypechecker, doubletypeinference *)
-       let t' = CicUniv.fresh() in
-       if not (CicUniv.add_ge t' t1) || not (CicUniv.add_ge t' t2) then
-         assert false ; (* not possible, error in CicUniv *)
-       C.Sort (C.Type t'),subst,metasenv
-     | (C.Sort _,C.Sort (C.Type t1)) -> 
-       (* TASSI: CONSRTAINTS: the same in cictypechecker, doubletypeinference *)
-       C.Sort (C.Type t1),subst,metasenv
-     | (C.Meta _, C.Sort _) -> t2'',subst,metasenv
-     | (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 *)
-         let (metasenv,idx) =
-          CicMkImplicit.mk_implicit_sort metasenv in
-         let (subst, metasenv) =
-           fo_unif_subst subst context_for_t2 metasenv (C.Meta (idx,[])) t2''
-         in
-          t2'',subst,metasenv
-     | (_,_) ->
-         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'')))
-
- and eat_prods subst metasenv context hetype tlbody_and_type =
- let rec mk_prod metasenv context =
-  function
-     [] ->
-       let (metasenv, idx) = CicMkImplicit.mk_implicit_type metasenv context in
-       let irl =
-        CicMkImplicit.identity_relocation_list_for_metavariable context
-       in
-        metasenv,Cic.Meta (idx, irl)
-   | (_,argty)::tl ->
-      let (metasenv, idx) = CicMkImplicit.mk_implicit_type metasenv context in
-      let irl =
-       CicMkImplicit.identity_relocation_list_for_metavariable context
-      in
-       let meta = Cic.Meta (idx,irl) in
-       let name =
-        (* The name must be fresh for context.                 *)
-        (* Nevertheless, argty is well-typed only in context.  *)
-        (* Thus I generate a name (name_hint) in context and   *)
-        (* then I generate a name --- using the hint name_hint *)
-        (* --- that is fresh in (context'@context).            *)
-        let name_hint =
-         FreshNamesGenerator.mk_fresh_name
-          (CicMetaSubst.apply_subst_metasenv subst metasenv)
-          (CicMetaSubst.apply_subst_context subst context)
-          Cic.Anonymous
-          (CicMetaSubst.apply_subst subst argty)
-        in
-         (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
-         FreshNamesGenerator.mk_fresh_name
-          [] context name_hint (Cic.Sort Cic.Prop)
-       in
-       let metasenv,target =
-        mk_prod metasenv ((Some (name, Cic.Decl meta))::context) tl
-       in
-        metasenv,Cic.Prod (name,meta,target)
- in
-  let metasenv,hetype' = mk_prod metasenv context tlbody_and_type in
-  let (subst, metasenv) =
-   fo_unif_subst subst context metasenv hetype hetype'
-  in
-   let rec eat_prods metasenv subst context hetype =
-      function
-         [] -> metasenv,subst,hetype
-       | (hete, hety)::tl ->
-        (match hetype with
-            Cic.Prod (n,s,t) ->
-              let subst,metasenv =
-               fo_unif_subst subst context metasenv hety s
-              in
-               eat_prods metasenv subst context
-                (CicMetaSubst.subst subst hete t) tl
-          | _ -> assert false
-        )
-   in
-    let metasenv,subst,t =
-     eat_prods metasenv subst context hetype' tlbody_and_type
-    in
-     t,subst,metasenv
-(*
-  let rec aux context' args (resty,subst,metasenv) =
-   function
-      [] -> resty,subst,metasenv
-    | (arg,argty)::tl ->
-       let args' =
-        List.map
-         (function
-             None -> assert false
-           | Some t -> Some (CicMetaSubst.lift subst 1 t)
-         ) args in
-       let argty' = CicMetaSubst.lift subst (List.length args) argty in
-       let name =
-        (* The name must be fresh for (context'@context).      *)
-        (* Nevertheless, argty is well-typed only in context.  *)
-        (* Thus I generate a name (name_hint) in context and   *)
-        (* then I generate a name --- using the hint name_hint *)
-        (* --- that is fresh in (context'@context).            *)
-        let name_hint =
-         FreshNamesGenerator.mk_fresh_name
-          (CicMetaSubst.apply_subst_metasenv subst metasenv)
-          (CicMetaSubst.apply_subst_context subst context)
-          Cic.Anonymous
-          (CicMetaSubst.apply_subst subst argty)
-        in
-         (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
-         FreshNamesGenerator.mk_fresh_name
-          [] (context'@context) name_hint (Cic.Sort Cic.Prop)
-       in
-       let context'' = Some (name, Cic.Decl argty') :: context' in
-       let (metasenv, idx) =
-        CicMkImplicit.mk_implicit_type metasenv (context'' @ context) in
-       let irl =
-         (Some (Cic.Rel 1))::args' @
-          (CicMkImplicit.identity_relocation_list_for_metavariable ~start:2
-            context)
-       in
-       let newmeta = Cic.Meta (idx, irl) in
-       let prod = Cic.Prod (name, argty, newmeta) in
-       let (_, subst, metasenv) = type_of_aux subst metasenv context prod in
-       let (subst, metasenv) =
-         fo_unif_subst subst context metasenv resty prod
-       in
-        aux context'' (Some arg :: args)
-         (CicMetaSubst.subst subst arg newmeta, subst, metasenv) tl
-  in
-   aux [] [] (hetype,subst,metasenv) tlbody_and_type
-*)
- in
-  let ty,subst',metasenv' =
-   type_of_aux [] metasenv context t
-  in
-   let substituted_t = CicMetaSubst.apply_subst subst' t in
-   let substituted_ty = CicMetaSubst.apply_subst subst' ty in
-   let substituted_metasenv =
-    CicMetaSubst.apply_subst_metasenv subst' metasenv'
-   in
-    let cleaned_t =
-     FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
-    let cleaned_ty =
-     FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
-    let cleaned_metasenv =
-     List.map
-      (function (n,context,ty) ->
-        let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
-        let context' =
-         List.map
-          (function
-              None -> None
-            | Some (n, Cic.Decl t) ->
-               Some (n,
-                Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
-            | Some (n, Cic.Def (bo,ty)) ->
-               let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
-               let ty' =
-                match ty with
-                   None -> None
-                 | Some ty ->
-                    Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
-               in
-                Some (n, Cic.Def (bo',ty'))
-          ) context
-        in
-         (n,context',ty')
-      ) substituted_metasenv
-    in
-     (cleaned_t,cleaned_ty,cleaned_metasenv)
-
-;;
-
-(* DEBUGGING ONLY *)
-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 m s);
-*)
-   (t,ty,m)
- with
- | RefineFailure msg as e ->
-     debug_print ("@@@ REFINE FAILED: " ^ msg);
-     raise e
- | Uncertain msg as e ->
-     debug_print ("@@@ REFINE UNCERTAIN: " ^ msg);
-     raise e
-;;