diff options
author | Samuel Mimram <smimram@debian.org> | 2006-11-21 21:38:49 +0000 |
---|---|---|
committer | Samuel Mimram <smimram@debian.org> | 2006-11-21 21:38:49 +0000 |
commit | 208a0f7bfa5249f9795e6e225f309cbe715c0fad (patch) | |
tree | 591e9e512063e34099782e2518573f15ffeac003 /contrib/cc | |
parent | de0085539583f59dc7c4bf4e272e18711d565466 (diff) |
Imported Upstream version 8.1~gammaupstream/8.1.gamma
Diffstat (limited to 'contrib/cc')
-rw-r--r-- | contrib/cc/ccalgo.ml | 378 | ||||
-rw-r--r-- | contrib/cc/ccalgo.mli | 55 | ||||
-rw-r--r-- | contrib/cc/ccproof.ml | 7 | ||||
-rw-r--r-- | contrib/cc/ccproof.mli | 9 | ||||
-rw-r--r-- | contrib/cc/cctac.ml | 148 | ||||
-rw-r--r-- | contrib/cc/cctac.mli | 6 | ||||
-rw-r--r-- | contrib/cc/g_congruence.ml4 | 16 |
7 files changed, 487 insertions, 132 deletions
diff --git a/contrib/cc/ccalgo.ml b/contrib/cc/ccalgo.ml index 3e2d11a2..8bdae54b 100644 --- a/contrib/cc/ccalgo.ml +++ b/contrib/cc/ccalgo.ml @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: ccalgo.ml 7298 2005-08-17 12:56:38Z corbinea $ *) +(* $Id: ccalgo.ml 9151 2006-09-19 13:32:22Z corbinea $ *) (* This file implements the basic congruence-closure algorithm by *) (* Downey,Sethi and Tarjan. *) @@ -55,6 +55,8 @@ module ST=struct Hashtbl.replace st.tosign t sign let query sign st=Hashtbl.find st.toterm sign + + let rev_query term st=Hashtbl.find st.tosign term let delete st t= try let sign=Hashtbl.find st.tosign t in @@ -72,10 +74,22 @@ type pa_constructor= arity : int; args : int list} +type pa_fun= + {fsym:int; + fnargs:int} + +type pa_mark= + Fmark of pa_fun + | Cmark of pa_constructor + module PacMap=Map.Make(struct type t=pa_constructor let compare=Pervasives.compare end) +module PafMap=Map.Make(struct + type t=pa_fun + let compare=Pervasives.compare end) + type cinfo= {ci_constr: constructor; (* inductive type *) ci_arity: int; (* # args *) @@ -87,16 +101,20 @@ type term= | Appli of term*term | Constructor of cinfo (* constructor arity + nhyps *) +type ccpattern = + PApp of term * ccpattern list (* arguments are reversed *) + | PVar of int + type rule= Congruence - | Axiom of identifier * bool + | Axiom of constr * bool | Injection of int * pa_constructor * int * pa_constructor * int type from= Goal - | Hyp of identifier - | HeqG of identifier - | HeqnH of identifier * identifier + | Hyp of constr + | HeqG of constr + | HeqnH of constr * constr type 'a eq = {lhs:int;rhs:int;rule:'a} @@ -104,6 +122,15 @@ type equality = rule eq type disequality = from eq +type quant_eq = + {qe_hyp_id: identifier; + qe_pol: bool; + qe_nvars:int; + qe_lhs: ccpattern; + qe_lhs_valid:bool; + qe_rhs: ccpattern; + qe_rhs_valid:bool} + let swap eq : equality = let swap_rule=match eq.rule with Congruence -> Congruence @@ -122,6 +149,7 @@ type representative= mutable lfathers:Intset.t; mutable fathers:Intset.t; mutable inductive_status: inductive_status; + mutable functions: Intset.t PafMap.t; mutable constructors: int PacMap.t} (*pac -> term = app(constr,t) *) type cl = Rep of representative| Eqto of int*equality @@ -138,7 +166,7 @@ type forest= {mutable max_size:int; mutable size:int; mutable map: node array; - axioms: (identifier,term*term) Hashtbl.t; + axioms: (constr,term*term) Hashtbl.t; mutable epsilons: pa_constructor list; syms:(term,int) Hashtbl.t} @@ -147,9 +175,13 @@ type state = sigtable:ST.t; mutable terms: Intset.t; combine: equality Queue.t; - marks: (int * pa_constructor) Queue.t; + marks: (int * pa_mark) Queue.t; mutable diseq: disequality list; - mutable pa_classes: Intset.t} + mutable quant: quant_eq list; + mutable pa_classes: Intset.t; + q_history: (constr,unit) Hashtbl.t; + mutable rew_depth:int; + mutable changed:bool} let dummy_node = {clas=Eqto(min_int,{lhs=min_int;rhs=min_int;rule=Congruence}); @@ -157,7 +189,7 @@ let dummy_node = vertex=Leaf; term=Symb (mkRel min_int)} -let empty ():state = +let empty depth:state = {uf= {max_size=init_size; size=0; @@ -170,7 +202,11 @@ let empty ():state = marks=Queue.create (); sigtable=ST.empty (); diseq=[]; - pa_classes=Intset.empty} + quant=[]; + pa_classes=Intset.empty; + q_history=Hashtbl.create init_size; + rew_depth=depth; + changed=false} let forest state = state.uf @@ -221,11 +257,19 @@ let append_pac t p = let tail_pac p= {p with arity=succ p.arity;args=List.tl p.args} + +let fsucc paf = + {paf with fnargs=succ paf.fnargs} let add_pac rep pac t = if not (PacMap.mem pac rep.constructors) then rep.constructors<-PacMap.add pac t rep.constructors +let add_paf rep paf t = + let already = + try PafMap.find paf rep.functions with Not_found -> Intset.empty in + rep.functions<- PafMap.add paf (Intset.add t already) rep.functions + let term uf i=uf.map.(i).term let subterms uf i= @@ -256,8 +300,36 @@ let new_representative ()= lfathers=Intset.empty; fathers=Intset.empty; inductive_status=Unknown; + functions=PafMap.empty; constructors=PacMap.empty} +(* rebuild a constr from an applicative term *) + +let rec constr_of_term = function + Symb s->s + | Eps -> anomaly "epsilon constant has no value" + | Constructor cinfo -> mkConstruct cinfo.ci_constr + | Appli (s1,s2)-> + make_app [(constr_of_term s2)] s1 +and make_app l=function + Appli (s1,s2)->make_app ((constr_of_term s2)::l) s1 + | other -> applistc (constr_of_term other) l + +(* rebuild a term from a pattern and a substitution *) + +let build_subst uf subst = + Array.map (fun i -> + try term uf i + with _ -> anomaly "incomplete matching") subst + +let rec inst_pattern subst = function + PVar i -> + subst.(pred i) + | PApp (t, args) -> + List.fold_right + (fun spat f -> Appli (f,inst_pattern subst spat)) + args t + let rec add_term state t= let uf=state.uf in try Hashtbl.find uf.syms t with @@ -265,7 +337,16 @@ let rec add_term state t= let b=next uf in let new_node= match t with - Symb _ | Eps -> + Symb _ -> + let paf = + {fsym=b; + fnargs=0} in + Queue.add (b,Fmark paf) state.marks; + {clas= Rep (new_representative ()); + cpath= -1; + vertex= Leaf; + term= t} + | Eps -> {clas= Rep (new_representative ()); cpath= -1; vertex= Leaf; @@ -280,11 +361,15 @@ let rec add_term state t= vertex= Node(i1,i2); term= t} | Constructor cinfo -> + let paf = + {fsym=b; + fnargs=0} in + Queue.add (b,Fmark paf) state.marks; let pac = {cnode= b; arity= cinfo.ci_arity; args=[]} in - Queue.add (b,pac) state.marks; + Queue.add (b,Cmark pac) state.marks; {clas=Rep (new_representative ()); cpath= -1; vertex=Leaf; @@ -294,17 +379,54 @@ let rec add_term state t= Hashtbl.add uf.syms t b; b -let add_equality state id s t= +let add_equality state c s t= let i = add_term state s in let j = add_term state t in - Queue.add {lhs=i;rhs=j;rule=Axiom(id,false)} state.combine; - Hashtbl.add state.uf.axioms id (s,t) + Queue.add {lhs=i;rhs=j;rule=Axiom(c,false)} state.combine; + Hashtbl.add state.uf.axioms c (s,t) let add_disequality state from s t = let i = add_term state s in let j = add_term state t in state.diseq<-{lhs=i;rhs=j;rule=from}::state.diseq +let add_quant state id pol (nvars,valid1,patt1,valid2,patt2) = + state.quant<- + {qe_hyp_id= id; + qe_pol= pol; + qe_nvars=nvars; + qe_lhs= patt1; + qe_lhs_valid=valid1; + qe_rhs= patt2; + qe_rhs_valid=valid2}::state.quant + +let add_inst state (inst,int_subst) = + if state.rew_depth > 0 then + let subst = build_subst (forest state) int_subst in + let prfhead= mkVar inst.qe_hyp_id in + let args = Array.map constr_of_term subst in + let _ = array_rev args in (* highest deBruijn index first *) + let prf= mkApp(prfhead,args) in + try Hashtbl.find state.q_history prf + with Not_found -> + (* this instance is new, we can go on *) + let s = inst_pattern subst inst.qe_lhs + and t = inst_pattern subst inst.qe_rhs in + state.changed<-true; + state.rew_depth<-pred state.rew_depth; + if inst.qe_pol then + begin + debug msgnl + (str "adding new equality, depth="++ int state.rew_depth); + add_equality state prf s t + end + else + begin + debug msgnl (str "adding new disequality, depth="++ + int state.rew_depth); + add_disequality state (Hyp prf) s t + end + let link uf i j eq = (* links i -> j *) let node=uf.map.(i) in node.clas<-Eqto (j,eq); @@ -336,7 +458,13 @@ let union state i1 i2 eq= r2.lfathers<-Intset.union r1.lfathers r2.lfathers; ST.delete_set state.sigtable r1.fathers; state.terms<-Intset.union state.terms r1.fathers; - PacMap.iter (fun pac b -> Queue.add (b,pac) state.marks) r1.constructors; + PacMap.iter + (fun pac b -> Queue.add (b,Cmark pac) state.marks) + r1.constructors; + PafMap.iter + (fun paf -> Intset.iter + (fun b -> Queue.add (b,Fmark paf) state.marks)) + r1.functions; match r1.inductive_status,r2.inductive_status with Unknown,_ -> () | Partial pac,Unknown -> @@ -351,7 +479,7 @@ let union state i1 i2 eq= state.pa_classes<-Intset.remove i2 state.pa_classes; r2.inductive_status<-Partial_applied | Total cpl,Unknown -> r2.inductive_status<-Total cpl; - | Total cpl,Total _ -> Queue.add cpl state.marks + | Total (i,pac),Total _ -> Queue.add (i,Cmark pac) state.marks | _,_ -> () let merge eq state = (* merge and no-merge *) @@ -380,19 +508,22 @@ let update t state = (* update 1 and 2 *) | _ -> () end; PacMap.iter - (fun pac _ -> Queue.add (t,append_pac v pac) state.marks) + (fun pac _ -> Queue.add (t,Cmark (append_pac v pac)) state.marks) rep.constructors; + PafMap.iter + (fun paf _ -> Queue.add (t,Fmark (fsucc paf)) state.marks) + rep.functions; try let s = ST.query sign state.sigtable in Queue.add {lhs=t;rhs=s;rule=Congruence} state.combine with Not_found -> ST.enter t sign state.sigtable -let process_mark t pac state = - debug msgnl - (str "Processing mark for term " ++ int t ++ str "."); - let i=find state.uf t in - let rep=get_representative state.uf i in +let process_function_mark t rep paf state = + add_paf rep paf t; + state.terms<-Intset.union rep.lfathers state.terms + +let process_constructor_mark t i rep pac state = match rep.inductive_status with Total (s,opac) -> if pac.cnode <> opac.cnode then (* Conflict *) @@ -424,6 +555,15 @@ let process_mark t pac state = state.pa_classes<- Intset.add i state.pa_classes end +let process_mark t m state = + debug msgnl + (str "Processing mark for term " ++ int t ++ str "."); + let i=find state.uf t in + let rep=get_representative state.uf i in + match m with + Fmark paf -> process_function_mark t rep paf state + | Cmark pac -> process_constructor_mark t i rep pac state + type explanation = Discrimination of (int*pa_constructor*int*pa_constructor) | Contradiction of disequality @@ -447,15 +587,21 @@ let check_disequalities state = let one_step state = try let eq = Queue.take state.combine in - merge eq state + merge eq state; + true with Queue.Empty -> try let (t,m) = Queue.take state.marks in - process_mark t m state + process_mark t m state; + true with Queue.Empty -> + try let t = Intset.choose state.terms in state.terms<-Intset.remove t state.terms; - update t state + update t state; + true + with Not_found -> false + let complete_one_class state i= match (get_representative state.uf i).inductive_status with @@ -470,38 +616,162 @@ let complete_one_class state i= let complete state = Intset.iter (complete_one_class state) state.pa_classes +type matching_problem = +{mp_subst : int array; + mp_inst : quant_eq; + mp_stack : (ccpattern*int) list } + +let make_fun_table state = + let uf= state.uf in + let funtab=ref PafMap.empty in + for cl=0 to pred uf.size do + match uf.map.(cl).clas with + Rep rep -> + PafMap.iter + (fun paf _ -> + let elem = + try PafMap.find paf !funtab + with Not_found -> Intset.empty in + funtab:= PafMap.add paf (Intset.add cl elem) !funtab) + rep.functions + | _ -> () + done; + !funtab + + +let rec do_match state res pb_stack = + let mp=Stack.pop pb_stack in + match mp.mp_stack with + [] -> + res:= (mp.mp_inst,mp.mp_subst) :: !res + | (patt,cl)::remains -> + let uf=state.uf in + match patt with + PVar i -> + if mp.mp_subst.(pred i)<0 then + begin + mp.mp_subst.(pred i)<- cl; (* no aliasing problem here *) + Stack.push {mp with mp_stack=remains} pb_stack + end + else + if mp.mp_subst.(pred i) = cl then + Stack.push {mp with mp_stack=remains} pb_stack + | PApp (f,[]) -> + begin + try let j=Hashtbl.find uf.syms f in + if find uf j =cl then + Stack.push {mp with mp_stack=remains} pb_stack + with Not_found -> () + end + | PApp(f, ((last_arg::rem_args) as args)) -> + try + let j=Hashtbl.find uf.syms f in + let paf={fsym=j;fnargs=List.length args} in + let rep=get_representative uf cl in + let good_terms = PafMap.find paf rep.functions in + let aux i = + let (s,t) = ST.rev_query i state.sigtable in + Stack.push + {mp with + mp_subst=Array.copy mp.mp_subst; + mp_stack= + (PApp(f,rem_args),s) :: + (last_arg,t) :: remains} pb_stack in + Intset.iter aux good_terms + with Not_found -> () + +let paf_of_patt syms = function + PVar _ -> invalid_arg "paf_of_patt: pattern is trivial" + | PApp (f,args) -> + {fsym=Hashtbl.find syms f; + fnargs=List.length args} + +let init_pb_stack state = + let syms= state.uf.syms in + let pb_stack = Stack.create () in + let funtab = make_fun_table state in + let aux inst = + begin + if inst.qe_lhs_valid then + try + let paf= paf_of_patt syms inst.qe_lhs in + let good_classes = PafMap.find paf funtab in + Intset.iter (fun i -> + Stack.push + {mp_subst = Array.make inst.qe_nvars (-1); + mp_inst=inst; + mp_stack=[inst.qe_lhs,i]} pb_stack) good_classes + with Not_found -> () + end; + begin + if inst.qe_rhs_valid then + try + let paf= paf_of_patt syms inst.qe_rhs in + let good_classes = PafMap.find paf funtab in + Intset.iter (fun i -> + Stack.push + {mp_subst = Array.make inst.qe_nvars (-1); + mp_inst=inst; + mp_stack=[inst.qe_rhs,i]} pb_stack) good_classes + with Not_found -> () + end in + List.iter aux state.quant; + pb_stack + +let find_instances state = + let pb_stack= init_pb_stack state in + let res =ref [] in + let _ = + debug msgnl (str "Running E-matching algorithm ... "); + try + while true do + do_match state res pb_stack + done; + anomaly "get out of here !" + with Stack.Empty -> () in + !res + let rec execute first_run state = debug msgnl (str "Executing ... "); try - while true do - one_step state + while one_step state do () done; - anomaly "keep out of here" - with - Discriminable(s,spac,t,tpac) -> - Some - begin - if first_run then - Discrimination (s,spac,t,tpac) - else - Incomplete - end - | Not_found -> - match check_disequalities state with - None -> - if not(Intset.is_empty state.pa_classes) then - begin - debug msgnl - (str "First run was incomplete, completing ... "); - complete state; - execute false state - end - else None - | Some dis -> Some - begin - if first_run then - Contradiction dis + match check_disequalities state with + None -> + if not(Intset.is_empty state.pa_classes) then + begin + debug msgnl (str "First run was incomplete, completing ... "); + complete state; + execute false state + end + else + if state.rew_depth>0 then + let l=find_instances state in + List.iter (add_inst state) l; + if state.changed then + begin + state.changed <- false; + execute true state + end else - Incomplete + begin + debug msgnl (str "Out of instances ... "); + None + end + else + begin + debug msgnl (str "Out of depth ... "); + None end + | Some dis -> Some + begin + if first_run then Contradiction dis + else Incomplete + end + with Discriminable(s,spac,t,tpac) -> Some + begin + if first_run then Discrimination (s,spac,t,tpac) + else Incomplete + end + diff --git a/contrib/cc/ccalgo.mli b/contrib/cc/ccalgo.mli index 74132811..05a5c4d1 100644 --- a/contrib/cc/ccalgo.mli +++ b/contrib/cc/ccalgo.mli @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: ccalgo.mli 7298 2005-08-17 12:56:38Z corbinea $ *) +(* $Id: ccalgo.mli 9151 2006-09-19 13:32:22Z corbinea $ *) open Util open Term @@ -23,6 +23,10 @@ type term = | Appli of term*term | Constructor of cinfo (* constructor arity + nhyps *) +type ccpattern = + PApp of term * ccpattern list + | PVar of int + type pa_constructor = { cnode : int; arity : int; @@ -36,14 +40,14 @@ type state type rule= Congruence - | Axiom of identifier * bool + | Axiom of constr * bool | Injection of int * pa_constructor * int * pa_constructor * int type from= Goal - | Hyp of identifier - | HeqG of identifier - | HeqnH of identifier * identifier + | Hyp of constr + | HeqG of constr + | HeqnH of constr*constr type 'a eq = {lhs:int;rhs:int;rule:'a} @@ -56,22 +60,28 @@ type explanation = | Contradiction of disequality | Incomplete +val constr_of_term : term -> constr + val debug : (Pp.std_ppcmds -> unit) -> Pp.std_ppcmds -> unit val forest : state -> forest -val axioms : forest -> (identifier, term * term) Hashtbl.t +val axioms : forest -> (constr, term * term) Hashtbl.t val epsilons : forest -> pa_constructor list -val empty : unit -> state +val empty : int -> state val add_term : state -> term -> int -val add_equality : state -> identifier -> term -> term -> unit +val add_equality : state -> constr -> term -> term -> unit val add_disequality : state -> from -> term -> term -> unit +val add_quant : state -> identifier -> bool -> + int * bool * ccpattern * bool * ccpattern -> unit + + val tail_pac : pa_constructor -> pa_constructor val find : forest -> int -> int @@ -87,6 +97,35 @@ val subterms : forest -> int -> int * int val join_path : forest -> int -> int -> ((int * int) * equality) list * ((int * int) * equality) list +type quant_eq= + {qe_hyp_id: identifier; + qe_pol: bool; + qe_nvars:int; + qe_lhs: ccpattern; + qe_lhs_valid:bool; + qe_rhs: ccpattern; + qe_rhs_valid:bool} + + +type pa_fun= + {fsym:int; + fnargs:int} + +type matching_problem + +module PafMap: Map.S with type key = pa_fun + +val make_fun_table : state -> Intset.t PafMap.t + +val do_match : state -> + (quant_eq * int array) list ref -> matching_problem Stack.t -> unit + +val init_pb_stack : state -> matching_problem Stack.t + +val paf_of_patt : (term, int) Hashtbl.t -> ccpattern -> pa_fun + +val find_instances : state -> (quant_eq * int array) list + val execute : bool -> state -> explanation option diff --git a/contrib/cc/ccproof.ml b/contrib/cc/ccproof.ml index 1200dc2e..1ffa347a 100644 --- a/contrib/cc/ccproof.ml +++ b/contrib/cc/ccproof.ml @@ -6,18 +6,19 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: ccproof.ml 7298 2005-08-17 12:56:38Z corbinea $ *) +(* $Id: ccproof.ml 9151 2006-09-19 13:32:22Z corbinea $ *) (* This file uses the (non-compressed) union-find structure to generate *) (* proof-trees that will be transformed into proof-terms in cctac.ml4 *) open Util open Names +open Term open Ccalgo type proof= - Ax of identifier - | SymAx of identifier + Ax of constr + | SymAx of constr | Refl of term | Trans of proof*proof | Congr of proof*proof diff --git a/contrib/cc/ccproof.mli b/contrib/cc/ccproof.mli index 18c745bf..abdd6fea 100644 --- a/contrib/cc/ccproof.mli +++ b/contrib/cc/ccproof.mli @@ -6,14 +6,15 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: ccproof.mli 7298 2005-08-17 12:56:38Z corbinea $ *) +(* $Id: ccproof.mli 9151 2006-09-19 13:32:22Z corbinea $ *) open Ccalgo open Names +open Term type proof = - Ax of identifier - | SymAx of identifier + Ax of constr + | SymAx of constr | Refl of term | Trans of proof * proof | Congr of proof * proof @@ -25,6 +26,6 @@ val build_proof : | `Prove of int * int ] -> proof val type_proof : - (identifier, (term * term)) Hashtbl.t -> proof -> term * term + (constr, (term * term)) Hashtbl.t -> proof -> term * term diff --git a/contrib/cc/cctac.ml b/contrib/cc/cctac.ml index 4a719f38..ea8aceeb 100644 --- a/contrib/cc/cctac.ml +++ b/contrib/cc/cctac.ml @@ -8,7 +8,7 @@ (*i camlp4deps: "parsing/grammar.cma" i*) -(* $Id: cctac.ml 7909 2006-01-21 11:09:18Z herbelin $ *) +(* $Id: cctac.ml 9151 2006-09-19 13:32:22Z corbinea $ *) (* This file is the interface between the c-c algorithm and Coq *) @@ -63,7 +63,7 @@ let rec decompose_term env t= Constructor {ci_constr=c; ci_arity=nargs; ci_nhyps=nargs-oib.mind_nparams} - | _ ->(Symb t) + | _ ->if closed0 t then (Symb t) else raise Not_found (* decompose equality in members and type *) @@ -79,34 +79,72 @@ let atom_of_constr env term = else `Other (decompose_term env term) | _ -> `Other (decompose_term env term) -let rec litteral_of_constr env term= +let rec pattern_of_constr env c = + match kind_of_term (whd env c) with + App (f,args)-> + let pf = decompose_term env f in + let pargs,lrels = List.split + (array_map_to_list (pattern_of_constr env) args) in + PApp (pf,List.rev pargs), + List.fold_left Intset.union Intset.empty lrels + | Rel i -> PVar i,Intset.singleton i + | _ -> + let pf = decompose_term env c in + PApp (pf,[]),Intset.empty + +let non_trivial = function + PVar _ -> false + | _ -> true + +let patterns_of_constr env nrels term= + let f,args= + try destApp (whd_delta env term) with _ -> raise Not_found in + if eq_constr f (Lazy.force _eq) && (Array.length args)=3 + then + let patt1,rels1 = pattern_of_constr env args.(1) + and patt2,rels2 = pattern_of_constr env args.(2) in + let valid1 = (Intset.cardinal rels1 = nrels && non_trivial patt1) + and valid2 = (Intset.cardinal rels2 = nrels && non_trivial patt2) in + if valid1 || valid2 then + nrels,valid1,patt1,valid2,patt2 + else raise Not_found + else raise Not_found + +let rec quantified_atom_of_constr env nrels term = match kind_of_term (whd_delta env term) with Prod (_,atom,ff) -> if eq_constr ff (Lazy.force _False) then + let patts=patterns_of_constr env nrels atom in + `Nrule patts + else + quantified_atom_of_constr env (succ nrels) ff + | _ -> + let patts=patterns_of_constr env nrels term in + `Rule patts + +let litteral_of_constr env term= + match kind_of_term (whd_delta env term) with + | Prod (_,atom,ff) -> + if eq_constr ff (Lazy.force _False) then match (atom_of_constr env atom) with `Eq(t,a,b) -> `Neq(t,a,b) | `Other(p) -> `Nother(p) - else - `Other (decompose_term env term) - | _ -> atom_of_constr env term + else + begin + try + quantified_atom_of_constr env 1 ff + with Not_found -> + `Other (decompose_term env term) + end + | _ -> + atom_of_constr env term -(* rebuild a term from applicative format *) - -let rec make_term = function - Symb s->s - | Eps -> anomaly "epsilon constant has no value" - | Constructor cinfo -> mkConstruct cinfo.ci_constr - | Appli (s1,s2)-> - make_app [(make_term s2)] s1 -and make_app l=function - Appli (s1,s2)->make_app ((make_term s2)::l) s1 - | other -> applistc (make_term other) l (* store all equalities from the context *) -let rec make_prb gls additionnal_terms = +let rec make_prb gls depth additionnal_terms = let env=pf_env gls in - let state = empty () in + let state = empty depth in let pos_hyps = ref [] in let neg_hyps =ref [] in List.iter @@ -116,21 +154,24 @@ let rec make_prb gls additionnal_terms = List.iter (fun (id,_,e) -> begin + let cid=mkVar id in match litteral_of_constr env e with - `Eq (t,a,b) -> add_equality state id a b - | `Neq (t,a,b) -> add_disequality state (Hyp id) a b + `Eq (t,a,b) -> add_equality state cid a b + | `Neq (t,a,b) -> add_disequality state (Hyp cid) a b | `Other ph -> List.iter - (fun (idn,nh) -> - add_disequality state (HeqnH (id,idn)) ph nh) + (fun (cidn,nh) -> + add_disequality state (HeqnH (cid,cidn)) ph nh) !neg_hyps; - pos_hyps:=(id,ph):: !pos_hyps + pos_hyps:=(cid,ph):: !pos_hyps | `Nother nh -> List.iter - (fun (idp,ph) -> - add_disequality state (HeqnH (idp,id)) ph nh) + (fun (cidp,ph) -> + add_disequality state (HeqnH (cidp,cid)) ph nh) !pos_hyps; - neg_hyps:=(id,nh):: !neg_hyps + neg_hyps:=(cid,nh):: !neg_hyps + | `Rule patts -> add_quant state id true patts + | `Nrule patts -> add_quant state id false patts end) (Environ.named_context_of_val gls.it.evar_hyps); begin match atom_of_constr env gls.it.evar_concl with @@ -170,18 +211,18 @@ let build_projection intype outtype (cstr:constructor) special default gls= (* generate an adhoc tactic following the proof tree *) let rec proof_tac axioms=function - Ax id->exact_check (mkVar id) - | SymAx id->tclTHEN symmetry (exact_check (mkVar id)) - | Refl t->reflexivity - | Trans (p1,p2)->let t=(make_term (snd (type_proof axioms p1))) in + Ax c -> exact_check c + | SymAx c -> tclTHEN symmetry (exact_check c) + | Refl t -> reflexivity + | Trans (p1,p2)->let t=(constr_of_term (snd (type_proof axioms p1))) in (tclTHENS (transitivity t) [(proof_tac axioms p1);(proof_tac axioms p2)]) | Congr (p1,p2)-> fun gls-> let (f1,f2)=(type_proof axioms p1) and (x1,x2)=(type_proof axioms p2) in - let tf1=make_term f1 and tx1=make_term x1 - and tf2=make_term f2 and tx2=make_term x2 in + let tf1=constr_of_term f1 and tx1=constr_of_term x1 + and tf2=constr_of_term f2 and tx2=constr_of_term x2 in let typf=pf_type_of gls tf1 and typx=pf_type_of gls tx1 and typfx=pf_type_of gls (mkApp(tf1,[|tx1|])) in let id=pf_get_new_id (id_of_string "f") gls in @@ -204,52 +245,52 @@ let rec proof_tac axioms=function (fun gls -> let ti,tj=type_proof axioms prf in let ai,aj=type_proof axioms gprf in - let cti=make_term ti in - let ctj=make_term tj in - let cai=make_term ai in + let cti=constr_of_term ti in + let ctj=constr_of_term tj in + let cai=constr_of_term ai in let intype=pf_type_of gls cti in let outtype=pf_type_of gls cai in let special=mkRel (1+nargs-argind) in - let default=make_term ai in + let default=constr_of_term ai in let proj=build_projection intype outtype cstr special default gls in let injt= mkApp (Lazy.force _f_equal,[|intype;outtype;proj;cti;ctj|]) in tclTHEN (apply injt) (proof_tac axioms prf) gls) -let refute_tac axioms id t1 t2 p gls = - let tt1=make_term t1 and tt2=make_term t2 in +let refute_tac axioms c t1 t2 p gls = + let tt1=constr_of_term t1 and tt2=constr_of_term t2 in let intype=pf_type_of gls tt1 in let neweq= mkApp(Lazy.force _eq, [|intype;tt1;tt2|]) in let hid=pf_get_new_id (id_of_string "Heq") gls in - let false_t=mkApp (mkVar id,[|mkVar hid|]) in + let false_t=mkApp (c,[|mkVar hid|]) in tclTHENS (true_cut (Name hid) neweq) [proof_tac axioms p; simplest_elim false_t] gls -let convert_to_goal_tac axioms id t1 t2 p gls = - let tt1=make_term t1 and tt2=make_term t2 in +let convert_to_goal_tac axioms c t1 t2 p gls = + let tt1=constr_of_term t1 and tt2=constr_of_term t2 in let sort=pf_type_of gls tt2 in let neweq=mkApp(Lazy.force _eq,[|sort;tt1;tt2|]) in let e=pf_get_new_id (id_of_string "e") gls in let x=pf_get_new_id (id_of_string "X") gls in let identity=mkLambda (Name x,sort,mkRel 1) in let endt=mkApp (Lazy.force _eq_rect, - [|sort;tt1;identity;mkVar id;tt2;mkVar e|]) in + [|sort;tt1;identity;c;tt2;mkVar e|]) in tclTHENS (true_cut (Name e) neweq) [proof_tac axioms p;exact_check endt] gls -let convert_to_hyp_tac axioms id1 t1 id2 t2 p gls = - let tt2=make_term t2 in +let convert_to_hyp_tac axioms c1 t1 c2 t2 p gls = + let tt2=constr_of_term t2 in let h=pf_get_new_id (id_of_string "H") gls in - let false_t=mkApp (mkVar id2,[|mkVar h|]) in + let false_t=mkApp (c2,[|mkVar h|]) in tclTHENS (true_cut (Name h) tt2) - [convert_to_goal_tac axioms id1 t1 t2 p; + [convert_to_goal_tac axioms c1 t1 t2 p; simplest_elim false_t] gls let discriminate_tac axioms cstr p gls = let t1,t2=type_proof axioms p in - let tt1=make_term t1 and tt2=make_term t2 in + let tt1=constr_of_term t1 and tt2=constr_of_term t2 in let intype=pf_type_of gls tt1 in let concl=pf_concl gls in let outsort=mkType (new_univ ()) in @@ -273,15 +314,15 @@ let discriminate_tac axioms cstr p gls = let build_term_to_complete uf meta pac = let cinfo = get_constructor_info uf pac.cnode in - let real_args = List.map (fun i -> make_term (term uf i)) pac.args in + let real_args = List.map (fun i -> constr_of_term (term uf i)) pac.args in let dummy_args = List.rev (list_tabulate meta pac.arity) in let all_args = List.rev_append real_args dummy_args in applistc (mkConstruct cinfo.ci_constr) all_args -let cc_tactic additionnal_terms gls= +let cc_tactic depth additionnal_terms gls= Coqlib.check_required_library ["Coq";"Init";"Logic"]; let _ = debug Pp.msgnl (Pp.str "Reading subgoal ...") in - let state = make_prb gls additionnal_terms in + let state = make_prb gls depth additionnal_terms in let _ = debug Pp.msgnl (Pp.str "Problem built, solving ...") in let sol = execute true state in let _ = debug Pp.msgnl (Pp.str "Computation completed.") in @@ -334,3 +375,8 @@ let cc_tactic additionnal_terms gls= let cc_fail gls = errorlabstrm "Congruence" (Pp.str "congruence failed.") + +let congruence_tac depth l = + tclORELSE + (tclTHEN (tclREPEAT introf) (cc_tactic depth l)) + cc_fail diff --git a/contrib/cc/cctac.mli b/contrib/cc/cctac.mli index 6082beb6..97fa4d77 100644 --- a/contrib/cc/cctac.mli +++ b/contrib/cc/cctac.mli @@ -6,11 +6,13 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: cctac.mli 7298 2005-08-17 12:56:38Z corbinea $ *) +(* $Id: cctac.mli 9151 2006-09-19 13:32:22Z corbinea $ *) open Term open Proof_type -val cc_tactic : constr list -> tactic +val cc_tactic : int -> constr list -> tactic val cc_fail : tactic + +val congruence_tac : int -> constr list -> tactic diff --git a/contrib/cc/g_congruence.ml4 b/contrib/cc/g_congruence.ml4 index 0bdf7608..693aebb4 100644 --- a/contrib/cc/g_congruence.ml4 +++ b/contrib/cc/g_congruence.ml4 @@ -8,7 +8,7 @@ (*i camlp4deps: "parsing/grammar.cma" i*) -(* $Id: g_congruence.ml4 7734 2005-12-26 14:06:51Z herbelin $ *) +(* $Id: g_congruence.ml4 9151 2006-09-19 13:32:22Z corbinea $ *) open Cctac open Tactics @@ -17,13 +17,9 @@ open Tacticals (* Tactic registration *) TACTIC EXTEND cc - [ "congruence" ] -> [ tclORELSE - (tclTHEN (tclREPEAT introf) (cc_tactic [])) - cc_fail ] -END - -TACTIC EXTEND cc_with - [ "congruence" "with" ne_constr_list(l) ] -> [ tclORELSE - (tclTHEN (tclREPEAT introf) (cc_tactic l)) - cc_fail] + [ "congruence" ] -> [ congruence_tac 0 [] ] + |[ "congruence" integer(n) ] -> [ congruence_tac n [] ] + |[ "congruence" "with" ne_constr_list(l) ] -> [ congruence_tac 0 l ] + |[ "congruence" integer(n) "with" ne_constr_list(l) ] -> + [ congruence_tac n l ] END |