X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2FgTopLevel%2FproofEngine.ml;h=5f0ba8aaa97ee00f7c085f70386e17b5244e3484;hb=d2c60bae1c4badba0a0f29e3fd2faed6d3a1869e;hp=fc0df2d02e50521ed730a0d25e9fe295f7069486;hpb=2329c7fd13fb6c88f9f82ccad6b25a67c9ce7acf;p=helm.git diff --git a/helm/gTopLevel/proofEngine.ml b/helm/gTopLevel/proofEngine.ml index fc0df2d02..5f0ba8aaa 100644 --- a/helm/gTopLevel/proofEngine.ml +++ b/helm/gTopLevel/proofEngine.ml @@ -1,8 +1,277 @@ -type binder_type = - Declaration - | Definition -;; +(* Copyright (C) 2000, HELM Team. + * + * This file is part of HELM, an Hypertextual, Electronic + * Library of Mathematics, developed at the Computer Science + * Department, University of Bologna, Italy. + * + * HELM is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * HELM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with HELM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * For details, see the HELM World-Wide-Web page, + * http://cs.unibo.it/helm/. + *) -type context = (binder_type * Cic.name * Cic.term) list;; +open ProofEngineHelpers +open ProofEngineTypes -type sequent = context * Cic.term;; + (* proof assistant status *) + +let proof = ref (None : proof option) +let goal = ref (None : goal option) + +let apply_tactic ~tactic:tactic = + match !proof,!goal with + None,_ + | _,None -> assert false + | Some proof', Some goal' -> + let (newproof, newgoals) = tactic ~status:(proof', goal') in + proof := Some newproof; + goal := + (match newgoals, newproof with + goal::_, _ -> Some goal + | [], (_,(goal,_,_)::_,_,_) -> + (* the tactic left no open goal ; let's choose the first open goal *) +(*CSC: here we could implement and use a proof-tree like notion... *) + Some goal + | _, _ -> None) + +(* metas_in_term term *) +(* Returns the ordered list of the metas that occur in [term]. *) +(* Duplicates are removed. The implementation is not very efficient. *) +let metas_in_term term = + let module C = Cic in + let rec aux = + function + C.Rel _ + | C.Var _ -> [] + | C.Meta (n,_) -> [n] + | C.Sort _ + | C.Implicit -> [] + | C.Cast (te,ty) -> (aux te) @ (aux ty) + | C.Prod (_,s,t) -> (aux s) @ (aux t) + | C.Lambda (_,s,t) -> (aux s) @ (aux t) + | C.LetIn (_,s,t) -> (aux s) @ (aux t) + | C.Appl l -> List.fold_left (fun i t -> i @ (aux t)) [] l + | C.Const _ + | C.MutInd _ + | C.MutConstruct _ -> [] + | C.MutCase (sp,cookingsno,i,outt,t,pl) -> + (aux outt) @ (aux t) @ + (List.fold_left (fun i t -> i @ (aux t)) [] pl) + | C.Fix (i,fl) -> + List.fold_left (fun i (_,_,ty,bo) -> i @ (aux bo) @ (aux ty)) [] fl + | C.CoFix (i,fl) -> + List.fold_left (fun i (_,ty,bo) -> i @ (aux bo) @ (aux ty)) [] fl + in + let metas = aux term in + let rec elim_duplicates = + function + [] -> [] + | he::tl -> + he::(elim_duplicates (List.filter (function el -> he <> el) tl)) + in + elim_duplicates metas + +(* perforate context term ty *) +(* replaces the term [term] in the proof with a new metavariable whose type *) +(* is [ty]. [context] must be the context of [term] in the whole proof. This *) +(* could be easily computed; so the only reasons to have it as an argument *) +(* are efficiency reasons. *) +let perforate context term ty = + let module C = Cic in + match !proof with + None -> assert false + | Some (uri,metasenv,bo,gty as proof') -> + let newmeta = new_meta proof' in + (* We push the new meta at the end of the list for pretty-printing *) + (* purposes: in this way metas are ordered. *) + let metasenv' = metasenv@[newmeta,context,ty] in + let irl = identity_relocation_list_for_metavariable context in +(*CSC: Bug: se ci sono due term uguali nella prova dovrei bucarne uno solo!!!*) + let bo' = + ProofEngineReduction.replace (==) term (C.Meta (newmeta,irl)) bo + in + (* It may be possible that some metavariables occurred only in *) + (* the term we are perforating and they now occurs no more. We *) + (* get rid of them, collecting the really useful metavariables *) + (* in metasenv''. *) +(*CSC: Bug: una meta potrebbe non comparire in bo', ma comparire nel tipo *) +(*CSC: di una metavariabile che compare in bo'!!!!!!! *) + let newmetas = metas_in_term bo' in + let metasenv'' = + List.filter (function (n,_,_) -> List.mem n newmetas) metasenv' + in + proof := Some (uri,metasenv'',bo',gty) ; + goal := Some newmeta + + +(************************************************************) +(* Some easy tactics. *) +(************************************************************) + +(*CSC: generatore di nomi? Chiedere il nome? *) +let fresh_name = + let next_fresh_index = ref 0 +in + function () -> + incr next_fresh_index ; + "fresh_name" ^ string_of_int !next_fresh_index + +let reduction_tactic reduction_function term = + let curi,metasenv,pbo,pty = + match !proof with + None -> assert false + | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty + in + let metano,context,ty = + match !goal with + None -> assert false + | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv + in + (* We don't know if [term] is a subterm of [ty] or a subterm of *) + (* the type of one metavariable. So we replace it everywhere. *) + (*CSC: Il vero problema e' che non sapendo dove sia il term non *) + (*CSC: sappiamo neppure quale sia il suo contesto!!!! Insomma, *) + (*CSC: e' meglio prima cercare il termine e scoprirne il *) + (*CSC: contesto, poi ridurre e infine rimpiazzare. *) + let replace context where= +(*CSC: Per il momento se la riduzione fallisce significa solamente che *) +(*CSC: siamo nel contesto errato. Metto il try, ma che schifo!!!! *) +(*CSC: Anche perche' cosi' catturo anche quelle del replace che non dovrei *) + try + let term' = reduction_function context term in + ProofEngineReduction.replace ~equality:(==) ~what:term ~with_what:term' + ~where:where + with + _ -> where + in + let ty' = replace context ty in + let context' = + List.fold_right + (fun entry context -> + match entry with + Some (name,Cic.Def t) -> + (Some (name,Cic.Def (replace context t)))::context + | Some (name,Cic.Decl t) -> + (Some (name,Cic.Decl (replace context t)))::context + | None -> None::context + ) context [] + in + let metasenv' = + List.map + (function + (n,_,_) when n = metano -> (metano,context',ty') + | _ as t -> t + ) metasenv + in + proof := Some (curi,metasenv',pbo,pty) ; + goal := Some metano + +(* Reduces [term] using [reduction_function] in the current scratch goal [ty] *) +let reduction_tactic_in_scratch reduction_function term ty = + let metasenv = + match !proof with + None -> [] + | Some (_,metasenv,_,_) -> metasenv + in + let metano,context,_ = + match !goal with + None -> assert false + | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv + in + let term' = reduction_function context term in + ProofEngineReduction.replace + ~equality:(==) ~what:term ~with_what:term' ~where:ty + +let whd = reduction_tactic CicReduction.whd +let reduce = reduction_tactic ProofEngineReduction.reduce +let simpl = reduction_tactic ProofEngineReduction.simpl + +let whd_in_scratch = reduction_tactic_in_scratch CicReduction.whd +let reduce_in_scratch = + reduction_tactic_in_scratch ProofEngineReduction.reduce +let simpl_in_scratch = + reduction_tactic_in_scratch ProofEngineReduction.simpl + +(* It is just the opposite of whd. The code should probably be merged. *) +let fold term = + let curi,metasenv,pbo,pty = + match !proof with + None -> assert false + | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty + in + let metano,context,ty = + match !goal with + None -> assert false + | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv + in + let term' = CicReduction.whd context term in + (* We don't know if [term] is a subterm of [ty] or a subterm of *) + (* the type of one metavariable. So we replace it everywhere. *) + (*CSC: ma si potrebbe ovviare al problema. Ma non credo *) + (*CSC: che si guadagni nulla in fatto di efficienza. *) + let replace = + ProofEngineReduction.replace + ~equality: + (ProofEngineReduction.syntactic_equality ~alpha_equivalence:false) + ~what:term' ~with_what:term + in + let ty' = replace ty in + let context' = + List.map + (function + Some (n,Cic.Decl t) -> Some (n,Cic.Decl (replace t)) + | Some (n,Cic.Def t) -> Some (n,Cic.Def (replace t)) + | None -> None + ) context + in + let metasenv' = + List.map + (function + (n,_,_) when n = metano -> (metano,context',ty') + | _ as t -> t + ) metasenv + in + proof := Some (curi,metasenv',pbo,pty) ; + goal := Some metano + +(************************************************************) +(* Tactics defined elsewhere *) +(************************************************************) + + (* primitive tactics *) + +let apply term = apply_tactic (PrimitiveTactics.apply_tac ~term) +let intros () = + apply_tactic (PrimitiveTactics.intros_tac ~name:(fresh_name ())) +let cut term = apply_tactic (PrimitiveTactics.cut_tac ~term) +let letin term = apply_tactic (PrimitiveTactics.letin_tac ~term) +let exact term = apply_tactic (PrimitiveTactics.exact_tac ~term) +let elim_intros_simpl term = + apply_tactic (PrimitiveTactics.elim_intros_simpl_tac ~term) +let change ~goal_input:what ~input:with_what = + apply_tactic (PrimitiveTactics.change_tac ~what ~with_what) + + (* structural tactics *) + +let clearbody hyp = apply_tactic (ProofEngineStructuralRules.clearbody ~hyp) +let clear hyp = apply_tactic (ProofEngineStructuralRules.clear ~hyp) + + (* other tactics *) + +let elim_type term = apply_tactic (Ring.elim_type_tac ~term) +let ring () = apply_tactic Ring.ring_tac +let fourier () = apply_tactic FourierR.fourier_tac +let rewrite_simpl term = apply_tactic (FourierR.rewrite_simpl_tac ~term)