kodkod_translate2(member(BElem,BSet),pred,Info,Env,K) :-
get_texpr_expr(BSet,BFun),
BFun =.. [FunFunctor,BDom,BRange],
KFun =.. [FunFunctor,KDom,KRange],
get_texpr_type(BSet,Type),
kodkod_translate_binary_membership(KFun,KElem,Type,Info,K),!,
kodkod_translate1(BElem,Env,KElem),
kodkod_translate1(BDom,Env,KDom),
kodkod_translate1(BRange,Env,KRange).
kodkod_translate2(not_member(BElem,BSet),pred,Info,Env,not(K)) :-
!,kodkod_translate2(member(BElem,BSet),pred,Info,Env,K).
kodkod_translate2(domain_restriction(Dom,Rel),set(couple(_,RhType)),_,Env,
intersection(product(KDom,relref(KRhRel)),KRel)) :-
!,kodkod_translate1(Dom,Env,KDom),
kodkod_translate1(Rel,Env,KRel),
lookup_type_relation(RhType,Env,KRhRel).
kodkod_translate2(domain_subtraction(Dom,Rel),set(couple(_,RhType)),_,Env,
intersection(product(difference(univ,KDom),relref(KRhRel)),KRel)) :-
!,kodkod_translate1(Dom,Env,KDom),
kodkod_translate1(Rel,Env,KRel),
lookup_type_relation(RhType,Env,KRhRel).
kodkod_translate2(range_restriction(Rel,Dom),set(couple(LhType,_)),_,Env,
intersection(KRel,product(relref(KLhRel),KDom))) :-
!,kodkod_translate1(Dom,Env,KDom),
kodkod_translate1(Rel,Env,KRel),
lookup_type_relation(LhType,Env,KLhRel).
kodkod_translate2(range_subtraction(Rel,Dom),set(couple(LhType,_)),_,Env,
intersection(KRel,product(relref(KLhRel),difference(univ,KDom)))) :-
!,kodkod_translate1(Dom,Env,KDom),
kodkod_translate1(Rel,Env,KRel),
lookup_type_relation(LhType,Env,KLhRel).
kodkod_translate2(identifier(Id),_BType,_Info,Env,Ref) :- !,
( lookup_var(Id,Env,Varname) ->
Ref = varref(Varname)
; lookup_id_relation(Id,Env,Relname,_KTypes) ->
Ref = relref(Relname)
; lookup_type_relation(global(Id),Env,Relname) ->
Ref = relref(Relname)).
kodkod_translate2(set_extension([]),BType,Info,Env,Result) :-
!, % normally should not happen, unless AST constructed by hand
kodkod_translate2(empty_set,BType,Info,Env,Result).
kodkod_translate2(set_extension(List),_BType,_,Env,Result) :-
!, kodkod_translate_l(List,Env,KList),
kodkod_extension_set(KList,Result).
kodkod_translate2(forall(BIds,_,_),pred,_,_Env,true) :-
% If there is an identifier without possible solution, the result is always true
somechk(is_inconsistent_expression,BIds),!.
kodkod_translate2(forall(BIds, Condition, Predicate),pred,_,Env,
forall(Decls,Result)) :-
!,kodkod_declarations1(BIds,Env,Subenv,ProvDecls),
kodkod_translate1(Condition,Subenv,KCond),
kodkod_translate1(Predicate,Subenv,KPred),
kodkod_declarations2(ProvDecls,Env,KCond,NewKCond,Decls),
kodkod_implication(NewKCond,KPred,Result).
kodkod_translate2(exists(BIds,_),pred,_,_Env,false) :-
% If there is an identifier without possible solution, the result is always false
somechk(is_inconsistent_expression,BIds),!.
kodkod_translate2(exists([BId], Membership),pred,_,Env,some(KSet)) :-
% translate #e.e:M to some(M)
get_texpr_expr(Membership,member(Elem,Set)),
get_texpr_id(BId,Id),get_texpr_id(Elem,Id),!,
kodkod_translate1(Set,Env,KSet).
kodkod_translate2(exists(BIds, Predicate),pred,_,Env,exists(Decls,Result)) :-
!,kodkod_declarations1(BIds,Env,Subenv,ProvDecls),
kodkod_translate1(Predicate,Subenv,KPred),
kodkod_declarations2(ProvDecls,Env,KPred,Result,Decls).
kodkod_translate2(comprehension_set(BIds,_),BType,Info,Env,KEmptySet) :-
% If there is an identifier without possible solution, the result is always empty
somechk(is_inconsistent_expression,BIds),!,
kodkod_translate2(empty_set,BType,Info,Env,KEmptySet).
kodkod_translate2(comprehension_set(BIds,Predicate),set(_BType),_,Env,
comp(Decls,Result)) :-
!,kodkod_declarations1(BIds,Env,Subenv,ProvDecls),
kodkod_translate1(Predicate,Subenv,KPred),
kodkod_declarations2(ProvDecls,Env,KPred,Result,Decls).
kodkod_translate2(domain(Rel),_,_,Env,K) :-
!,get_texpr_type(Rel,RelType),
kodkod_domain(KRel,RelType,K),
kodkod_translate1(Rel,Env,KRel).
kodkod_translate2(range(Rel),_,_,Env,K) :-
!,get_texpr_type(Rel,RelType),
kodkod_range(KRel,RelType,K),
kodkod_translate1(Rel,Env,KRel).
kodkod_translate2(first_of_pair(Couple),Type,Info,Env,K) :-
!,kodkod_translate2(domain(Couple),Type,Info,Env,K).
kodkod_translate2(second_of_pair(Couple),Type,Info,Env,K) :-
!,kodkod_translate2(range(Couple),Type,Info,Env,K).
kodkod_translate2(composition(A,B),_BType,_,Env,join(KA,KB)) :-
get_texpr_set_type(A,couple(_,IType)),
type_arity(IType,1),!,
kodkod_translate1(A,Env,KA),
kodkod_translate1(B,Env,KB).
kodkod_translate2(function(BFun,BArg),_BType,_,Env,Res) :-
!, kodkod_function_application(BFun,BArg,Env,Res).
kodkod_translate2(image(BRel,BArg),_BType,_,Env,Res) :-
!, kodkod_function_application(BRel,BArg,Env,Res).
kodkod_translate2(reverse(BRel),_BType,_,Env,Res) :-
!, kodkod_reverse(BRel,Env,Res).
kodkod_translate2(integer(I),integer,_,_Env,int(I)) :- !.
kodkod_translate2(unary_minus(TExpr),integer,_,_Env,int(N)) :-
% Expressions of the form "-(1)" are translated to "-1"
% there is another rule below for other forms of unary minus (translating "-x" to "0-x")
get_texpr_expr(TExpr,integer(P)),!,N is -P.
kodkod_translate2(general_sum([TId],TPred,Expr),integer,_,Env,sum(KSet)) :-
% we support only a restricted sort of the general sum:
% SIGMA (x).(x:S|x)
% The rewriting rules (see kodkod2.pl) convert the more general form "SIGMA (x).(P|x)"
% into this form by "SIGMA (x).(x:{x|P}|x)"
% The expression must only contain the quantified variable:
get_texpr_id(TId,Id), get_texpr_id(Expr,Id),!,
% Simple form: the predicate is of the form x:S
get_texpr_expr(TPred,member(TElem,TSet)),get_texpr_id(TElem,Id),
kodkod_translate1(TSet,Env,KSet).
kodkod_translate2(boolean_true,boolean,_,Env,relref(Relname)) :- !,
lookup_id_relation('__kodkod__true',Env,Relname,_KTypes).
kodkod_translate2(boolean_false,boolean,_,Env,relref(Relname)) :- !,
lookup_id_relation('__kodkod__false',Env,Relname,_KTypes).
kodkod_translate2(bool_set,set(boolean),_,Env,relref(Relname)) :- !,
lookup_type_relation(boolean,Env,Relname).
kodkod_translate2(empty_set,set(T),_,Env,Empty) :- !,
kodkod_type_as_list(T,Env,Typelist),
create_empty_set(Typelist,Empty).
kodkod_translate2(partition(Set,Subsets),_,_,Env,and(KEquals,KDisjunct)) :- !,
kodkod_translate_l([Set|Subsets],Env,[KSet|KSubsets]),
kodkod_extension_set(KSubsets,KUnion),
KEquals = equals(KSet,KUnion),
all_disjunct(KSubsets,KDisjunct).
kodkod_translate2(convert_bool(BCond),boolean,_,Env,if(KCond,KTrue,KFalse)) :- !,
kodkod_translate1(BCond,Env,KCond),
kodkod_translate2(boolean_true,boolean,[],Env,KTrue),
kodkod_translate2(boolean_false,boolean,[],Env,KFalse).
kodkod_translate2(concat(BA,BB),_,_,Env,union(KA,join(Adder,KB))) :- !,
% To compute A^B, we use a form A \/ Adder[B]
kodkod_translate1(BA,Env,KA),
kodkod_translate1(BB,Env,KB),
intset_relation_kodkod_name(I),
% Adder is a set of the form {a,b | a=b+card(A)}
Adder = comp([decl(lhr,1,one,relref(I)),decl(rhr,1,one,relref(I))],
equals(sum(varref(lhr)),add(sum(varref(rhr)),card(KA)))).
kodkod_translate2(value(V),Type,_Info,Env,K) :- ground(V), %print(try_translate_value(V)),nl,
translate_value_to_kodkod(Type,Env,V,K),!.
kodkod_translate2(value(Val),Type,Infos,Env,K) :-
was_identifier(Val,Infos,ID),!, % identifier was compiled to value; this is a bit dangerous; we should ensure that the identifier ID is used only once
%print(kodkod_value_as_id(V,ID)),nl,
kodkod_translate2(identifier(ID),Type,Infos,Env,K).
kodkod_translate2(event_b_identity,set(couple(Type,Type)),Info,Env,K) :- !,
create_maximal_type_set(Type,TSet),
kodkod_translate2(identity(TSet),set(couple(Type,Type)),Info,Env,K).
kodkod_translate2(external_pred_call('LEQ_SYM',_),Type,Info,Env,K) :- !,
kodkod_translate2(truth,Type,Info,Env,K).
kodkod_translate2(external_pred_call('LEQ_SYM_BREAK',_),Type,Info,Env,K) :- !,
kodkod_translate2(truth,Type,Info,Env,K).
kodkod_translate2(Expr,_,Info,Env,Result) :-
functor(Expr,Functor,Arity),
functor(Tmp,Functor,Arity),
kodkod_short(Tmp,_,SC),!,
check_side_condition(SC,Expr,Info),
Expr =.. [Functor|Args],
same_length(Args,TArgs),
Lookup =.. [Functor|TArgs],
kodkod_translate_l(Args,Env,TArgs),
kodkod_short(Lookup,Result,_).
kodkod_translate2(E,T,I,_,_) :-
create_texpr(E,T,I,TE),
%print(expr(E,T)),nl,
throw(kodkod(unsupported_expression(TE))).