weakest_precondition2(any(Parameters,PreCond,Body),Pred,WP) :- !,
weakest_precondition(Body,Pred,InnerWP),
safe_create_texpr(implication(PreCond,InnerWP),pred,UnquantifiedWP),
create_forall(Parameters,UnquantifiedWP,WP).
weakest_precondition2(assign(TIds,Exprs),Pred,WP) :- !,
function_assignment_to_overwrite(TIds,Exprs,TIds2,Exprs2),
get_texpr_ids(TIds2,StrippedIDs),
replace_ids_by_exprs(Pred,StrippedIDs,Exprs2,WP).
weakest_precondition2(assign_single_id(TId,Expr),Pred,WP) :- !,
function_assignment_to_overwrite([TId],[Expr],[TId2],[Expr2]),
get_texpr_id(TId2,Id),
replace_id_by_expr(Pred,Id,Expr2,WP).
weakest_precondition2(becomes_element_of(IDs,Set),Pred,WP) :- !,
create_members(Set,IDs,MemberOf),
safe_create_texpr(implication(MemberOf,Pred),pred,InnerWP),
create_forall(IDs,InnerWP,WP).
weakest_precondition2(choice(Choices),Pred,WP) :- !,
choice_wps(Choices,Pred,WPs),
conjunct_predicates(WPs,WP).
weakest_precondition2(if(IfList),Pred,WP) :- !,
if_wp(IfList,Pred,WP).
weakest_precondition2(let(Parameters,Defs,Body),Pred,WP) :- !,
weakest_precondition(Body,Pred,InnerWP),
safe_create_texpr(implication(Defs,InnerWP),pred,UnquantifiedWP),
create_forall(Parameters,UnquantifiedWP,WP).
weakest_precondition2(operation_call(Operation,ResultsCall,ParametersCall),Pred,WP) :- !,
lookup_operation(Operation,ResultsOperation,ParametersOperation,Body),
% replace parameter/results identifiers
append([ResultsOperation,ParametersOperation],IDs), append([ResultsCall,ParametersCall],Replacements),
get_texpr_ids(IDs,StrippedIDs),
replace_ids_by_exprs(Body,StrippedIDs,Replacements,NewBody),
weakest_precondition(NewBody,Pred,WP).
weakest_precondition2(parallel(Actions),Pred,WP) :- !,
merge_parallels(Actions,Action),
weakest_precondition(Action,Pred,WP).
weakest_precondition2(precondition(Condition,Action),Pred,WP) :- !,
weakest_precondition(Action,Pred,InnerWP),
conjunct_predicates([Condition,InnerWP],WP).
weakest_precondition2(rlevent(_Name,_Section,_Stat,Parameters,Guard,_Thm,Act,_VWit,_PWit,_Unmod,_AbsEvents),Pred,WP) :- !,
(is_list(Act)
-> create_texpr(parallel(Act),subst,[],NewAct)
; NewAct=Act
),
weakest_precondition2(any(Parameters,Guard,NewAct),Pred,WP).
weakest_precondition2(select(Whens),Pred,WP) :- !,
select_whens_wps(Whens,Pred,WPs),
conjunct_predicates(WPs,WP).
weakest_precondition2(select(Whens,Else),Pred,WP) :- !,
select_whens_wps(Whens,Pred,WPs),
conjunct_predicates(WPs,WhensWP),
% collect all guards and negate them
% => precondition for else-case
findall(PC,(member(SW,Whens),get_texpr_expr(SW,select_when(PC,_))), AllPreconds),
maplist(create_negation,AllPreconds,NegAllPreconds),
conjunct_predicates(NegAllPreconds,ElsePrecond),
% imply [T_n]S
weakest_precondition(Else,Pred,InnerWP),
safe_create_texpr(implication(ElsePrecond,InnerWP),pred,ElseWP),
conjunct_predicates([WhensWP,ElseWP],WP).
weakest_precondition2(sequence(Actions),Pred,WP) :- !,
sequence_wp(Actions,Pred,WP).
weakest_precondition2(skip,Pred,WP) :- !,WP=Pred.
weakest_precondition2(var(IDs,Subst),Pred,WP) :- !,
weakest_precondition(Subst,Pred,InnerWP),
create_forall(IDs,InnerWP,WP).
weakest_precondition2(while(P,S,I,V),R,WP) :- !,
% [while P DO S INVARIANT I VARIANT V END] R
% see abrial, b-book, p. 395:
% there are five predicates. their conjunction is equal to the weakest precondition
% first, create the list of all variables modified by the Stmt (used in forall)
find_typed_identifier_uses(S,AllIdentifiersInStmt),
get_accessed_vars(S,[],ModifiedVarsInStmt,_Reads),
% the identifiers in ModifiedVarsInStmt are not typed. fetch the types from the list of all identifiers
% TypedModifiedVarsInStmt = X
get_texpr_ids(TypedModifiedVarsInStmt,ModifiedVarsInStmt),
subset(TypedModifiedVarsInStmt,AllIdentifiersInStmt),
ForAlls = TypedModifiedVarsInStmt,
% first obligation: the invariant
WP1 = I,
% second obligation: forall x in X: (I & P => [S]I)
conjunct_predicates([I,P],LHS2),
weakest_precondition(S,I,RHS2),
safe_create_texpr(implication(LHS2,RHS2),pred,Inner2),
create_forall(ForAlls,Inner2,WP2),
% third obligation: forall x in X: (I => v in N)
safe_create_texpr(member(V,b(integer_set('NATURAL'),set(integer),[])),pred,RHS3),
safe_create_texpr(implication(I,RHS3),pred,Inner3),
create_forall(ForAlls,Inner3,WP3),
% fourth obligation: forall x in X: I & P => [gamma:=V][S](V
create_texpr(identifier('gamma\''),integer,[],Gamma),
create_texpr(assign_single_id(Gamma,V),subst,[],AssignVariantToGamma),
safe_create_texpr(less(V,Gamma),pred,VLessGamma),
weakest_precondition(S,VLessGamma,RHS4T),
weakest_precondition(AssignVariantToGamma,RHS4T,RHS4),
LHS4 = LHS2,
safe_create_texpr(implication(LHS4,RHS4),pred,Inner4),
create_forall(ForAlls,Inner4,WP4),
% fifth obligation: forall x in X: (I & not P) => R
create_negation(P,NotP), conjunct_predicates([I,NotP],LHS5),
safe_create_texpr(implication(LHS5,R),pred,Inner5),
create_forall(ForAlls,Inner5,WP5),
% conjunct them all together
conjunct_predicates([WP1,WP2,WP3,WP4,WP5],WP).
weakest_precondition2(Action,Pred,_WeakestPrecondition) :- !,
get_texpr_expr(Action,ActionExpr),
add_error_fail(weakest_precondition,'weakest-precondition implementation missing: ',[ActionExpr,Pred]).