35
36:- module(apply_macros,
37 [ expand_phrase/2, 38 expand_phrase/4 39 ]). 40:- use_module(library(lists)). 41
66
67:- dynamic
68 user:goal_expansion/2. 69:- multifile
70 user:goal_expansion/2. 71
72
76
77expand_maplist(Callable0, Lists, Goal) :-
78 length(Lists, N),
79 expand_closure_no_fail(Callable0, N, Callable1),
80 ( Callable1 = _:_
81 -> strip_module(Callable0, M, Callable),
82 NextGoal = M:NextCall
83 ; Callable = Callable1,
84 NextGoal = NextCall
85 ),
86 Callable =.. [Pred|Args],
87 length(Args, Argc),
88 length(Argv, Argc),
89 length(Vars, N),
90 MapArity is N + 1,
91 format(atom(AuxName), '__aux_maplist/~d_~w+~d', [MapArity, Pred, Argc]),
92 append(Lists, Args, AuxArgs),
93 Goal =.. [AuxName|AuxArgs],
94
95 AuxArity is N+Argc,
96 prolog_load_context(module, Module),
97 functor(NextCall, Pred, AuxArity),
98 \+ predicate_property(Module:NextGoal, transparent),
99 ( predicate_property(Module:Goal, defined)
100 -> true
101 ; empty_lists(N, BaseLists),
102 length(Anon, Argc),
103 append(BaseLists, Anon, BaseArgs),
104 BaseClause =.. [AuxName|BaseArgs],
105
106 heads_and_tails(N, NextArgs, Vars, Tails),
107 append(NextArgs, Argv, AllNextArgs),
108 NextHead =.. [AuxName|AllNextArgs],
109 append(Argv, Vars, PredArgs),
110 NextCall =.. [Pred|PredArgs],
111 append(Tails, Argv, IttArgs),
112 NextIterate =.. [AuxName|IttArgs],
113 NextClause = (NextHead :- NextGoal, NextIterate),
114 compile_aux_clauses([BaseClause, NextClause])
115 ).
116
117expand_closure_no_fail(Callable0, N, Callable1) :-
118 '$expand_closure'(Callable0, N, Callable1),
119 !.
120expand_closure_no_fail(Callable, _, Callable).
121
122empty_lists(0, []) :- !.
123empty_lists(N, [[]|T]) :-
124 N2 is N - 1,
125 empty_lists(N2, T).
126
127heads_and_tails(0, [], [], []).
128heads_and_tails(N, [[H|T]|L1], [H|L2], [T|L3]) :-
129 N2 is N - 1,
130 heads_and_tails(N2, L1, L2, L3).
131
132
136
137expand_apply(Maplist, Goal) :-
138 compound(Maplist),
139 compound_name_arity(Maplist, maplist, N),
140 N >= 2,
141 Maplist =.. [maplist, Callable|Lists],
142 qcall_instantiated(Callable),
143 !,
144 expand_maplist(Callable, Lists, Goal).
145
155
156expand_apply(forall(Cond, Action), Pos0, Goal, Pos) :-
157 Goal = \+((Cond, \+(Action))),
158 ( nonvar(Pos0),
159 Pos0 = term_position(_,_,_,_,[PosCond,PosAct])
160 -> Pos = term_position(0,0,0,0, 161 [ term_position(0,0,0,0, 162 [ PosCond,
163 term_position(0,0,0,0, 164 [PosAct])
165 ])
166 ])
167 ; true
168 ).
169expand_apply(once(Once), Pos0, Goal, Pos) :-
170 Goal = (Once->true),
171 ( nonvar(Pos0),
172 Pos0 = term_position(_,_,_,_,[OncePos]),
173 compound(OncePos)
174 -> Pos = term_position(0,0,0,0, 175 [ OncePos,
176 F-T 177 ]),
178 arg(2, OncePos, F), 179 T is F+1
180 ; true
181 ).
182expand_apply(ignore(Ignore), Pos0, Goal, Pos) :-
183 Goal = (Ignore->true;true),
184 ( nonvar(Pos0),
185 Pos0 = term_position(_,_,_,_,[IgnorePos]),
186 compound(IgnorePos)
187 -> Pos = term_position(0,0,0,0, 188 [ term_position(0,0,0,0, 189 [ IgnorePos,
190 F-T 191 ]),
192 F-T 193 ]),
194 arg(2, IgnorePos, F), 195 T is F+1
196 ; true
197 ).
198expand_apply(Phrase, Pos0, Expanded, Pos) :-
199 expand_phrase(Phrase, Pos0, Expanded, Pos),
200 !.
201
202
219
220expand_phrase(Phrase, Goal) :-
221 expand_phrase(Phrase, _, Goal, _).
222
223expand_phrase(phrase(NT,Xs), Pos0, NTXsNil, Pos) :-
224 !,
225 extend_pos(Pos0, 1, Pos1),
226 expand_phrase(phrase(NT,Xs,[]), Pos1, NTXsNil, Pos).
227expand_phrase(Goal, Pos0, NewGoal, Pos) :-
228 dcg_goal(Goal, NT, Xs0, Xs),
229 nonvar(NT),
230 nt_pos(Pos0, NTPos),
231 dcg_extend(NT, NTPos, NewGoal, Pos, Xs0, Xs).
232
233dcg_goal(phrase(NT,Xs0,Xs), NT, Xs0, Xs).
234dcg_goal(call_dcg(NT,Xs0,Xs), NT, Xs0, Xs).
235
237
238dcg_extend(Compound0, Pos0, Compound, Pos, Xs0, Xs) :-
239 compound(Compound0),
240 \+ dcg_control(Compound0),
241 !,
242 extend_pos(Pos0, 2, Pos),
243 compound_name_arguments(Compound0, Name, Args0),
244 append(Args0, [Xs0,Xs], Args),
245 compound_name_arguments(Compound, Name, Args).
246dcg_extend(Name, Pos0, Compound, Pos, Xs0, Xs) :-
247 atom(Name),
248 \+ dcg_control(Name),
249 !,
250 extend_pos(Pos0, 2, Pos),
251 compound_name_arguments(Compound, Name, [Xs0,Xs]).
252dcg_extend(Q0, Pos0, M:Q, Pos, Xs0, Xs) :-
253 compound(Q0), Q0 = M:Q1,
254 '$expand':f2_pos(Pos0, MPos, APos0, Pos, MPos, APos),
255 dcg_extend(Q1, APos0, Q, APos, Xs0, Xs).
256dcg_extend(Terminal, Pos0, Xs0 = DList, Pos, Xs0, Xs) :-
257 terminal(Terminal, DList, Xs),
258 !,
259 t_pos(Pos0, Pos).
260
261dcg_control(!).
262dcg_control([]).
263dcg_control([_|_]).
264dcg_control({_}).
265dcg_control((_,_)).
266dcg_control((_;_)).
267dcg_control((_->_)).
268dcg_control((_*->_)).
269dcg_control(_:_).
270
271terminal(List, DList, Tail) :-
272 compound(List),
273 List = [_|_],
274 !,
275 '$skip_list'(_, List, T0),
276 ( var(T0)
277 -> DList = List,
278 Tail = T0
279 ; T0 == []
280 -> append(List, Tail, DList)
281 ; type_error(list, List)
282 ).
283terminal(List, DList, Tail) :-
284 List == [],
285 !,
286 DList = Tail.
287terminal(String, DList, Tail) :-
288 string(String),
289 string_codes(String, List),
290 append(List, Tail, DList).
291
292extend_pos(Var, _, Var) :-
293 var(Var),
294 !.
295extend_pos(term_position(F,T,FF,FT,ArgPos0), Extra,
296 term_position(F,T,FF,FT,ArgPos)) :-
297 !,
298 extra_pos(Extra, T, ExtraPos),
299 append(ArgPos0, ExtraPos, ArgPos).
300extend_pos(FF-FT, Extra,
301 term_position(FF,FT,FF,FT,ArgPos)) :-
302 !,
303 extra_pos(Extra, FT, ArgPos).
304
(1, T, [T-T]).
306extra_pos(2, T, [T-T,T-T]).
307
308nt_pos(PhrasePos, _NTPos) :-
309 var(PhrasePos),
310 !.
311nt_pos(term_position(_,_,_,_,[NTPos|_]), NTPos).
312
313t_pos(Pos0, term_position(F,T,F,T,[F-T,F-T])) :-
314 compound(Pos0),
315 !,
316 arg(1, Pos0, F),
317 arg(2, Pos0, T).
318t_pos(_, _).
319
320
326
327qcall_instantiated(Var) :-
328 var(Var),
329 !,
330 fail.
331qcall_instantiated(M:C) :-
332 !,
333 atom(M),
334 callable(C).
335qcall_instantiated(C) :-
336 callable(C).
337
338
339 342
343:- multifile
344 prolog_clause:unify_goal/5. 345
346prolog_clause:unify_goal(Maplist, Expanded, _Module, Pos0, Pos) :-
347 is_maplist(Maplist),
348 maplist_expansion(Expanded),
349 Pos0 = term_position(F,T,FF,FT,[_MapPos|ArgsPos]),
350 Pos = term_position(F,T,FF,FT,ArgsPos).
351
352is_maplist(Goal) :-
353 compound(Goal),
354 functor(Goal, maplist, A),
355 A >= 2.
356
357maplist_expansion(Expanded) :-
358 compound(Expanded),
359 functor(Expanded, Name, _),
360 sub_atom(Name, 0, _, _, '__aux_maplist/').
361
362
363 366
367:- multifile
368 prolog_colour:vararg_goal_classification/3. 369
370prolog_colour:vararg_goal_classification(maplist, Arity, expanded) :-
371 Arity >= 2.
372
373
374 377
378:- multifile
379 system:goal_expansion/2,
380 system:goal_expansion/4. 381
383
384system:goal_expansion(GoalIn, GoalOut) :-
385 \+ current_prolog_flag(xref, true),
386 expand_apply(GoalIn, GoalOut).
387system:goal_expansion(GoalIn, PosIn, GoalOut, PosOut) :-
388 expand_apply(GoalIn, PosIn, GoalOut, PosOut)