| 1 | % (c) 2009-2013 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
| 2 | % Heinrich Heine Universitaet Duesseldorf | |
| 3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
| 4 | ||
| 5 | :- module(units_prettyprint, [units_pp_trans/2, | |
| 6 | units_pp_prop/2, | |
| 7 | units_pp_value/2, | |
| 8 | pp/3, | |
| 9 | pp_fixpoint_result/3 | |
| 10 | ]). | |
| 11 | ||
| 12 | :- use_module(library(codesio)). | |
| 13 | :- use_module(library(lists)). | |
| 14 | :- use_module(library(avl)). | |
| 15 | ||
| 16 | :- use_module(probsrc(tools)). | |
| 17 | :- use_module(probsrc(error_manager)). | |
| 18 | ||
| 19 | :- use_module(units_alias). | |
| 20 | :- use_module(units_tools). | |
| 21 | :- use_module(units). | |
| 22 | :- use_module(units_interpreter). | |
| 23 | ||
| 24 | :- use_module(probsrc(module_information)). | |
| 25 | :- module_info(group,plugin_units). | |
| 26 | :- module_info(description,'Units Plugin: Prettyprinter for properties and transitions'). | |
| 27 | ||
| 28 | units_pp_trans(Transition,Pretty) :- | |
| 29 | %write(units_pp_trans(Transition,Pretty)), | |
| 30 | pp(classic,Transition,PrettyTerm), | |
| 31 | write_to_codes(PrettyTerm,Pretty). | |
| 32 | ||
| 33 | units_pp_prop(Property,Pretty) :- | |
| 34 | pp(classic,Property,PrettyTerm), | |
| 35 | write_to_codes(PrettyTerm,Pretty). | |
| 36 | ||
| 37 | units_pp_value(Value,Pretty) :- | |
| 38 | pp(classic,Value,PrettyTerm), | |
| 39 | write_to_codes(PrettyTerm,Pretty). | |
| 40 | ||
| 41 | ||
| 42 | pp(_ClassicOrEventB,X,unknown) :- var(X), !. | |
| 43 | pp(ClassicOrEventB,integer(X),Y) :- !, pp(ClassicOrEventB,X,Y). | |
| 44 | pp(ClassicOrEventB,int(X),Y) :- !, pp(ClassicOrEventB,X,Y). | |
| 45 | pp(ClassicOrEventB,boolean(X),Y) :- !, pp(ClassicOrEventB,X,Y). | |
| 46 | pp(ClassicOrEventB,string(X),Y) :- !, pp(ClassicOrEventB,X,Y). | |
| 47 | pp(ClassicOrEventB,global_set(X),Y) :- !, pp(ClassicOrEventB,X,Y). | |
| 48 | pp(ClassicOrEventB,set(X),Y) :- !, pp(ClassicOrEventB,X,Y). | |
| 49 | pp(ClassicOrEventB,couple(X,Y),Pretty) :- !, | |
| 50 | pp(ClassicOrEventB,X,PPX), pp(ClassicOrEventB,Y,PPY), | |
| 51 | ajoin([PPX, ' -> ', PPY],Pretty). | |
| 52 | pp(ClassicOrEventB,global(X,_Y),Pretty) :- !, | |
| 53 | pp(ClassicOrEventB,X,Pretty). | |
| 54 | % in the tcltk interface, the error is shown in a different way | |
| 55 | % thus, we do not need to include it in the prettyprint | |
| 56 | pp(classic,X,error) :- X=top(_), !. | |
| 57 | % in rodin, we show an error listing all infered units | |
| 58 | pp(eventb,X,PPOut) :- | |
| 59 | X=top(List), !, | |
| 60 | maplist(pp_unit(eventb),List,PPList), | |
| 61 | ajoin([multiple, '(', PPList, ')'], PPOut). | |
| 62 | % avl_sets from inside a value term | |
| 63 | pp(ClassicOrEventB,avl_set(A),PPOut) :- !, | |
| 64 | avl_domain(A,Dom), maplist(pp(ClassicOrEventB),Dom,PPDom), | |
| 65 | ajoin_with_sep(PPDom,',',JoinedDom), | |
| 66 | ajoin(['{',JoinedDom,'}'],PPOut). | |
| 67 | pp(_ClassicOrEventB,'$setup_constants','SETUP_CONSTANTS') :- !. | |
| 68 | pp(_ClassicOrEventB,'$initialise_machine','INITIALISATION') :- !. | |
| 69 | pp(_ClassicOrEventB,X,X) :- atom(X), !. | |
| 70 | pp(_ClassicOrEventB,X,X) :- number(X), !. | |
| 71 | pp(ClassicOrEventB,'-->'(Operation,ResultValues),PrettyTransition) :- !, | |
| 72 | pp(ClassicOrEventB,Operation,PrettyOperation), | |
| 73 | pp(ClassicOrEventB,ResultValues,PrettyResults), | |
| 74 | ajoin([PrettyOperation, '-->', PrettyResults],PrettyTransition). | |
| 75 | pp(ClassicOrEventB,L,Result) :- | |
| 76 | is_unit_list(L), | |
| 77 | pp_unit(ClassicOrEventB,L,Result),!. | |
| 78 | pp(_ClassicOrEventB,[],[]) :- !. | |
| 79 | pp(ClassicOrEventB,[H|T],[PH|PT]) :- !, | |
| 80 | pp(ClassicOrEventB,H,PH), | |
| 81 | pp(ClassicOrEventB,T,PT). | |
| 82 | pp(ClassicOrEventB,Compound,Pretty) :- | |
| 83 | Compound =.. [Head|Args], !, | |
| 84 | pp(ClassicOrEventB,Head,PrettyHead), | |
| 85 | pp(ClassicOrEventB,Args,PrettyArgs), | |
| 86 | Pretty =.. [PrettyHead|PrettyArgs]. | |
| 87 | pp(_ClassicOrEventB,Term,_Pretty) :- | |
| 88 | !, add_error_fail(units_prettyprint, 'Term not implemented: ', [Term]). | |
| 89 | ||
| 90 | pp_unit(ClassicOrEventB,L,Result) :- | |
| 91 | subseq(L,Com,Sub), | |
| 92 | unit_alias(Aliased,Sub), !, | |
| 93 | (Com = [] | |
| 94 | -> Result = Aliased | |
| 95 | ; pp_unit(ClassicOrEventB,Com,ComPP), | |
| 96 | ajoin_with_sep([Aliased,ComPP],' * ',Result)). | |
| 97 | pp_unit(ClassicOrEventB,[[EtoT,Symbol,EtoS]|T],Result) :- | |
| 98 | exponentiation_operator(ClassicOrEventB,Exponentiation), | |
| 99 | (EtoT = 0 | |
| 100 | -> EtoTPP = '' | |
| 101 | ; (EtoT = 1 -> EtoTPP = '10*' ; ajoin([10,Exponentiation,EtoT,'*'],EtoTPP))), | |
| 102 | (EtoS = 1 -> EtoSPP = Symbol ; ajoin([Symbol,Exponentiation,EtoS],EtoSPP)), | |
| 103 | ajoin([EtoTPP,EtoSPP],FirstUnitPP), | |
| 104 | (T = [] | |
| 105 | -> Result = FirstUnitPP | |
| 106 | ; pp_unit(ClassicOrEventB,T,TPP), | |
| 107 | ajoin_with_sep([FirstUnitPP,TPP],' * ',Result)). | |
| 108 | ||
| 109 | exponentiation_operator(classic,'**'). | |
| 110 | exponentiation_operator(eventb,'^'). | |
| 111 | ||
| 112 | ||
| 113 | % predicates below should only be called from tcltk | |
| 114 | pp_fixpoint_result(FixPointState,UnboundInConstraint,PP) :- | |
| 115 | pp_state(FixPointState,PPFixPointState), | |
| 116 | evaluate_fixpoint(FixPointState,UnboundInConstraint,Part2), | |
| 117 | units:iterations(Iterations), | |
| 118 | evaluate_operation(OperationsResult), | |
| 119 | ajoin(['Fixpoint reached after ', Iterations,' Iterations\n\nState:\n',PPFixPointState,'\n\n',Part2,'\n',OperationsResult],PP). | |
| 120 | ||
| 121 | pp_state([],''). | |
| 122 | pp_state([bind(Key,Val)|T],Res) :- | |
| 123 | pp_state(T,PPT), | |
| 124 | pp(classic,Val,PPVal), | |
| 125 | ajoin([Key, ' = ', PPVal, '\n', PPT],Res). | |
| 126 | ||
| 127 | evaluate_operation(OperationsResult) :- | |
| 128 | findall(Name, units_interpreter:top_in_parameters(Name), ListOfNames1), | |
| 129 | findall(Name, units_interpreter:top_in_results(Name), ListOfNames2), | |
| 130 | (ListOfNames1 = [] | |
| 131 | -> OperationsResult1 = '' | |
| 132 | ; ajoin(['Multiple units inferred for parameters of: ', ListOfNames1, '\n\n'], OperationsResult1) | |
| 133 | ), | |
| 134 | (ListOfNames2 = [] | |
| 135 | -> OperationsResult = OperationsResult1 | |
| 136 | ; ajoin([OperationsResult1,'Multiple units inferred for results of: ', ListOfNames2], OperationsResult) | |
| 137 | ). | |
| 138 | ||
| 139 | evaluate_fixpoint([],_Unbound,''). | |
| 140 | evaluate_fixpoint([bind(Id,Val)|State],Unbound,AtomOut) :- | |
| 141 | \+(ground(Val)), member(Id,Unbound), !, | |
| 142 | ajoin(['No unit inferred for Variable / Constant, but used in constraint: ',Id,'\n'],Out1), | |
| 143 | evaluate_fixpoint(State,Unbound,SubOut), | |
| 144 | ajoin([Out1,SubOut],AtomOut). | |
| 145 | evaluate_fixpoint([bind(Id,Val)|State],Unbound,AtomOut) :- | |
| 146 | \+(ground(Val)), !, | |
| 147 | ajoin(['No unit inferred for Variable / Constant: ',Id,'\n'],Out1), | |
| 148 | evaluate_fixpoint(State,Unbound,SubOut), | |
| 149 | ajoin([Out1,SubOut],AtomOut). | |
| 150 | evaluate_fixpoint([bind(Id,Val)|State],Unbound,AtomOut) :- | |
| 151 | contains_top(Val), !, | |
| 152 | ajoin(['Multiple units inferred for Variable / Constant: ',Id,'\n'],Out1), | |
| 153 | evaluate_fixpoint(State,Unbound,SubOut), | |
| 154 | ajoin([Out1,SubOut],AtomOut). | |
| 155 | evaluate_fixpoint([bind(_Id,_Val)|State],Unbound,SubOut) :- | |
| 156 | evaluate_fixpoint(State,Unbound,SubOut). |