]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/acic_procedural/procedural2.ml
made executable again
[helm.git] / helm / software / components / acic_procedural / procedural2.ml
index dbd70428c7cba8195bc408b4fea6e46889fe3d5a..ff8f864eabb31320e8af90737ae1501be4085434 100644 (file)
@@ -26,6 +26,7 @@
 module C    = Cic
 module I    = CicInspect
 module S    = CicSubstitution
+module R    = CicReduction
 module TC   = CicTypeChecker 
 module Un   = CicUniv
 module UM   = UriManager
@@ -53,6 +54,7 @@ type status = {
    max_depth: int option;
    depth    : int;
    defaults : bool;
+   cr       : bool;
    context  : C.context;
    case     : int list
 }
@@ -135,10 +137,10 @@ let get_inner_types st v =
 try
    let id = Ut.id_of_annterm v in
    try match Hashtbl.find st.types id with
-      | {A.annsynthesized = st; A.annexpected = Some et} -> Some (st, et)
-      | {A.annsynthesized = st; A.annexpected = None}    -> Some (st, st)
+      | {A.annsynthesized = ity; A.annexpected = Some ety} -> Some (ity, ety)
+      | {A.annsynthesized = ity; A.annexpected = None}     -> Some (ity, ity)
    with Not_found -> None
-with Invalid_argument _ -> failwith "A2P.get_inner_types"
+with Invalid_argument _ -> failwith "P2.get_inner_types"
 
 let get_entry st id =
    let rec aux = function
@@ -167,23 +169,75 @@ let get_sub_names head l =
 
 let get_type msg st t = H.get_type msg st.context (H.cic t) 
 
+let get_uri_of_head = function
+   | C.AConst (_, u, _)                                 ->
+      Some (u, 0, 0, 0)
+   | C.AAppl (_, C.AConst (_, u, _) :: vs)              ->
+      Some (u, 0, 0, List.length vs)
+   | C.AMutInd (_, u, i, _)                             ->
+      Some (u, succ i, 0, 0)
+   | C.AAppl (_, C.AMutInd (_, u, i, _) :: vs)          ->
+      Some (u, succ i, 0, List.length vs)
+   | C.AMutConstruct (_, u, i, j, _)                    ->
+      Some (u, succ i, j, 0)
+   | C.AAppl (_, C.AMutConstruct (_, u, i, j, _) :: vs) ->
+      Some (u, succ i, j, List.length vs)
+   | _                                                  ->
+      None
+
+let get_uri_of_apply = function
+   | T.Exact (t, _)
+   | T.Apply (t, _) -> get_uri_of_head t
+   | _              -> None
+
+let is_reflexivity st step =
+   match get_uri_of_apply step with
+      | None                -> false
+      | Some (uri, i, j, n) ->
+         st.defaults && Obj.is_eq_URI uri && i = 1 && j = 1 && n = 0
+
+let is_ho_reflexivity st step =
+   match get_uri_of_apply step with
+      | None                -> false
+      | Some (uri, i, j, n) ->
+         st.defaults && Obj.is_eq_URI uri && i = 1 && j = 1 && n > 0
+
+let are_convertible st pred sx dx =
+   let pred, sx, dx = H.cic pred, H.cic sx, H.cic dx in
+   let sx, dx = C.Appl [pred; sx], C.Appl [pred; dx] in
+   fst (R.are_convertible st.context sx dx Un.default_ugraph)
+
 (* proof construction *******************************************************)
 
 let anonymous_premise = C.Name "UNNAMED"
 
-let mk_exp_args hd tl classes synth =
-   let meta id = C.AImplicit (id, None) in
+let mk_lapply_args hd tl classes = 
+   let map _ = Cn.meta "" in
+   let args = List.rev_map map tl in
+   if args = [] then hd else C.AAppl ("", hd :: args)
+
+let mk_apply_args hd tl classes synth qs =
+   let exp = ref 0 in
    let map v (cl, b) =
-      if I.overlaps synth cl && b then v else meta ""
+      if I.overlaps synth cl
+         then if b then v, v else Cn.meta "", v
+         else Cn.meta "", Cn.meta ""
    in
-   let rec aux b = function
-      | [] -> b, []
+   let rec rev a = function
+      | []       -> a
       | hd :: tl -> 
-         if hd = meta "" then aux true tl else b, List.rev (hd :: tl)
+         if snd hd <> Cn.meta "" then incr exp;
+         rev (snd hd :: a) tl 
+   in
+   let rec aux = function
+      | []       -> []
+      | hd :: tl -> 
+         if fst hd = Cn.meta "" then aux tl else rev [] (hd :: tl)
    in
    let args = T.list_rev_map2 map tl classes in
