]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/cic_unification/cicUnification.ml
First version of refine for MutCase, still largely incomplete.
[helm.git] / helm / ocaml / cic_unification / cicUnification.ml
index 2f27bea85adac6a996c5152d40d5b7635996d1c0..164a9cdce3bf88b9cb377eecd079bae24dcc04a3 100644 (file)
@@ -29,235 +29,320 @@ exception OccurCheck;;
 exception RelToHiddenHypothesis;;
 exception OpenTerm;;
 
-type substitution = (int * Cic.term) list
+(**** DELIFT ****)
 
-(* NUOVA UNIFICAZIONE *)
-(* A substitution is a (int * Cic.term) list that associates a
-   metavariable i with its body.
-   A metaenv is a (int * Cic.term) list that associate a metavariable
-   i with is type. 
-   fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
-   a new substitution which is _NOT_ unwinded. It must be unwinded before
-   applying it. *)
-let fo_unif_new metasenv context t1 t2 =
-    let module C = Cic in
-    let module R = CicReduction in
-    let module S = CicSubstitution in
-    let rec fo_unif_aux subst context metasenv t1 t2 =  
-    match (t1, t2) with
-         (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
-           let ok =
-            List.fold_left2
-             (fun b t1 t2 ->
-               b &&
-                match t1,t2 with
-                  None,_
-                | _,None -> true
-                | Some t1', Some t2' ->
-                   (* First possibility:  restriction    *)
-                   (* Second possibility: unification    *)
-                   (* Third possibility:  convertibility *)
-                  R.are_convertible context t1' t2'
-             ) true ln lm
-           in
-            if ok then subst,metasenv else
-             raise UnificationFailed
-       | (C.Meta (n,l), C.Meta (m,_)) when n>m ->
-          fo_unif_aux subst context metasenv t2 t1
-       | (C.Meta (n,l), t)   
-       | (t, C.Meta (n,l)) ->
-          let subst',metasenv' =
-            try
-              let oldt = (List.assoc n subst) in
-              let lifted_oldt = S.lift_meta l oldt in
-              fo_unif_aux subst context metasenv lifted_oldt t
-            with Not_found ->
-prerr_endline ("DELIFT2(" ^ CicPp.ppterm t ^ ")") ; flush stderr ;
-List.iter (function (Some t) -> prerr_endline ("l: " ^ CicPp.ppterm t) | None -> prerr_endline " _ ") l ; flush stderr ;
-prerr_endline "<DELIFT2" ; flush stderr ;
-              let t',metasenv' = S.delift context metasenv l t in
-              (n, t')::subst, metasenv'
-          in
-           let (_,_,meta_type) = 
-             List.find (function (m,_,_) -> m=n) metasenv' in
-           let tyt = CicTypeChecker.type_of_aux' metasenv' context t in
-            fo_unif_aux subst' context metasenv' (S.lift_meta l meta_type) tyt
-       | (C.Rel _, _)
-       | (_,  C.Rel _) 
-       | (C.Var _, _)
-       | (_, C.Var _) 
-       | (C.Sort _ ,_)
-       | (_, C.Sort _)
-       | (C.Implicit, _)
-       | (_, C.Implicit) -> 
-          if R.are_convertible context t1 t2 then subst, metasenv
-           else raise UnificationFailed
-       | (C.Cast (te,ty), t2) -> fo_unif_aux subst context metasenv te t2
-       | (t1, C.Cast (te,ty)) -> fo_unif_aux subst context metasenv t1 te
-       | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) -> 
-          let subst',metasenv' = fo_unif_aux subst context metasenv s1 s2 in
-           fo_unif_aux subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2
-       | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) -> 
-           let subst',metasenv' = fo_unif_aux subst context metasenv s1 s2 in
-           fo_unif_aux subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2
-       | (C.LetIn (_,s1,t1), t2)  
-       | (t2, C.LetIn (_,s1,t1)) -> 
-          fo_unif_aux subst context metasenv t2 (S.subst s1 t1)
-       | (C.Appl l1, C.Appl l2) -> 
-           let lr1 = List.rev l1 in
-           let lr2 = List.rev l2 in
-           let rec fo_unif_l subst metasenv = function
-               [],_
-             | _,[] -> assert false
-             | ([h1],[h2]) ->
-                 fo_unif_aux subst context metasenv h1 h2
-             | ([h],l) 
-             | (l,[h]) ->
-                 fo_unif_aux subst context metasenv h (C.Appl (List.rev l))
-             | ((h1::l1),(h2::l2)) -> 
-                let subst', metasenv' = 
-                  fo_unif_aux subst context metasenv h1 h2
-                 in 
-                 fo_unif_l subst' metasenv' (l1,l2)
-           in
-           fo_unif_l subst metasenv (lr1, lr2) 
-       | (C.Const _, _) 
-       | (_, C.Const _)
-       | (C.Abst _, _) 
-       | (_, C.Abst _) 
-       | (C.MutInd  _, _) 
-       | (_, C.MutInd _)
-       | (C.MutConstruct _, _)
-       | (_, C.MutConstruct _) -> 
-          if R.are_convertible context t1 t2 then subst, metasenv
-           else raise UnificationFailed
-       | (C.MutCase (_,_,_,outt1,t1,pl1), C.MutCase (_,_,_,outt2,t2,pl2))->
-         let subst', metasenv' = 
-          fo_unif_aux subst context metasenv outt1 outt2 in
-         let subst'',metasenv'' = 
-          fo_unif_aux subst' context metasenv' t1 t2 in
-         List.fold_left2 
-          (function (subst,metasenv) ->
-             fo_unif_aux subst context metasenv
-           ) (subst'',metasenv'') pl1 pl2 
-       | (C.Fix _, _)
-       | (_, C.Fix _) 
-       | (C.CoFix _, _)
-       | (_, C.CoFix _) -> 
-          if R.are_convertible context t1 t2 then subst, metasenv
-           else raise UnificationFailed
-       | (_,_) -> raise UnificationFailed
-   in fo_unif_aux [] context metasenv t1 t2;;
+(* the delift function takes in input an ordered list of optional terms       *)
+(* [t1,...,tn] and a term t, and substitutes every tk = Some (rel(nk)) with   *)
+(* rel(k). Typically, the list of optional terms is the explicit substitution *)
+(* that is applied to a metavariable occurrence and the result of the delift  *)
+(* function is a term the implicit variable can be substituted with to make   *)
+(* the term [t] unifiable with the metavariable occurrence.                   *)
+(* In general, the problem is undecidable if we consider equivalence in place *)
+(* of alpha convertibility. Our implementation, though, is even weaker than   *)
+(* alpha convertibility, since it replace the term [tk] if and only if [tk]   *)
+(* is a Rel (missing all the other cases). Does this matter in practice?      *)
 
