]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/ng_tactics/nTactics.ml
Analizyng the inductive type of the eliminated term and
[helm.git] / helm / software / components / ng_tactics / nTactics.ml
index 7fa2b48d8bc081f1a6fb3a5566253cd9bc89d7c7..b34a3a34dd0b4c594ffc7812e92dc437184778dc 100644 (file)
@@ -18,6 +18,10 @@ let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
 
 open Continuationals.Stack
 open NTacStatus
+module Ast = CicNotationPt
+
+let id_tac status = status ;;
+let print_tac message status = prerr_endline message; status ;;
 
 let dot_tac status =
   let new_gstatus = 
@@ -152,8 +156,13 @@ let block_tac l status =
 let compare_statuses ~past ~present =
  let _,_,past,_,_ = past.pstatus in 
  let _,_,present,_,_ = present.pstatus in 
- List.map fst (List.filter (fun (i,_) -> not (List.mem_assoc i past)) present),
- List.map fst (List.filter (fun (i,_) -> not (List.mem_assoc i present)) past)
+ let closed = 
+  List.map fst (List.filter (fun (i,_) -> not (List.mem_assoc i present)) past)
+ in
+ let opened = 
+   List.map fst (List.filter (fun (i,_) -> not(List.mem_assoc i past)) present)
+ in
+ opened, closed
 ;;
 
 
@@ -164,6 +173,7 @@ let compare_statuses ~past ~present =
          distribute_tac (exec tac) [s]::G = (G1@...Gn)::G'
     3) tac G = distribute_tac (exec tac) G if  
        tac = distribute_tac lowtac
+    4) atomic_tac t === distribute_tac (exec t)
 
    Note that executing an high tactic on a set of goals may be stronger
    than executing the same tactic on those goals, but once at a time
@@ -183,7 +193,9 @@ let distribute_tac tac status =
       debug_print (lazy ("context length " ^string_of_int (List.length g)));
       let rec aux s go gc =
         function
-        | [] -> s, go, gc
+        | [] -> 
+            debug_print (lazy "no selected goals");
+            s, go, gc
         | loc :: loc_tl ->
             debug_print (lazy "inner eval tactical");
             let s, go, gc =
@@ -195,7 +207,7 @@ let distribute_tac tac status =
                 | Open n -> 
                    let sn = tac s n in
                    let go', gc' = compare_statuses ~past:s ~present:sn in
