]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/acic_procedural/proceduralPreprocess.ml
elim tactic: it needs two arguments, a term as well as a pattern
[helm.git] / helm / software / components / acic_procedural / proceduralPreprocess.ml
index d31d0113b9067b6ba0c3b456fd8a2a1329ae3450..d3e655da70ea6ee20f54674c8782bb5f0deed028 100644 (file)
  * http://cs.unibo.it/helm/.
  *)
 
+module UM   = UriManager
 module C    = Cic
+module Pp   = CicPp
 module Un   = CicUniv
+module I    = CicInspect
+module E    = CicEnvironment
 module S    = CicSubstitution
-module R    = CicReduction
 module TC   = CicTypeChecker 
+module Rf   = CicRefine
 module DTI  = DoubleTypeInference
 module HEL  = HExtlib
+module PEH  = ProofEngineHelpers
 
 (* helper functions *********************************************************)
 
@@ -38,12 +43,30 @@ let identity x = x
 let comp f g x = f (g x)
 
 let get_type c t =
-   let ty, _ = TC.type_of_aux' [] c t Un.empty_ugraph in ty
+   try let ty, _ = TC.type_of_aux' [] c t Un.empty_ugraph in ty
+   with e -> 
+      Printf.eprintf "TC: context: %s\n" (Pp.ppcontext c);
+      Printf.eprintf "TC: term   : %s\n" (Pp.ppterm t);
+      raise e
+
+let refine c t =
+   try let t, _, _, _ = Rf.type_of_aux' [] c t Un.empty_ugraph in t
+   with e -> 
+      Printf.eprintf "REFINE EROR: %s\n" (Printexc.to_string e);
+      Printf.eprintf "Ref: context: %s\n" (Pp.ppcontext c);
+      Printf.eprintf "Ref: term   : %s\n" (Pp.ppterm t);
+      raise e
+
+let get_tail c t =
+   match PEH.split_with_whd (c, t) with
+      | (_, hd) :: _, _ -> hd
+      | _               -> assert false
 
 let is_proof c t =
-   match (get_type c (get_type c t)) with
+   match get_tail c (get_type c (get_type c t)) with
       | C.Sort C.Prop -> true
-      | _             -> false
+      | C.Sort _      -> false
+      | _             -> assert false 
 
 let is_not_atomic = function
    | C.Sort _
@@ -54,14 +77,57 @@ let is_not_atomic = function
    | C.MutConstruct _ -> false
    | _                -> true
 
-let split c t =
-   let add s v c = Some (s, C.Decl v) :: c in
-   let rec aux whd a n c = function
-      | C.Prod (s, v, t)  -> aux false (v :: a) (succ n) (add s v c) t
-      | v when whd        -> v :: a, n
-      | v                 -> aux true a n c (R.whd ~delta:true c v)
-    in
-    aux false [] 0 c t
+let clear_absts m =
+   let rec aux k n = function
+      | C.Lambda (s, v, t) when k > 0    -> 
+         C.Lambda (s, v, aux (pred k) n t)
+      | C.Lambda (_, _, t) when n > 0    -> 
+         aux 0 (pred n) (S.lift (-1) t)
+      | t                     when n > 0 ->
+         Printf.eprintf "CicPPP clear_absts: %u %s\n" n (Pp.ppterm t);
+        assert false 
+      | t                                 -> t
+   in 
+   aux m
+
+let rec add_abst k = function 
+   | C.Lambda (s, v, t) when k > 0 -> C.Lambda (s, v, add_abst (pred k) t)
+   | t when k > 0 -> assert false
+   | t -> C.Lambda (C.Anonymous, C.Implicit None, S.lift 1 t)
+
+let get_ind_type uri tyno =
+   match E.get_obj Un.empty_ugraph uri with
+      | C.InductiveDefinition (tys, _, lpsno, _), _ -> lpsno, List.nth tys tyno
+      | _                                           -> assert false
+
+let get_ind_parameters c t =
+   let ty = get_type c t in
+   let ps = match get_tail c ty with
+      | C.MutInd _                  -> []
+      | C.Appl (C.MutInd _ :: args) -> args
+      | _                           -> assert false
+   in
+   let disp = match get_tail c (get_type c ty) with
+      | C.Sort C.Prop -> 0
+      | C.Sort _      -> 1
+      | _             -> assert false
+   in
+   ps, disp
+
+let get_default_eliminator context uri tyno ty =
+   let _, (name, _, _, _) = get_ind_type uri tyno in
+   let ext = match get_tail context (get_type context ty) with
+      | C.Sort C.Prop     -> "_ind"
+      | C.Sort C.Set      -> "_rec"
+      | C.Sort C.CProp    -> "_rec"
+      | C.Sort (C.Type _) -> "_rect"
+      | t                 -> 
+         Printf.eprintf "CicPPP get_default_eliminator: %s\n" (Pp.ppterm t);
+         assert false
+   in
+   let buri = UM.buri_of_uri uri in
+   let uri = UM.uri_of_string (buri ^ "/" ^ name ^ ext ^ ".con") in
+   C.Const (uri, [])
 
 let add g htbl t proof decurry =
    if proof then C.CicHash.add htbl t decurry; 