-   let b, args = aux false args in
-   if args = [] then b, hd else b, C.AAppl ("", hd :: args)
+   let args = aux args in
+   let part = !exp < List.length tl in
+   if args = [] then part, hd, qs else part, C.AAppl ("", hd :: args), qs
 
 let mk_convert st ?name sty ety note =
    let ppterm t = 
@@ -198,13 +252,16 @@ let mk_convert st ?name sty ety note =
             note sname (ppterm csty) (ppterm cety)
       else ""
    in
-   if H.alpha_equivalence ~flatten:true st.context csty cety then [T.Note note] else 
+   if H.alpha ~flatten:true st.context csty cety then [T.Note note] else 
    let sty, ety = H.acic_bc st.context sty, H.acic_bc st.context ety in
    match name with
       | None         -> [T.Change (sty, ety, None, e, note)]
       | Some (id, i) -> 
          begin match get_entry st id with
-           | C.Def _  -> assert false (* T.ClearBody (id, "") :: script *)
+           | C.Def _  -> 
+              [T.Change (ety, sty, Some (id, Some id), e, note);
+               T.ClearBody (id, "")
+              ]
            | C.Decl _ -> 
               [T.Change (ety, sty, Some (id, Some id), e, note)] 
          end
@@ -220,6 +277,10 @@ let get_intro = function
    | C.Name s    -> Some s
 
 let mk_preamble st what script = match script with
+   | step :: script when is_reflexivity st step ->
+      T.Reflexivity (T.note_of_step step) :: script
+   | step :: script when is_ho_reflexivity st step ->
+      convert st what @ T.Reflexivity (T.note_of_step step) :: script
    | T.Exact _ :: _ -> script
    | _              -> convert st what @ script   
 
@@ -227,14 +288,14 @@ let mk_arg st = function
    | C.ARel (_, _, i, name) as what -> convert st ~name:(name, i) what
    | _                              -> []
 
-let mk_fwd_rewrite st dtext name tl direction v t ity =
+let mk_fwd_rewrite st dtext name tl direction v t ity ety =
    let compare premise = function
       | None   -> true
       | Some s -> s = premise
    in
    assert (List.length tl = 6);
    let what, where, predicate = List.nth tl 5, List.nth tl 3, List.nth tl 2 in
-   let e = Cn.mk_pattern 1 predicate in
+   let e = Cn.mk_pattern 1 ety predicate in
    if (Cn.does_not_occur e) then st, [] else 
    match where with
       | C.ARel (_, _, i, premise) as w ->
@@ -255,15 +316,27 @@ let mk_fwd_rewrite st dtext name tl direction v t ity =
         end
       | _                         -> assert false
 
-let mk_rewrite st dtext where qs tl direction t = 
+let mk_rewrite st dtext where qs tl direction t ity = 
+   let ppterm t = 
+      let a = ref "" in Ut.pp_term (fun s -> a := !a ^ s) [] st.context t; !a
+   in 
    assert (List.length tl = 5);
-   let predicate = List.nth tl 2 in
-   let e = Cn.mk_pattern 1 predicate in
+   let pred, sx, dx = List.nth tl 2, List.nth tl 1, List.nth tl 4 in
+   let dtext = if !debug then dtext ^ ppterm (H.cic pred) else dtext in
+   let e = Cn.mk_pattern 1 ity pred in
    let script = [T.Branch (qs, "")] in
-   if (Cn.does_not_occur e) then script else
+   if Cn.does_not_occur e then script else
+   if st.cr && are_convertible st pred sx dx then 
+      let dtext = "convertible rewrite" ^ dtext in
+      let ity, ety, e = Cn.beta sx pred, Cn.beta dx pred, Cn.hole "" in
+      let city, cety = H.cic ity, H.cic ety in
+      if H.alpha ~flatten:true st.context city cety then script else
+      T.Change (ity, ety, None, e, dtext) :: script
+   else
    T.Rewrite (direction, where, None, e, dtext) :: script
 
 let rec proc_lambda st what name v t =
+   let dtext = if !debug then CicPp.ppcontext st.context else "" in
    let name = match name with
       | C.Anonymous -> H.mk_fresh_name true st.context anonymous_premise
       | name        -> name
@@ -271,28 +344,53 @@ let rec proc_lambda st what name v t =
    let entry = Some (name, C.Decl (H.cic v)) in
    let intro = get_intro name in
    let script = proc_proof (add st entry) t in
