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(b_abstract_mappings,[
6 call_unary_test/4,
7 call_binary_test/6,
8
9 call_alpha/4,
10
11 call_unary_expression/3,
12 call_binary_expression/4,
13 call_nary_expression/3,
14
15 glb/3,
16 lub/3
17 ]).
18
19 :- use_module(probsrc(error_manager)).
20 :- use_module(probsrc(tools)).
21
22 :- use_module(library(file_systems)).
23 :- use_module(probsrc(module_information)).
24 :- module_info(group,plugin_absint).
25 :- module_info(description,'Experimental abstract interpretation plugin: this module maps regular operators to the ones in the selected abstract domain.').
26 :- module_info(revision,'$Rev$').
27 :- module_info(lastchanged,'$LastChangedDate$').
28
29 :- dynamic domain/2.
30
31 % ---------
32 % loading of the abstract domain modules at compiletime, lookup in directory
33 % ---------
34
35 load_compiletime_domains :-
36 findall(Module,
37 (directory_member_of_directory('domains',Dir,Fullname),
38 atom_concat(Dir,'.pl',PrologFilename),
39 file_member_of_directory(Fullname,PrologFilename,_),
40 ajoin([Dir,'/',PrologFilename], Modulename),
41 Module = abstract_domains(Modulename)),
42 Domains),
43 load_domains2(Domains).
44
45 load_domains2([]).
46 load_domains2([Module|Prest]) :-
47 load_domain(Module,Id),
48 (nonvar(Id) -> assert(domain(Id,Module)); true),
49 load_domains2(Prest).
50
51 load_domain(Module,Id) :-
52 catch( ( load_domain2(Module,Id) ->
53 ajoin(['Loaded domain ', Id], Msg),
54 print_message(informational, Msg)
55 ; otherwise ->
56 ajoin(['Loading of module ', Id, ' failed: '], Msg),
57 print_message(error, Msg)),
58 E,
59 ( ajoin(['Loading of module ', Id, ' raised an exception: ', E], Msg),
60 print_message(error, Msg))).
61
62 load_domain2(Module,Id) :-
63 use_module(IdVar,Module,[]),
64 IdVar = Id,
65 ( domain(Id,_) ->
66 ajoin(['Domain ID ',Id,'used twice'],Msg),
67 print_message(error,Msg),
68 fail
69 ; otherwise ->
70 true).
71
72
73 :- load_compiletime_domains.
74
75 % ----------------
76 % Call GLB and LUB
77 % ----------------
78 lub(X, Y, Z) :-
79 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
80 current_predicate(DomainModule:lub/1),
81 DomainModule:lub(LUB),
82 call(DomainModule:LUB, X, Y, Z),
83 !.
84 lub(_, _, _) :-
85 add_error(lub, 'Least upper bound is not defined or failed. Define a lub/3 predicate in the abstract domain file'), fail.
86
87 glb(X, Y, Z) :-
88 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
89 current_predicate(DomainModule:glb/1),
90 DomainModule:glb(GLB),
91 call(DomainModule:GLB, X, Y, Z),
92 !.
93 glb(_, _, _) :-
94 add_error(glb, 'Greatest lower bound is not defined or failed. Define a glb/3 predicate in the abstract domain file'), fail.
95
96 % -----------------
97 % Call Alpha
98 % -----------------
99 call_alpha(Concrete,Type,Infos,Abstract) :-
100 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
101 DomainModule:map_alpha(alpha, CallAlpha),
102 call(DomainModule:CallAlpha,Concrete,Type,Infos,Abstract), !.
103 call_alpha(C,T,I,top) :-
104 add_error(call_alpha, 'no mapping for alpha or no result defined (using top instead) for ', [C,T,I]).
105
106 % ----------------
107 % Call predicates
108 % ----------------
109 call_unary_test(UOP, Arg1, NewArg1, Test) :-
110 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
111 (DomainModule:map_unary_test_operator(UOP, CallUOP) -> true
112 ; Expr =.. [UOP, Arg1],add_error(call_unary_test, 'no mapping for operator or no result defined (using true instead) for ', Expr)),
113 !,
114 (call(DomainModule:CallUOP, Arg1, NewArg1, Test1) -> Test = Test1
115 ; Test = false, Arg1 = NewArg1).
116
117 call_binary_test(BOP, Arg1, Arg2, NewArg1, NewArg2, Test) :-
118 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
119 (DomainModule:map_binary_test_operator(BOP, CallBOP) -> true
120 ; Expr =.. [BOP, Arg1, Arg2],add_error(call_binary_test, 'no mapping for operator or no result defined (using true instead) for ', Expr)),
121 !,
122 (call(DomainModule:CallBOP, Arg1, Arg2, NewArg1, NewArg2, Test1) -> Test = Test1
123 ; Test = false, Arg1 = NewArg1, Arg2 = NewArg2).
124
125 % -----------------
126 % Call expressions
127 % -----------------
128 call_unary_expression(UOP, Arg1, Result) :-
129 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
130 DomainModule:map_unary_operator(UOP, CallUOP),
131 !,
132 call(DomainModule:CallUOP, Arg1, Result).
133 call_unary_expression(UOP, Arg1, top) :-
134 Expr =.. [UOP, Arg1],
135 add_error_fail(call_unary_expression, 'no mapping for operator or no result defined for ', Expr).
136
137 call_binary_expression(BOP, Arg1, Arg2, Result) :-
138 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
139 DomainModule:map_binary_operator(BOP, CallBOP),
140 !,
141 call(DomainModule:CallBOP, Arg1, Arg2, Result).
142 call_binary_expression(BOP, Arg1, Arg2, top_) :-
143 Expr =.. [BOP, Arg1, Arg2],
144 add_error_fail(call_binary_expression, 'no mapping for operator or no result defined for ', Expr).
145
146 call_nary_expression(OP, Arg, Result) :-
147 preferences:preference(plugin(absint,abstract_domain_module), DomainModule),
148 DomainModule:map_nary_operator(OP, CallOP),
149 !,
150 call(DomainModule:CallOP, Arg, Result).
151 call_nary_expression(OP, Arg, top) :-
152 Expr =.. [OP, Arg],
153 add_error_fail(call_unary_expression, 'no mapping for operator or no result defined for ', Expr).