-                   sn, (go @- gc') @+ go', gc @+ gc'
+                   sn, ((go @+ [n]) @- gc') @+ go', gc @+ gc'
             in
             aux s go gc loc_tl
       in
@@ -211,21 +223,7 @@ let distribute_tac tac status =
        { gstatus = stack; istatus = sn }
 ;;
 
-
-let select ~where status goal = 
- let goalty = get_goalty status goal in
- let (wanted,_,where) = GrafiteDisambiguate.disambiguate_npattern where in
- let path = 
-   match where with None -> NCic.Implicit `Term | Some where -> where 
- in
- let status, newgoalty = select_term status goalty (wanted,path) in
- let status, instance = 
-   mk_meta status (ctx_of newgoalty) (`Decl newgoalty) 
- in
- instantiate status goal instance
-;;
-
-let select_tac ~where = distribute_tac (select ~where) ;;
+let atomic_tac htac = distribute_tac (exec htac) ;;
 
 let exact t status goal =
  let goalty = get_goalty status goal in
@@ -235,18 +233,91 @@ let exact t status goal =
 
 let exact_tac t = distribute_tac (exact t) ;;
 
+let find_in_context name context =
+  let rec aux acc = function
+    | [] -> raise Not_found
+    | (hd,_) :: tl when hd = name -> acc
+    | _ :: tl ->  aux (acc + 1) tl
+  in
+  aux 1 context
+;;
+
+let clear names status goal =
+ let goalty = get_goalty status goal in
+ let js =
+   List.map 
+     (fun name -> 
+        try find_in_context name (ctx_of goalty)
+        with Not_found -> 
+          fail (lazy ("hypothesis '" ^ name ^ "' not found"))) 
+     names
+ in
+ let n,h,metasenv,subst,o = status.pstatus in
+ let metasenv,subst,_ = NCicMetaSubst.restrict metasenv subst goal js in
+  { status with pstatus = n,h,metasenv,subst,o }
+;;
+
+let clear_tac names =
+ if names = [] then id_tac else distribute_tac (clear names)
+;;
+
+let generalize0_tac args =
+ if args = [] then id_tac
+ else exact_tac ("",0,Ast.Appl (Ast.Implicit :: args))
+;;
+
+let select0_tac ~where:(wanted,_,where) ~argsno = 
+ distribute_tac (fun status goal ->
+   let goalty = get_goalty status goal in
+   let path = 
+     match where with None -> NCic.Implicit `Term | Some where -> where 
+   in
+   let status, newgoalty = select_term status argsno goalty (wanted,path) in
+   let status, instance = 
+     mk_meta status (ctx_of newgoalty) (`Decl newgoalty) 
+   in
+   instantiate status goal instance)
+;;
+
+let select_tac ~where ~argsno move_down_hyps = 
+ let (wanted,hyps,where) = GrafiteDisambiguate.disambiguate_npattern where in
+ let path = 
+  match where with None -> NCic.Implicit `Term | Some where -> where in
+ if not move_down_hyps then
+  select0_tac ~where:(wanted,hyps,Some path) ~argsno
+ else
+  let path = 
+   List.fold_left
+     (fun path (name,path_name) -> NCic.Prod ("_",path_name,path))
+     path (List.rev hyps)
+  in
+   block_tac [ 
+     generalize0_tac (List.map (fun (name,_) -> Ast.Ident (name,None)) hyps);
+     select0_tac ~where:(wanted,[],Some path) ~argsno;
+     clear_tac (List.map fst hyps) ]
+;;
+
+(*
+let generalize_tac ~where = 
+ block_tac [ select_tac ~where true ; generalize0_tac ???? ]
+;;
+*)
+
+
 let reopen status =
  let n,h,metasenv,subst,o = status.pstatus in
  let subst, newm = 
    List.partition 
     (function (_,(Some tag,_,_,_)) -> 
-            tag <> in_scope_tag && tag <> out_scope_tag
+            tag <> NCicMetaSubst.in_scope_tag && 
+            not (NCicMetaSubst.is_out_scope_tag tag)
     | _ -> true)
     subst 
  in
  let in_m, out_m = 
    List.partition
-     (function (_,(Some tag,_,_,_)) -> tag = in_scope_tag | _ -> assert false)
+     (function (_,(Some tag,_,_,_)) -> 
+         tag = NCicMetaSubst.in_scope_tag | _ -> assert false)
      newm
  in
  let metasenv = List.map (fun (i,(_,c,_,t)) -> i,(None,c,t)) in_m @ metasenv in
@@ -261,7 +332,7 @@ let change ~where ~with_what status goal =
  let path = 
    match where with None -> NCic.Implicit `Term | Some where -> where 
  in
- let status, newgoalty = select_term status goalty (wanted,path) in
+ let status, newgoalty = select_term status goalty (wanted,path) in
  let status, in_scope, out_scope = reopen status in
  let status =  List.fold_left (exact with_what) status in_scope in
 
@@ -283,49 +354,117 @@ let apply t status goal = exact t status goal;;
 let apply_tac t = distribute_tac (apply t) ;;
 let change_tac ~where ~with_what = distribute_tac (change ~where ~with_what) ;;
 
