]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/gTopLevel/cic2acic.ml
Initial revision
[helm.git] / helm / gTopLevel / cic2acic.ml
index ec9dc680e376c0a3ae0ddbf888775d6ad208501b..f08bb877a1029eac2d5ee939245e76d431a329e0 100644 (file)
 
 exception NotImplemented;;
 
+type anntypes =
+ {annsynthesized : Cic.annterm ; annexpected : Cic.annterm option}
+;;
+
 let fresh_id seed ids_to_terms ids_to_father_ids =
  fun father t ->
   let res = "i" ^ string_of_int !seed in
@@ -47,241 +51,268 @@ let rec get_nth l n =
   | (_,_) -> raise NotEnoughElements
 ;;
 
-let acic_of_cic_env' seed ids_to_terms ids_to_father_ids ids_to_inner_sorts
-     ids_to_inner_types metasenv env t
+let acic_of_cic_context' seed ids_to_terms ids_to_father_ids ids_to_inner_sorts
+     ids_to_inner_types metasenv context t expectedty
 =
+ let module D = DoubleTypeInference in
  let module T = CicTypeChecker in
  let module C = Cic in
   let fresh_id' = fresh_id seed ids_to_terms ids_to_father_ids in
-   let rec aux computeinnertypes father bs tt =
-    let fresh_id'' = fresh_id' father tt in
-    let aux' = aux true (Some fresh_id'') in
-     (* First of all we compute the inner type and the inner sort *)
-     (* of the term. They may be useful in what follows.          *)
-     (*CSC: This is a very inefficient way of computing inner types *)
-     (*CSC: and inner sorts: very deep terms have their types/sorts *)
-     (*CSC: computed again and again.                               *)
-     let string_of_sort =
-      function 
-         C.Sort C.Prop -> "Prop"
-       | C.Sort C.Set  -> "Set"
-       | C.Sort C.Type -> "Type"
-       | _ -> assert false
-     in
-      let ainnertype,innertype,innersort =
-       let cicenv = List.map (function (_,ty) -> ty) bs in
-        let innertype = T.type_of_aux' metasenv cicenv tt in
-         let innersort = T.type_of_aux' metasenv cicenv innertype in
-          let ainnertype =
+   let terms_to_types =
+    D.double_type_of metasenv context t expectedty
+   in
+    let rec aux computeinnertypes father context tt =
+     let fresh_id'' = fresh_id' father tt in
+     (*CSC: computeinnertypes era true, il che e' proprio sbagliato, no? *)
+     let aux' = aux computeinnertypes (Some fresh_id'') in
+      (* First of all we compute the inner type and the inner sort *)
+      (* of the term. They may be useful in what follows.          *)
+      (*CSC: This is a very inefficient way of computing inner types *)
+      (*CSC: and inner sorts: very deep terms have their types/sorts *)
+      (*CSC: computed again and again.                               *)
+      let string_of_sort t =
+       match CicReduction.whd context t with 
+          C.Sort C.Prop -> "Prop"
+        | C.Sort C.Set  -> "Set"
+        | C.Sort C.Type -> "Type"
+        | _ -> assert false
+      in
+       let ainnertypes,innertype,innersort,expected_available =
+(*CSC: Here we need the algorithm for Coscoy's double type-inference  *)
+(*CSC: (expected type + inferred type). Just for now we use the usual *)
+(*CSC: type-inference, but the result is very poor. As a very weak    *)
+(*CSC: patch, I apply whd to the computed type. Full beta             *)
+(*CSC: reduction would be a much better option.                       *)
+        let {D.synthesized = synthesized; D.expected = expected} =
+         if computeinnertypes then
+          D.CicHash.find terms_to_types tt
+         else
+          (* We are already in an inner-type and Coscoy's double *)
+          (* type inference algorithm has not been applied.      *)
+          {D.synthesized =
+            CicReduction.whd context (T.type_of_aux' metasenv context tt) ;
+           D.expected = None}
+        in
+         let innersort = T.type_of_aux' metasenv context synthesized in
+          let ainnertypes,expected_available =
            if computeinnertypes then
-            Some (aux false (Some fresh_id'') bs innertype)
+            let annexpected,expected_available =
+               match expected with
+                  None -> None,false
+                | Some expectedty' ->
+                   Some (aux false (Some fresh_id'') context expectedty'),true
+            in
+             Some
+              {annsynthesized =
+                aux false (Some fresh_id'') context synthesized ;
+               annexpected = annexpected
+              }, expected_available
            else
-            None
+            None,false
           in
-           ainnertype, innertype, string_of_sort innersort
-      in
-      let add_inner_type id =
-       match ainnertype with
-          None -> ()
-        | Some ainnertype -> Hashtbl.add ids_to_inner_types id ainnertype
-      in
-       match tt with
-          C.Rel n ->
-           let id =
-            match get_nth bs n with
-               (C.Name s,_) -> s
-             | _ -> raise NameExpected
-           in
-            Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-            C.ARel (fresh_id'', n, id)
-        | C.Var uri ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           C.AVar (fresh_id'', uri)
-        | C.Meta n ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           C.AMeta (fresh_id'', n)
-        | C.Sort s -> C.ASort (fresh_id'', s)
-        | C.Implicit -> C.AImplicit (fresh_id'')
-        | C.Cast (v,t) ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           if innersort = "Prop" then
-            add_inner_type fresh_id'' ;
-           C.ACast (fresh_id'', aux' bs v, aux' bs t)
-        | C.Prod (n,s,t) ->
-            Hashtbl.add ids_to_inner_sorts fresh_id''
-             (string_of_sort innertype) ;
-            C.AProd (fresh_id'', n, aux' bs s, aux' ((n, C.Decl s)::bs) t)
-        | C.Lambda (n,s,t) ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           if innersort = "Prop" then
-            begin
-             let father_is_lambda =
-              match father with
-                 None -> false
-               | Some father' ->
-                  match Hashtbl.find ids_to_terms father' with
-                     C.Lambda _ -> true
-                   | _ -> false
+           ainnertypes,synthesized, string_of_sort innersort, expected_available
+       in
+        let add_inner_type id =
+         match ainnertypes with
+            None -> ()
+          | Some ainnertypes -> Hashtbl.add ids_to_inner_types id ainnertypes
+        in
+         match tt with
+            C.Rel n ->
+             let id =
+              match get_nth context n with
+                 (Some (C.Name s,_)) -> s
+               | _ -> raise NameExpected
              in
-              if not father_is_lambda then
-               add_inner_type fresh_id''
-            end ;
-           C.ALambda (fresh_id'',n, aux' bs s, aux' ((n, C.Decl s)::bs) t)
-        | C.LetIn (n,s,t) ->
-          Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-          C.ALetIn (fresh_id'', n, aux' bs s, aux' ((n, C.Def s)::bs) t)
-        | C.Appl l ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           if innersort = "Prop" then
-            add_inner_type fresh_id'' ;
-           C.AAppl (fresh_id'', List.map (aux' bs) l)
-        | C.Const (uri,cn) ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           C.AConst (fresh_id'', uri, cn)
-        | C.Abst _ -> raise NotImplemented
-        | C.MutInd (uri,cn,tyno) -> C.AMutInd (fresh_id'', uri, cn, tyno)
-        | C.MutConstruct (uri,cn,tyno,consno) ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           C.AMutConstruct (fresh_id'', uri, cn, tyno, consno)
-        | C.MutCase (uri, cn, tyno, outty, term, patterns) ->
-           Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-           if innersort = "Prop" then
-            add_inner_type fresh_id'' ;
-           C.AMutCase (fresh_id'', uri, cn, tyno, aux' bs outty,
-            aux' bs term, List.map (aux' bs) patterns)
-        | C.Fix (funno, funs) ->
-           let names =
-            List.map (fun (name,_,ty,_) -> C.Name name, C.Decl ty) funs
-           in
-            Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-            if innersort = "Prop" then
-             add_inner_type fresh_id'' ;
-            C.AFix (fresh_id'', funno,
-             List.map
-              (fun (name, indidx, ty, bo) ->
-                (name, indidx, aux' bs ty, aux' (names@bs) bo)
-              ) funs
-           )
-        | C.CoFix (funno, funs) ->
-           let names =
-            List.map (fun (name,ty,_) -> C.Name name, C.Decl ty) funs in
-            Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
-            if innersort = "Prop" then
-             add_inner_type fresh_id'' ;
-            C.ACoFix (fresh_id'', funno,
-             List.map
-              (fun (name, ty, bo) ->
-                (name, aux' bs ty, aux' (names@bs) bo)
-              ) funs
-            )
-      in
-       aux true None env t
+              Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+              if innersort = "Prop"  && expected_available then
+               add_inner_type fresh_id'' ;
+              C.ARel (fresh_id'', n, id)
+          | C.Var uri ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop"  && expected_available then
+              add_inner_type fresh_id'' ;
+             C.AVar (fresh_id'', uri)
+          | C.Meta (n,l) ->
+             let (_,canonical_context,_) =
+              List.find (function (m,_,_) -> n = m) metasenv
+             in
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop"  && expected_available then
+              add_inner_type fresh_id'' ;
+             C.AMeta (fresh_id'', n,
+              (List.map2
+                (fun ct t ->
+                  match (ct, t) with
+                  | None, _ -> None
+                  | _, Some t -> Some (aux' context t)
+                  | Some _, None -> assert false (* due to typing rules *))
+                canonical_context l))
+          | C.Sort s -> C.ASort (fresh_id'', s)
+          | C.Implicit -> C.AImplicit (fresh_id'')
+          | C.Cast (v,t) ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop" then
+              add_inner_type fresh_id'' ;
+             C.ACast (fresh_id'', aux' context v, aux' context t)
+          | C.Prod (n,s,t) ->
+              Hashtbl.add ids_to_inner_sorts fresh_id''
+               (string_of_sort innertype) ;
+              C.AProd
+               (fresh_id'', n, aux' context s,
+                aux' ((Some (n, C.Decl s))::context) t)
+          | C.Lambda (n,s,t) ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop" then
+              begin
+               let father_is_lambda =
+                match father with
+                   None -> false
+                 | Some father' ->
+                    match Hashtbl.find ids_to_terms father' with
+                       C.Lambda _ -> true
+                     | _ -> false
+               in
+                if (not father_is_lambda) || expected_available then
+                 add_inner_type fresh_id''
+              end ;
+             C.ALambda
+              (fresh_id'',n, aux' context s,
+               aux' ((Some (n, C.Decl s)::context)) t)
+          | C.LetIn (n,s,t) ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop" then
+              add_inner_type fresh_id'' ;
+             C.ALetIn
+              (fresh_id'', n, aux' context s,
+               aux' ((Some (n, C.Def s))::context) t)
+          | C.Appl l ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop" then
+              add_inner_type fresh_id'' ;
+             C.AAppl (fresh_id'', List.map (aux' context) l)
+          | C.Const (uri,cn) ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop"  && expected_available then
+              add_inner_type fresh_id'' ;
+             C.AConst (fresh_id'', uri, cn)
+          | C.MutInd (uri,cn,tyno) -> C.AMutInd (fresh_id'', uri, cn, tyno)
+          | C.MutConstruct (uri,cn,tyno,consno) ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop"  && expected_available then
+              add_inner_type fresh_id'' ;
+             C.AMutConstruct (fresh_id'', uri, cn, tyno, consno)
+          | C.MutCase (uri, cn, tyno, outty, term, patterns) ->
+             Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+             if innersort = "Prop" then
+              add_inner_type fresh_id'' ;
+             C.AMutCase (fresh_id'', uri, cn, tyno, aux' context outty,
+              aux' context term, List.map (aux' context) patterns)
+          | C.Fix (funno, funs) ->
+             let tys =
+              List.map (fun (name,_,ty,_) -> Some (C.Name name, C.Decl ty)) funs
+             in
+              Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+              if innersort = "Prop" then
+               add_inner_type fresh_id'' ;
+              C.AFix (fresh_id'', funno,
+               List.map
+                (fun (name, indidx, ty, bo) ->
+                  (name, indidx, aux' context ty, aux' (tys@context) bo)
+                ) funs
+             )
+          | C.CoFix (funno, funs) ->
+             let tys =
+              List.map (fun (name,ty,_) -> Some (C.Name name, C.Decl ty)) funs
+             in
+              Hashtbl.add ids_to_inner_sorts fresh_id'' innersort ;
+              if innersort = "Prop" then
+               add_inner_type fresh_id'' ;
+              C.ACoFix (fresh_id'', funno,
+               List.map
+                (fun (name, ty, bo) ->
+                  (name, aux' context ty, aux' (tys@context) bo)
+                ) funs
+              )
+        in
+         aux true None context t
 ;;
 
-let acic_of_cic_env metasenv env t =
+let acic_of_cic_context metasenv context t =
  let ids_to_terms = Hashtbl.create 503 in
  let ids_to_father_ids = Hashtbl.create 503 in
  let ids_to_inner_sorts = Hashtbl.create 503 in
  let ids_to_inner_types = Hashtbl.create 503 in
  let seed = ref 0 in
-   acic_of_cic_env' seed ids_to_terms ids_to_father_ids ids_to_inner_sorts
-    ids_to_inner_types metasenv env t,
+   acic_of_cic_context' seed ids_to_terms ids_to_father_ids ids_to_inner_sorts
+    ids_to_inner_types metasenv context t,
    ids_to_terms, ids_to_father_ids, ids_to_inner_sorts, ids_to_inner_types
 ;;
 
-exception Found of (Cic.name * Cic.context_entry) list;;
-
-(* get_context_of_meta meta term                                 *)
-(* returns the context of the occurrence of [meta] in [term].    *)
-(* Warning: if [meta] occurs not linearly in [term], the context *)
-(* of one "random" occurrence is returned.                       *)
-let get_context_of_meta meta term =
- let module C = Cic in
-  let rec aux ctx =
-   function
-      C.Rel _
-    | C.Var _ -> ()
-    | C.Meta i when meta = i -> raise (Found ctx)
-    | C.Meta _
-    | C.Sort _
-    | C.Implicit -> ()
-    | C.Cast (te,ty) -> aux ctx te ; aux ctx ty
-    | C.Prod (n,s,t) -> aux ctx s ; aux ((n, C.Decl s)::ctx) t
-    | C.Lambda (n,s,t) -> aux ctx s ; aux ((n, C.Decl s)::ctx) t
-    | C.LetIn (n,s,t) -> aux ctx s ; aux ((n, C.Def s)::ctx) t
-    | C.Appl l -> List.iter (aux ctx) l
-    | C.Const _ -> ()
-    | C.Abst _ -> assert false
-    | C.MutInd _
-    | C.MutConstruct _ -> ()
-    | C.MutCase (_,_,_,outt,t,pl) ->
-       aux ctx outt ; aux ctx t; List.iter (aux ctx) pl
-    | C.Fix (_,ifl) ->
-       let counter = ref 0 in
-        let ctx' =
-         List.rev_map
-          (function (name,_,ty,bo) ->
-            let res = (C.Name name, C.Def (C.Fix (!counter,ifl))) in
-             incr counter ;
-             res
-          ) ifl
-         @ ctx
-        in
-         List.iter (function (_,_,ty,bo) -> aux ctx ty ; aux ctx' bo) ifl
-    | C.CoFix (_,ifl) ->
-       let counter = ref 0 in
-        let ctx' =
-         List.rev_map
-          (function (name,ty,bo) ->
-            let res = (C.Name name, C.Def (C.CoFix (!counter,ifl))) in
-             incr counter ;
-             res
-          ) ifl
-         @ ctx
-        in
-         List.iter (function (_,ty,bo) -> aux ctx ty ; aux ctx' bo) ifl
-  in
-   try
-    aux [] term ;
-    assert false (* No occurrences found. *)
-   with
-    Found context -> context
-;;
-
-exception NotImplemented;;
-
 let acic_object_of_cic_object obj =
  let module C = Cic in
   let ids_to_terms = Hashtbl.create 503 in
   let ids_to_father_ids = Hashtbl.create 503 in
   let ids_to_inner_sorts = Hashtbl.create 503 in
   let ids_to_inner_types = Hashtbl.create 503 in
+  let ids_to_conjectures = Hashtbl.create 11 in
+  let ids_to_hypotheses = Hashtbl.create 127 in
+  let hypotheses_seed = ref 0 in
+  let conjectures_seed = ref 0 in
   let seed = ref 0 in
-  let acic_term_of_cic_term_env' =
-   acic_of_cic_env' seed ids_to_terms ids_to_father_ids ids_to_inner_sorts
+  let acic_term_of_cic_term_context' =
+   acic_of_cic_context' seed ids_to_terms ids_to_father_ids ids_to_inner_sorts
     ids_to_inner_types in
-  let acic_term_of_cic_term' = acic_term_of_cic_term_env' [] [] in
+  let acic_term_of_cic_term' = acic_term_of_cic_term_context' [] [] in
    let aobj =
     match obj with
       C.Definition (id,bo,ty,params) ->
-       let abo = acic_term_of_cic_term' bo in
-       let aty = acic_term_of_cic_term' ty
-       in
+       let abo = acic_term_of_cic_term' bo (Some ty) in
+       let aty = acic_term_of_cic_term' ty None in
         C.ADefinition ("mettereaposto",id,abo,aty,(Cic.Actual params))
     | C.Axiom (id,ty,params) -> raise NotImplemented
     | C.Variable (id,bo,ty) -> raise NotImplemented
     | C.CurrentProof (id,conjectures,bo,ty) ->
        let aconjectures =
         List.map
-         (function (i,term) ->
-           let context = get_context_of_meta i bo in
-            let aterm = acic_term_of_cic_term_env' conjectures context term in
-             (i, aterm))
-         conjectures in
-       let abo = acic_term_of_cic_term_env' conjectures [] bo in
-       let aty = acic_term_of_cic_term_env' conjectures [] ty in
+         (function (i,canonical_context,term) as conjecture ->
+           let cid = "c" ^ string_of_int !conjectures_seed in
+            Hashtbl.add ids_to_conjectures cid conjecture ;
+            incr conjectures_seed ;
+            let acanonical_context =
+             let rec aux =
+              function
+                 [] -> []
+               | hyp::tl ->
+                  let hid = "h" ^ string_of_int !hypotheses_seed in
+                   Hashtbl.add ids_to_hypotheses hid hyp ;
+                   incr hypotheses_seed ;
+                   match hyp with
+                      (Some (n,C.Decl t)) ->
+                        let at =
+                         acic_term_of_cic_term_context' conjectures tl t None
+                        in
+                         (hid,Some (n,C.ADecl at))::(aux tl)
+                    | (Some (n,C.Def t)) ->
+                        let at =
+                         acic_term_of_cic_term_context' conjectures tl t None
+                        in
+                         (hid,Some (n,C.ADef at))::(aux tl)
+                    | None -> (hid,None)::(aux tl)
+             in
+              aux canonical_context
+            in
+             let aterm =
+              acic_term_of_cic_term_context' conjectures canonical_context
+               term None
+             in
+              (cid,i,acanonical_context,aterm)
+         ) conjectures in
+       let abo = acic_term_of_cic_term_context' conjectures [] bo (Some ty) in
+       let aty = acic_term_of_cic_term_context' conjectures [] ty None in
         C.ACurrentProof ("mettereaposto",id,aconjectures,abo,aty)
     | C.InductiveDefinition (tys,params,paramsno) -> raise NotImplemented
    in
-    aobj,ids_to_terms,ids_to_father_ids,ids_to_inner_sorts,ids_to_inner_types
+    aobj,ids_to_terms,ids_to_father_ids,ids_to_inner_sorts,ids_to_inner_types,
+     ids_to_conjectures,ids_to_hypotheses
 ;;