1 % (c) 2009-2017 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_tools, [contains_top/1,
6 check_state_add_error/2,
7 insert_spacer_and_join/2,
8 is_unit_list/1,
9 append_to_tcltk_replay_sequence/1,
10 reset_tcltk_replay_sequence/0,
11 replay_tcltk_sequence/0,
12 state_was_updated/2,
13 extract_value_list/2
14 ]).
15
16 :- use_module(library(lists)).
17
18 %:- use_module(library(tcltk)). % will be included automatically by prob_tcltk.pl; we do not want probcli to depend on Tcl/Tk
19
20 :- use_module(probsrc(tools)).
21 :- use_module(probsrc(self_check)).
22 :- use_module(probsrc(state_space)).
23 %:- use_module(probsrc(coverage_tools_annotations),['$NOT_COVERED'/1]).
24
25 :- use_module(probsrc(module_information)).
26 :- module_info(group,plugin_units).
27 :- module_info(description,'Units Plugin: Analysis tools used in several places.').
28
29
30 :- use_module(units).
31
32 :- dynamic tcltk_replay_sequence/1.
33
34 % TO DO: remove this callback to Tcl/Tk
35 %:- use_module(library(tcltk),[tcl_eval/3]).
36 to_tcltk(Command) :-
37 on_exception(_E, (user:cur_tcl_process(Tcl), tcltk:tcl_eval(Tcl, Command, _)), true).
38
39 append_to_tcltk_replay_sequence(X) :-
40 retract(tcltk_replay_sequence(S1)),
41 assert(tcltk_replay_sequence([X|S1])).
42
43 reset_tcltk_replay_sequence :-
44 retractall(tcltk_replay_sequence(_)),
45 assert(tcltk_replay_sequence([])).
46
47 replay_tcltk_sequence :-
48 to_tcltk('procInsertHistoryOptionsState'),
49 retract(tcltk_replay_sequence(Seq)),
50 reverse(Seq,Seq2),
51 replay_tcltk_sequence(Seq2).
52 replay_tcltk_sequence([]).
53 % in tcltk mode
54 %replay_tcltk_sequence([Op|T]) :-
55 % state_space:current_options(Options),
56 % nth0(N,Options,(_,_,Op,_)),
57 % ajoin(['procPerformOptionByIOption', ' ', N],Command),
58 % to_tcltk(Command), !,
59 % replay_tcltk_sequence(T),
60 % '$NOT_COVERED'('GUI code not used in automatic tests').
61 % in cli mode
62 replay_tcltk_sequence([Op|T]) :-
63 current_state_id(CurID),
64 visited_expression(CurID,CurState),
65 user:compute_all_transitions(CurID,CurState),
66 user:tcltk_perform_action(Op,_NewID),
67 replay_tcltk_sequence(T).
68 insert_spacer_and_join(List,Output) :-
69 atomic(List) -> Output=List ; ajoin_with_sep(List,' ',Output).
70
71 :- assert_must_succeed(contains_top(type(top([])))).
72 :- assert_must_succeed(contains_top(type(top([_])))).
73 :- assert_must_succeed(contains_top(type(type2(top([]),_)))).
74 :- assert_must_succeed(contains_top(type(type2(top([_]),_)))).
75 :- assert_must_fail(contains_top(type(_))).
76 contains_top(X) :- var(X), !, fail.
77 contains_top(X) :- X=top(_).
78 contains_top([H|T]) :-
79 !, (contains_top(H) ; contains_top(T)).
80 contains_top(Pred) :-
81 !, Pred =.. [Head|Tail],
82 Tail = [_|_],
83 (contains_top(Head) ; contains_top(Tail)).
84
85 check_state_add_error(ID, concrete_constants(State)) :-
86 !, check_state_add_error(ID,State).
87 check_state_add_error(_ID,[]).
88 check_state_add_error(ID,[bind(Var,Type)|T]) :-
89 contains_top(Type), !,
90 ajoin(['Multiple Units inferred for variable ', Var, '. This is a type error.'], ErrTerm),
91 units:units_error_context(Context),
92 store_state_error(ID,abort_error('Multiple Units inferred',
93 'State contains Error',ErrTerm,Context),_),
94 check_state_add_error(ID,T).
95 check_state_add_error(ID,[bind(Var,Type)|T]) :-
96 \+(ground(Type)), units:static_result(_,ListOfVars),
97 member(Var,ListOfVars), !,
98 ajoin(['Variable ', Var, ' is involved in constraint but still unset'], ErrTerm),
99 units:units_error_context(Context),
100 store_state_error(ID,abort_error('Constraint variable unset',
101 'Unsolved Constraint',ErrTerm,Context),_),
102 check_state_add_error(ID,T).
103 check_state_add_error(ID, [_H|T]) :-
104 check_state_add_error(ID,T).
105
106 is_unit_list(X) :- var(X), !, fail.
107 is_unit_list([X]) :- var(X), !, fail.
108 is_unit_list([]).
109 is_unit_list([[_,_,_]|T]) :-
110 is_unit_list(T).
111
112 :- assert_must_succeed(state_was_updated([bind(a,_A)],[bind(a,a)])).
113 :- assert_must_fail(state_was_updated([bind(a,_A)],[bind(a,_B)])).
114 :- assert_must_fail(state_was_updated([bind(a,top([]))],[bind(a,top([]))])).
115 :- assert_must_fail(state_was_updated([bind(a,top([]))],[bind(a,top([[[0,s,1]]]))])).
116 :- assert_must_fail(state_was_updated([bind(a,top([]))],[bind(a,top([[[0,s,1]],[[0,m,1]]]))])).
117 :- assert_must_succeed(state_was_updated([bind(a,top([])),bind(b,1)],[bind(a,top([[[0,s,1]]])),bind(b,2)])).
118 :- assert_must_succeed(state_was_updated([bind(a,A),bind(b,_B)],[bind(a,A),bind(b,b)])).
119 :- assert_must_succeed(state_was_updated([bind(a,A),bind(b,integer(_B))],[bind(a,A),bind(b,integer([[0,m,1],[0,s,-1]]))])).
120 :- assert_must_succeed(state_was_updated([bind(a,5),bind(b,integer(_B))],[bind(a,5),bind(b,integer([[0,m,1],[0,s,-1]]))])).
121 :- assert_must_succeed(state_was_updated([bind(a,integer(_A))],[bind(a,integer([[0,m,1],[0,s,-1]]))])).
122 :- assert_must_succeed(state_was_updated([bind(v,integer([[0,s,1]])),bind(w,integer(_)),bind(x,integer([[0,m,1]])),bind(y,integer([[0,m,-1]]))],
123 [bind(v,integer(top([]))),bind(w,integer(_)),bind(x,integer([[0,m,1]])),bind(y,integer([[0,m,-1]]))])).
124 state_was_updated([bind(ID,Val)|T1],[bind(ID,Val2)|T2]) :-
125 (\+ground(Val)), (\+ground(Val2)),
126 !, state_was_updated(T1,T2).
127 state_was_updated([bind(ID,Val)|_T1],[bind(ID,Val2)|_T2]) :-
128 (\+ground(Val)), ground(Val2).
129 state_was_updated([bind(ID,Val)|T1],[bind(ID,Val2)|T2]) :-
130 Val == Val2,
131 !, state_was_updated(T1,T2).
132 state_was_updated([bind(ID,Val)|T1],[bind(ID,Val2)|T2]) :-
133 contains_top(Val), contains_top(Val2), !,
134 state_was_updated(T1,T2).
135 state_was_updated([bind(ID,Val)|_T1],[bind(ID,Val2)|_T2]) :-
136 Val \== Val2.
137
138 extract_value_list([],[]).
139 extract_value_list([bind(_,X)|T],[X|ET]) :- extract_value_list(T,ET).