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