13
14:-module(term_based_metapred_finder, [ infer_meta_arguments_for/3,
15 find_meta_pred_args_in_clause/3]). 16:- use_module(pdt_prolog_library(utils4modules)). 17:- use_module(library(lists)). 18:- use_module(metafile_referencer). 19
31infer_meta_arguments_for(Module,AHead,MetaSpec):-
32 ( var(AHead)
33 -> defined_in_module(Module,Functor,Arity)
34 ; functor(AHead, Functor, Arity)
35 ),
36 functor(Head, Functor, Arity), 37 findall( MetaArgs,
38 find_meta_pred_args_in_clause(Module, Head, MetaArgs),
39 AllMetaArgs
40 ),
41 ( AllMetaArgs = []
42 -> fail
43 ; ( combine_meta_args(AllMetaArgs,CombinedArgs),
44 MetaSpec =.. [Functor|CombinedArgs]
45 )
46 ).
47
48
49find_meta_pred_args_in_clause(Module, Head, MetaArgs):-
50 \+(var(Head)),
51 predicate_property(Module:Head, built_in), !,
52 predicate_property(Module:Head, meta_predicate(Spec)),
53 Spec =.. [_|MetaArgs].
54find_meta_pred_args_in_clause(Module, Head, MetaArgs):-
55 clause(Module:Head, Body), !,
56 find_meta_vars_in_body(Body, Module, [], MetaVars),
57 find_meta_vars_in_head(Head, MetaVars, MetaArgs).
58find_meta_pred_args_in_clause(AModule, Head, MetaArgs):-
59 defined_in(AModule, Head, Module),
60 clause(Module:Head, Body), !,
61 find_meta_vars_in_body(Body, Module, [], MetaVars),
62 find_meta_vars_in_head(Head, MetaVars, MetaArgs).
63
64
65
66
67
81find_meta_vars_in_body(A, _, MetaVars, MetaVars):-
82 ( atomic(A)
83 ; var(A)
84 ),
85 !.
86
87find_meta_vars_in_body(Module:Term, _, KnownMetaVars, MetaVars):-
88 !,
89 find_meta_vars_in_body(Term, Module, KnownMetaVars, MetaVars).
90
91find_meta_vars_in_body((Cond -> Then ; Else), Context, KnownMetaVars, MetaVars):-
92 !, 93 find_meta_vars_in_body(Then, Context, KnownMetaVars, MetaVarsA),
94 ( (KnownMetaVars \= MetaVarsA) 95 -> find_meta_vars_in_body(Cond, Context, MetaVarsA, MetaVars) 96 ; find_meta_vars_in_body(Else, Context, KnownMetaVars, MetaVars) 97 ). 98
99find_meta_vars_in_body((TermA, TermB), Context, KnownMetaVars, MetaVars):-
100 !,
101 find_meta_vars_in_body(TermB, Context, KnownMetaVars, MetaVarsB),
102 find_meta_vars_in_body(TermA, Context, MetaVarsB, MetaVars). 103 104find_meta_vars_in_body((TermA; TermB), Context, KnownMetaVars, MetaVars):-
105 !,
106 find_meta_vars_in_body(TermB, Context, KnownMetaVars, MetaVarsB),
107 find_meta_vars_in_body(TermA, Context, MetaVarsB, MetaVars).
108
109find_meta_vars_in_body((TermA = TermB), _Context, KnownMetaVars, MetaVars):-
110 !,
111 ( occurs_in(TermA, KnownMetaVars)
112 -> add_var_to_set(TermB, KnownMetaVars, OwnMetaVars2)
113 ; OwnMetaVars2 = KnownMetaVars
114 ),
115 ( occurs_in(TermB, OwnMetaVars2)
116 -> add_var_to_set(TermA, OwnMetaVars2, MetaVars3)
117 ; MetaVars3 = OwnMetaVars2
118 ),
119 check_inner_vars(TermA, TermB, MetaVars3, MetaVars).
120
121find_meta_vars_in_body(functor(Term,Functor,_), _Context, KnownMetaVars, MetaVars):-
122 !,
123 ( occurs_in(Term,KnownMetaVars)
124 -> add_var_to_set(Functor, KnownMetaVars, MetaVars)
125 ; ( occurs_in(Functor,KnownMetaVars)
126 -> add_var_to_set(Term, KnownMetaVars, MetaVars)
127 ; MetaVars = KnownMetaVars
128 )
129 ).
130find_meta_vars_in_body(atom_concat(A,B,C), _Context, KnownMetaVars, AllMeta):-
131 !,
132 free_vars_of([A,B,C],Candidates),
133 add_meta_vars(Candidates,KnownMetaVars,AllMeta).
134
135find_meta_vars_in_body(( Term =.. List ), _Context, KnownMetaVars, MetaVars):-
136 !,
137 ( occurs_in(Term,KnownMetaVars)
138 -> ( add_var_to_set(List, KnownMetaVars, MetaVars1),
139 ( ( \+(var(List)),
140 List = [Functor|_]
141 )
143 -> add_var_to_set(Functor, MetaVars1, MetaVars) 144 ; MetaVars = MetaVars1
145 )
146 )
147 ; ( ( occurs_in(List,KnownMetaVars)
148 -> add_var_to_set(Term, KnownMetaVars, MetaVars)
149 ; ( ( \+(var(List)),
150 List = [Functor|_],
151 occurs_in(Functor, KnownMetaVars)
152 )
153 -> add_var_to_set(Term, KnownMetaVars, MetaVars)
154 ; MetaVars = KnownMetaVars
155 )
156 )
157 )
158 ).
159find_meta_vars_in_body(arg(_,Term,Arg), _Context, KnownMetaVars, MetaVars):-
160 !, 161 ( occurs_in(Term,KnownMetaVars)
162 -> add_var_to_set(Arg, KnownMetaVars, MetaVars)
163 ; ( occurs_in(Arg,KnownMetaVars)
164 -> add_var_to_set(Term, KnownMetaVars, MetaVars)
165 ; MetaVars = KnownMetaVars
166 )
167 ).
168
169
170find_meta_vars_in_body(Term, Context, KnownMetaVars, MetaVars):-
171 is_metaterm(Context, Term, MetaCombos), !,
172 extract_vars(MetaCombos, MetaArgs),
173 handel_meta_args(MetaArgs, Context, KnownMetaVars, MetaVars).
174
175find_meta_vars_in_body(_Term, _Context, MetaVars, MetaVars).
176 177
178
179
191find_meta_vars_in_head(Head, MetaVars, MetaArgs):- 192 Head =.. [_Functor|Args],
193 find_args_in_list(Args, MetaVars, MetaArgs, IsMeta),
194 ( IsMeta = true
195 -> true
196 ; fail
197 ).
198
199
200find_args_in_list([],_,[], false).
201find_args_in_list([Arg|Rest], MetaVars, MetaArgs, IsMeta):-
202 find_args_in_list(Rest,MetaVars,RestMetaArgs, MetaFound),
203 ( occurs_in(Arg,MetaVars)
204 -> ( MetaArgs=[0|RestMetaArgs],
205 IsMeta = true
206 )
207 ; ( MetaArgs=[?|RestMetaArgs],
208 IsMeta = MetaFound
209 )
210 ).
211
212
214
([],[]).
216extract_vars([(_,Var)|RestCombo], [Var|RestVars]):-
217 extract_vars(RestCombo, RestVars).
218
219
220
221
222
223handel_meta_args([], _, Known, Known).
224handel_meta_args([A|Rest], Context, Known, MetaVars):-
225 var(A), !,
226 add_var_to_set(A, Known, OwnMetaVars),
227 handel_meta_args(Rest, Context, OwnMetaVars, MetaVars).
228handel_meta_args([A|Rest], Context, Known, MetaVars):-
229 handel_meta_args(Rest, Context, Known, AllOthers),
230 find_meta_vars_in_body(A, Context, AllOthers, MetaVars).
231
232
233
234
235
236check_inner_vars(TermA,TermB,OldMetaVars,NewMetaVars):-
237 unifiable(TermA, TermB, Unifiers), !, 238 check_unifier_list(Unifiers,OldMetaVars,NewMetaVars).% 239check_inner_vars(_, _, MetaVars, MetaVars).
240
241
242check_unifier_list([], Metas, Metas).
243check_unifier_list([A=B|Rest], OldMetas, Metas):- 244 ( occurs_in(A, OldMetas) 245 -> add_var_to_set(B, OldMetas, Metas1)
246 ; Metas1 = OldMetas
247 ),
248 ( occurs_in(B, OldMetas)
249 -> add_var_to_set(A, Metas1, Metas2)
250 ; Metas2 = Metas1
251 ),
252 check_unifier_list(Rest, Metas2, Metas).
259free_vars_of(List,Free) :-
260 ( setof( X, (member(X,List), var(X)), Free),
261 !
262 ; Free = []
263 ).
272add_meta_vars(Candidates,KnownMeta,AllMeta) :-
273 select(Var,Candidates,OtherCandidates),
274 occurs_in(Var,KnownMeta),
275 combine_sets_nonbinding(OtherCandidates, KnownMeta, AllMeta),
276 !.
277
278combine_sets_nonbinding([],Set,Set).
279combine_sets_nonbinding([E|Rest],OldSet,NewSet):-
280 add_var_to_set(E,OldSet,Set),
281 combine_sets_nonbinding(Rest,Set,NewSet).
282
283
292add_var_to_set(Var, Set, NewSet):-
293 ( occurs_in(Var, Set)
294 -> NewSet = Set
295 ; NewSet = [Var|Set]
296 ).
297
298
304occurs_in(Var, Set):-
305 nth1(_, Set, OldVar),
306 OldVar == Var,
307 !.
308
309combine_meta_args([],[]):- !.
310combine_meta_args([List],List):- !.
311combine_meta_args([MetaArgs|RestMetaArgs],CombinedArgs):-
312 combine_meta_args(RestMetaArgs,RestCombinedArgs),
313 combine_two_arg_lists(MetaArgs, RestCombinedArgs, CombinedArgs).
314
315combine_two_arg_lists([], [], []):- !.
316combine_two_arg_lists([ArgA|ArgsA], [ArgB|ArgsB], [CombinedArg|CombinedRest]):-
317 combine_two_arg_lists(ArgsA,ArgsB,CombinedRest),
318 ( number(ArgA)
319 -> ( number(ArgB)
320 -> max_list([ArgA,ArgB],CombinedArg)
321 ; CombinedArg = ArgA
322 )
323 ; ( number(ArgB)
324 -> CombinedArg = ArgB
325 ; CombinedArg = ?
326 )
327 )