@@ -78,30 +144,54 @@ let expanded_premise = "EXPANDED"
 
 let defined_premise = "DEFINED"
 
-let eta_expand n t =
-   let ty = C.Implicit None in
+let eta_expand g tys t =
+   assert (tys <> []);
    let name i = Printf.sprintf "%s%u" expanded_premise i in 
-   let lambda i t = C.Lambda (C.Name (name i), ty, t) in
-   let arg i n = C.Rel (n - i) in
-   let rec aux i f a =
-      if i >= n then f, a else aux (succ i) (comp f (lambda i)) (arg i n :: a)
+   let lambda i ty t = C.Lambda (C.Name (name i), ty, t) in
+   let arg i = C.Rel (succ i) in
+   let rec aux i f a = function
+      | []            -> f, a 
+      | (_, ty) :: tl -> aux (succ i) (comp f (lambda i ty)) (arg i :: a) tl
    in
-   let absts, args = aux 0 identity [] in
-   absts (C.Appl (S.lift n t :: args))
+   let n = List.length tys in
+   let absts, args = aux 0 identity [] tys in
+   let t = match S.lift n t with
+      | C.Appl ts -> C.Appl (ts @ args)
+      | t         -> C.Appl (t :: args)
+   in
+   g (absts t)
+
+let get_tys c decurry =
+   let rec aux n = function
+(*      | C.Appl (hd :: tl) -> aux (n + List.length tl) hd *)
+      | t                 ->
+         let tys, _ = PEH.split_with_whd (c, get_type c t) in
+         let _, tys = HEL.split_nth n (List.rev tys) in
+        let tys, _ = HEL.split_nth decurry tys in
+         tys
+   in
+   aux 0
 
-let eta_fix t proof decurry =
-   if proof && decurry > 0 then eta_expand decurry t else t
+let eta_fix c t proof decurry =
+   let rec aux g c = function
+      | C.LetIn (name, v, t) ->
+         let g t = g (C.LetIn (name, v, t)) in
+        let entry = Some (name, C.Def (v, None)) in
+         aux g (entry :: c) t
+      | t                    -> eta_expand g (get_tys c decurry t) t 
+   in 
+   if proof && decurry > 0 then aux identity c t else t
 
 let rec pp_cast g ht es c t v =
-   if es then pp_proof g ht es c t else find g ht t
+   if true then pp_proof g ht es c t else find g ht t
 
 and pp_lambda g ht es c name v t =
    let name = if DTI.does_not_occur 1 t then C.Anonymous else name in
    let entry = Some (name, C.Decl v) in
    let g t _ decurry = 
-      let t = eta_fix t true decurry in
+      let t = eta_fix (entry :: c) t true decurry in
       g (C.Lambda (name, v, t)) true 0 in
-   if es then pp_proof g ht es (entry :: c) t else find g ht t
+   if true then pp_proof g ht es (entry :: c) t else find g ht t
 
 and pp_letin g ht es c name v t =
    let entry = Some (name, C.Def (v, None)) in
@@ -112,12 +202,12 @@ and pp_letin g ht es c name v t =
             let x = C.LetIn (mame, w, C.LetIn (name, u, S.lift_from 2 1 t)) in
            pp_proof g ht false c x 
          | v                               -> 
-            let v = eta_fix v proof d in
+            let v = eta_fix v proof d in
            g (C.LetIn (name, v, t)) true decurry
       in
-      if es then pp_term g ht es c v else find g ht v
+      if true then pp_term g ht es c v else find g ht v
    in
-   if es then pp_proof g ht es (entry :: c) t else find g ht t
+   if true then pp_proof g ht es (entry :: c) t else find g ht t
 
 and pp_appl_one g ht es c t v =
    let g t _ decurry =
@@ -130,20 +220,19 @@ and pp_appl_one g ht es c t v =
                let x = C.LetIn (mame, w, C.Appl [u; S.lift 1 v]) in
               pp_proof g ht false c x
            | C.Appl ts, v when decurry > 0      ->
