]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/ng_tactics/nTactics.ml
minor fixes
[helm.git] / helm / software / components / ng_tactics / nTactics.ml
index f967a2ac47a2fc82d0850887df32ff82bfb4e0ef..a2042dda6d2ce6d40d491f2512f96b0714c61dea 100644 (file)
@@ -20,7 +20,8 @@ open Continuationals.Stack
 open NTacStatus
 module Ast = CicNotationPt
 
-let id_tac status = status;;
+let id_tac status = status ;;
+let print_tac message status = prerr_endline message; status ;;
 
 let dot_tac status =
   let new_gstatus = 
@@ -155,7 +156,7 @@ 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 past)) present),
  List.map fst (List.filter (fun (i,_) -> not (List.mem_assoc i present)) past)
 ;;
 
@@ -167,6 +168,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
@@ -186,7 +188,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 =
@@ -198,7 +202,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
@@ -214,14 +218,14 @@ let distribute_tac tac status =
        { gstatus = stack; istatus = sn }
 ;;
 
-let exact t status goal =
+let atomic_tac htac = distribute_tac (exec htac) ;;
+
+let exact_tac t = distribute_tac (fun status goal ->
  let goalty = get_goalty status goal in
  let status, t = disambiguate status t (Some goalty) (ctx_of goalty) in
- instantiate status goal t
+ instantiate status goal t)
 ;;
 
-let exact_tac t = distribute_tac (exact t) ;;
-
 let find_in_context name context =
   let rec aux acc = function
     | [] -> raise Not_found
@@ -231,50 +235,57 @@ let find_in_context name context =
   aux 1 context
 ;;
 
-let clear names status goal =
- let goalty = get_goalty status goal in
- let js =
-   List.map 
+let clear_tac names =
+ if names = [] then id_tac
+ else
+  distribute_tac (fun 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 }
  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 force f s = Lazy.force f s;;
 
 let generalize0_tac args =
  if args = [] then id_tac
  else exact_tac ("",0,Ast.Appl (Ast.Implicit :: args))
 ;;
 
-let select ~where:(wanted,_,where) 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 goalty (wanted,path) in
- let status, instance = 
-   mk_meta status (ctx_of newgoalty) (`Decl newgoalty) 
+let select0_tac ~where:(wanted,_,where) ~job  =
+ let found, postprocess = 
+   match job with
+   | `Substexpand argsno -> mk_in_scope, mk_out_scope argsno
+   | `Collect l -> (fun s t -> l := t::!l; mk_in_scope s t), mk_out_scope 1
  in
- instantiate status goal instance
+ 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 ~found ~postprocess goalty (wanted,path) 
+   in
+   let status, instance = 
+     mk_meta status (ctx_of newgoalty) (`Decl newgoalty) 
+   in
+   instantiate status goal instance)
 ;;
 
-let select0_tac ~where = distribute_tac (select ~where) ;;
-
-let select_tac ~where move_down_hyps = 
+let select_tac ~where ~job 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)
+  select0_tac ~where:(wanted,hyps,Some path) ~job
  else
   let path = 
    List.fold_left
@@ -283,15 +294,27 @@ let select_tac ~where move_down_hyps =
   in
    block_tac [ 
      generalize0_tac (List.map (fun (name,_) -> Ast.Ident (name,None)) hyps);
-     select0_tac ~where:(wanted,[],Some path);
+     select0_tac ~where:(wanted,[],Some path) ~job;
      clear_tac (List.map fst hyps) ]
 ;;
 
-(*
 let generalize_tac ~where = 
- block_tac [ select_tac ~where true ; generalize0_tac ???? ]
+ let l = ref [] in
+ block_tac [ 
+   select_tac ~where ~job:(`Collect l) true; 
+   force (lazy (distribute_tac (fun status goal ->
+     if !l = [] then fail (lazy "No term to generalize");
+     let goalty = get_goalty status goal in
+     let canon = List.hd !l in
+     let status = 
+       List.fold_left 
+         (fun s t -> unify s (ctx_of goalty) canon t) status (List.tl !l)
+     in
+     instantiate status goal 
+       (mk_cic_term (ctx_of goalty) (NCic.Appl [NCic.Implicit `Term ; 
+         term_of_cic_term canon (ctx_of goalty) ]))
+   ))) ]
 ;;
