]> matita.cs.unibo.it Git - helm.git/commitdiff
Optional callbacks have been added to tactics that need to introduce
authorClaudio Sacerdoti Coen <claudio.sacerdoticoen@unibo.it>
Wed, 29 Jan 2003 10:19:55 +0000 (10:19 +0000)
committerClaudio Sacerdoti Coen <claudio.sacerdoticoen@unibo.it>
Wed, 29 Jan 2003 10:19:55 +0000 (10:19 +0000)
new fresh names directly (i.e. without calling other tactics that need
fresh names). The default behaviour is _MUCH_ nicer than the previous
dummy one and is fully functional.

Corollary 1: all the code of tactics.cma is now reentrant.
Corollary 2: the user can be asked the fresh name if it is requested
             by a top-level tactic.

14 files changed:
helm/gTopLevel/gTopLevel.ml
helm/gTopLevel/proofEngine.ml
helm/gTopLevel/proofEngine.mli
helm/ocaml/tactics/eliminationTactics.ml
helm/ocaml/tactics/eliminationTactics.mli
helm/ocaml/tactics/equalityTactics.ml
helm/ocaml/tactics/fourierR.ml
helm/ocaml/tactics/negationTactics.ml
helm/ocaml/tactics/primitiveTactics.ml
helm/ocaml/tactics/primitiveTactics.mli
helm/ocaml/tactics/proofEngineHelpers.ml
helm/ocaml/tactics/proofEngineHelpers.mli
helm/ocaml/tactics/proofEngineTypes.ml
helm/ocaml/tactics/variousTactics.ml

index 396c968fd99e170eb100854f0bd3c0f341bc41bd..a94472bf2f87f45a7b61ee76197d6cfcc6e4c598 100644 (file)
@@ -1658,6 +1658,22 @@ let new_inductive () =
       ("<h1 color=\"red\">" ^ Printexc.to_string e ^ "</h1>") ;
 ;;
 