-              let v = eta_fix v proof d in
+              let v = eta_fix v proof d in
               g (C.Appl (List.append ts [v])) true (pred decurry)
            | t, v  when is_not_atomic t         ->
               let mame = C.Name defined_premise in
               let x = C.LetIn (mame, t, C.Appl [C.Rel 1; S.lift 1 v]) in
               pp_proof g ht false c x
            | t, v                               ->
-               let _, premsno = split c (get_type c t) in
-              let v = eta_fix v proof d in
-               g (C.Appl [t; v]) true (pred premsno)
+              let v = eta_fix c v proof d in
+               g (C.Appl [t; v]) true (pred decurry)
       in
-      if es then pp_term g ht es c v else find g ht v
+      if true then pp_term g ht es c v else find g ht v
    in
-   if es then pp_proof g ht es c t else find g ht t
+   if true then pp_proof g ht es c t else find g ht t
 
 and pp_appl g ht es c t = function
    | []             -> pp_proof g ht es c t
@@ -152,14 +241,53 @@ and pp_appl g ht es c t = function
       let x = C.Appl (C.Appl [t; v1] :: v2 :: vs) in 
       pp_proof g ht es c x
 
+and pp_atomic g ht es c t =
+   let _, premsno = PEH.split_with_whd (c, get_type c t) in
+   g t true premsno
+
+and pp_mutcase g ht es c uri tyno outty arg cases =
+   let eliminator = get_default_eliminator c uri tyno outty in
+   let lpsno, (_, _, _, constructors) = get_ind_type uri tyno in
+   let ps, sort_disp = get_ind_parameters c arg in
+   let lps, rps = HEL.split_nth lpsno ps in
+   let rpsno = List.length rps in
+   let predicate = clear_absts rpsno (1 - sort_disp) outty in   
+   let is_recursive t =
+      I.S.mem tyno (I.get_mutinds_of_uri uri t) 
+   in
+   let map2 case (_, cty) = 
+      let map (h, case, k) (_, premise) = 
+         if h > 0 then pred h, case, k else
+        if is_recursive premise then 
+           0, add_abst k case, k + 2 
+        else
+           0, case, succ k
+      in
+      let premises, _ = PEH.split_with_whd (c, cty) in
+      let _, lifted_case, _ =
+         List.fold_left map (lpsno, case, 1) (List.rev (List.tl premises))
+      in
+      lifted_case
+   in
+   let lifted_cases = List.map2 map2 cases constructors in
+   let args = eliminator :: lps @ predicate :: lifted_cases @ rps @ [arg] in
+   let x = refine c (C.Appl args) in
+   pp_proof g ht es c x
+
 and pp_proof g ht es c t = 
-   let g t proof decurry = add g ht t proof decurry in
+(*  Printf.eprintf "IN: |- %s\n" (*CicPp.ppcontext c*) (CicPp.ppterm t);
+  let g t proof decurry = 
+     Printf.eprintf "OUT: %b %u |- %s\n" proof decurry (CicPp.ppterm t);
+     g t proof decurry
+  in *)
+(*   let g t proof decurry = add g ht t proof decurry in *)
    match t with
-      | C.Cast (t, v)         -> pp_cast g ht es c t v
-      | C.Lambda (name, v, t) -> pp_lambda g ht es c name v t
-      | C.LetIn (name, v, t)  -> pp_letin g ht es c name v t
-      | C.Appl (t :: vs)      -> pp_appl g ht es c t vs
-      | t                     -> g t true 0
+      | C.Cast (t, v)              -> pp_cast g ht es c t v
+      | C.Lambda (name, v, t)      -> pp_lambda g ht es c name v t
+      | C.LetIn (name, v, t)       -> pp_letin g ht es c name v t
+      | C.Appl (t :: vs)           -> pp_appl g ht es c t vs
+      | C.MutCase (u, n, t, v, ws) -> pp_mutcase g ht es c u n t v ws
+      | t                          -> pp_atomic g ht es c t
 
 and pp_term g ht es c t =
    if is_proof c t then pp_proof g ht es c t else g t false 0
@@ -169,9 +297,11 @@ and pp_term g ht es c t =
 let pp_obj = function
    | C.Constant (name, Some bo, ty, pars, attrs) ->
       let g bo proof decurry = 
-         let bo = eta_fix bo proof decurry in
+         let bo = eta_fix [] bo proof decurry in
          C.Constant (name, Some bo, ty, pars, attrs)
       in
       let ht = C.CicHash.create 1 in
-      pp_term g ht true [] bo
+      Printf.eprintf "BEGIN: %s\n" name;
+      begin try pp_term g ht true [] bo
+      with e -> failwith ("PPP: " ^ Printexc.to_string e) end
    | obj                                         -> obj