-(*CSC: ???????????????
-(* m is the index of a metavariable to restrict, k is nesting depth
-of the occurrence m, and l is its relocation list. canonical_context
-is the context of the metavariable we are instantiating - containing
-m - Only rel in the domain of canonical_context are accessible.
-This function takes in input a metasenv and gives back a metasenv.
-A rel(j) in the canonical context of m, is rel(List.nth l j) for the 
-instance of m under consideration, that is rel (List.nth l j) - k 
-in canonical_context. *)
+exception NotInTheList;;
 
-let restrict canonical_context m k l =
-  let rec erase i = 
+let position n =
+  let rec aux k =
+   function 
+       [] -> raise NotInTheList
+     | (Some (Cic.Rel m))::_ when m=n -> k
+     | _::tl -> aux (k+1) tl in
+  aux 1
+;;
+(*CSC: this restriction function is utterly wrong, since it does not check  *)
+(*CSC: that the variable that is going to be restricted does not occur free *)
+(*CSC: in a part of the sequent that is not going to be restricted.         *)
+(*CSC: In particular, the whole approach is wrong; if restriction can fail  *)
+(*CSC: (as indeed it is the case), we can not collect all the restrictions  *)
+(*CSC: and restrict everything at the end ;-(                               *)
+let restrict to_be_restricted =
+  let rec erase i n = 
     function
-       [] -> []
-      |        None::tl -> None::(erase (i+1) tl)
-      |        he::tl -> 
-         let i' = (List.nth l (i-1)) in
-         if i' <= k 
-          then he::(erase (i+1) tl) (* local variable *) 
-          else 
-           let acc = 
-             (try List.nth canonical_context (i'-k-1)
-              with Failure _ -> None) in
-           if acc = None 
-            then None::(erase (i+1) tl)
-            else he::(erase (i+1) tl) in
+        [] -> []
+      |        _::tl when List.mem (n,i) to_be_restricted ->
+          None::(erase (i+1) n tl) 
+      | he::tl -> he::(erase (i+1) n tl) in
   let rec aux =
     function 
-       [] -> []
-      |        (n,context,t)::tl when n=m -> (n,erase 1 context,t)::tl
-      |        hd::tl -> hd::(aux tl)
-  in
-   aux
+        [] -> []
+      |        (n,context,t)::tl -> (n,erase 1 n context,t)::(aux tl) in
+  aux
 ;;
 
 
-let check_accessibility metasenv i =
-  let module C = Cic in
-  let module S = CicSubstitution in
-  let (_,canonical_context,_) = 
-    List.find (function (m,_,_) -> m=i) metasenv in
-   List.map
-    (function t ->
-      let =
-       S.delift canonical_context metasenv ? t
-    ) canonical_context
-CSCSCS
+(*CSC: maybe we should rename delift in abstract, as I did in my dissertation *)
+let delift context metasenv l t =
+ let module S = CicSubstitution in
+  let to_be_restricted = ref [] in
+  let rec deliftaux k =
+   let module C = Cic in
+    function
+       C.Rel m -> 
+         if m <=k then
+          C.Rel m   (*CSC: che succede se c'e' un Def? Dovrebbe averlo gia' *)
+                    (*CSC: deliftato la regola per il LetIn                 *)
+                    (*CSC: FALSO! La regola per il LetIn non lo fa          *)
+         else
+          (match List.nth context (m-k-1) with
+            Some (_,C.Def (t,_)) ->
+             (*CSC: Hmmm. This bit of reduction is not in the spirit of    *)
+             (*CSC: first order unification. Does it help or does it harm? *)
+             deliftaux k (S.lift m t)
+          | Some (_,C.Decl t) ->
+             (*CSC: The following check seems to be wrong!             *)
+             (*CSC: B:Set |- ?2 : Set                                  *)
+             (*CSC: A:Set ; x:?2[A/B] |- ?1[x/A] =?= x                 *)
+             (*CSC: Why should I restrict ?2 over B? The instantiation *)
+             (*CSC: ?1 := A is perfectly reasonable and well-typed.    *)
+             (*CSC: Thus I comment out the following two lines that    *)
+             (*CSC: are the incriminated ones.                         *)
+             (*(* It may augment to_be_restricted *)
+               ignore (deliftaux k (S.lift m t)) ;*)
+             (*CSC: end of bug commented out                           *)
+             C.Rel ((position (m-k) l) + k)
+          | None -> raise RelToHiddenHypothesis)
+     | C.Var (uri,exp_named_subst) ->
+        let exp_named_subst' =
+         List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
+        in
+         C.Var (uri,exp_named_subst')
+     | C.Meta (i, l1) as t -> 
+        let rec deliftl j =
+         function
+            [] -> []
+          | None::tl -> None::(deliftl (j+1) tl)
+          | (Some t)::tl ->
+             let l1' = (deliftl (j+1) tl) in
+              try
+               Some (deliftaux k t)::l1'
+              with
+                 RelToHiddenHypothesis
+               | NotInTheList ->
+                  to_be_restricted := (i,j)::!to_be_restricted ; None::l1'
+        in
+         let l' = deliftl 1 l1 in
+          C.Meta(i,l')
+     | C.Sort _ as t -> t
+     | C.Implicit as t -> t
+     | C.Cast (te,ty) -> C.Cast (deliftaux k te, deliftaux k ty)
+     | C.Prod (n,s,t) -> C.Prod (n, deliftaux k s, deliftaux (k+1) t)
+     | C.Lambda (n,s,t) -> C.Lambda (n, deliftaux k s, deliftaux (k+1) t)
+     | C.LetIn (n,s,t) -> C.LetIn (n, deliftaux k s, deliftaux (k+1) t)
+     | C.Appl l -> C.Appl (List.map (deliftaux k) l)
+     | C.Const (uri,exp_named_subst) ->
+        let exp_named_subst' =
+         List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
+        in
+         C.Const (uri,exp_named_subst')
+     | C.MutInd (uri,typeno,exp_named_subst) ->
+        let exp_named_subst' =
+         List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
+        in
+         C.MutInd (uri,typeno,exp_named_subst')
+     | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
+        let exp_named_subst' =
+         List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
+        in
+         C.MutConstruct (uri,typeno,consno,exp_named_subst')
+     | C.MutCase (sp,i,outty,t,pl) ->
+        C.MutCase (sp, i, deliftaux k outty, deliftaux k t,
+         List.map (deliftaux k) pl)
+     | C.Fix (i, fl) ->
+        let len = List.length fl in
+        let liftedfl =
+         List.map
+          (fun (name, i, ty, bo) ->
+           (name, i, deliftaux k ty, deliftaux (k+len) bo))
+           fl
+        in
+         C.Fix (i, liftedfl)
+     | C.CoFix (i, fl) ->
+        let len = List.length fl in
+        let liftedfl =
+         List.map
+          (fun (name, ty, bo) -> (name, deliftaux k ty, deliftaux (k+len) bo))
+           fl
+        in
+         C.CoFix (i, liftedfl)
+  in
+   let res =
+    try
+     deliftaux 0 t
+    with
+     NotInTheList ->
+      (* This is the case where we fail even first order unification. *)
+      (* The reason is that our delift function is weaker than first  *)
+      (* order (in the sense of alpha-conversion). See comment above  *)
+      (* related to the delift function.                              *)
+prerr_endline "!!!!!!!!!!! First Order UnificationFailed, but maybe it could have been successful even in a first order setting (no conversion, only alpha convertibility)! Please, implement a better delift function !!!!!!!!!!!!!!!!" ;
+      raise UnificationFailed
+   in
+    res, restrict !to_be_restricted metasenv
+;;
 
+(**** END OF DELIFT ****)
 
+type substitution = (int * Cic.term) list
 
-  let rec aux metasenv k =
-    function
-      C.Rel i -> 
-       if i <= k then
-        metasenv
-       else 
-        (try
-          match List.nth canonical_context (i-k-1) with
-            Some (_,C.Decl t) 
-          | Some (_,C.Def t) -> aux metasenv k (S.lift i t)
-          | None -> raise RelToHiddenHypothesis
-          with
-           Failure _ -> raise OpenTerm
-        )
-    | C.Var _  -> metasenv
-    | C.Meta (i,l) -> restrict canonical_context i k l metasenv 
-    | C.Sort _ -> metasenv
-    | C.Implicit -> metasenv
-    | C.Cast (te,ty) -> 
-       let metasenv' = aux metasenv k te in
-       aux metasenv' k ty
-    | C.Prod (_,s,t) 
-    | C.Lambda (_,s,t) 
-    | C.LetIn (_,s,t) ->
-       let metasenv' = aux metasenv k s in
-       aux metasenv' (k+1) t
-    | C.Appl l ->
-       List.fold_left
-         (function metasenv -> aux metasenv k) metasenv l
-    | C.Const _
-    | C.Abst _
-    | C.MutInd _ 
-    | C.MutConstruct _ -> metasenv
-    | C.MutCase (_,_,_,outty,t,pl) ->
-       let metasenv' = aux metasenv k outty in
-       let metasenv'' = aux metasenv' k t in
-       List.fold_left
-         (function metasenv -> aux metasenv k) metasenv'' pl
-    | C.Fix (i, fl) ->
-       let len = List.length fl in
-       List.fold_left
-         (fun metasenv f ->
-          let (_,_,ty,bo) = f in
-          let metasenv' = aux metasenv k ty in
-          aux metasenv' (k+len) bo
-         ) metasenv fl
-    | C.CoFix (i, fl) ->
-       let len = List.length fl in
-        List.fold_left
-         (fun metasenv f ->
-          let (_,ty,bo) = f in
-          let metasenv' = aux metasenv k ty in
-          aux metasenv' (k+len) bo
-         ) metasenv fl
-  in aux metasenv 0
-;;
-*)
+(* NUOVA UNIFICAZIONE *)
+(* A substitution is a (int * Cic.term) list that associates a
+   metavariable i with its body.
+   A metaenv is a (int * Cic.term) list that associate a metavariable
+   i with is type. 
+   fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
+   a new substitution which is _NOT_ unwinded. It must be unwinded before
+   applying it. *)
+let rec fo_unif_subst subst context metasenv t1 t2 =  
+ let module C = Cic in
+ let module R = CicReduction in
+ let module S = CicSubstitution in
+  match (t1, t2) with
+     (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
+       let ok =
+        List.fold_left2
+         (fun b t1 t2 ->
+           b &&
+            match t1,t2 with
+               None,_
+             | _,None -> true
+             | Some t1', Some t2' ->
+                (* First possibility:  restriction    *)
+                (* Second possibility: unification    *)
+                (* Third possibility:  convertibility *)
+                R.are_convertible context t1' t2'
+         ) true ln lm
+       in
+        if ok then subst,metasenv else raise UnificationFailed
+   | (C.Meta (n,l), C.Meta (m,_)) when n>m ->
+       fo_unif_subst subst context metasenv t2 t1
+   | (C.Meta (n,l), t)   
+   | (t, C.Meta (n,l)) ->
+       let subst',metasenv' =
+        try
+         let oldt = (List.assoc n subst) in
+         let lifted_oldt = S.lift_meta l oldt in
+          fo_unif_subst subst context metasenv lifted_oldt t
+        with Not_found ->
+         let t',metasenv' = delift context metasenv l t in
+          (n, t')::subst, metasenv'
+       in
+        let (_,_,meta_type) = 
+         List.find (function (m,_,_) -> m=n) metasenv' in
+        let tyt = CicTypeChecker.type_of_aux' metasenv' context t in
+         fo_unif_subst subst' context metasenv' (S.lift_meta l meta_type) tyt
+   | (C.Var (uri1,exp_named_subst1),C.Var (uri2,exp_named_subst2))
+   | (C.Const (uri1,exp_named_subst1),C.Const (uri2,exp_named_subst2)) ->
+      if UriManager.eq uri1 uri2 then
+       fo_unif_subst_exp_named_subst subst context metasenv
+        exp_named_subst1 exp_named_subst2
+      else
+       raise UnificationFailed
+   | C.MutInd (uri1,i1,exp_named_subst1),C.MutInd (uri2,i2,exp_named_subst2) ->
+      if UriManager.eq uri1 uri2 && i1 = i2 then
+       fo_unif_subst_exp_named_subst subst context metasenv
+        exp_named_subst1 exp_named_subst2
+      else
+       raise UnificationFailed
+   | C.MutConstruct (uri1,i1,j1,exp_named_subst1),
+     C.MutConstruct (uri2,i2,j2,exp_named_subst2) ->
+      if UriManager.eq uri1 uri2 && i1 = i2 && j1 = j2 then
+       fo_unif_subst_exp_named_subst subst context metasenv
+        exp_named_subst1 exp_named_subst2
+      else
+       raise UnificationFailed
+   | (C.Rel _, _)
+   | (_,  C.Rel _) 
+   | (C.Sort _ ,_)
+   | (_, C.Sort _)
+   | (C.Implicit, _)
+   | (_, C.Implicit) -> 
+       if R.are_convertible context t1 t2 then
+        subst, metasenv
+       else
+        raise UnificationFailed
+   | (C.Cast (te,ty), t2) -> fo_unif_subst subst context metasenv te t2
+   | (t1, C.Cast (te,ty)) -> fo_unif_subst subst context metasenv t1 te
+   | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) -> 
+       let subst',metasenv' = fo_unif_subst subst context metasenv s1 s2 in
+        fo_unif_subst subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2
+   | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) -> 
+       let subst',metasenv' = fo_unif_subst subst context metasenv s1 s2 in
+        fo_unif_subst subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2
+   | (C.LetIn (_,s1,t1), t2)  
+   | (t2, C.LetIn (_,s1,t1)) -> 
+       fo_unif_subst subst context metasenv t2 (S.subst s1 t1)
+   | (C.Appl l1, C.Appl l2) -> 
+       let lr1 = List.rev l1 in
+       let lr2 = List.rev l2 in
+       let rec fo_unif_l subst metasenv =
+        function
+           [],_
+         | _,[] -> assert false
+         | ([h1],[h2]) ->
+             fo_unif_subst subst context metasenv h1 h2
+         | ([h],l) 
+         | (l,[h]) ->
+             fo_unif_subst subst context metasenv h (C.Appl (List.rev l))
+         | ((h1::l1),(h2::l2)) -> 
+            let subst', metasenv' = 
+             fo_unif_subst subst context metasenv h1 h2
+            in 
+             fo_unif_l subst' metasenv' (l1,l2)
+       in
+        fo_unif_l subst metasenv (lr1, lr2) 
+   | (C.Const _, _) 
+   | (_, C.Const _)
+   | (C.MutInd  _, _) 
+   | (_, C.MutInd _)
+   | (C.MutConstruct _, _)
+   | (_, C.MutConstruct _) -> 
+      if R.are_convertible context t1 t2 then
+       subst, metasenv
+      else
+       raise UnificationFailed
+   | (C.MutCase (_,_,outt1,t1,pl1), C.MutCase (_,_,outt2,t2,pl2))->
+       let subst', metasenv' = 
+        fo_unif_subst subst context metasenv outt1 outt2 in
+       let subst'',metasenv'' = 
+        fo_unif_subst subst' context metasenv' t1 t2 in
+       List.fold_left2 
+        (function (subst,metasenv) ->
+          fo_unif_subst subst context metasenv
+        ) (subst'',metasenv'') pl1 pl2 
+   | (C.Fix _, _)
+   | (_, C.Fix _) 
+   | (C.CoFix _, _)
+   | (_, C.CoFix _) -> 
+       if R.are_convertible context t1 t2 then
+        subst, metasenv
+       else
+        raise UnificationFailed
+   | (_,_) ->
+       if R.are_convertible context t1 t2 then
+        subst, metasenv
+       else
+        raise UnificationFailed
 
+and fo_unif_subst_exp_named_subst subst context metasenv
+ exp_named_subst1 exp_named_subst2
+=
+try
+ List.fold_left2
+  (fun (subst,metasenv) (uri1,t1) (uri2,t2) ->
+    assert (uri1=uri2) ;
+    fo_unif_subst subst context metasenv t1 t2
+  ) (subst,metasenv) exp_named_subst1 exp_named_subst2
+with
+e ->
+let uri = UriManager.uri_of_string "cic:/dummy.var" in
+prerr_endline ("@@@: " ^ CicPp.ppterm (Cic.Var (uri,exp_named_subst1)) ^
+" <==> " ^ CicPp.ppterm (Cic.Var (uri,exp_named_subst2))) ; raise e
+;;
 
 let unwind metasenv subst unwinded t =
  let unwinded = ref unwinded in
@@ -269,25 +354,22 @@ let unwind metasenv subst unwinded t =
       C.Rel _ as t -> t,metasenv
     | C.Var _  as t -> t,metasenv
     | C.Meta (i,l) -> 
-       (try
+        (try
           S.lift_meta l (List.assoc i !unwinded), metasenv
          with Not_found ->
            if List.mem i !frozen then raise OccurCheck
            else
             let saved_frozen = !frozen in 
-           frozen := i::!frozen ;
+            frozen := i::!frozen ;
             let res =
              try
-             let t = List.assoc i subst in
+              let t = List.assoc i subst in
               let t',metasenv' = um_aux metasenv t in
-             let _,metasenv'' =
+              let _,metasenv'' =
                let (_,canonical_context,_) = 
                 List.find (function (m,_,_) -> m=i) metasenv
                in
-prerr_endline ("DELIFT(" ^ CicPp.ppterm t' ^ ")") ; flush stderr ;
-List.iter (function (Some t) -> prerr_endline ("l: " ^ CicPp.ppterm t) | None -> prerr_endline " _ ") l ; flush stderr ;
-prerr_endline "<DELIFT" ; flush stderr ;
-                S.delift canonical_context metasenv' l t'
+                delift canonical_context metasenv' l t'
               in
                unwinded := (i,t')::!unwinded ;
                S.lift_meta l t', metasenv'
@@ -296,13 +378,13 @@ prerr_endline "<DELIFT" ; flush stderr ;
                (* not constrained variable, i.e. free in subst*)
                let l',metasenv' =
                 List.fold_right
-                (fun t (tl,metasenv) ->
+                 (fun t (tl,metasenv) ->
                    match t with
                       None -> None::tl,metasenv
                     | Some t -> 
-                      let t',metasenv' = um_aux metasenv t in
-                       (Some t')::tl, metasenv'
-                ) l ([],metasenv)
+                       let t',metasenv' = um_aux metasenv t in
+                        (Some t')::tl, metasenv'
+                 ) l ([],metasenv)
                in
                 C.Meta (i,l'), metasenv'
             in
@@ -330,10 +412,10 @@ prerr_endline "<DELIFT" ; flush stderr ;
     | C.Appl (he::tl) ->
        let tl',metasenv' =
         List.fold_right
-        (fun t (tl,metasenv) ->
-          let t',metasenv' = um_aux metasenv t in
-           t'::tl, metasenv'
-        ) tl ([],metasenv)
+         (fun t (tl,metasenv) ->
+           let t',metasenv' = um_aux metasenv t in
+            t'::tl, metasenv'
+         ) tl ([],metasenv)
        in
         begin
          match um_aux metasenv' he with
@@ -341,30 +423,53 @@ prerr_endline "<DELIFT" ; flush stderr ;
           | (he', metasenv'') -> C.Appl (he'::tl'),metasenv''
         end
     | C.Appl _ -> assert false
-    | C.Const _
-    | C.Abst _
-    | C.MutInd _
-    | C.MutConstruct _ as t -> t,metasenv
-    | C.MutCase (sp,cookingsno,i,outty,t,pl) ->
+    | C.Const (uri,exp_named_subst) ->
+       let exp_named_subst', metasenv' =
+        List.fold_right
+         (fun (uri,t) (tl,metasenv) ->
+           let t',metasenv' = um_aux metasenv t in
+            (uri,t')::tl, metasenv'
+         ) exp_named_subst ([],metasenv)
+       in
+        C.Const (uri,exp_named_subst'),metasenv'
+    | C.MutInd (uri,typeno,exp_named_subst) ->
+       let exp_named_subst', metasenv' =
+        List.fold_right
+         (fun (uri,t) (tl,metasenv) ->
+           let t',metasenv' = um_aux metasenv t in
+            (uri,t')::tl, metasenv'
+         ) exp_named_subst ([],metasenv)
+       in
+        C.MutInd (uri,typeno,exp_named_subst'),metasenv'
+    | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
+       let exp_named_subst', metasenv' =
+        List.fold_right
+         (fun (uri,t) (tl,metasenv) ->
+           let t',metasenv' = um_aux metasenv t in
+            (uri,t')::tl, metasenv'
+         ) exp_named_subst ([],metasenv)
+       in
+        C.MutConstruct (uri,typeno,consno,exp_named_subst'),metasenv'
+    | C.MutCase (sp,i,outty,t,pl) ->
        let outty',metasenv' = um_aux metasenv outty in
        let t',metasenv'' = um_aux metasenv' t in
        let pl',metasenv''' =
         List.fold_right
-        (fun p (pl,metasenv) ->
-          let p',metasenv' = um_aux metasenv p in
-           p'::pl, metasenv'
-        ) pl ([],metasenv'')
+         (fun p (pl,metasenv) ->
+           let p',metasenv' = um_aux metasenv p in
+            p'::pl, metasenv'
+         ) pl ([],metasenv'')
        in
-        C.MutCase (sp, cookingsno, i, outty', t', pl'),metasenv'''
+        C.MutCase (sp, i, outty', t', pl'),metasenv'''
     | C.Fix (i, fl) ->
        let len = List.length fl in
        let liftedfl,metasenv' =
         List.fold_right
          (fun (name, i, ty, bo) (fl,metasenv) ->
-          let ty',metasenv' = um_aux metasenv ty in
-          let bo',metasenv'' = um_aux metasenv' bo in
-           (name, i, ty', bo')::fl,metasenv''
-        ) fl ([],metasenv)
+           let ty',metasenv' = um_aux metasenv ty in
+           let bo',metasenv'' = um_aux metasenv' bo in
+            (name, i, ty', bo')::fl,metasenv''
+         ) fl ([],metasenv)
        in
         C.Fix (i, liftedfl),metasenv'
     | C.CoFix (i, fl) ->
@@ -372,10 +477,10 @@ prerr_endline "<DELIFT" ; flush stderr ;
        let liftedfl,metasenv' =
         List.fold_right
          (fun (name, ty, bo) (fl,metasenv) ->
-          let ty',metasenv' = um_aux metasenv ty in
-          let bo',metasenv'' = um_aux metasenv' bo in
-           (name, ty', bo')::fl,metasenv''
-        ) fl ([],metasenv)
+           let ty',metasenv' = um_aux metasenv ty in
+           let bo',metasenv'' = um_aux metasenv' bo in
+            (name, ty', bo')::fl,metasenv''
+         ) fl ([],metasenv)
        in
         C.CoFix (i, liftedfl),metasenv'
  in
@@ -394,6 +499,7 @@ prerr_endline "<DELIFT" ; flush stderr ;
 (*  during the unwinding the eta-expansions are undone.                 *)
 
 let apply_subst_reducing subst meta_to_reduce t =
+ (* andrea: che senso ha questo ref ?? *)
  let unwinded = ref subst in
  let rec um_aux =
   let module C = Cic in
@@ -436,12 +542,23 @@ let apply_subst_reducing subst meta_to_reduce t =
            | _,_ -> t'
          end
     | C.Appl _ -> assert false
-    | C.Const _ as t -> t
-    | C.Abst _  as t -> t
-    | C.MutInd _ as t -> t
-    | C.MutConstruct _ as t -> t
-    | C.MutCase (sp,cookingsno,i,outty,t,pl) ->
-       C.MutCase (sp, cookingsno, i, um_aux outty, um_aux t,
+    | C.Const (uri,exp_named_subst) ->
+       let exp_named_subst' =
+        List.map (function (uri,t) -> (uri,um_aux t)) exp_named_subst
+       in
+        C.Const (uri,exp_named_subst')
+    | C.MutInd (uri,typeno,exp_named_subst) ->
+       let exp_named_subst' =
+        List.map (function (uri,t) -> (uri,um_aux t)) exp_named_subst
+       in
+        C.MutInd (uri,typeno,exp_named_subst')
+    | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
+       let exp_named_subst' =
+        List.map (function (uri,t) -> (uri,um_aux t)) exp_named_subst
+       in
+        C.MutConstruct (uri,typeno,consno,exp_named_subst')
+    | C.MutCase (sp,i,outty,t,pl) ->
+       C.MutCase (sp, i, um_aux outty, um_aux t,
         List.map um_aux pl)
     | C.Fix (i, fl) ->
        let len = List.length fl in
@@ -504,11 +621,6 @@ let apply_subst subst t =
 (* a new metasenv in which some hypothesis in the contexts of the            *)
 (* metavariables may have been restricted.                                   *)
 let fo_unif metasenv context t1 t2 =
-prerr_endline "INIZIO FASE 1" ; flush stderr ;
- let subst_to_unwind,metasenv' = fo_unif_new metasenv context t1 t2 in
-prerr_endline "FINE FASE 1" ; flush stderr ;
-let res =
+ let subst_to_unwind,metasenv' = fo_unif_subst [] context metasenv t1 t2 in
   unwind_subst metasenv' subst_to_unwind
-in
-prerr_endline "FINE FASE 2" ; flush stderr ; res
 ;;