| 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). |