+let mk_fresh_name_callback context name ~typ =
+ let fresh_name =
+  match ProofEngineHelpers.mk_fresh_name context name ~typ with
+     Cic.Name fresh_name -> fresh_name
+   | Cic.Anonymous -> assert false
+ in
+  match
+   GToolbox.input_string ~title:"Enter a fresh hypothesis name" ~text:fresh_name
+    ("Enter a fresh name for the hypothesis " ^
+      CicPp.pp typ
+       (List.map (function None -> None | Some (n,_) -> Some n) context))
+  with
+     Some fresh_name' -> Cic.Name fresh_name'
+   | None -> raise NoChoice
+;;
+
 let new_proof () =
  let inputt = ((rendering_window ())#inputt : term_editor) in
  let outputhtml = ((rendering_window ())#outputhtml : GHtml.xmhtml) in
@@ -1758,7 +1774,10 @@ let new_proof () =
      refresh_sequent notebook ;
      refresh_proof output ;
      !save_set_sensitive true ;
-     inputt#reset
+     inputt#reset ;
+     ProofEngine.intros ~mk_fresh_name_callback () ;
+     refresh_sequent notebook ;
+     refresh_proof output
   with
      RefreshSequentException e ->
       output_html outputhtml
@@ -2138,7 +2157,7 @@ let call_tactic_with_hypothesis_input tactic () =
 ;;
 
 
-let intros = call_tactic ProofEngine.intros;;
+let intros = call_tactic (ProofEngine.intros ~mk_fresh_name_callback);;
 let exact = call_tactic_with_input ProofEngine.exact;;
 let apply = call_tactic_with_input ProofEngine.apply;;
 let elimintrossimpl = call_tactic_with_input ProofEngine.elim_intros_simpl;;
@@ -2149,9 +2168,9 @@ let simpl = call_tactic_with_goal_input ProofEngine.simpl;;
 let fold_whd = call_tactic_with_input ProofEngine.fold_whd;;
 let fold_reduce = call_tactic_with_input ProofEngine.fold_reduce;;
 let fold_simpl = call_tactic_with_input ProofEngine.fold_simpl;;
-let cut = call_tactic_with_input ProofEngine.cut;;
+let cut = call_tactic_with_input (ProofEngine.cut ~mk_fresh_name_callback);;
 let change = call_tactic_with_input_and_goal_input ProofEngine.change;;
-let letin = call_tactic_with_input ProofEngine.letin;;
+let letin = call_tactic_with_input (ProofEngine.letin ~mk_fresh_name_callback);;
 let ring = call_tactic ProofEngine.ring;;
 let clearbody = call_tactic_with_hypothesis_input ProofEngine.clearbody;;
 let clear = call_tactic_with_hypothesis_input ProofEngine.clear;;
index e333ec3b8ec9e5d741a2c856164ddfbbe0c32f66..99e6a081cdeaccb8940fe687eb30ae6bb380ea35 100644 (file)
@@ -165,9 +165,12 @@ let simpl_in_scratch  = reduction_tactic_in_scratch ProofEngineReduction.simpl
 
 let can_apply term = can_apply_tactic (PrimitiveTactics.apply_tac ~term)
 let apply term = apply_tactic (PrimitiveTactics.apply_tac ~term)
-let intros () = apply_tactic PrimitiveTactics.intros_tac
-let cut term = apply_tactic (PrimitiveTactics.cut_tac ~term)
-let letin term = apply_tactic (PrimitiveTactics.letin_tac ~term)
+let intros ?mk_fresh_name_callback () =
+ apply_tactic (PrimitiveTactics.intros_tac ?mk_fresh_name_callback ())
+let cut ?mk_fresh_name_callback term =
+ apply_tactic (PrimitiveTactics.cut_tac ?mk_fresh_name_callback term)
+let letin ?mk_fresh_name_callback term =
+ apply_tactic (PrimitiveTactics.letin_tac ?mk_fresh_name_callback term)
 let exact term = apply_tactic (PrimitiveTactics.exact_tac ~term)
 let elim_intros_simpl term =
   apply_tactic (PrimitiveTactics.elim_intros_simpl_tac ~term)
@@ -232,7 +235,7 @@ let absurd term = apply_tactic (NegationTactics.absurd_tac ~term)
 let contradiction () = apply_tactic NegationTactics.contradiction_tac
 
 let decompose ~uris_choice_callback term =
- apply_tactic (EliminationTactics.decompose_tac ~term ~uris_choice_callback)
+ apply_tactic (EliminationTactics.decompose_tac ~uris_choice_callback term)
 
 (*
 let decide_equality () = apply_tactic VariousTactics.decide_equality_tac
index deb8483ac0348e7b3cc31ea85e858edb79b4968b..c845c2b1ea2ee392ad7b0ed98568554d3da3e224 100644 (file)
@@ -46,9 +46,12 @@ val simpl_in_scratch : Cic.term -> Cic.term -> Cic.term
   (* "primitive" tactics *)
 val can_apply : Cic.term -> bool
 val apply : Cic.term -> unit
-val intros : unit -> unit
-val cut : Cic.term -> unit
-val letin : Cic.term -> unit
+val intros :
+ ?mk_fresh_name_callback:ProofEngineTypes.mk_fresh_name_type -> unit -> unit
+val cut :
+ ?mk_fresh_name_callback:ProofEngineTypes.mk_fresh_name_type -> Cic.term -> unit
+val letin :
+ ?mk_fresh_name_callback:ProofEngineTypes.mk_fresh_name_type -> Cic.term -> unit
 val exact : Cic.term -> unit
 val elim_intros_simpl : Cic.term -> unit
 val change : goal_input:Cic.term -> input:Cic.term -> unit
index ae947f5ec4bd35759702588c95790410d10d07ee..73d1771ff6d0002c0ece8743c09d25fcfac72dc0 100644 (file)
@@ -49,7 +49,7 @@ let elim_type_tac ~term ~status =
   let module P = PrimitiveTactics in
   let module T = Tacticals in
    T.thens
-    ~start: (P.cut_tac ~term)
+    ~start: (P.cut_tac term)
     ~continuations:[ P.elim_intros_simpl_tac ~term:(C.Rel 1) ; T.id_tac ]
     ~status
 ;;
@@ -96,7 +96,9 @@ let cic_textual_parser_uri_of_string uri' =
   _ -> raise (IllFormedUri uri')
 ;;
 
-let decompose_tac ~term ~uris_choice_callback ~status:((proof,goal) as status) =
+let decompose_tac ?(uris_choice_callback=(function l -> l)) term
+ ~status:((proof,goal) as status)
+=
   let module C = Cic in
   let module R = CicReduction in
   let module P = PrimitiveTactics in
index 5e132c4966366860cad1e3cefa44b881e7aa1c2b..92d9eee016ebdcbb2d941d4ee54614f69f651760 100644 (file)
 
 val elim_type_tac: term:Cic.term -> ProofEngineTypes.tactic
 
+(* The default callback always decomposes the term as much as possible *)
 val decompose_tac:
- term:Cic.term ->
- uris_choice_callback:
+ ?uris_choice_callback:
   ((UriManager.uri * int * (UriManager.uri * Cic.term) list) list ->
    (UriManager.uri * int * (UriManager.uri * Cic.term) list) list) ->
-   ProofEngineTypes.tactic
+ Cic.term ->
+  ProofEngineTypes.tactic
index 79b5b1dbe499e50a6b2d26788a023bcf30081554..29df82c08ab5f21f121a688231ecf98d46058836 100644 (file)
@@ -162,12 +162,11 @@ let replace_tac ~what ~with_what ~status:((proof, goal) as status) =
        then T.thens
               ~start:(
                 P.cut_tac 
-                   ~term:(
-                     C.Appl [
-                      (C.MutInd ((U.uri_of_string "cic:/Coq/Init/Logic/eq.ind"), 0, [])) ; (* quale uguaglianza usare, eq o eqT ? *)
-                      wty ; 
-                      what ; 
-                      with_what]))
+                 (C.Appl [
+                   (C.MutInd ((U.uri_of_string "cic:/Coq/Init/Logic/eq.ind"), 0, [])) ; (* quale uguaglianza usare, eq o eqT ? *)
+                     wty ; 
+                     what ; 
+                     with_what]))
               ~continuations:[
                 T.then_
                    ~start:(rewrite_back_tac ~term:(C.Rel 1)) (* C.Name "dummy_for_replace" *)
index 370b5db50c9194f49922a401afe724e8f504051c..bd4eeae3e8b33747937e3e5d5ae4e130e8ea014f 100644 (file)
@@ -1049,7 +1049,7 @@ theoreme,so let's parse our thesis *)
    let proof,gl =
     Tacticals.then_ 
      ~start:(PrimitiveTactics.apply_tac ~term:!th_to_appl)
-     ~continuation:PrimitiveTactics.intros_tac
+     ~continuation:(PrimitiveTactics.intros_tac ())
      ~status:(s_proof,s_goal) in
    let goal = if List.length gl = 1 then List.hd gl 
                                     else failwith "a new goal" in
index 28e5ceeb5b937ed90fd44853f4644c6b06ece952..25c29918fc157097b7cd1bf526dd77ff95073889 100644 (file)
@@ -44,7 +44,7 @@ let contradiction_tac ~status =
   let module T = Tacticals in
    try
     T.then_
-      ~start: P.intros_tac
+      ~start:(P.intros_tac ())
       ~continuation:(
         T.then_
            ~start:
index ccd8ccfe0ad63eddcd5c572092a78fd11d2ece72..8abaae1b849e67711982ba74a0a626a51e965e72 100644 (file)
@@ -37,13 +37,13 @@ exception WrongUriToVariable of string
 (* and [bo] = Lambda/LetIn [context].(Meta [newmeta])       *)
 (* So, lambda_abstract is the core of the implementation of *)
 (* the Intros tactic.                                       *)
-let lambda_abstract context newmeta ty mknames =
+let lambda_abstract context newmeta ty mk_fresh_name =
  let module C = Cic in
   let rec collect_context context =
    function
       C.Cast (te,_)   -> collect_context context te
     | C.Prod (n,s,t)  ->
-       let n' = C.Name (mknames n) in
+       let n' = mk_fresh_name context n ~typ:s in
         let (context',ty,bo) =
          collect_context ((Some (n',(C.Decl s)))::context) t
         in
@@ -112,7 +112,10 @@ let eta_expand metasenv context t arg =
    let argty =
     T.type_of_aux' metasenv context arg
    in
-    (C.Appl [C.Lambda ((C.Name "dummy"),argty,aux 0 t) ; arg])
+    let fresh_name =
+     ProofEngineHelpers.mk_fresh_name context (Cic.Name "Heta") ~typ:argty
+    in
+     (C.Appl [C.Lambda (fresh_name,argty,aux 0 t) ; arg])
 
 (*CSC: ma serve solamente la prima delle new_uninst e l'unione delle due!!! *)
 let classify_metas newmeta in_subst_domain subst_in metasenv =
@@ -301,35 +304,43 @@ let apply_tac ~term ~status =
   with CicUnification.UnificationFailed as e ->
     raise (Fail (Printexc.to_string e))
 
-let intros_tac ~status:(proof, goal) =
+let intros_tac
+ ?(mk_fresh_name_callback = ProofEngineHelpers.mk_fresh_name) ()
+ ~status:(proof, goal)
+=
  let module C = Cic in
  let module R = CicReduction in
   let (_,metasenv,_,_) = proof in
   let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
    let newmeta = new_meta ~proof in
     let (context',ty',bo') =
-     lambda_abstract context newmeta ty (ProofEngineHelpers.fresh_name)
+     lambda_abstract context newmeta ty mk_fresh_name_callback
     in
      let (newproof, _) =
        subst_meta_in_proof proof metano bo' [newmeta,context',ty']
      in
       (newproof, [newmeta])
 
-let cut_tac ~term ~status:(proof, goal) =
+let cut_tac
+ ?(mk_fresh_name_callback = ProofEngineHelpers.mk_fresh_name)
+ term ~status:(proof, goal)
+=
  let module C = Cic in
   let curi,metasenv,pbo,pty = proof in
   let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
    let newmeta1 = new_meta ~proof in
    let newmeta2 = newmeta1 + 1 in
+   let fresh_name =
+    mk_fresh_name_callback context (Cic.Name "Hcut") ~typ:term in
    let context_for_newmeta1 =
-    (Some (C.Name "dummy_for_cut",C.Decl term))::context in
+    (Some (fresh_name,C.Decl term))::context in
    let irl1 =
     identity_relocation_list_for_metavariable context_for_newmeta1 in
    let irl2 = identity_relocation_list_for_metavariable context in
     let newmeta1ty = CicSubstitution.lift 1 ty in
     let bo' =
      C.Appl
-      [C.Lambda (C.Name "dummy_for_cut",term,C.Meta (newmeta1,irl1)) ;
+      [C.Lambda (fresh_name,term,C.Meta (newmeta1,irl1)) ;
        C.Meta (newmeta2,irl2)]
     in
      let (newproof, _) =
@@ -338,18 +349,23 @@ let cut_tac ~term ~status:(proof, goal) =
      in
       (newproof, [newmeta1 ; newmeta2])
 
-let letin_tac ~term ~status:(proof, goal) =
+let letin_tac
+ ?(mk_fresh_name_callback = ProofEngineHelpers.mk_fresh_name)
+ term ~status:(proof, goal)
+=
  let module C = Cic in
   let curi,metasenv,pbo,pty = proof in
   let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
    let _ = CicTypeChecker.type_of_aux' metasenv context term in
     let newmeta = new_meta ~proof in
+    let fresh_name =
+     mk_fresh_name_callback context (Cic.Name "Hletin") ~typ:term in
     let context_for_newmeta =
-     (Some (C.Name "dummy_for_letin",C.Def term))::context in
+     (Some (fresh_name,C.Def term))::context in
     let irl =
      identity_relocation_list_for_metavariable context_for_newmeta in
      let newmetaty = CicSubstitution.lift 1 ty in
-     let bo' = C.LetIn (C.Name "dummy_for_letin",term,C.Meta (newmeta,irl)) in
+     let bo' = C.LetIn (fresh_name,term,C.Meta (newmeta,irl)) in
       let (newproof, _) =
         subst_meta_in_proof
           proof metano bo'[newmeta,context_for_newmeta,newmetaty]
@@ -505,7 +521,7 @@ let elim_intros_simpl_tac ~term =
  Tacticals.then_ ~start:(elim_tac ~term)
   ~continuation:
    (Tacticals.thens
-     ~start:intros_tac
+     ~start:(intros_tac ())
      ~continuations:
        [ReductionTactics.simpl_tac ~also_in_hypotheses:false ~term:None])
 ;;
index dad385339b876bbe4da402bf4d9068c62d9b3923..bef3bb2e8041bacb6f5125e932d99c6676be5862 100644 (file)
@@ -28,11 +28,14 @@ val apply_tac:
 val exact_tac:
   term: Cic.term -> ProofEngineTypes.tactic
 val intros_tac:
-  ProofEngineTypes.tactic
+  ?mk_fresh_name_callback:ProofEngineTypes.mk_fresh_name_type -> unit ->
+   ProofEngineTypes.tactic
 val cut_tac:
-  term: Cic.term -> ProofEngineTypes.tactic 
+  ?mk_fresh_name_callback:ProofEngineTypes.mk_fresh_name_type -> Cic.term ->
+   ProofEngineTypes.tactic 
 val letin_tac:
-  term: Cic.term -> ProofEngineTypes.tactic 
+  ?mk_fresh_name_callback:ProofEngineTypes.mk_fresh_name_type -> Cic.term ->
+   ProofEngineTypes.tactic 
 
 val elim_intros_simpl_tac:
   term: Cic.term -> ProofEngineTypes.tactic 
index 74b6fcdaca1f344032da1afc7df9c393f30f9206..84eaa2559ae383a3d83f9de0b36d8998aba7e985 100644 (file)
  * http://cs.unibo.it/helm/.
  *)
 
-(*CSC: generatore di nomi? Chiedere il nome? *)
-let fresh_name =
- let next_fresh_index = ref 0 in
-  function
-     Cic.Anonymous ->
-      incr next_fresh_index ;
-      "fresh_name" ^ string_of_int !next_fresh_index
-   | Cic.Name name ->
-      incr next_fresh_index ;
-      name ^ string_of_int !next_fresh_index
+(* mk_fresh_name context name typ                      *)
+(* returns an identifier which is fresh in the context *)
+(* and that resembles [name] as much as possible.      *)
+(* [typ] will be the type of the variable              *)
+let mk_fresh_name context name ~typ =
+ let module C = Cic in
+  let basename =
+   match name with
+      C.Anonymous ->
+       (*CSC: great space for improvements here *)
+       (try
+         (match CicTypeChecker.type_of_aux' [] context typ with
+             C.Sort C.Prop -> "H"
+           | C.Sort C.Set -> "x"
+           | _ -> "H"
+         )
+        with _ ->
+         "H"
+       )
+    | C.Name name ->
+       Str.global_replace (Str.regexp "[0-9]*$") "" name
+  in
+   let already_used name =
+    List.exists (function Some (C.Name n,_) -> n=name | _ -> false) context
+   in
+    if not (already_used basename) then
+     C.Name basename
+    else
+     let rec try_next n =
+      let name' = basename ^ string_of_int n in
+       if already_used name' then
+        try_next (n+1)
+       else
+        C.Name name'
+     in
+      try_next 1
+;;
 
 (* identity_relocation_list_for_metavariable i canonical_context         *)
 (* returns the identity relocation list, which is the list [1 ; ... ; n] *)
index de0b375960ffa6fe190e40576cb2da849b42b088..a1e4d21b61078b4c95c2bb03de597b6ea8f01ec5 100644 (file)
  * http://cs.unibo.it/helm/.
  *)
 
-val fresh_name : Cic.name -> string
+(* mk_fresh_name context name typ                      *)
+(* returns an identifier which is fresh in the context *)
+(* and that resembles [name] as much as possible.      *)
+(* [typ] will be the type of the variable              *)
+val mk_fresh_name : ProofEngineTypes.mk_fresh_name_type
 
 (* identity_relocation_list_for_metavariable i canonical_context         *)
 (* returns the identity relocation list, which is the list [1 ; ... ; n] *)
index f5e75fc47e817acc192fffd24e003839c70f4049..974e6893c9d42df4770fe62a33e47cb12dc96457 100644 (file)
@@ -39,3 +39,6 @@ type tactic = status:(proof * goal) -> proof * goal list
   (** tactic failure *)
 exception Fail of string
 
+  (** constraint: the returned value will always be constructed by Cic.Name **)
+type mk_fresh_name_type =
+ Cic.context -> Cic.name -> typ:Cic.term -> Cic.name
index 5f6dade405eeb62df65c1c82a9a1c1ced6f46401..f0a3070f7ffd2652e436e8eecb365010310b5667 100644 (file)
@@ -103,17 +103,17 @@ let generalize_tac ~term ~status:((proof,goal) as status) =
      in
 *)
      T.thens 
-      ~start:(P.cut_tac 
-       ~term:(
-         C.Prod(
-          (C.Name "dummy_for_gen"), 
-          (CicTypeChecker.type_of_aux' metasenv context term),
-          (ProofEngineReduction.replace_lifting_csc 1
-            ~equality:(==) 
-            ~what:term 
-            ~with_what:(C.Rel 1) (* C.Name "dummy_for_gen" *)  
-            ~where:ty)
-        )))    
+      ~start:
+        (P.cut_tac 
+         (C.Prod(
+           (C.Name "dummy_for_gen"), 
+           (CicTypeChecker.type_of_aux' metasenv context term),
+           (ProofEngineReduction.replace_lifting_csc 1
+             ~equality:(==) 
+             ~what:term 
+             ~with_what:(C.Rel 1) (* C.Name "dummy_for_gen" *)  
+             ~where:ty)
+         )))
       ~continuations: [(P.apply_tac ~term:(C.Rel 1)) ; T.id_tac]
       ~status
 ;;
@@ -153,9 +153,9 @@ let compare_tac ~term ~status:((proof, goal) as status) =
            ] 
           in
             T.thens 
-               ~start:(P.cut_tac ~term:term')
+               ~start:(P.cut_tac term')
                ~continuations:[
-                 T.then_ ~start:(P.intros_tac) ~continuation:(P.elim_intros_simpl_tac ~term:(C.Rel 1)) ; 
+                 T.then_ ~start:(P.intros_tac ()) ~continuation:(P.elim_intros_simpl_tac ~term:(C.Rel 1)) ; 
                  decide_equality_tac]  
       | (C.Appl [(C.MutInd (uri, 0, [])); _; t1; t2]) when (uri = (U.uri_of_string "cic:/Coq/Init/Logic_Type/eqT.ind")) ->
           let term' = (* (t1=t2) \/ ~(t1=t2) *)
@@ -170,9 +170,9 @@ let compare_tac ~term ~status:((proof, goal) as status) =
            ] 
           in
             T.thens 
-               ~start:(P.cut_tac ~term:term')
+               ~start:(P.cut_tac term')
                ~continuations:[
-                 T.then_ ~start:(P.intros_tac) ~continuation:(P.elim_intros_simpl_tac ~term:(C.Rel 1)) ; 
+                 T.then_ ~start:(P.intros_tac ()) ~continuation:(P.elim_intros_simpl_tac ~term:(C.Rel 1)) ; 
                  decide_equality_tac]  
       | _ -> raise (ProofEngineTypes.Fail "Compare: Not an equality") 
 ;;