-   let script = T.Intros (Some 1, [intro], "") :: script in
+   let script = T.Intros (Some 1, [intro], dtext) :: script in
    mk_preamble st what script
 
 and proc_letin st what name v w t =
    let intro = get_intro name in
    let proceed, dtext = test_depth st in
    let script = if proceed then 
-      let st, hyp, rqv = match get_inner_types st v with
-         | Some (ity, _) ->
+      let st, hyp, rqv = match get_inner_types st what, get_inner_types st v with
+         | Some (C.ALetIn (_, _, iv, iw, _), _), _ when
+           H.alpha ~flatten:true st.context (H.cic v) (H.cic iv) &&
+           H.alpha ~flatten:true st.context (H.cic w) (H.cic iw)
+                                                  ->
+           st, C.Def (H.cic v, H.cic w), [T.Intros (Some 1, [intro], dtext)]
+        | _, Some (ity, ety)                      ->
            let st, rqv = match v with
                | C.AAppl (_, hd :: tl) when is_fwd_rewrite_right st hd tl ->
-                 mk_fwd_rewrite st dtext intro tl true v t ity
+                 mk_fwd_rewrite st dtext intro tl true v t ity ety
               | C.AAppl (_, hd :: tl) when is_fwd_rewrite_left st hd tl  ->
-                 mk_fwd_rewrite st dtext intro tl false v t ity
+                 mk_fwd_rewrite st dtext intro tl false v t ity ety
+              | C.AAppl (_, hd :: tl)                                    ->
+                  let ty = match get_inner_types st hd with
+                     | Some (ity, _) -> H.cic ity 
+                    | None          -> get_type "TC3" st hd 
+                  in
+                 let classes, _ = Cl.classify st.context ty in
+                  let parsno, argsno = List.length classes, List.length tl in
+                  let decurry = parsno - argsno in
+                 if decurry <> 0 then begin              
+(* FG: we fall back in the cut case *)              
+                    assert (Ut.is_sober st.context (H.cic ety));
+                    let ety = H.acic_bc st.context ety in
+                    let qs = [proc_proof (next st) v; [T.Id ""]] in
+                    st, [T.Branch (qs, ""); T.Cut (intro, ety, dtext)]
+                 end else
+                 let names, synth = get_sub_names hd tl, I.S.empty in
+                 let qs = proc_bkd_proofs (next st) synth names classes tl in
+                  let hd = mk_lapply_args hd tl classes in
+                 let qs = [T.Id ""] :: qs in
+                 st, [T.Branch (qs, ""); T.LApply (intro, hd, dtext)]
               | v                                                        ->
-                 assert (Ut.is_sober st.context (H.cic ity));
-                 let ity = H.acic_bc st.context ity in
+                 assert (Ut.is_sober st.context (H.cic ety));
+                 let ety = H.acic_bc st.context ety in
                  let qs = [proc_proof (next st) v; [T.Id ""]] in
-                 st, [T.Branch (qs, ""); T.Cut (intro, ity, dtext)]
+                 st, [T.Branch (qs, ""); T.Cut (intro, ety, dtext)]
            in
            st, C.Decl (H.cic ity), rqv
-        | None          ->
+        | _, None                 ->
            st, C.Def (H.cic v, H.cic w), [T.LetIn (intro, v, dtext)]
       in
       let entry = Some (name, hyp) in
@@ -328,47 +426,59 @@ and proc_appl st what hd tl =
       in
       let classes, rc = Cl.classify st.context ty in
       let goal_arity, goal = match get_inner_types st what with
-         | None            -> 0, None
-        | Some (ity, ety) -> 
-          snd (PEH.split_with_whd (st.context, H.cic ity)), Some (H.cic ety)
+         | None          -> 0, None
+        | Some (ity, _) -> 
+          snd (PEH.split_with_whd (st.context, H.cic ity)), Some (H.cic ity)
       in
       let parsno, argsno = List.length classes, List.length tl in
       let decurry = parsno - argsno in
       let diff = goal_arity - decurry in
-      if diff < 0 then failwith (Printf.sprintf "NOT TOTAL: %i %s |--- %s" diff (Pp.ppcontext st.context) (Pp.ppterm (H.cic hd)));
+      if diff < 0 then 
+         let text = Printf.sprintf "partial application: %i" diff in
+        prerr_endline ("Procedural 2: " ^ text);
+        [T.Exact (what, dtext ^ text)]
+      else
       let classes = Cl.adjust st.context tl ?goal classes in
       let rec mk_synth a n =
          if n < 0 then a else mk_synth (I.S.add n a) (pred n)
       in
       let synth = mk_synth I.S.empty decurry in
