b_compute_expression2(value(Val),_T,_I,_LS,_S,V,WF) :- !, equal_object_wf(Val,V,WF). %Val=V.
b_compute_expression2(boolean_true,_T,_I,_LState,_State,Res,_WF) :- !, Res = pred_true /* bool_true */. % for simple types we can use ordinary unification
b_compute_expression2(boolean_false,_T,_I,_LState,_State,Res,_WF) :- !, Res = pred_false /* bool_false */.
b_compute_expression2(integer_set(NSET),_T,_I,_LState,_State,Res,WF) :- !, equal_object_wf(Res,global_set(NSET),WF). %Res = global_set(NSET).
b_compute_expression2(bool_set,_T,_I,_LState,_State,Res,WF) :- !, % b_type2_set(bool,Res).
equal_object_wf(Res,avl_set(node(pred_false,true,1,empty,node(pred_true,true,0,empty,empty))),WF).
b_compute_expression2(float_set,_T,_I,_LState,_State,Res,WF) :- !, equal_object_wf(Res,global_set('FLOAT'),WF).
b_compute_expression2(real_set,_T,_I,_LState,_State,Res,WF) :- !, equal_object_wf(Res,global_set('REAL'),WF).
b_compute_expression2(string_set,_T,_I,_LState,_State,Res,WF) :- !, equal_object_wf(Res,global_set('STRING'),WF).
b_compute_expression2(string(S),_T,_I,_LState,_State,Res,_WF) :- !,
% TODO(ML,26.8.2008): Check if we should use a different functor for syntax tree vs data
Res = string(S).
b_compute_expression2(typeset,Type,_I,_LState,_State,Res,WF) :- !,
is_set_type(Type,ElType), % we could generate global_set('STRING'),... for certain types
equal_object_wf(Res,closure('_zzzz_unary',[ElType],b(truth,pred,[])),WF).
b_compute_expression2(empty_set,_T,_I,_LState,_State,Res,_WF) :- !, empty_set(Res).
b_compute_expression2(empty_sequence,_T,_I,_LState,_State,Res,_WF) :- !, empty_sequence(Res).
b_compute_expression2(event_b_identity,EType,_I,_LState,_State,Res,WF) :-
get_set_type(EType,couple(Type,Type)),!,
event_b_identity_for_type(Type,Res,WF).
b_compute_expression2(integer(Val),_T,_I,_LocalState,_State,Res,_WF) :- !, Res = int(Val).
b_compute_expression2(max_int,_T,_I,_LS,_S,Res,_WF) :-
preferences:get_preference(maxint,CVal),!, Res = int(CVal).
b_compute_expression2(min_int,_T,_I,_LS,_S,Res,_WF) :-
preferences:get_preference(minint,CVal),!, Res = int(CVal).
b_compute_expression2(identifier(Id),Type,Info,LocalState,State,Res,WF) :- !,
lookup_value_in_store_and_global_sets_wf(Id,Type,LocalState,State,Value,Info,WF),
equal_object_wf(Res,Value,WF).
b_compute_expression2(lazy_lookup_expr(Id),_Type,_Info,LocalState,_State,Res,WF) :- !,
lookup_value_for_existing_id_wf(Id,LocalState,(Trigger,Value),WF), % should normally only occur in LocalState; value introduced by lazy_let
Trigger = pred_true, % force evaluation
equal_object_wf(Res,Value,WF).
b_compute_expression2(lazy_let_expr(Id,AssignmentExpr,Expr),_T,_I,LocalState,State,Value,WF) :-
!,
add_lazy_let_id_and_expression(Id,AssignmentExpr,LocalState,State,NewLocalState,WF),
%Trigger = pred_true, % expressions cannot be delayed !? (TO DO: more refined check)
%block_lazy_compute_expression(Trigger,_,AssignmentExpr,LocalState,State,IdValue,WF,Ai),
b_compute_expression(Expr,NewLocalState,State,Value,WF).
b_compute_expression2(real(Atom),_T,_I,_LocalState,_State,Res,_WF) :- !, construct_real(Atom,Res).
b_compute_expression2(rec(Fields),_T,_I,LocalState,State,Record,WF) :- !,
l_compute_field(Fields,LocalState,State,FieldValues,WF),
construct_record_wf(FieldValues,Record,WF).
b_compute_expression2(record_field(RecEx,Name),_T,_I,LocalState,State,Value,WF) :- !,
b_compute_expression(RecEx,LocalState,State,RecValue,WF),
access_record_wf(RecValue,Name,Value,WF).
b_compute_expression2(freetype_set(Id),_T,_I,_LState,_State,Val,_WF) :- !, Val=freetype(Id). %% NOT COVERED (17)
b_compute_expression2(function(Function,FunArg),Type,Info,LocalState,State,Res,WF) :- !,
b_compute_expression_function(Function,FunArg,Type,Info,LocalState,State,Res,WF).
b_compute_expression2(card(b(Arg1,Type,Info)),integer,OuterInfo,LocalState,State,Card,WF) :- !,
b_compute_card(Arg1,Type,Info,OuterInfo,LocalState,State,Card,WF).
b_compute_expression2(max(b(Arg1,Type,Info)),integer,_I,LocalState,State,Max,WF) :- !,
b_compute_max(Arg1,Type,Info,LocalState,State,Max,WF).
b_compute_expression2(min(b(Arg1,Type,Info)),integer,_I,LocalState,State,Min,WF) :- !,
b_compute_min(Arg1,Type,Info,LocalState,State,Min,WF).
b_compute_expression2(set_extension(Ex),Type,_I,LocalState,State,Res,WF) :- !,
b_compute_expressions(Ex,LocalState,State,ExValue,WF),
kernel_call(b_interpreter:convert_list_of_expressions_into_set_wf(ExValue,ValueSet,Type,WF),ExValue,WF, set_extension(Ex)),
equal_object_wf(Res,ValueSet,WF).
b_compute_expression2(sequence_extension(Ex),_T,_I,LocalState,State,ValueSeq,WF) :- !,
b_compute_expressions(Ex,LocalState,State,Value,WF),
kernel_call(b_interpreter:convert_list_of_expressions_into_sequence(Value,ValueSeq),Value,WF,sequence_extension(Ex)).
b_compute_expression2(convert_bool(PRED),_T,_I,LocalState,State,Val,WF) :- !, /* B bool(.) operator */
b_convert_bool(PRED,LocalState,State,WF,Val).
b_compute_expression2(couple(El1,El2),_T,_I,LocalState,State,Result,WF) :- !, Result = (Val1,Val2),
b_compute_expression(El1,LocalState,State,Val1,WF),
b_compute_expression(El2,LocalState,State,Val2,WF).
b_compute_expression2(comprehension_set(Parameters,Condition),_T,Info,LocalState,State,Result,WF) :- !,
b_compute_comprehension_set(Parameters,Condition,Info,LocalState,State,Result,WF).
b_compute_expression2(recursive_let(TId,TSet),OrigType,OrigInfo,LocalState,State,Result,WF) :- !,
% LET TId = TSet in TSet
( get_texpr_expr(TSet,comprehension_set(Parameters,Condition)) ->
true % if the argument TSet is a comprehension set,
% we just add a recursive parameter
; get_texpr_set_type(TSet,Type) ->
% if not, we construct a new comprehension set {x | x:TSet}
unique_typed_id("_tmparg_",Type,TArg),
Parameters=[TArg],
safe_create_texpr(member(TArg,TSet),pred,Condition)
;
add_internal_error('Expected set as argument to recursive_let',
b_compute_expression2(recursive_let(TId,TSet),OrigType,OrigInfo,LocalState,State,Result,WF)),fail
),
% Generate closure where the references to the recursion are kept
% add recursion ID to parameters to prevent removal of references during compilation
generate_recursive_closure(TId,recursion,[TId|Parameters],Condition,LocalState,State,Closure1,WF),
% add_message(b_interpreter,'Recursive Let for: ',TId,TId),
% remove recursion ID from parameters after compilation
Closure1=closure([_|P],[_|T],Cond),RClosure=closure(P,T,Cond),
% Generate closure where the references to the recursion are kept
generate_recursive_closure(TId,RClosure,Parameters,Condition,LocalState,State,Result,WF).
b_compute_expression2(general_sum(Ids,Condition,Expression),Type,Info,LocalState,State,SumResult,WF) :- !,
b_general_sum_or_mul(Ids,Condition,Expression,Type,Info,LocalState,State,SumResult,WF,sum).
b_compute_expression2(general_product(Ids,Condition,Expression),Type,Info,LocalState,State,MulResult,WF) :- !,
b_general_sum_or_mul(Ids,Condition,Expression,Type,Info,LocalState,State,MulResult,WF,mul).
b_compute_expression2(if_then_else(If,Then,Else),T,_I,LocalState,State,Value,WF) :- !,
b_try_check_boolean_expression_wf(If,LocalState,State,WF,PredRes),
(var(PredRes), can_get_full_fd_value(T), preferences:preference(use_clpfd_solver,true),
always_well_defined(Then), always_well_defined(Else)
% Note: always_well_defined_or_disprover_mode probably not ok, as we evaluate the expressions unconditionally
-> b_clpfd_if_then_else(PredRes,T,Then,Else,LocalState,State,Value,WF)
; b_compute_if_then_else(PredRes,Then,Else,LocalState,State,Value,WF)
).
b_compute_expression2(let_expression_global(Ids,AssignmentExprs,Expr),_T,Info,LocalState,State,Value,WF) :-
debug_println(4,global_let(Ids,Info)),
% store variables globally (not in LocalState) to be visible to subsidiary operation_calls
!, set_up_localstate_for_global_let(Ids,AssignmentExprs,LocalState,State,LetState,WF),
b_compute_expression(Expr,LocalState,LetState,Value,WF).
b_compute_expression2(let_expression(Ids,AssignmentExprs,Expr),_T,_I,LocalState,State,Value,WF) :-
!, set_up_localstate_for_let(Ids,_ParaValues,AssignmentExprs,LocalState,State,LetState,WF),
b_compute_expression(Expr,LetState,State,Value,WF). %% NOT COVERED (30)
b_compute_expression2(freetype_constructor(Id,Case,Expr),_T,_I,LocalState,State,FreeValue,WF) :-
!, FreeValue = freeval(Id,Case,Value),
b_compute_expression(Expr,LocalState,State,Value,WF). %% NOT COVERED (32)
b_compute_expression2(freetype_destructor(Id,Case,Expr),_T,Info,LocalState,State,Value,WF) :-
!, b_compute_expression(Expr,LocalState,State,freeval(Id,VCase,VValue),WF),
check_freetype_case(Id,Case,VCase,VValue,Value,Info,WF).
b_compute_expression2(assertion_expression(Cond,ErrMsg,Expr),T,Info,LocalState,State,Value,WF) :- !,
opt_push_wait_flag_call_stack_info(WF,
span_predicate(b(assertion_expression(Cond,ErrMsg,b(value(string('')),string,[])),T,Info),LocalState,State),WF2),
% should we use another term for call stack?
(get_preference(disprover_mode,true) -> PredRes = pred_true ; true), % in Disprover mode we know Cond must be true
b_try_check_boolean_expression_no_enum_wf(Cond,LocalState,State,WF2,PredRes), % DO NOT ENUM, unless we cannot reify
% does not make sense to enumerate PredRes as with pred_false we get no value anyway
% however, we may get pending co-routines if Cond cannot be reified
( PredRes==pred_false ->
translate_bexpression_with_limit(Cond,100,CS),
add_wd_error_span(ErrMsg,CS,span_predicate(Cond,LocalState,State),WF2),
get_last_wait_flag(assertion_expression,WF2,WFC),
when(nonvar(WFC),
(ground_value(Value) -> true % we have a WD Error, any Value goes
; b_compute_expression(Expr,LocalState,State,Value,WF2) % compute Value; avoid infinite enumeration of possible values; useful e.g. for prj1/prj2 assertion expressions
))
; b_compute_expression(Expr,LocalState,State,Value,WF),
add_wd_error_if_false(PredRes,ErrMsg,Cond,span_predicate(Cond,LocalState,State),WF2)
). %% NOT COVERED (34)
b_compute_expression2(multiplication(Arg1,Arg2),integer,Info,LocalState,State,Value,WF) :-
same_texpr(Arg1,Arg2), !, % is less useful when CLPFD is already turned on, calls square(Arg1,Value,WF)
b_compute_expression(Arg1,LocalState,State,SV1,WF),
unary_kernel_call(kernel_objects,square,SV1,Value,WF,multiplication(Arg1,Arg1),integer,Info).
b_compute_expression2(image(Relation,Set),_EType,_Info,LocalState,State,Value,WF) :-
special_operator_for_image(Relation,Kind,Args),
% we have closure1(Rel)[Set] or similar -> avoid computing full closure
!,
b_compute_expression(Set,LocalState,State,SV,WF),
b_compute_expressions(Args,LocalState,State,EArgs,WF),
kernel_call(bsets_clp:image_for_special_operator(Kind,EArgs,SV,Value,WF),[SV|EArgs],WF,image(Relation,Set)).
b_compute_expression2(external_function_call(FunName,Args),EType,Info,LocalState,State,Value,WF) :-
!,
b_compute_expressions(Args, LocalState,State, EvaluatedArgs, WF),
push_wait_flag_call_stack_info(WF,external_call(FunName,EvaluatedArgs,Info),WF2),
call_external_function(FunName,Args,EvaluatedArgs,Value,EType,Info,WF2).
b_compute_expression2(Expression,EType,Info,LocalState,State,Res,WF) :-
is_set_type(EType,Type),
/* avoid evaluating certain expensive expressions:
convert them into symbolic closures and expand only if really required */
functor(Expression,UnOp,1),
symbolic_closure_unary_operator(UnOp),
/* TO DO: UNFOLD THIS OR WRAP in CONSTRUCTOR */
arg(1,Expression,BType),
!, %preferences:get_preference(convert_types_into_closures,true),!,
% print_message(delayed_un_op(UnOp,BType)),
b_compute_expression(BType,LocalState,State,ArgValue,WF),
( do_not_keep_symbolic_unary(UnOp,ArgValue), unary_function(UnOp,Module,KernelFunction) ->
/* special treatment for empty set: no need to keep symbolic */
unary_kernel_call(Module,KernelFunction,ArgValue,Res,WF,Expression,EType,Info)
;
get_texpr_type(BType,ArgType),
create_texpr(value(ArgValue),ArgType,[],TValue),
ClosureSetExpression =.. [UnOp,TValue],
construct_member_closure('_zzzz_unary',Type,Info,ClosureSetExpression,Value),
(unop_to_be_marked_as_symbolic(UnOp,ArgValue) ->
mark_closure_as_symbolic(Value,SValue),
equal_object_wf(Res,SValue,WF)
; equal_object_wf(Res,Value,WF))
).
b_compute_expression2(Expression,EType,Info,LocalState,State,Res,WF) :-
is_set_type(EType,Type),
/* avoid evaluating certain expensive expressions:
convert them into symbolic closures and expand only if really required */
functor(Expression,BinOp,2),
arg(1,Expression,BType1),
arg(2,Expression,BType2),
kernel_mappings:symbolic_closure_binary_operator(BinOp),
!,
%preferences:get_preference(convert_types_into_closures,true),!,
b_compute_expression(BType1,LocalState,State,ArgValue1,WF),
(binary_arg1_determines_value(BinOp,ArgValue1,DetResult)
-> /* print(det(BinOp,ArgValue1)),nl, */
equal_object_wf(Res,DetResult,b_compute_expression2(BinOp),WF)
; b_compute_expression(BType2,LocalState,State,ArgValue2,WF),
% print_message(delayed_bin_op(BinOp,ArgValue1,ArgValue2)),
(is_definitely_empty(BinOp,ArgValue1,ArgValue2)
-> empty_set(Res)
; if(do_not_keep_symbolic(BinOp,ArgValue1,ArgValue2,ERes,WF),
% then:
equal_object_wf(Res,ERes,b_compute_expression2(BinOp),WF),
% else:
(get_texpr_type(BType1,TypeArg1), create_texpr(value(ArgValue1),TypeArg1,[],TArg1),
get_texpr_type(BType2,TypeArg2), create_texpr(value(ArgValue2),TypeArg2,[],TArg2),
ClosureSetExpression =.. [BinOp,TArg1,TArg2],
construct_member_closure('_zzzz_unary',Type,Info,ClosureSetExpression,Value),
% print('Constructed Symbolic Closure : '), translate:print_bvalue(Value),nl,
(binop_to_be_marked_as_symbolic(BinOp,ArgValue1,ArgValue2) ->
mark_closure_as_symbolic(Value,SValue),
equal_object_wf(Res,SValue,WF)
; equal_object_wf(Res,Value,WF))
)
) % if
)
).
b_compute_expression2(Expression,Type,Info,LocalState,State,Value,WF) :-
functor(Expression,Op,1),
unary_function(Op,Module,KernelFunction),
arg(1,Expression,Arg1),!,
%opt_push_wait_flag_call_stack_info(WF,b_operator_arg_evaluation(Op,1,[SV1],Arg1),WF1),
b_compute_expression(Arg1,LocalState,State,SV1,WF),
unary_kernel_call(Module,KernelFunction,SV1,Value,WF,Expression,Type,Info).
b_compute_expression2(Expression,Type,Info,LocalState,State,Value,WF) :-
functor(Expression,Op,2),
binary_function(Op,Module,KernelFunction),
arg(1,Expression,Arg1),
arg(2,Expression,Arg2),!,
%opt_push_wait_flag_call_stack_info(WF,b_operator_arg_evaluation(Op,1,[SV1,_],Arg1),WF1),
b_compute_expression(Arg1,LocalState,State,SV1,WF),
(binary_arg1_determines_value(Op,SV1,Result) % we could disable this if find_abort_values=true or if SV1 not guaranteed to be wd
->
equal_object_wf(Value,Result,b_compute_expression2(Op),WF)
; b_compute_expression(Arg2,LocalState,State,SV2,WF),
binary_kernel_call(Module,KernelFunction,SV1,SV2,Value,WF,Expression,Type,Info)
).
b_compute_expression2(operation_call_in_expr(Operation,Parameters),_T,Info,LocalState,State,Value,WF) :-
!, def_get_texpr_id(Operation,op(OperationName)),
% TODO: check that this is a query operation; probably done in type checker
b_execute_operation_in_expression(OperationName,LocalState,State,Parameters,Value,Info,WF).
b_compute_expression2(E,T,Info,_L,_S,_R,_WF) :-
(T==pred -> add_internal_error('Uncovered expression; looks like a predicate in the wrong place: ',b(E,T,Info))
; T==subst -> add_internal_error('Uncovered expression; looks like a substitution in the wrong place: ',b(E,T,Info))
; add_internal_error('Uncovered expression: ',b(E,T,Info))
),
print_functor(E), print(' : '), print(T),nl,fail.