-*)
 
 
 let reopen status =
@@ -317,12 +340,14 @@ let reopen status =
 ;;
 
 let change ~where ~with_what status goal =
+assert false; (*
  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, newgoalty = assert false (*
+   select_term status 1 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
 
@@ -337,46 +362,87 @@ let change ~where ~with_what status goal =
    mk_meta status (ctx_of newgoalty) (`Decl newgoalty) 
  in
  instantiate status goal instance
+*)
 ;;
+let change_tac ~where ~with_what = distribute_tac (change ~where ~with_what) ;;
 
-let apply t status goal = exact t status goal;;
+let apply_tac = exact_tac;;
 
-let apply_tac t = distribute_tac (apply t) ;;
-let change_tac ~where ~with_what = distribute_tac (change ~where ~with_what) ;;
+type indtyinfo = {
+        rightno: int;
+        leftno: int;
+        consno: int;
+        lefts: NCic.term list;
+        rights: NCic.term list;
+        reference: NReference.reference;
+ }
+;;
 
-let elim_tac ~what ~where status =
- block_tac
-   [ select_tac ~where true;
-     distribute_tac (fun status goal ->
-       let goalty = get_goalty status goal in
-       let goalsort = typeof status (ctx_of goalty) goalty in
+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;
+  };
+  exec id_tac status goal)
+;;
+
+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
+    sort := Some goalsort;
+    exec id_tac status goal)
+  in
+  atomic_tac (block_tac [
+    analyze_indty_tac ~what indtyinfo;    
+    force (lazy (select_tac 
+      ~where ~job:(`Substexpand ((HExtlib.unopt !indtyinfo).rightno+1)) true));
+    compute_goal_sort_tac;
+    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
-       let status, what = 
-         disambiguate status what None (ctx_of goalty) in
-       let ty_what = typeof status (ctx_of what) what in 
-       let NReference.Ref (uri,_),consno,lefts,rights =
-        analyse_indty status ty_what in
-       let name = NUri.name_of_uri uri ^
-        match term_of_cic_term goalsort (ctx_of goalsort) with
-           NCic.Sort NCic.Prop -> "_ind"
-         | NCic.Sort _ -> "_rect"
-         | _ -> assert false in
-       let leftno = List.length rights in
-       let rightno = List.length rights in
-       let holes=HExtlib.mk_list Ast.Implicit (leftno + 1 + consno + rightno) in
-       let eliminator = 
-         Ast.Appl(Ast.Ident(name,None)::holes @ [ w ])
-       in
-       exec (apply_tac ("",0,eliminator)) status goal) ] 
-   status
+       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 ~job:(`Substexpand 1) true;
+     exact_tac
+      ("",0,
+       Ast.Appl(Ast.Ident(name,None)::HExtlib.mk_list Ast.Implicit 5 @
+        [what]))]
 ;;
 
 let intro_tac name =
  block_tac
   [ exact_tac
-    ("",0,(Ast.Binder (`Lambda,
-     (Ast.Ident (name,None),None),Ast.Implicit)));
-     if name = "_" then clear_tac [name] else id_tac ]
+     ("",0,(Ast.Binder (`Lambda,
+      (Ast.Ident (name,None),None),Ast.Implicit)));
+    if name = "_" then clear_tac [name] else id_tac ]
 ;;
 
 let cases ~what status goal =
@@ -394,7 +460,13 @@ let cases ~what status goal =
 ;;
 
 let cases_tac ~what ~where = 
-        block_tac [ select_tac ~where true ; distribute_tac (cases ~what) ]
+  let indtyinfo = ref None in
+  atomic_tac 
+   (block_tac [
+      analyze_indty_tac ~what indtyinfo;
+      force (lazy (select_tac 
+        ~where ~job:(`Substexpand ((HExtlib.unopt !indtyinfo).rightno+1))true));
+      distribute_tac (cases ~what) ])
 ;;
 
 let case1_tac name =