-let elim_tac ~what ~where status =
- block_tac
-   [ select_tac ~where;
-     distribute_tac (fun status goal ->
-       let goalty = get_goalty status goal in
-       let status, what = 
-         disambiguate status what None (ctx_of goalty) in
-       let _ty_what = typeof status (ctx_of what) what in 
-       (* check inductive... find eliminator *)
-       let w = (*astify what *) CicNotationPt.Ident ("m",None) in
-       let holes = [ 
-         CicNotationPt.Implicit;CicNotationPt.Implicit;CicNotationPt.Implicit]
-       in
-       let eliminator = 
-         CicNotationPt.Appl(CicNotationPt.Ident("nat_ind",None)::holes @ [ w ])
-       in
-       exec (apply_tac ("",0,eliminator)) status goal) ] 
-   status
+type indtyinfo = {
+        rightno: int;
+        leftno: int;
+        consno: int;
+        lefts: NCic.term list;
+        rights: NCic.term list;
+        reference: NReference.reference;
+ }
+;;
+
+let analyze_indty_tac ~what indtyref = distribute_tac (fun status goal ->
+  let goalty = get_goalty status goal in
+  let status, what = disambiguate status what None (ctx_of goalty) in
+  let ty_what = typeof status (ctx_of what) what in 
+  let r,consno,lefts,rights = analyse_indty status ty_what in
+  let leftno = List.length rights in
+  let rightno = List.length rights in
+  indtyref := Some { 
+    rightno = rightno; leftno = leftno; consno = consno;
+    lefts = lefts; rights = rights; reference = r;
+  };
+  prerr_endline "FO";
+  exec id_tac status goal)
+;;
+
+let force f s = Lazy.force f s;;
+
+let elim_tac ~what ~where = 
+  let indtyinfo = ref None in
+  let sort = ref None in
+  let compute_goal_sort_tac = distribute_tac (fun status goal ->
+    let goalty = get_goalty status goal in
+    let goalsort = typeof status (ctx_of goalty) goalty in
+    prerr_endline "XXXXXXXX";
+    sort := Some goalsort;
+    exec id_tac status goal)
+  in
+  atomic_tac (block_tac [
+    analyze_indty_tac ~what indtyinfo;    
+    force (lazy (select_tac 
+      ~where ~argsno:((HExtlib.unopt !indtyinfo).rightno+1) true));
+    print_tac "CIAO";
+    compute_goal_sort_tac;
+    print_tac "CIAO2";
+    force (lazy (
+     let sort = HExtlib.unopt !sort in
+     let ity = HExtlib.unopt !indtyinfo in
+     let NReference.Ref (uri, _) = ity.reference in
+     let name = NUri.name_of_uri uri ^
+      match term_of_cic_term sort (ctx_of sort) with
+       | NCic.Sort NCic.Prop -> "_ind"
+       | NCic.Sort _ -> "_rect"
+       | _ -> assert false 
+     in
+     let holes = 
+       HExtlib.mk_list Ast.Implicit (ity.leftno+1+ ity.consno + ity.rightno) in
+     let eliminator = 
+       let _,_,w = what in
+       Ast.Appl(Ast.Ident(name,None)::holes @ [ w ])
+     in
+     exact_tac ("",0,eliminator))) ]) 
+;;
+
+let rewrite_tac ~dir ~what:(_,_,what) ~where =
+ let name =
+  match dir with `LeftToRight -> "eq_elim_r" | `RightToLeft -> "eq_ind"
+ in
+  block_tac
+   [ select_tac ~where ~argsno:2 true;
+     exact_tac
+      ("",0,
+       Ast.Appl(Ast.Ident(name,None)::HExtlib.mk_list Ast.Implicit 5 @
+        [what]))]
 ;;
 
 let intro_tac name =
- exact_tac
-  ("",0,(CicNotationPt.Binder (`Lambda,
-   (CicNotationPt.Ident (name,None),None),CicNotationPt.Implicit)))
+ block_tac
+  [ exact_tac
+    ("",0,(Ast.Binder (`Lambda,
+     (Ast.Ident (name,None),None),Ast.Implicit)));
+     if name = "_" then clear_tac [name] else id_tac ]
 ;;
 
-let case ~what status goal =
+let cases ~what status goal =
  let gty = get_goalty status goal in
  let status, what = disambiguate status what None (ctx_of gty) in
  let ty = typeof status (ctx_of what) what in
- let ref, consno, left, right = analyse_indty status ty in
+ let ref, consno, _, _ = analyse_indty status ty in
  let t =
-  NCic.Match (ref,NCic.Implicit `Term,NCic.Rel 1,
+  NCic.Match (ref,NCic.Implicit `Term, term_of_cic_term what (ctx_of gty),
     HExtlib.mk_list (NCic.Implicit `Term) consno)
  in
  let ctx = ctx_of gty in
- let status,t,ty = refine status ctx (mk_cic_term ctx t) None in
+ let status,t,ty = refine status ctx (mk_cic_term ctx t) (Some gty) in
  instantiate status goal t
 ;;
 
-let case_tac ~what = distribute_tac (case ~what);;
+let cases_tac ~what ~where = 
+  let indtyinfo = ref None in
+  atomic_tac 
+   (block_tac [
+      analyze_indty_tac ~what indtyinfo;
+      select_tac ~where ~argsno:((HExtlib.unopt !indtyinfo).rightno+1) true;
+      distribute_tac (cases ~what) ])
+;;
 
 let case1_tac name =
+ let name = if name = "_" then "_clearme" else name in
  block_tac [ intro_tac name; 
-             case_tac ~what:("",0,CicNotationPt.Ident (name,None)) ]
+             cases_tac 
+              ~where:("",0,(None,[],None)) 
+              ~what:("",0,Ast.Ident (name,None));
+              if name = "_clearme" then clear_tac ["_clearme"] else id_tac ]
 ;;