pp_expr2(Expr,_,_LimitReached) --> {var(Expr)},!,"_".
pp_expr2(_,_,LimitReached) --> {LimitReached==limit_reached},!,"...".
pp_expr2(atom_string(V),500,_) --> !,pp_atom_opt_latex_mathit(V). % hardwired_atom
pp_expr2(global_set(V),500,_) --> !, pp_identifier(V).
pp_expr2(freetype_set(V),500,_) --> !,{pretty_freetype(V,P)},ppatom_opt_scramble(P).
pp_expr2(lazy_lookup_expr(I),500,_) --> !, pp_identifier(I).
pp_expr2(lazy_lookup_pred(I),500,_) --> !, pp_identifier(I).
pp_expr2(identifier(I),500,_) --> !,
{( I=op(Id) -> true; I=Id)},
( {atomic(Id)} -> ({translated_identifier(Id,TId)},
({latex_mode} -> ppatom(TId) ; pp_identifier(TId)))
;
"'",ppterm(Id), "'").
pp_expr2(integer(N),500,_) --> !, ppnumber(N).
pp_expr2(real(N),500,_) --> !, ppatom(N).
pp_expr2(integer_set(S),500,_) --> !,
{integer_set_mapping(S,T)},ppatom(T).
pp_expr2(string(S),500,_) --> !, string_start_symbol, ppstring_opt_scramble(S), string_end_symbol.
pp_expr2(set_extension(Ext),500,LimitReached) --> !, {set_brackets(L,R)},
pp_expr_wrap_l(L,Ext,R,LimitReached).
pp_expr2(sequence_extension(Ext),500,LimitReached) --> !,
pp_begin_sequence,
({get_preference(translate_print_cs_style_sequences,true)} -> pp_expr_l_sep(Ext,"",LimitReached)
; pp_expr_l_sep(Ext,",",LimitReached)),
pp_end_sequence.
pp_expr2(assign(LHS,RHS),10,LimitReached) --> !,
pp_expr_wrap_l(',',LHS,'',LimitReached), ":=", pp_expr_wrap_l(',',RHS,'',LimitReached).
pp_expr2(assign_single_id(LHS,RHS),10,LimitReached) --> !, pp_expr2(assign([LHS],[RHS]),10,LimitReached).
pp_expr2(parallel(RHS),10,LimitReached) --> !,
pp_expr_wrap_l('||',RHS,'',LimitReached).
pp_expr2(sequence(RHS),10,LimitReached) --> !,
pp_expr_wrap_l(';',RHS,'',LimitReached).
pp_expr2(event_b_comprehension_set(Ids,E,P1),500,LimitReached) --> !, % normally conversion above should trigger; this is if we call pp_expr for untyped expressions
pp_event_b_comprehension_set(Ids,E,P1,LimitReached).
pp_expr2(recursive_let(Id,S),500,LimitReached) --> !,
({eventb_translation_mode} -> "" % otherwise we get strange characters in Rodin
; enter_comment," recursive ID ", pp_expr(Id,_,LimitReached), " ", exit_comment),
pp_expr(S,_,LimitReached).
pp_expr2(image(A,B),300,LimitReached) --> !,
pp_expr_m(A,249,LimitReached),"[", % was 0; but we may have to bracket A; e.g., f <| {2} [{2}] is not ok; 250 is priority of lambda
pp_expr_m(B,0,LimitReached),"]". % was 500, now set to 0: we never need an outer pair of () !?
pp_expr2(function(A,B),300,LimitReached) --> !,
pp_expr_m(A,249,LimitReached), % was 0; but we may have to bracket A; e.g., f <| {2} (2) is not ok; 250 is priority of lambda
pp_function_left_bracket,
pp_expr_m(B,0,LimitReached), % was 500, now set to 0: we never need an outer pair of () !?
pp_function_right_bracket.
pp_expr2(definition(A,B),300,LimitReached) --> !, % definition call; usually inlined,...
ppatom(A),
pp_function_left_bracket,
pp_expr_l_sep(B,",",LimitReached),
pp_function_right_bracket.
pp_expr2(operation_call_in_expr(A,B),300,LimitReached) --> !,
pp_expr_m(A,249,LimitReached),
pp_function_left_bracket,
pp_expr_l_sep(B,",",LimitReached),
pp_function_right_bracket.
pp_expr2(enumerated_set_def(GS,ListEls),200,LimitReached) --> !, % for pretty printing enumerate set defs
{reverse(ListEls,RLE)}, /* they have been inserted in inverse order */
pp_identifier(GS), "=", pp_expr_wrap_l('{',RLE,'}',LimitReached).
pp_expr2(forall(Ids,D1,P),Prio,LimitReached) --> !,
({eventb_translation_mode} -> {Prio=60} ; {Prio=250}), % in Rodin forall/exists cannot be mixed with &, or, <=>, ...
forall_symbol,pp_expr_ids_in_mode(Ids,LimitReached),
{add_normal_typing_predicates(Ids,D1,D)},
dot_symbol,pp_expr_m(b(implication(D,P),pred,[]),221,LimitReached).
pp_expr2(exists(Ids,P1),Prio,LimitReached) --> !,
({eventb_translation_mode} -> {Prio=60} ; {Prio=250}), % exists has Prio 250, but dot has 220
exists_symbol,pp_expr_ids_in_mode(Ids,LimitReached),
{add_normal_typing_predicates(Ids,P1,P)},
dot_symbol,
({eventb_translation_mode} -> {MinPrio=29} ; {MinPrio=500}),
% used to be 221, but #x.x>7 or #x.not(...) are not parsed by Atelier-B or ProB, x.x and x.not are parsed as composed identifiers
% In Event-B โyยทy>x โง (y=x+1 โจ y=x+2) is valid and requires no outer parenthesis
pp_expr_m(P,MinPrio,LimitReached).
pp_expr2(record_field(R,I),250,LimitReached) --> !,
pp_expr_m(R,251,LimitReached),"'",pp_identifier(I).
pp_expr2(rec(Fields),500,LimitReached) --> !,
{function_like_in_mode(rec,Symbol)},
ppatom(Symbol), "(",pp_expr_fields(Fields,LimitReached),")".
pp_expr2(struct(Rec),500,LimitReached) -->
{get_texpr_expr(Rec,rec(Fields)),Val=false ; get_texpr_expr(Rec,value(rec(Fields)))},!,
{function_like_in_mode(struct,Symbol)},
ppatom(Symbol), "(",
({Val==false} -> pp_expr_fields(Fields,LimitReached)
; pp_value_l(Fields,',',LimitReached)),
")".
pp_expr2(freetype_case(FT,L,Expr),500,LimitReached) --> !,
pp_freetype_term('__is_ft_case',FT,L,Expr,LimitReached).
pp_expr2(freetype_constructor(_FT,L,Expr),500,LimitReached) --> !,
ppatom_opt_scramble(L),ppatom('('),pp_expr(Expr,_,LimitReached),ppatom(')').
pp_expr2(freetype_destructor(FT,Case,Expr),500,LimitReached) --> !,
({unicode_mode}
-> {unicode_translation(reverse,PowMinus1Symbol)},
ppatom(Case),ppatom(PowMinus1Symbol), % Note: we do not print the freetype's name FT
"(",pp_expr_m(Expr,0,LimitReached),")"
; pp_freetype_term('__ft~',FT,Case,Expr,LimitReached) % TODO: maybe find better print
).
pp_expr2(let_predicate(Ids,Exprs,P),1,LimitReached) --> !,
pp_expr_let_exists(Ids,Exprs,P,LimitReached). % instead of pp_expr_let
pp_expr2(let_expression(Ids,Exprs,P),1,LimitReached) --> !,
pp_expr_let(Ids,Exprs,P,LimitReached).
pp_expr2(let_expression_global(Ids,Exprs,P),1,LimitReached) --> !, " /", "* global *", "/ ",
pp_expr_let(Ids,Exprs,P,LimitReached).
pp_expr2(lazy_let_pred(Id,Expr,P),Pr,LimitReached) --> !, pp_expr2(lazy_let_expr(Id,Expr,P),Pr,LimitReached).
pp_expr2(lazy_let_subst(Id,Expr,P),Pr,LimitReached) --> !, pp_expr2(lazy_let_expr(Id,Expr,P),Pr,LimitReached).
pp_expr2(lazy_let_expr(Id,Expr,P),1,LimitReached) --> !,
pp_expr_let([Id],[Expr],P,LimitReached).
pp_expr2(norm_conjunct(Cond,[]),1,LimitReached) --> !, % norm_conjunct: flattened version generated by b_interpreter_check,...
"( ",pp_expr(Cond,_,LimitReached), ")".
pp_expr2(norm_conjunct(Cond,[H|T]),1,LimitReached) --> !,
"( ",pp_expr(Cond,_,LimitReached), ") ", and_symbol, " (", pp_expr2(norm_conjunct(H,T),_,LimitReached), ")".
pp_expr2(assertion_expression(Cond,Msg,Expr),1,LimitReached) --> !,
" ASSERT_EXPR (",
pp_expr_m(b(convert_bool(Cond),pred,[]),30,LimitReached), ",",
pp_expr_m(string(Msg),30,LimitReached), ",",
pp_expr_m(Expr,30,LimitReached),
" )".
pp_expr2(partition(S,Elems),500,LimitReached) -->
{eventb_translation_mode ;
\+ atelierb_mode(_), length(Elems,Len), Len>50 % we need to print a quadratic number of disjoints
},!,
"partition(",pp_expr(S,_,LimitReached),
({Elems=[]} -> ")" ; pp_expr_wrap_l(',',Elems,')',LimitReached)).
pp_expr2(partition(S,Elems),500,LimitReached) --> !,
"(",pp_expr(S,_,LimitReached), " = ",
({Elems=[]} -> "{})"
; pp_expr_l_sep(Elems,"\\/",LimitReached), pp_all_disjoint(Elems,LimitReached),")").
pp_expr2(finite(S),Prio,LimitReached) --> {\+ eventb_translation_mode}, %{atelierb_mode(_)},
!,
pp_expr2(member(S,b(fin_subset(S),set(any),[])),Prio,LimitReached).
pp_expr2(if_then_else(If,Then,Else),1,LimitReached) --> {animation_minor_mode(z)},!,
"\\IF ",pp_expr_m(If,30,LimitReached),
" \\THEN ",pp_expr_m(Then,30,LimitReached),
" \\ELSE ",pp_expr_m(Else,30,LimitReached).
pp_expr2(if_then_else(If,Then,Else),Prio,LimitReached) --> {atelierb_mode(_)},!,
% print IF-THEN-ELSE using a translation that Atelier-B can understand:
{rewrite_if_then_else_expr_to_b(if_then_else(If,Then,Else), NExpr),
get_texpr_type(Then,Type),
NAst = b(NExpr,Type,[])},
% construct {d,x| If => x=Then & not(if) => x=Else}(TRUE)
pp_expr(NAst,Prio,LimitReached).
pp_expr2(if_then_else(If,Then,Else),1,LimitReached) --> !,
pp_atom_opt_mathit('IF'),pp_space, % "IF ",
pp_expr_m(If,30,LimitReached),
pp_space, pp_atom_opt_mathit('THEN'),pp_space, " THEN ",
pp_expr_m(Then,30,LimitReached),
pp_space, pp_atom_opt_mathit('ELSE'),pp_space, " ELSE ",
pp_expr_m(Else,30,LimitReached),
pp_space, pp_atom_opt_mathit('END'). " END"
pp_expr2(kodkod(Id,Identifiers),300,LimitReached) --> !,
"KODKOD_CALL(",ppnumber(Id),": ",pp_expr_ids(Identifiers,LimitReached),")".
pp_expr2(Expr,500,_) -->
{constants_in_mode(Expr,Symbol)},!,ppatom(Symbol).
pp_expr2(equal(A,B),Prio,LimitReached) -->
{get_preference(pp_propositional_logic_mode,true), % a mode for printing propositional logic formuli
is_boolean_value(B,BV),
get_texpr_id(A,_)},!,
({BV=pred_true} -> pp_expr(A,Prio,LimitReached)
; pp_expr2(negation(b(equal(A,b(boolean_true,boolean,[])),pred,[])),Prio,LimitReached)).
pp_expr2(Expr,Prio,LimitReached) -->
{functor(Expr,F,1),
unary_prefix(F,Symbol,Prio),!,
arg(1,Expr,Arg),APrio is Prio+1},
ppatom(Symbol), " ",
pp_expr_m(Arg,APrio,LimitReached).
pp_expr2(Expr,500,LimitReached) -->
{functor(Expr,F,1),
unary_prefix_parentheses(F,Symbol),!,
arg(1,Expr,Arg)},
pp_atom_opt_latex(Symbol), "(", pp_expr(Arg,_,LimitReached), ")".
pp_expr2(Expr,Prio,LimitReached) -->
{functor(Expr,F,1),
unary_postfix_in_mode(F,Symbol,Prio),!,
arg(1,Expr,Arg),APrio is Prio+1},
pp_expr_m(Arg,APrio,LimitReached),ppatom(Symbol).
pp_expr2(power_of(Left,Right),Prio,LimitReached) --> {latex_mode},!, % special case, as we need to put {} around RHS
{Prio=200, LPrio is Prio+1, RPrio = Prio},
pp_expr_m(Left,LPrio,LimitReached),
"^{",
pp_expr_m(Right,RPrio,LimitReached),
"}".
pp_expr2(power_of_real(Left,Right),Prio,LimitReached) --> !,
({get_texpr_expr(Right,convert_real(RI))}
-> pp_expr2(power_of(Left,RI),Prio,LimitReached) % the Atelier-B power_of expects integer exponent
; pp_external_call('RPOW',[Left,Right],expression,Prio,LimitReached)
).
pp_expr2(Expr,OPrio,LimitReached) -->
{functor(Expr,F,2),
binary_infix_in_mode(F,Symbol,Prio,Ass),!,
arg(1,Expr,Left),
arg(2,Expr,Right),
( Ass = left, binary_infix_symbol(Left,Symbol) -> LPrio is Prio-1, RPrio is Prio+1
; Ass = right, binary_infix_symbol(Right,Symbol) -> LPrio is Prio+1, RPrio is Prio-1
; LPrio is Prio+1, RPrio is Prio+1)},
% Note: Prio+1 is actually not necessary, Prio would be sufficient, as pp_expr_m uses a strict comparison <
({always_surround_by_parentheses(F)} -> "(",{OPrio=1000} ; {OPrio=Prio}),
pp_expr_m(Left,LPrio,LimitReached),
" ", ppatom(Symbol), " ",
pp_expr_m(Right,RPrio,LimitReached),
({always_surround_by_parentheses(F)} -> ")" ; []).
pp_expr2(first_of_pair(X),500,LimitReached) --> {get_texpr_type(X,couple(From,To))},!,
"prj1(", % TO DO: Latex version
({\+ atelierb_mode(_)} % eventb_translation_mode
-> "" % no need to print types in Event-B or with new parser;
% TODO: also with new parser no longer required; only print in Atelier-B mode
; {pretty_normalized_type(From,FromT),
pretty_normalized_type(To,ToT)},
pp_atom_opt_latex(FromT), ",", pp_atom_opt_latex(ToT),
")("
),
pp_expr(X,_,LimitReached),")".
pp_expr2(second_of_pair(X),500,LimitReached) --> {get_texpr_type(X,couple(From,To))},!,
"prj2(", % TO DO: Latex version
({\+ atelierb_mode(_)} -> "" % no need to print types in Event-B or with new parser
; {pretty_normalized_type(From,FromT),
pretty_normalized_type(To,ToT)},
pp_atom_opt_latex(FromT), ",", pp_atom_opt_latex(ToT),
")("
),
pp_expr(X,_,LimitReached),")".
pp_expr2(Call,Prio,LimitReached) --> {external_call(Call,Kind,Symbol,Args)},!,
pp_external_call(Symbol,Args,Kind,Prio,LimitReached).
pp_expr2(card(A),500,LimitReached) --> {latex_mode, get_preference(latex_pp_greek_ids,true)},!,
"|",pp_expr_m(A,0,LimitReached),"|".
pp_expr2(Expr,500,LimitReached) -->
{functor(Expr,F,_),
function_like_in_mode(F,Symbol),!,
Expr =.. [F|Args]},
ppatom(Symbol),
({Args=[]}
-> "" % some operators like pred and succ do not expect arguments
; pp_expr_wrap_l('(',Args,')',LimitReached)).
pp_expr2(Expr,250,LimitReached) -->
{functor(Expr,F,3),
quantified_in_mode(F,Symbol),
Expr =.. [F,Ids,P1,E],
!,
add_normal_typing_predicates(Ids,P1,P)},
ppatom(Symbol),pp_expr_ids(Ids,LimitReached),".(",
pp_expr_m(P,11,LimitReached),pp_such_that_bar(E),
pp_expr_m(E,11,LimitReached),")".
pp_expr2(Expr,Prio,LimitReached) -->
{functor(Expr,F,N),
(debug_mode(on)
-> format('**** Unknown functor ~w/~w in pp_expr2~n expression: ~w~n',[F,N,Expr])
; format('**** Unknown functor ~w/~w in pp_expr2~n',[F,N])
),
%add_internal_error('Unknown Expression: ',pp_expr2(Expr,Prio)),
Prio=20},
ppterm_with_limit_reached(Expr,LimitReached).