diff options
| author | corbinea | 2003-04-25 19:55:41 +0000 |
|---|---|---|
| committer | corbinea | 2003-04-25 19:55:41 +0000 |
| commit | e12ff90edcc4af4eb0998f11186e998b23ada15d (patch) | |
| tree | 8d9f1939569005ea89a2e69bab1557ec1f601886 | |
| parent | b8f8a4fc5636d7751cf58c01044e8da56e92b074 (diff) | |
Added the Ground tactic.
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@3955 85f007b7-540e-0410-9357-904b9bb8a0f7
| -rw-r--r-- | .depend | 95 | ||||
| -rw-r--r-- | .depend.camlp4 | 1 | ||||
| -rw-r--r-- | Makefile | 25 | ||||
| -rw-r--r-- | contrib/first-order/engine.ml4 | 105 | ||||
| -rw-r--r-- | contrib/first-order/formula.ml | 213 | ||||
| -rw-r--r-- | contrib/first-order/formula.mli | 69 | ||||
| -rw-r--r-- | contrib/first-order/rules.ml | 186 | ||||
| -rw-r--r-- | contrib/first-order/rules.mli | 51 | ||||
| -rw-r--r-- | contrib/first-order/sequent.ml | 97 | ||||
| -rw-r--r-- | contrib/first-order/sequent.mli | 44 | ||||
| -rw-r--r-- | contrib/first-order/unify.ml | 131 | ||||
| -rw-r--r-- | contrib/first-order/unify.mli | 13 | ||||
| -rw-r--r-- | lib/heap.ml | 153 | ||||
| -rw-r--r-- | lib/heap.mli | 54 | ||||
| -rw-r--r-- | tactics/hipattern.ml | 15 | ||||
| -rw-r--r-- | tactics/hipattern.mli | 5 |
16 files changed, 1250 insertions, 7 deletions
@@ -400,6 +400,15 @@ contrib/extraction/scheme.cmi: contrib/extraction/miniml.cmi kernel/names.cmi \ lib/pp.cmi contrib/extraction/table.cmi: kernel/environ.cmi library/libnames.cmi \ contrib/extraction/miniml.cmi kernel/names.cmi kernel/term.cmi +contrib/first-order/formula.cmi: kernel/names.cmi kernel/sign.cmi \ + kernel/term.cmi +contrib/first-order/rules.cmi: contrib/first-order/formula.cmi \ + kernel/names.cmi contrib/first-order/sequent.cmi proofs/tacmach.cmi \ + kernel/term.cmi +contrib/first-order/sequent.cmi: contrib/first-order/formula.cmi lib/heap.cmi \ + kernel/names.cmi proofs/tacmach.cmi kernel/term.cmi lib/util.cmi +contrib/first-order/unify.cmi: contrib/first-order/sequent.cmi \ + kernel/term.cmi contrib/funind/tacinvutils.cmi: interp/coqlib.cmi tactics/equality.cmi \ pretyping/evd.cmi pretyping/inductiveops.cmi kernel/names.cmi lib/pp.cmi \ parsing/printer.cmi proofs/proof_type.cmi pretyping/reductionops.cmi \ @@ -733,6 +742,8 @@ lib/gset.cmo: lib/gset.cmi lib/gset.cmx: lib/gset.cmi lib/hashcons.cmo: lib/hashcons.cmi lib/hashcons.cmx: lib/hashcons.cmi +lib/heap.cmo: lib/heap.cmi +lib/heap.cmx: lib/heap.cmi lib/options.cmo: lib/util.cmi lib/options.cmi lib/options.cmx: lib/util.cmx lib/options.cmi lib/pp.cmo: lib/pp_control.cmi lib/pp.cmi @@ -2305,6 +2316,40 @@ translate/ppvernacnew.cmx: parsing/ast.cmx interp/constrextern.cmx \ pretyping/rawterm.cmx interp/reserve.cmx proofs/tacexpr.cmx \ tactics/tacinterp.cmx pretyping/termops.cmx interp/topconstr.cmx \ lib/util.cmx toplevel/vernacexpr.cmx translate/ppvernacnew.cmi +user-contrib/formula.cmo: interp/coqlib.cmi kernel/declarations.cmi \ + library/global.cmi tactics/hipattern.cmi pretyping/inductiveops.cmi \ + kernel/names.cmi pretyping/reductionops.cmi kernel/sign.cmi \ + proofs/tacmach.cmi kernel/term.cmi pretyping/termops.cmi lib/util.cmi +user-contrib/formula.cmx: interp/coqlib.cmx kernel/declarations.cmx \ + library/global.cmx tactics/hipattern.cmx pretyping/inductiveops.cmx \ + kernel/names.cmx pretyping/reductionops.cmx kernel/sign.cmx \ + proofs/tacmach.cmx kernel/term.cmx pretyping/termops.cmx lib/util.cmx +user-contrib/rules.cmo: kernel/declarations.cmi \ + contrib/first-order/formula.cmi kernel/names.cmi pretyping/rawterm.cmi \ + pretyping/reductionops.cmi contrib/first-order/sequent.cmi \ + kernel/sign.cmi proofs/tacmach.cmi tactics/tacticals.cmi \ + tactics/tactics.cmi kernel/term.cmi pretyping/termops.cmi \ + contrib/first-order/unify.cmi lib/util.cmi +user-contrib/rules.cmx: kernel/declarations.cmx \ + contrib/first-order/formula.cmx kernel/names.cmx pretyping/rawterm.cmx \ + pretyping/reductionops.cmx contrib/first-order/sequent.cmx \ + kernel/sign.cmx proofs/tacmach.cmx tactics/tacticals.cmx \ + tactics/tactics.cmx kernel/term.cmx pretyping/termops.cmx \ + contrib/first-order/unify.cmx lib/util.cmx +user-contrib/sequent.cmo: interp/constrextern.cmi \ + contrib/first-order/formula.cmi library/global.cmi kernel/names.cmi \ + lib/pp.cmi parsing/ppconstr.cmi proofs/tacmach.cmi kernel/term.cmi \ + lib/util.cmi +user-contrib/sequent.cmx: interp/constrextern.cmx \ + contrib/first-order/formula.cmx library/global.cmx kernel/names.cmx \ + lib/pp.cmx parsing/ppconstr.cmx proofs/tacmach.cmx kernel/term.cmx \ + lib/util.cmx +user-contrib/unify.cmo: proofs/clenv.cmi contrib/first-order/formula.cmi \ + pretyping/reductionops.cmi contrib/first-order/sequent.cmi \ + proofs/tacmach.cmi kernel/term.cmi pretyping/termops.cmi lib/util.cmi +user-contrib/unify.cmx: proofs/clenv.cmx contrib/first-order/formula.cmx \ + pretyping/reductionops.cmx contrib/first-order/sequent.cmx \ + proofs/tacmach.cmx kernel/term.cmx pretyping/termops.cmx lib/util.cmx contrib/cc/ccalgo.cmo: kernel/names.cmi kernel/term.cmi contrib/cc/ccalgo.cmi contrib/cc/ccalgo.cmx: kernel/names.cmx kernel/term.cmx contrib/cc/ccalgo.cmi contrib/cc/ccproof.cmo: contrib/cc/ccalgo.cmi kernel/names.cmi \ @@ -2721,6 +2766,54 @@ contrib/field/field.cmx: toplevel/cerrors.cmx interp/constrintern.cmx \ proofs/tacmach.cmx tactics/tacticals.cmx kernel/term.cmx \ interp/topconstr.cmx pretyping/typing.cmx lib/util.cmx \ toplevel/vernacexpr.cmx toplevel/vernacinterp.cmx +contrib/first-order/engine.cmo: toplevel/cerrors.cmi parsing/egrammar.cmi \ + contrib/first-order/formula.cmi interp/genarg.cmi parsing/pcoq.cmi \ + lib/pp.cmi parsing/pptactic.cmi proofs/refiner.cmi \ + contrib/first-order/rules.cmi contrib/first-order/sequent.cmi \ + proofs/tacexpr.cmo tactics/tacinterp.cmi proofs/tacmach.cmi \ + tactics/tacticals.cmi tactics/tactics.cmi kernel/term.cmi lib/util.cmi +contrib/first-order/engine.cmx: toplevel/cerrors.cmx parsing/egrammar.cmx \ + contrib/first-order/formula.cmx interp/genarg.cmx parsing/pcoq.cmx \ + lib/pp.cmx parsing/pptactic.cmx proofs/refiner.cmx \ + contrib/first-order/rules.cmx contrib/first-order/sequent.cmx \ + proofs/tacexpr.cmx tactics/tacinterp.cmx proofs/tacmach.cmx \ + tactics/tacticals.cmx tactics/tactics.cmx kernel/term.cmx lib/util.cmx +contrib/first-order/formula.cmo: interp/coqlib.cmi kernel/declarations.cmi \ + library/global.cmi tactics/hipattern.cmi pretyping/inductiveops.cmi \ + kernel/names.cmi pretyping/reductionops.cmi kernel/sign.cmi \ + proofs/tacmach.cmi kernel/term.cmi pretyping/termops.cmi lib/util.cmi \ + contrib/first-order/formula.cmi +contrib/first-order/formula.cmx: interp/coqlib.cmx kernel/declarations.cmx \ + library/global.cmx tactics/hipattern.cmx pretyping/inductiveops.cmx \ + kernel/names.cmx pretyping/reductionops.cmx kernel/sign.cmx \ + proofs/tacmach.cmx kernel/term.cmx pretyping/termops.cmx lib/util.cmx \ + contrib/first-order/formula.cmi +contrib/first-order/rules.cmo: kernel/declarations.cmi \ + contrib/first-order/formula.cmi kernel/names.cmi pretyping/rawterm.cmi \ + pretyping/reductionops.cmi contrib/first-order/sequent.cmi \ + kernel/sign.cmi proofs/tacmach.cmi tactics/tacticals.cmi \ + tactics/tactics.cmi kernel/term.cmi pretyping/termops.cmi \ + contrib/first-order/unify.cmi lib/util.cmi contrib/first-order/rules.cmi +contrib/first-order/rules.cmx: kernel/declarations.cmx \ + contrib/first-order/formula.cmx kernel/names.cmx pretyping/rawterm.cmx \ + pretyping/reductionops.cmx contrib/first-order/sequent.cmx \ + kernel/sign.cmx proofs/tacmach.cmx tactics/tacticals.cmx \ + tactics/tactics.cmx kernel/term.cmx pretyping/termops.cmx \ + contrib/first-order/unify.cmx lib/util.cmx contrib/first-order/rules.cmi +contrib/first-order/sequent.cmo: contrib/first-order/formula.cmi lib/heap.cmi \ + kernel/names.cmi proofs/tacmach.cmi kernel/term.cmi lib/util.cmi \ + contrib/first-order/sequent.cmi +contrib/first-order/sequent.cmx: contrib/first-order/formula.cmx lib/heap.cmx \ + kernel/names.cmx proofs/tacmach.cmx kernel/term.cmx lib/util.cmx \ + contrib/first-order/sequent.cmi +contrib/first-order/unify.cmo: proofs/clenv.cmi \ + contrib/first-order/formula.cmi pretyping/reductionops.cmi \ + contrib/first-order/sequent.cmi proofs/tacmach.cmi kernel/term.cmi \ + pretyping/termops.cmi lib/util.cmi contrib/first-order/unify.cmi +contrib/first-order/unify.cmx: proofs/clenv.cmx \ + contrib/first-order/formula.cmx pretyping/reductionops.cmx \ + contrib/first-order/sequent.cmx proofs/tacmach.cmx kernel/term.cmx \ + pretyping/termops.cmx lib/util.cmx contrib/first-order/unify.cmi contrib/fourier/fourierR.cmo: proofs/clenv.cmi tactics/contradiction.cmi \ interp/coqlib.cmi tactics/equality.cmi contrib/fourier/fourier.cmo \ library/libnames.cmi library/library.cmi kernel/names.cmi \ @@ -3355,6 +3448,8 @@ contrib/linear/dpc.cmo: parsing/grammar.cma contrib/linear/dpc.cmx: parsing/grammar.cma contrib/funind/tacinv.cmo: parsing/grammar.cma contrib/funind/tacinv.cmx: parsing/grammar.cma +contrib/first-order/engine.cmo: parsing/grammar.cma +contrib/first-order/engine.cmx: parsing/grammar.cma parsing/lexer.cmo: parsing/lexer.cmx: parsing/q_util.cmo: diff --git a/.depend.camlp4 b/.depend.camlp4 index c607a972c2..e17db259d9 100644 --- a/.depend.camlp4 +++ b/.depend.camlp4 @@ -20,6 +20,7 @@ contrib/cc/cctac.ml: parsing/grammar.cma contrib/linear/ccidpc.ml: parsing/grammar.cma contrib/linear/dpc.ml: parsing/grammar.cma contrib/funind/tacinv.ml: parsing/grammar.cma +contrib/first-order/engine.ml: parsing/grammar.cma parsing/lexer.ml: parsing/q_util.ml: parsing/q_coqast.ml: @@ -8,6 +8,7 @@ # $Id$ + # Makefile for Coq # # To be used with GNU Make. @@ -46,7 +47,7 @@ LOCALINCLUDES=-I config -I tools -I scripts -I lib -I kernel -I library \ -I contrib/extraction -I contrib/correctness \ -I contrib/interface -I contrib/fourier \ -I contrib/jprover -I contrib/cc -I contrib/linear \ - -I contrib/funind + -I contrib/funind -I contrib/first-order MLINCLUDES=$(LOCALINCLUDES) -I $(MYCAMLP4LIB) @@ -83,7 +84,8 @@ LIBREP=\ lib/hashcons.cmo lib/dyn.cmo lib/system.cmo lib/options.cmo \ lib/bstack.cmo lib/edit.cmo lib/gset.cmo lib/gmap.cmo \ lib/tlm.cmo lib/bij.cmo lib/gmapl.cmo lib/profile.cmo lib/explore.cmo \ - lib/predicate.cmo lib/rtree.cmo # Rem: Cygwin already uses variable LIB + lib/predicate.cmo lib/rtree.cmo lib/heap.cmo +# Rem: Cygwin already uses variable LIB KERNEL=\ kernel/names.cmo kernel/univ.cmo \ @@ -273,6 +275,11 @@ JPROVERCMO=\ FUNINDCMO=\ contrib/funind/tacinvutils.cmo contrib/funind/tacinv.cmo +FOCMO=\ + contrib/first-order/formula.cmo contrib/first-order/sequent.cmo \ + contrib/first-order/unify.cmo contrib/first-order/rules.cmo \ + contrib/first-order/engine.cmo + CCCMO=contrib/cc/ccalgo.cmo contrib/cc/ccproof.cmo contrib/cc/cctac.cmo LINEARCMO=\ @@ -288,11 +295,21 @@ LINEARCMO=\ contrib/linear/dpc.cmo ML4FILES += contrib/jprover/jprover.ml4 contrib/cc/cctac.ml4 \ - contrib/linear/ccidpc.ml4 contrib/linear/dpc.ml4 contrib/funind/tacinv.ml4 + contrib/linear/ccidpc.ml4 contrib/linear/dpc.ml4 contrib/funind/tacinv.ml4 \ + contrib/first-order/engine.ml4 + +USERCMO =\ + user-contrib/formula.cmo \ + user-contrib/prio.cmo \ + user-contrib/sequent.cmo \ + user-contrib/unify.cmo \ + user-contrib/rules.cmo \ + user-contrib/engine.cmo + CONTRIB=$(OMEGACMO) $(ROMEGACMO) $(RINGCMO) $(FIELDCMO) \ $(FOURIERCMO) $(EXTRACTIONCMO) $(JPROVERCMO) $(XMLCMO) \ - $(CORRECTNESSCMO) $(CCCMO) $(LINEARCMO) $(FUNINDCMO) $(USERCMO) + $(CORRECTNESSCMO) $(CCCMO) $(LINEARCMO) $(FUNINDCMO) $(FOCMO) CMA=$(CLIBS) $(CAMLP4OBJS) CMXA=$(CMA:.cma=.cmxa) diff --git a/contrib/first-order/engine.ml4 b/contrib/first-order/engine.ml4 new file mode 100644 index 0000000000..8b85316a90 --- /dev/null +++ b/contrib/first-order/engine.ml4 @@ -0,0 +1,105 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(*i camlp4deps: "parsing/grammar.cma" i*) + +(* $Id$ *) + +open Formula +open Sequent +open Rules +open Term +open Tacmach +open Tactics +open Tacticals +open Util + +let mytac ninst solver gl= + let metagen=newcnt () in + let rec toptac ninst seq gl= + match seq.gl with + Atomic t-> + tclORELSE (axiom_tac t seq) (left_tac ninst seq []) gl + | Complex (pat,l)-> + match pat with + Rand->and_tac seq (toptac ninst) metagen gl + | Rforall->forall_tac seq (toptac ninst) metagen gl + | Rarrow->arrow_tac seq (toptac ninst) metagen gl + | _-> + if not (is_empty_left seq) && rev_left seq then + left_tac ninst seq [] gl + else + right_tac ninst seq pat l [] gl + and right_tac ninst seq pat atoms ctx gl= + let re_add s=re_add_left_list ctx s in + match pat with + Ror-> + tclORELSE + (or_tac (re_add seq) (toptac ninst) metagen) + (left_tac ninst seq ctx) gl + | Rexists(i,dom)-> + tclORELSE + (if ninst=0 then tclFAIL 0 "max depth" else + exists_tac i dom atoms (re_add seq) (toptac (ninst-1)) metagen) + (left_tac ninst seq ctx) gl + | _-> anomaly "unreachable place" + and left_tac ninst seq ctx gl= + if is_empty_left seq then + solver gl (* put solver here *) + else + let (hd,seq1)=take_left seq in + let re_add s=re_add_left_list ctx s in + match hd.pat with + Lfalse->left_false_tac hd.id gl + | Land ind->left_and_tac ind hd.id seq1 (toptac ninst) metagen gl + | Lor ind->left_or_tac ind hd.id seq1 (toptac ninst) metagen gl + | Lforall (i,dom)-> + tclORELSE + (if ninst=0 then tclFAIL 0 "max depth" else + left_forall_tac i dom hd.atoms hd.id (re_add seq) + (toptac (ninst-1)) metagen) + (left_tac ninst seq1 (hd::ctx)) gl + | Lexists ->left_exists_tac hd.id seq1 (toptac ninst) metagen gl + | LAatom a-> + let pat,atoms= + match seq1.gl with + Atomic t->assert false + | Complex (pat,atoms)->pat,atoms in + tclORELSE + (ll_atom_tac a hd.id (re_add seq1) (toptac ninst) metagen) + (right_tac ninst seq1 pat atoms (hd::ctx)) gl + | LAfalse->ll_false_tac hd.id seq1 (toptac ninst) metagen gl + | LAand (ind,largs) | LAor(ind,largs) -> + ll_ind_tac ind largs hd.id seq1 (toptac ninst) metagen gl + | LAforall p -> + tclORELSE + (if ninst=0 then tclFAIL 0 "max depth" else + ll_forall_tac p hd.id (re_add seq1) + (toptac (ninst-1)) metagen) + (left_tac ninst seq1 (hd::ctx)) gl + | LAexists (ind,a,p,_) -> + ll_ind_tac ind [a;p] hd.id seq1 (toptac ninst) metagen gl + | LAarrow (a,b,c) -> + tclORELSE + (ll_arrow_tac a b c hd.id (re_add seq1) + (toptac ninst) metagen) + (left_tac ninst seq1 (hd::ctx)) gl in + wrap (List.length (pf_hyps gl)) true empty_seq (toptac ninst) metagen gl + +let default_solver=Tacinterp.interp <:tactic<Auto with *>> + +let default_depth=5 + +TACTIC EXTEND Ground + [ "Ground" ] -> [ mytac default_depth default_solver] +| [ "Ground" integer(n)] -> [ mytac n default_solver] +| [ "Ground" tactic(t)] -> [ mytac default_depth (snd t)] +| [ "Ground" integer(n) tactic(t)] -> [ mytac n (snd t)] +END + + diff --git a/contrib/first-order/formula.ml b/contrib/first-order/formula.ml new file mode 100644 index 0000000000..aee1c01d07 --- /dev/null +++ b/contrib/first-order/formula.ml @@ -0,0 +1,213 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Hipattern +open Names +open Term +open Termops +open Reductionops +open Tacmach +open Util +open Declarations + +type ('a,'b)sum=Left of 'a|Right of 'b + +type kind_of_formula= + Arrow of constr*constr + |And of inductive*constr list + |Or of inductive*constr list + |Exists of inductive*constr*constr*constr + |Forall of constr*constr + |Atom of constr + |False + +type counter = bool -> int + +let newcnt ()= + let cnt=ref (-1) in + fun b->if b then incr cnt;!cnt + +let constant path str ()=Coqlib.gen_constant "User" ["Init";path] str + +let op2bool=function Some _->true |None->false + +let id_ex=constant "Logic" "ex" +let id_sig=constant "Specif" "sig" +let id_sigT=constant "Specif" "sigT" +let id_sigS=constant "Specif" "sigS" +let id_not=constant "Logic" "not" + +let is_ex t = + t=(id_ex ()) || + t=(id_sig ()) || + t=(id_sigT ()) || + t=(id_sigS ()) + +let match_with_exist_term t= + match kind_of_term t with + App(t,v)-> + if t=id_ex () && (Array.length v)=2 then + let p=v.(1) in + match kind_of_term p with + Lambda(na,a,b)->Some(t,a,b,p) + | _ ->Some(t,v.(0),mkApp(p,[|mkRel 1|]),p) + else None + | _->None + +let match_with_not_term t= + match match_with_nottype t with + | None -> + (match kind_of_term t with + App (no,b) when no=id_not ()->Some (no,b.(0)) + | _->None) + | o -> o + +let rec nb_prod_after n c= + match kind_of_term c with + | Prod (_,_,b) ->if n>0 then nb_prod_after (n-1) b else + 1+(nb_prod_after 0 b) + | _ -> 0 + +let nhyps mip = + let constr_types = mip.mind_nf_lc in + let nhyps = nb_prod_after mip.mind_nparams in + Array.map nhyps constr_types + +let construct_nhyps ind= nhyps (snd (Global.lookup_inductive ind)) + +(* builds the array of arrays of constructor hyps for (ind Vargs)*) +let ind_hyps ind largs= + let (mib,mip) = Global.lookup_inductive ind in + if Inductiveops.mis_is_recursive (ind,mib,mip) then + failwith "no_recursion" else + let n=mip.mind_nparams in + if n<>(List.length largs) then anomaly "params ?" else + let p=nhyps mip in + let lp=Array.length p in + let types= mip.mind_nf_lc in + let myhyps i= + let t1=Term.prod_applist types.(i) largs in + fst (Sign.decompose_prod_n_assum p.(i) t1) in + Array.init lp myhyps + +let kind_of_formula cciterm = + match match_with_imp_term cciterm with + Some (a,b)-> Arrow(a,(pop b)) + |_-> + match match_with_forall_term cciterm with + Some (_,a,b)-> Forall(a,b) + |_-> + match match_with_exist_term cciterm with + Some (i,a,b,p)-> Exists((destInd i),a,b,p) + |_-> + match match_with_nodep_ind cciterm with + None -> Atom cciterm + | Some (i,l)-> + let ind=destInd i in + let (mib,mip) = Global.lookup_inductive ind in + if Inductiveops.mis_is_recursive (ind,mib,mip) then + Atom cciterm + else + match Array.length mip.mind_consnames with + 0->False + | 1->And(ind,l) + | _->Or(ind,l) + +let build_atoms metagen= + let rec build_rec env polarity cciterm = + match kind_of_formula cciterm with + False->[] + | Arrow (a,b)-> + (build_rec env (not polarity) a)@ + (build_rec env polarity b) + | And(i,l) | Or(i,l)-> + let v = ind_hyps i l in + Array.fold_right + (fun l accu-> + List.fold_right + (fun (_,_,t) accu0-> + (build_rec env polarity t)@accu0) l accu) v [] + | Forall(_,b)|Exists(_,_,b,_)-> + let var=mkMeta (metagen true) in + build_rec (var::env) polarity b + | Atom t-> + [polarity,(substnl env 0 cciterm)] + in build_rec [] + +type right_pattern = + Rand + | Ror + | Rforall + | Rexists of int*constr + | Rarrow + +type right_formula = + Complex of right_pattern*((bool*constr) list) + | Atomic of constr + +type left_pattern= + Lfalse + | Land of inductive + | Lor of inductive + | Lforall of int*constr + | Lexists + | LAatom of constr + | LAfalse + | LAand of inductive*constr list + | LAor of inductive*constr list + | LAforall of constr + | LAexists of inductive*constr*constr*constr + | LAarrow of constr*constr*constr + +type left_formula={id:identifier; + pat:left_pattern; + atoms:(bool*constr) list} + +exception Is_atom of constr + +let build_left_entry nam typ metagen= + try + let pattern= + match kind_of_formula typ with + False -> Lfalse + | Atom a -> raise (Is_atom a) + | And(i,_) -> Land i + | Or(i,_) -> Lor i + | Exists (_,_,_,_) -> Lexists + | Forall (d,_) -> let m=1+(metagen false) in Lforall(m,d) + | Arrow (a,b) -> + (match kind_of_formula a with + False-> LAfalse + | Atom a-> LAatom a + | And(i,l)-> LAand(i,l) + | Or(i,l)-> LAor(i,l) + | Arrow(a,c)-> LAarrow(a,c,b) + | Exists(i,a,_,p)->LAexists(i,a,p,b) + | Forall(_,_)->LAforall a) in + let l=build_atoms metagen false typ in + Left {id=nam;pat=pattern;atoms=l} + with Is_atom a-> Right a + +let build_right_entry typ metagen= + try + let pattern= + match kind_of_formula typ with + False -> raise (Is_atom typ) + | Atom a -> raise (Is_atom a) + | And(_,_) -> Rand + | Or(_,_) -> Ror + | Exists (_,d,_,_) -> + let m=1+(metagen false) in Rexists(m,d) + | Forall (_,a) -> Rforall + | Arrow (a,b) -> Rarrow in + let l=build_atoms metagen true typ in + Complex(pattern,l) + with Is_atom a-> Atomic a + diff --git a/contrib/first-order/formula.mli b/contrib/first-order/formula.mli new file mode 100644 index 0000000000..bb6dc030aa --- /dev/null +++ b/contrib/first-order/formula.mli @@ -0,0 +1,69 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Term +open Names + +type ('a,'b) sum = Left of 'a | Right of 'b + +type kind_of_formula= + Arrow of constr*constr + |And of inductive*constr list + |Or of inductive*constr list + |Exists of inductive*constr*constr*constr + |Forall of constr*constr + |Atom of constr + |False + +type counter = bool -> int + +val newcnt : unit -> counter + +val construct_nhyps : inductive -> int array + +val ind_hyps : inductive -> constr list -> Sign.rel_context array + +val kind_of_formula : constr -> kind_of_formula + +type right_pattern = + Rand + | Ror + | Rforall + | Rexists of int*constr + | Rarrow + +type right_formula = + Complex of right_pattern*((bool*constr) list) + | Atomic of constr + +type left_pattern= + Lfalse + | Land of inductive + | Lor of inductive + | Lforall of int*constr + | Lexists + | LAatom of constr + | LAfalse + | LAand of inductive*constr list + | LAor of inductive*constr list + | LAforall of constr + | LAexists of inductive*constr*constr*constr + | LAarrow of constr*constr*constr + +type left_formula={id:identifier; + pat:left_pattern; + atoms:(bool*constr) list} + +val build_left_entry : + identifier -> types -> counter -> (left_formula,types) sum + +val build_right_entry : types -> counter -> right_formula + + diff --git a/contrib/first-order/rules.ml b/contrib/first-order/rules.ml new file mode 100644 index 0000000000..5e2e0a72d6 --- /dev/null +++ b/contrib/first-order/rules.ml @@ -0,0 +1,186 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Util +open Names +open Term +open Tacmach +open Tactics +open Tacticals +open Termops +open Reductionops +open Declarations +open Formula +open Sequent +open Unify + +type hptac= Sequent.t -> (Sequent.t -> tactic) -> counter -> tactic + +type lhptac= identifier -> hptac + +let wrap n b seq tacrec metagen gls= + let nc=pf_hyps gls in + let rec aux i nc= + if i<=0 then seq else + match nc with + []->anomaly "Not the expected number of hyps" + | (id,_,typ)::q-> (add_left (id,typ) (aux (i-1) q) metagen) in + let seq1= + if b then + (change_right (pf_concl gls) (aux n nc) metagen) + else + (aux n nc) in + tacrec seq1 gls + +let axiom_tac t seq= + try exact_no_check (mkVar (find_left t seq)) + with Not_found->tclFAIL 0 "No axiom link" + +let and_tac seq tacrec metagen= + tclTHEN simplest_split (wrap 0 true seq tacrec metagen) + +let left_and_tac ind id seq tacrec metagen= + let n=(construct_nhyps ind).(0) in + tclTHENLIST + [simplest_elim (mkVar id); + clear [id]; + tclDO n intro; + wrap n false seq tacrec metagen] + +let or_tac seq tacrec metagen= + any_constructor (Some (tclSOLVE [wrap 0 true seq tacrec metagen])) + +let left_or_tac ind id seq tacrec metagen= + let v=construct_nhyps ind in + let f n= + tclTHENLIST + [clear [id]; + tclDO n intro; + wrap n false seq tacrec metagen] in + tclTHENSV + (simplest_elim (mkVar id)) + (Array.map f v) + +let forall_tac seq tacrec metagen= + tclTHEN intro (wrap 0 true seq tacrec metagen) + +let left_forall_tac i dom atoms id seq tacrec metagen= + let insts=find_instances i atoms seq in + if insts=[] then + tclTHENS (cut dom) + [tclTHENLIST + [intro; + (fun gls->generalize + [mkApp(mkVar id,[|mkVar (Tacmach.pf_nth_hyp_id gls 1)|])] gls); + intro; + tclSOLVE [wrap 1 false seq tacrec metagen]] + ;tclIDTAC] + else + let tac t= + tclTHENLIST + [generalize [mkApp(mkVar id,[|t|])]; + intro; + tclSOLVE [wrap 1 false seq tacrec metagen]] in + tclFIRST (List.map tac insts) + +let arrow_tac seq tacrec metagen= + tclTHEN intro (wrap 1 true seq tacrec metagen) + +let exists_tac i dom atoms seq tacrec metagen= + let insts=find_instances i atoms seq in + if insts=[] then + tclTHENS (cut dom) + [tclTHENLIST + [intro; + (fun gls-> + split (Rawterm.ImplicitBindings + [mkVar (Tacmach.pf_nth_hyp_id gls 1)]) gls); + tclSOLVE [wrap 0 false seq tacrec metagen]] + ;tclIDTAC] + else + let tac t= + tclTHEN (split (Rawterm.ImplicitBindings [t])) + (tclSOLVE [wrap 0 true seq tacrec metagen]) in + tclFIRST (List.map tac insts) + +let left_exists_tac id seq tacrec metagen= + tclTHENLIST + [simplest_elim (mkVar id); + clear [id]; + tclDO 2 intro; + (wrap 1 false seq tacrec metagen)] + +let ll_arrow_tac a b c id seq tacrec metagen= + let cc=mkProd(Anonymous,a,(lift 1 b)) in + let d=mkLambda (Anonymous,b, + mkApp ((mkVar id), + [|mkLambda (Anonymous,(lift 1 a),(mkRel 2))|])) in + tclTHENS (cut c) + [tclTHENLIST + [intro; + clear [id]; + wrap 1 false seq tacrec metagen]; + tclTHENS (cut cc) + [exact_no_check (mkVar id); + tclTHENLIST + [generalize [d]; + intro; + clear [id]; + tclSOLVE [wrap 1 true seq tacrec metagen]]]] + +let ll_atom_tac a id seq tacrec metagen= + try + tclTHENLIST + [generalize [mkApp(mkVar id,[|mkVar (find_left a seq)|])]; + clear [id]; + intro; + wrap 1 false seq tacrec metagen] + with Not_found->tclFAIL 0 "No link" + +let ll_false_tac id seq tacrec metagen= + tclTHEN (clear [id]) (wrap 0 false seq tacrec metagen) + +let left_false_tac id= + simplest_elim (mkVar id) + +(*We use this function for and, or, exists*) + +let ll_ind_tac ind largs id seq tacrec metagen gl= + (try + let rcs=ind_hyps ind largs in + let vargs=Array.of_list largs in + (* construire le terme H->B, le generaliser etc *) + let myterm i= + let rc=rcs.(i) in + let p=List.length rc in + let cstr=mkApp ((mkConstruct (ind,(i+1))),vargs) in + let vars=Array.init p (fun j->mkRel (p-j)) in + let capply=mkApp ((lift p cstr),vars) in + let head=mkApp ((lift p (mkVar id)),[|capply|]) in + Sign.it_mkLambda_or_LetIn head rc in + let lp=Array.length rcs in + let newhyps=List.map myterm (interval 0 (lp-1)) in + tclTHENLIST + [generalize newhyps; + clear [id]; + tclDO lp intro; + wrap lp false seq tacrec metagen] + with Invalid_argument _ ->tclFAIL 0 "") gl + +let ll_forall_tac prod id seq tacrec metagen= + tclTHENS (cut prod) + [tclTHENLIST + [(fun gls->generalize + [mkApp(mkVar id,[|mkVar (Tacmach.pf_nth_hyp_id gls 1)|])] gls); + clear [id]; + intro; + tclSOLVE [wrap 1 false seq tacrec metagen]]; + tclSOLVE [wrap 0 true seq tacrec metagen]] + diff --git a/contrib/first-order/rules.mli b/contrib/first-order/rules.mli new file mode 100644 index 0000000000..98dc01bbed --- /dev/null +++ b/contrib/first-order/rules.mli @@ -0,0 +1,51 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Term +open Tacmach +open Names + +type hptac= Sequent.t -> (Sequent.t -> tactic) -> Formula.counter -> tactic + +type lhptac= identifier -> hptac + +val wrap : int -> bool -> hptac + +val axiom_tac : constr -> Sequent.t -> tactic + +val and_tac : hptac + +val left_and_tac : inductive -> lhptac + +val or_tac : hptac + +val left_or_tac : inductive -> lhptac + +val forall_tac : hptac + +val left_forall_tac : int -> types -> (bool * constr) list -> lhptac + +val arrow_tac : hptac + +val exists_tac : int -> types -> (bool * constr) list -> hptac + +val left_exists_tac : lhptac + +val ll_arrow_tac : constr -> constr -> constr -> lhptac + +val ll_atom_tac : constr -> lhptac + +val ll_false_tac : lhptac + +val left_false_tac : identifier -> tactic + +val ll_ind_tac : inductive -> constr list -> lhptac + +val ll_forall_tac : types -> lhptac diff --git a/contrib/first-order/sequent.ml b/contrib/first-order/sequent.ml new file mode 100644 index 0000000000..84e3f18ed4 --- /dev/null +++ b/contrib/first-order/sequent.ml @@ -0,0 +1,97 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Term +open Util +open Formula +open Tacmach +open Names + +let priority=function (* pure heuristics, <=0 for non reversible *) + Lfalse ->1000 + | Land _ -> 90 + | Lor _ -> 40 + | Lforall (_,_) -> -20 + | Lexists -> 60 + | LAatom _ -> 0 + | LAfalse -> 100 + | LAand (_,_) -> 80 + | LAor (_,_) -> 70 + | LAforall _ -> -30 + | LAexists (_,_,_,_) -> 50 + | LAarrow (_,_,_) -> -10 + + +let right_atomic=function + Atomic _->true + | Complex (_,_) ->false + +let right_reversible= + function + Rarrow | Rand | Rforall->true + | _ ->false + +let left_reversible lpat=(priority lpat)>0 + +module OrderedFormula= +struct + type t=left_formula + let compare e1 e2=(priority e1.pat) - (priority e2.pat) +end + +module OrderedConstr= +struct + type t=constr + let compare=Pervasives.compare +end + +module CM=Map.Make(OrderedConstr) + +module HP=Heap.Functional(OrderedFormula) + +type t= + {hyps:HP.t;hatoms:identifier CM.t;gl:right_formula} + +let add_left (nam,t) seq metagen= + match build_left_entry nam t metagen with + Left f->{seq with hyps=HP.add f seq.hyps} + | Right t->{seq with hatoms=CM.add t nam seq.hatoms} + +let re_add_left_list lf seq= + {seq with hyps=List.fold_right HP.add lf seq.hyps} + +let change_right t seq metagen= + {seq with gl=build_right_entry t metagen} + +let find_left t seq=CM.find t seq.hatoms + +let atomic_right seq= right_atomic seq.gl + +let rev_left seq= + try + let lpat=(HP.maximum seq.hyps).pat in + left_reversible lpat + with Heap.EmptyHeap -> false + +let is_empty_left seq= + seq.hyps=HP.empty + +let take_left seq= + let hd=HP.maximum seq.hyps + and hp=HP.remove seq.hyps in + hd,{seq with hyps=hp} + +let take_right seq=seq.gl + +let empty_seq= + {hyps=HP.empty; + hatoms=CM.empty; + gl=Atomic (mkMeta 1)} + diff --git a/contrib/first-order/sequent.mli b/contrib/first-order/sequent.mli new file mode 100644 index 0000000000..8b72b3f210 --- /dev/null +++ b/contrib/first-order/sequent.mli @@ -0,0 +1,44 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Term +open Util +open Formula +open Tacmach +open Names + +val right_reversible : right_pattern -> bool + +val left_reversible : left_pattern -> bool + +module CM: Map.S with type key=constr + +module HP: Heap.S with type elt=left_formula + +type t = {hyps:HP.t;hatoms: identifier CM.t;gl:right_formula} + +val add_left : identifier * constr -> t -> counter -> t + +val re_add_left_list : left_formula list -> t -> t + +val change_right : constr -> t -> counter -> t + +val find_left : constr -> t -> identifier + +val rev_left : t -> bool + +val is_empty_left : t -> bool + +val take_left : t -> left_formula * t + +val take_right : t -> right_formula + +val empty_seq : t + diff --git a/contrib/first-order/unify.ml b/contrib/first-order/unify.ml new file mode 100644 index 0000000000..9d6bb39d31 --- /dev/null +++ b/contrib/first-order/unify.ml @@ -0,0 +1,131 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(*i $Id$ i*) + +open Util +open Formula +open Sequent +open Tacmach +open Term +open Termops +open Reductionops + +exception UFAIL of constr*constr + +let unif t1 t2= (* Martelli-Montanari style *) + let bige=Queue.create () + and sigma=ref [] in + let bind i t= + sigma:=(i,t):: + (List.map (function (n,tn)->(n,subst_meta [i,t] tn)) !sigma) in + let rec head_reduce t= + (* forbids non-sigma-normal meta in head position*) + match kind_of_term t with + Meta i-> + (try + head_reduce (List.assoc i !sigma) + with Not_found->t) + | _->t in + Queue.add (t1,t2) bige; + try while true do + let t1,t2=Queue.take bige in + let nt1=head_reduce (whd_betaiotazeta t1) + and nt2=head_reduce (whd_betaiotazeta t2) in + match (kind_of_term nt1),(kind_of_term nt2) with + Meta i,Meta j-> + if i<>j then + if i<j then bind j nt1 + else bind i nt2 + | Meta i,_ -> + let t=subst_meta !sigma nt2 in + if Intset.is_empty (free_rels t) && + not (occur_term (mkMeta i) t) then + bind i t else raise (UFAIL(nt1,nt2)) + | _,Meta i -> + let t=subst_meta !sigma nt1 in + if Intset.is_empty (free_rels t) && + not (occur_term (mkMeta i) t) then + bind i t else raise (UFAIL(nt1,nt2)) + | Cast(_,_),_->Queue.add (strip_outer_cast nt1,nt2) bige + | _,Cast(_,_)->Queue.add (nt1,strip_outer_cast nt2) bige + | (Prod(_,a,b),Prod(_,c,d))|(Lambda(_,a,b),Lambda(_,c,d))-> + Queue.add (a,c) bige;Queue.add (pop b,pop d) bige + | Case (_,pa,ca,va),Case (_,pb,cb,vb)-> + Queue.add (pa,pb) bige; + Queue.add (ca,cb) bige; + let l=Array.length va in + if l<>(Array.length vb) then + raise (UFAIL (nt1,nt2)) + else + for i=0 to l-1 do + Queue.add (va.(i),vb.(i)) bige + done + | App(ha,va),App(hb,vb)-> + Queue.add (ha,hb) bige; + let l=Array.length va in + if l<>(Array.length vb) then + raise (UFAIL (nt1,nt2)) + else + for i=0 to l-1 do + Queue.add (va.(i),vb.(i)) bige + done + | _->if not (eq_constr nt1 nt2) then raise (UFAIL (nt1,nt2)) + done; + assert false + (* this place is unreachable but needed for the sake of typing *) + with Queue.Empty-> !sigma + +(* collect tries finds ground instantiations for Meta i*) +let is_ground t=(Clenv.collect_metas t)=[] + +let collect i l= + try + let t=List.assoc i l in + if is_ground t then Some t else None + with Not_found->None + +let unif_atoms_for_meta i (b1,t1) (b2,t2)= + if b1=b2 then None else + try + collect i (unif t1 t2) + with UFAIL(_,_) ->None + +module OrderedConstr= +struct + type t=constr + let compare=Pervasives.compare +end + +module CS=Set.Make(OrderedConstr) + +let match_atom_list i atom l= + let f atom2 accu= + match unif_atoms_for_meta i atom atom2 with + None-> accu + | Some t-> CS.add t accu in + List.fold_right f l CS.empty + +let match_lists i l1 l2= + let f atom accu= + CS.union (match_atom_list i atom l2) accu in + List.fold_right f l1 CS.empty + +let find_instances i l seq= + let match_hyp f accu= + CS.union (match_lists i l f.atoms) accu in + let match_atom t nam accu= + CS.union (match_atom_list i (false,t) l) accu in + let s1= + match seq.gl with + Atomic t->(match_atom_list i (true,t) l) + | Complex(_,l1)->(match_lists i l l1) in + let s2=CM.fold match_atom seq.hatoms s1 in + let s3=HP.fold match_hyp seq.hyps s2 in + CS.fold (fun x l->x::l) s3 [] + diff --git a/contrib/first-order/unify.mli b/contrib/first-order/unify.mli new file mode 100644 index 0000000000..04d7951014 --- /dev/null +++ b/contrib/first-order/unify.mli @@ -0,0 +1,13 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Term + +val find_instances : int -> (bool * constr) list -> Sequent.t -> constr list diff --git a/lib/heap.ml b/lib/heap.ml new file mode 100644 index 0000000000..8b8f1ef1b1 --- /dev/null +++ b/lib/heap.ml @@ -0,0 +1,153 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +(*s Heaps *) + +module type Ordered = sig + type t + val compare : t -> t -> int +end + +module type S =sig + + (* Type of functional heaps *) + type t + + (* Type of elements *) + type elt + + (* The empty heap *) + val empty : t + + (* [add x h] returns a new heap containing the elements of [h], plus [x]; + complexity $O(log(n))$ *) + val add : elt -> t -> t + + (* [maximum h] returns the maximum element of [h]; raises [EmptyHeap] + when [h] is empty; complexity $O(1)$ *) + val maximum : t -> elt + + (* [remove h] returns a new heap containing the elements of [h], except + the maximum of [h]; raises [EmptyHeap] when [h] is empty; + complexity $O(log(n))$ *) + val remove : t -> t + + (* usual iterators and combinators; elements are presented in + arbitrary order *) + val iter : (elt -> unit) -> t -> unit + + val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a + +end + +exception EmptyHeap + +(*s Functional implementation *) + +module Functional(X : Ordered) = struct + + (* Heaps are encoded as complete binary trees, i.e., binary trees + which are full expect, may be, on the bottom level where it is filled + from the left. + These trees also enjoy the heap property, namely the value of any node + is greater or equal than those of its left and right subtrees. + + There are 4 kinds of complete binary trees, denoted by 4 constructors: + [FFF] for a full binary tree (and thus 2 full subtrees); + [PPF] for a partial tree with a partial left subtree and a full + right subtree; + [PFF] for a partial tree with a full left subtree and a full right subtree + (but of different heights); + and [PFP] for a partial tree with a full left subtree and a partial + right subtree. *) + + type t = + | Empty + | FFF of t * X.t * t (* full (full, full) *) + | PPF of t * X.t * t (* partial (partial, full) *) + | PFF of t * X.t * t (* partial (full, full) *) + | PFP of t * X.t * t (* partial (full, partial) *) + + type elt = X.t + + let empty = Empty + + (* smart constructors for insertion *) + let p_f l x r = match l with + | Empty | FFF _ -> PFF (l, x, r) + | _ -> PPF (l, x, r) + + let pf_ l x = function + | Empty | FFF _ as r -> FFF (l, x, r) + | r -> PFP (l, x, r) + + let rec add x = function + | Empty -> + FFF (Empty, x, Empty) + (* insertion to the left *) + | FFF (l, y, r) | PPF (l, y, r) -> + if X.compare x y > 0 then p_f (add y l) x r else p_f (add x l) y r + (* insertion to the right *) + | PFF (l, y, r) | PFP (l, y, r) -> + if X.compare x y > 0 then pf_ l x (add y r) else pf_ l y (add x r) + + let maximum = function + | Empty -> raise EmptyHeap + | FFF (_, x, _) | PPF (_, x, _) | PFF (_, x, _) | PFP (_, x, _) -> x + + (* smart constructors for removal; note that they are different + from the ones for insertion! *) + let p_f l x r = match l with + | Empty | FFF _ -> FFF (l, x, r) + | _ -> PPF (l, x, r) + + let pf_ l x = function + | Empty | FFF _ as r -> PFF (l, x, r) + | r -> PFP (l, x, r) + + let rec remove = function + | Empty -> + raise EmptyHeap + | FFF (Empty, _, Empty) -> + Empty + | PFF (l, _, Empty) -> + l + (* remove on the left *) + | PPF (l, x, r) | PFF (l, x, r) -> + let xl = maximum l in + let xr = maximum r in + let l' = remove l in + if X.compare xl xr >= 0 then + p_f l' xl r + else + p_f l' xr (add xl (remove r)) + (* remove on the right *) + | FFF (l, x, r) | PFP (l, x, r) -> + let xl = maximum l in + let xr = maximum r in + let r' = remove r in + if X.compare xl xr > 0 then + pf_ (add xr (remove l)) xl r' + else + pf_ l xr r' + + let rec iter f = function + | Empty -> + () + | FFF (l, x, r) | PPF (l, x, r) | PFF (l, x, r) | PFP (l, x, r) -> + iter f l; f x; iter f r + + let rec fold f h x0 = match h with + | Empty -> + x0 + | FFF (l, x, r) | PPF (l, x, r) | PFF (l, x, r) | PFP (l, x, r) -> + fold f l (fold f r (f x x0)) + +end diff --git a/lib/heap.mli b/lib/heap.mli new file mode 100644 index 0000000000..89e73af3f6 --- /dev/null +++ b/lib/heap.mli @@ -0,0 +1,54 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +(* Heaps *) + +module type Ordered = sig + type t + val compare : t -> t -> int +end + +module type S =sig + + (* Type of functional heaps *) + type t + + (* Type of elements *) + type elt + + (* The empty heap *) + val empty : t + + (* [add x h] returns a new heap containing the elements of [h], plus [x]; + complexity $O(log(n))$ *) + val add : elt -> t -> t + + (* [maximum h] returns the maximum element of [h]; raises [EmptyHeap] + when [h] is empty; complexity $O(1)$ *) + val maximum : t -> elt + + (* [remove h] returns a new heap containing the elements of [h], except + the maximum of [h]; raises [EmptyHeap] when [h] is empty; + complexity $O(log(n))$ *) + val remove : t -> t + + (* usual iterators and combinators; elements are presented in + arbitrary order *) + val iter : (elt -> unit) -> t -> unit + + val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a + +end + +exception EmptyHeap + +(*S Functional implementation. *) + +module Functional(X: Ordered) : S with type elt=X.t diff --git a/tactics/hipattern.ml b/tactics/hipattern.ml index c11fd1699b..ff735c9cd5 100644 --- a/tactics/hipattern.ml +++ b/tactics/hipattern.ml @@ -176,10 +176,19 @@ let match_with_nottype t = let is_nottype t = op2bool (match_with_nottype t) -let is_imp_term c = +let match_with_forall_term c= match kind_of_term c with - | Prod (_,_,b) -> not (dependent (mkRel 1) b) - | _ -> false + | Prod (nam,a,b) -> Some (nam,a,b) + | _ -> None + +let is_forall_term c = op2bool (match_with_forall_term c) + +let match_with_imp_term c= + match kind_of_term c with + | Prod (_,a,b) when not (dependent (mkRel 1) b) ->Some (a,b) + | _ -> None + +let is_imp_term c = op2bool (match_with_imp_term c) let rec has_nodep_prod_after n c = match kind_of_term c with diff --git a/tactics/hipattern.mli b/tactics/hipattern.mli index 053175269c..8beaaf65e9 100644 --- a/tactics/hipattern.mli +++ b/tactics/hipattern.mli @@ -74,6 +74,11 @@ val is_equation : testing_function val match_with_nottype : (constr * constr) matching_function val is_nottype : testing_function +val match_with_forall_term : (name * constr * constr) matching_function +val is_forall_term : testing_function + +val match_with_imp_term : (constr * constr) matching_function +val is_imp_term : testing_function (* I added these functions to test whether a type contains dependent products or not, and if an inductive has constructors with dependent types |