-      let text = "" (* Printf.sprintf "%u %s" parsno (Cl.to_string h) *) in
+      let text = if !debug
+         then Printf.sprintf "%u %s" parsno (Cl.to_string synth (classes, rc))
+        else ""
+      in
       let script = List.rev (mk_arg st hd) in
       let tactic b t n = if b then T.Apply (t, n) else T.Exact (t, n) in
       match rc with
-         | Some (i, j, uri, tyno) ->
+         | Some (i, j, uri, tyno) when decurry = 0 ->
            let classes2, tl2, _, where = split2_last classes tl in
            let script2 = List.rev (mk_arg st where) @ script in
            let synth2 = I.S.add 1 synth in
            let names = H.get_ind_names uri tyno in
            let qs = proc_bkd_proofs (next st) synth2 names classes2 tl2 in
-            if List.length qs <> List.length names then
+            let ity = match get_inner_types st what with
+                | Some (ity, _) -> ity 
+                | None          -> 
+                  Cn.fake_annotate "" st.context (get_type "TC3" st what)
+           in
+           if List.length qs <> List.length names then
               let qs = proc_bkd_proofs (next st) synth [] classes tl in
-              let b, hd = mk_exp_args hd tl classes synth in
+              let b, hd, qs = mk_apply_args hd tl classes synth qs in
               script @ [tactic b hd (dtext ^ text); T.Branch (qs, "")]
            else if is_rewrite_right st hd then 
-              script2 @ mk_rewrite st dtext where qs tl2 false what
+              script2 @ mk_rewrite st dtext where qs tl2 false what ity
            else if is_rewrite_left st hd then 
-              script2 @ mk_rewrite st dtext where qs tl2 true what
+              script2 @ mk_rewrite st dtext where qs tl2 true what ity
            else
               let predicate = List.nth tl2 (parsno - i) in
-               let e = Cn.mk_pattern j predicate in
+               let e = Cn.mk_pattern j ity predicate in
               let using = Some hd in
               script2 @ 
               [T.Elim (where, using, e, dtext ^ text); T.Branch (qs, "")]
-        | None        ->
+        | _                                       ->
            let names = get_sub_names hd tl in
            let qs = proc_bkd_proofs (next st) synth names classes tl in
-           let b, hd = mk_exp_args hd tl classes synth in
+           let b, hd, qs = mk_apply_args hd tl classes synth qs in
            script @ [tactic b hd (dtext ^ text); T.Branch (qs, "")]
    else
       [T.Exact (what, dtext)]
@@ -385,7 +495,12 @@ and proc_case st what uri tyno u v ts =
       let ps, _ = H.get_ind_parameters st.context (H.cic v) in
       let _, rps = HEL.split_nth lpsno ps in
       let rpsno = List.length rps in 
-      let e = Cn.mk_pattern rpsno u in
+      let ity = match get_inner_types st what with
+         | Some (ity, _) -> ity 
+         | None          -> 
+           Cn.fake_annotate "" st.context (get_type "TC4" st what)
+      in
+      let e = Cn.mk_pattern rpsno ity u in
       let text = "" in
       let script = List.rev (mk_arg st v) in
       script @ [T.Cases (v, e, dtext ^ text); T.Branch (qs, "")]   
@@ -402,14 +517,17 @@ and proc_other st what =
 
 and proc_proof st t = 
    let f st =
+(*      
       let xtypes, note = match get_inner_types st t with
          | Some (it, et) -> Some (H.cic it, H.cic et), 
          (Printf.sprintf "\nInferred: %s\nExpected: %s"
          (Pp.ppterm (H.cic it)) (Pp.ppterm (H.cic et))) 
          | None          -> None, "\nNo types"
-      in
-      let context, _clears = Cn.get_clears st.context (H.cic t) xtypes in
+      in    
+      let context, clears = Cn.get_clears st.context (H.cic t) xtypes in
       {st with context = context}
+*)
+      st
    in
    match t with
       | C.ALambda (_, name, w, t) as what        -> proc_lambda (f st) what name w t
@@ -462,6 +580,7 @@ let init ~ids_to_inner_sorts ~ids_to_inner_types params context =
       max_depth   = List.fold_left depth_map None params;
       depth       = 0;
       defaults    = not (List.mem G.IPNoDefaults params);
+      cr          = List.mem G.IPCR params;
       context     = context;
       case        = []
    }