/* -*- Mode: Prolog -*-
 * @(#)$Id: casesplit,v 1.5.2.1 1999/01/08 15:17:04 rjb Exp $
 *
 * $Log: casesplit,v $
 * Revision 1.5.2.1  1999/01/08 15:17:04  rjb
 * Bugfix: meta-variables in goal incorrectly being renamed apart by map_list.
 *
 * Revision 1.5  1997/10/10 09:17:26  img
 * uncomment datatype split
 *
 * Revision 1.4  1997/10/09 17:16:44  img
 * New clause added for splits on datatypes
 *
 * Revision 1.3  1996/12/11 14:07:11  img
 * Merge mthd and smthd libraries.
 *
 * Revision 1.2  1996/07/10  09:01:35  img
 * from submethod
 *
 * Revision 1.1  1995/05/11  16:21:25  img
 * 	* from submethod
 */

/* We introduce a case-split in the proof when there are "applicable"
 * conditional rules (either reduction or wave), none of whose
 * conditions are known as true among the hypotheses.  This will then
 * enable the application of the conditional rules in the next step of
 * the proof.  In case of rippling, some branches of the split will
 * not be recursive and so the proof-plan must apply the rewrite rules
 * which are complementary to the wave-rule(s) for the recursive
 * branch (cf ripple).  In these non-recursive branches then we have
 * to avoid the possibility of repeated casesplits and we do that by
 * checking that the conditions are not already provable.  */
method(casesplit(disjunction(Cs)),
	  H==>G,
	  [matrix(Vars, Matrix, G),
	   %% Removing annotations allows this method to be used in
	   %% base-case as well as step-case situations.
	   strip_meta_annotations(Matrix,Matrixstripped),
	   complementary_set(Cases-LHS),
	   exp_at(Matrixstripped,Pos,LHS),	
	   map_list(Cases, Cond-RHS-Dir-Name :=> Cond,
		    \+ elementary(H==>Cond,_), Cs)
	   %% We need to check that the free variables in each of the
	   %% Cases are in the context.  If they are not, we have to
	   %% introduce the corresponding quantifiers.  It may not be
	   %% possible to do this because (i) the quantification may
	   %% not be universal, and/or (ii) the quantifer may not be
	   %% in the prefix.  To add to the confusion, we need to
	   %% check to see which binding operator is indeed binding that
	   %% occurrence of the variable in the Case(s).  I
	   %% have code written for this already (in tactics.pl, for
	   %% rewriting beneath binding operators) but I haven't used it
	   %% here yet.  In the meantime, the following approximation
	   %% (in the post-conditions) will suffice.
	   ],
	  [%% Build the new goals according to each Case: i.e., stick
	   %% the case in the hypothesis.   V are the inhabitants: we
	   %% instantiate them at the end when we know how many there
	   %% are. 
	   listof(Var:Typ, 
		  (member(Var:Typ,Vars), not freevarinterm(Cs, Var)),
		  NVars1),
	   listof(Var:Typ,
		  (member(Var:Typ,Vars), freevarinterm(Cs, Var)), 
		  NVars2),
	   matrix(NVars1, Matrix, NewG),
	   append(NVars2, H, NewH),
	   hfree([V],NewH),
	   map_list(Cases,
		    Cond-RHS-Dir-Name :=> 
			([V:Cond | NewH]==>NewG),
		    true, NewGoals, NewH==>NewG)],
	  NewGoals,
	  casesplit(disjunction(Cs))).

/* not yet integrated: use at own risk */
method(casesplit(datatype([V:Type,CSD])),
       H==>G,
       [/* Do some analysis to suggest case splits.  */
	/* Only works on unannotated goals in non-inductive branches  */
	/* Currently fixed for lists and pnat */
	unannotated(G),
	\+ inductive_hypothesis(raw,_,H),
	\+ inductive_hypothesis(notraw(_),_,H),
	 
	casesplit_suggestion(H,G,S),
	member((V:Type)-CSD,S),
	\+ member(nosplit(V),H) ],		%dont split repeatedly
       [matrix(Vars,Matrix,G),
	once((select(V:Type,Vars,Vs); Vs = [])),

	(CSD = s(VV) ->
	 (VVdec = [VV:pnat],
	  replace_all(V,0,Matrix,NM1),matrix(Vs,NM1,NG1),
	  replace_all(V,s(VV),Matrix,NM2), matrix(Vs,NM2,NG2));
	 (CSD = Hd::Tl ->
	  (Type = Ty list,
	   VVdec = [Hd:Ty, Tl:Type],
	   replace_all(V,nil,Matrix,NM1),matrix(Vs,NM1,NG1),
	   replace_all(V,Hd::Tl,Matrix,NM2), matrix(Vs,NM2,NG2)))),
	append([nosplit(V),nosplit(VV)|VVdec],H,VVdecH)],
       [ H==> NG1, 
	 VVdecH==>NG2],
    casesplit(datatype([V:Type]))).
