37
38:- module('$expand',
39 [ expand_term/2, 40 expand_goal/2, 41 expand_term/4, 42 expand_goal/4, 43 var_property/2, 44
45 '$including'/0,
46 '$expand_closure'/3 47 ]).
72:- dynamic
73 system:term_expansion/2,
74 system:goal_expansion/2,
75 user:term_expansion/2,
76 user:goal_expansion/2,
77 system:term_expansion/4,
78 system:goal_expansion/4,
79 user:term_expansion/4,
80 user:goal_expansion/4. 81:- multifile
82 system:term_expansion/2,
83 system:goal_expansion/2,
84 user:term_expansion/2,
85 user:goal_expansion/2,
86 system:term_expansion/4,
87 system:goal_expansion/4,
88 user:term_expansion/4,
89 user:goal_expansion/4. 90
91:- meta_predicate
92 expand_terms(4, +, ?, -, -).
100expand_term(Term0, Term) :-
101 expand_term(Term0, _, Term, _).
102
103expand_term(Var, Pos, Expanded, Pos) :-
104 var(Var),
105 !,
106 Expanded = Var.
107expand_term(Term, Pos0, [], Pos) :-
108 cond_compilation(Term, X),
109 X == [],
110 !,
111 atomic_pos(Pos0, Pos).
112expand_term(Term, Pos0, Expanded, Pos) :-
113 setup_call_cleanup(
114 '$push_input_context'(expand_term),
115 expand_term_keep_source_loc(Term, Pos0, Expanded, Pos),
116 '$pop_input_context').
117
118expand_term_keep_source_loc(Term, Pos0, Expanded, Pos) :-
119 b_setval('$term', Term),
120 prepare_directive(Term),
121 '$def_modules'([term_expansion/4,term_expansion/2], MList),
122 call_term_expansion(MList, Term, Pos0, Term1, Pos1),
123 expand_terms(expand_term_2, Term1, Pos1, Expanded, Pos),
124 b_setval('$term', []).
133prepare_directive((:- Directive)) :-
134 '$current_source_module'(M),
135 prepare_directive(Directive, M),
136 !.
137prepare_directive(_).
138
139prepare_directive(Goal, _) :-
140 \+ callable(Goal),
141 !.
142prepare_directive((A,B), Module) :-
143 !,
144 prepare_directive(A, Module),
145 prepare_directive(B, Module).
146prepare_directive(module(_,_), _) :- !.
147prepare_directive(Goal, Module) :-
148 '$get_predicate_attribute'(Module:Goal, defined, 1),
149 !.
150prepare_directive(Goal, Module) :-
151 \+ current_prolog_flag(autoload, false),
152 ( compound(Goal)
153 -> compound_name_arity(Goal, Name, Arity)
154 ; Name = Goal, Arity = 0
155 ),
156 '$autoload'(Module:Name/Arity),
157 !.
158prepare_directive(_, _).
159
160
161call_term_expansion([], Term, Pos, Term, Pos).
162call_term_expansion([M-Preds|T], Term0, Pos0, Term, Pos) :-
163 current_prolog_flag(sandboxed_load, false),
164 !,
165 ( '$member'(Pred, Preds),
166 ( Pred == term_expansion/2
167 -> M:term_expansion(Term0, Term1),
168 Pos1 = Pos0
169 ; M:term_expansion(Term0, Pos0, Term1, Pos1)
170 )
171 -> expand_terms(call_term_expansion(T), Term1, Pos1, Term, Pos)
172 ; call_term_expansion(T, Term0, Pos0, Term, Pos)
173 ).
174call_term_expansion([M-Preds|T], Term0, Pos0, Term, Pos) :-
175 ( '$member'(Pred, Preds),
176 ( Pred == term_expansion/2
177 -> allowed_expansion(M:term_expansion(Term0, Term1)),
178 call(M:term_expansion(Term0, Term1)),
179 Pos1 = Pos
180 ; allowed_expansion(M:term_expansion(Term0, Pos0, Term1, Pos1)),
181 call(M:term_expansion(Term0, Pos0, Term1, Pos1))
182 )
183 -> expand_terms(call_term_expansion(T), Term1, Pos1, Term, Pos)
184 ; call_term_expansion(T, Term0, Pos0, Term, Pos)
185 ).
186
187expand_term_2((Head --> Body), Pos0, Expanded, Pos) :-
188 dcg_translate_rule((Head --> Body), Pos0, Expanded0, Pos1),
189 !,
190 expand_bodies(Expanded0, Pos1, Expanded1, Pos),
191 non_terminal_decl(Expanded1, Expanded).
192expand_term_2(Term0, Pos0, Term, Pos) :-
193 nonvar(Term0),
194 !,
195 expand_bodies(Term0, Pos0, Term, Pos).
196expand_term_2(Term, Pos, Term, Pos).
197
198non_terminal_decl(Clause, Decl) :-
199 \+ current_prolog_flag(xref, true),
200 clause_head(Clause, Head),
201 '$current_source_module'(M),
202 ( '$get_predicate_attribute'(M:Head, non_terminal, NT)
203 -> NT == 0
204 ; true
205 ),
206 !,
207 '$pi_head'(PI, Head),
208 Decl = [:-(non_terminal(M:PI)), Clause].
209non_terminal_decl(Clause, Clause).
210
211clause_head(Head:-_, Head) :- !.
212clause_head(Head, Head).
223expand_bodies(Terms, Pos0, Out, Pos) :-
224 '$def_modules'([goal_expansion/4,goal_expansion/2], MList),
225 expand_terms(expand_body(MList), Terms, Pos0, Out, Pos),
226 remove_attributes(Out, '$var_info').
227
228expand_body(MList, Clause0, Pos0, Clause, Pos) :-
229 clause_head_body(Clause0, Left0, Neck, Body0),
230 !,
231 clause_head_body(Clause, Left, Neck, Body),
232 f2_pos(Pos0, LPos0, BPos0, Pos, LPos, BPos),
233 ( head_guard(Left0, Neck, Head0, Guard0)
234 -> f2_pos(LPos0, HPos, GPos0, LPos, HPos, GPos),
235 mark_head_variables(Head0),
236 expand_goal(Guard0, GPos0, Guard, GPos, MList, Clause0),
237 Left = (Head,Guard)
238 ; LPos = LPos0,
239 Head0 = Left0,
240 Left = Head,
241 mark_head_variables(Head0)
242 ),
243 expand_goal(Body0, BPos0, Body1, BPos, MList, Clause0),
244 expand_head_functions(Head0, Head, Body1, Body).
245expand_body(MList, (:- Body), Pos0, (:- ExpandedBody), Pos) :-
246 !,
247 f1_pos(Pos0, BPos0, Pos, BPos),
248 expand_goal(Body, BPos0, ExpandedBody, BPos, MList, (:- Body)).
249
250clause_head_body((Head :- Body), Head, :-, Body).
251clause_head_body((Head => Body), Head, =>, Body).
252clause_head_body(?=>(Head, Body), Head, ?=>, Body).
253
254head_guard(Left, Neck, Head, Guard) :-
255 nonvar(Left),
256 Left = (Head,Guard),
257 ( Neck == (=>)
258 -> true
259 ; Neck == (?=>)
260 ).
261
262mark_head_variables(Head) :-
263 term_variables(Head, HVars),
264 mark_vars_non_fresh(HVars).
265
266expand_head_functions(Head0, Head, Body0, Body) :-
267 compound(Head0),
268 '$current_source_module'(M),
269 replace_functions(Head0, Eval, Head, M),
270 Eval \== true,
271 !,
272 Body = (Eval,Body0).
273expand_head_functions(Head, Head, Body, Body).
274
275expand_body(_MList, Head0, Pos, Clause, Pos) :- 276 compound(Head0),
277 '$current_source_module'(M),
278 replace_functions(Head0, Eval, Head, M),
279 Eval \== true,
280 !,
281 Clause = (Head :- Eval).
282expand_body(_, Head, Pos, Head, Pos).
292expand_terms(_, X, P, X, P) :-
293 var(X),
294 !.
295expand_terms(C, List0, Pos0, List, Pos) :-
296 nonvar(List0),
297 List0 = [_|_],
298 !,
299 ( is_list(List0)
300 -> list_pos(Pos0, Elems0, Pos, Elems),
301 expand_term_list(C, List0, Elems0, List, Elems)
302 ; '$type_error'(list, List0)
303 ).
304expand_terms(C, '$source_location'(File, Line):Clause0, Pos0, Clause, Pos) :-
305 !,
306 expand_terms(C, Clause0, Pos0, Clause1, Pos),
307 add_source_location(Clause1, '$source_location'(File, Line), Clause).
308expand_terms(C, Term0, Pos0, Term, Pos) :-
309 call(C, Term0, Pos0, Term, Pos).
316add_source_location(Clauses0, SrcLoc, Clauses) :-
317 ( is_list(Clauses0)
318 -> add_source_location_list(Clauses0, SrcLoc, Clauses)
319 ; Clauses = SrcLoc:Clauses0
320 ).
321
322add_source_location_list([], _, []).
323add_source_location_list([Clause|Clauses0], SrcLoc, [SrcLoc:Clause|Clauses]) :-
324 add_source_location_list(Clauses0, SrcLoc, Clauses).
328expand_term_list(_, [], _, [], []) :- !.
329expand_term_list(C, [H0|T0], [PH0], Terms, PosL) :-
330 !,
331 expand_terms(C, H0, PH0, H, PH),
332 add_term(H, PH, Terms, TT, PosL, PT),
333 expand_term_list(C, T0, [PH0], TT, PT).
334expand_term_list(C, [H0|T0], [PH0|PT0], Terms, PosL) :-
335 !,
336 expand_terms(C, H0, PH0, H, PH),
337 add_term(H, PH, Terms, TT, PosL, PT),
338 expand_term_list(C, T0, PT0, TT, PT).
339expand_term_list(C, [H0|T0], PH0, Terms, PosL) :-
340 expected_layout(list, PH0),
341 expand_terms(C, H0, PH0, H, PH),
342 add_term(H, PH, Terms, TT, PosL, PT),
343 expand_term_list(C, T0, [PH0], TT, PT).
347add_term(List, Pos, Terms, TermT, PosL, PosT) :-
348 nonvar(List), List = [_|_],
349 !,
350 ( is_list(List)
351 -> append_tp(List, Terms, TermT, Pos, PosL, PosT)
352 ; '$type_error'(list, List)
353 ).
354add_term(Term, Pos, [Term|Terms], Terms, [Pos|PosT], PosT).
355
356append_tp([], Terms, Terms, _, PosL, PosL).
357append_tp([H|T0], [H|T1], Terms, [HP], [HP|TP1], PosL) :-
358 !,
359 append_tp(T0, T1, Terms, [HP], TP1, PosL).
360append_tp([H|T0], [H|T1], Terms, [HP0|TP0], [HP0|TP1], PosL) :-
361 !,
362 append_tp(T0, T1, Terms, TP0, TP1, PosL).
363append_tp([H|T0], [H|T1], Terms, Pos, [Pos|TP1], PosL) :-
364 expected_layout(list, Pos),
365 append_tp(T0, T1, Terms, [Pos], TP1, PosL).
366
367
368list_pos(Var, _, _, _) :-
369 var(Var),
370 !.
371list_pos(list_position(F,T,Elems0,none), Elems0,
372 list_position(F,T,Elems,none), Elems).
373list_pos(Pos, [Pos], Elems, Elems).
374
375
376
384var_intersection(List1, List2, Intersection) :-
385 sort(List1, Set1),
386 sort(List2, Set2),
387 ord_intersection(Set1, Set2, Intersection).
393ord_intersection([], _Int, []).
394ord_intersection([H1|T1], L2, Int) :-
395 isect2(L2, H1, T1, Int).
396
397isect2([], _H1, _T1, []).
398isect2([H2|T2], H1, T1, Int) :-
399 compare(Order, H1, H2),
400 isect3(Order, H1, T1, H2, T2, Int).
401
402isect3(<, _H1, T1, H2, T2, Int) :-
403 isect2(T1, H2, T2, Int).
404isect3(=, H1, T1, _H2, T2, [H1|Int]) :-
405 ord_intersection(T1, T2, Int).
406isect3(>, H1, T1, _H2, T2, Int) :-
407 isect2(T2, H1, T1, Int).
411ord_subtract([], _Not, []).
412ord_subtract(S1, S2, Diff) :-
413 S1 == S2,
414 !,
415 Diff = [].
416ord_subtract([H1|T1], L2, Diff) :-
417 diff21(L2, H1, T1, Diff).
418
419diff21([], H1, T1, [H1|T1]).
420diff21([H2|T2], H1, T1, Diff) :-
421 compare(Order, H1, H2),
422 diff3(Order, H1, T1, H2, T2, Diff).
423
424diff12([], _H2, _T2, []).
425diff12([H1|T1], H2, T2, Diff) :-
426 compare(Order, H1, H2),
427 diff3(Order, H1, T1, H2, T2, Diff).
428
429diff3(<, H1, T1, H2, T2, [H1|Diff]) :-
430 diff12(T1, H2, T2, Diff).
431diff3(=, _H1, T1, _H2, T2, Diff) :-
432 ord_subtract(T1, T2, Diff).
433diff3(>, H1, T1, _H2, T2, Diff) :-
434 diff21(T2, H1, T1, Diff).
444merge_variable_info(State) :-
445 catch(merge_variable_info_(State),
446 error(uninstantiation_error(Term),_),
447 throw(error(goal_expansion_error(bound, Term), _))).
448
449merge_variable_info_([]).
450merge_variable_info_([Var=State|States]) :-
451 ( get_attr(Var, '$var_info', CurrentState)
452 -> true
453 ; CurrentState = (-)
454 ),
455 merge_states(Var, State, CurrentState),
456 merge_variable_info_(States).
457
458merge_states(_Var, State, State) :- !.
459merge_states(_Var, -, _) :- !.
460merge_states(Var, State, -) :-
461 !,
462 put_attr(Var, '$var_info', State).
463merge_states(Var, Left, Right) :-
464 ( get_dict(fresh, Left, false)
465 -> put_dict(fresh, Right, false)
466 ; get_dict(fresh, Right, false)
467 -> put_dict(fresh, Left, false)
468 ),
469 !,
470 ( Left >:< Right
471 -> put_dict(Left, Right, State),
472 put_attr(Var, '$var_info', State)
473 ; print_message(warning,
474 inconsistent_variable_properties(Left, Right)),
475 put_dict(Left, Right, State),
476 put_attr(Var, '$var_info', State)
477 ).
478
479
480save_variable_info([], []).
481save_variable_info([Var|Vars], [Var=State|States]):-
482 ( get_attr(Var, '$var_info', State)
483 -> true
484 ; State = (-)
485 ),
486 save_variable_info(Vars, States).
487
488restore_variable_info(State) :-
489 catch(restore_variable_info_(State),
490 error(uninstantiation_error(Term),_),
491 throw(error(goal_expansion_error(bound, Term), _))).
492
493restore_variable_info_([]).
494restore_variable_info_([Var=State|States]) :-
495 ( State == (-)
496 -> del_attr(Var, '$var_info')
497 ; put_attr(Var, '$var_info', State)
498 ),
499 restore_variable_info_(States).
515var_property(Var, Property) :-
516 prop_var(Property, Var).
517
518prop_var(fresh(Fresh), Var) :-
519 ( get_attr(Var, '$var_info', Info),
520 get_dict(fresh, Info, Fresh0)
521 -> Fresh = Fresh0
522 ; Fresh = true
523 ).
524prop_var(singleton(Singleton), Var) :-
525 nb_current('$term', Term),
526 term_singletons(Term, Singletons),
527 ( '$member'(V, Singletons),
528 V == Var
529 -> Singleton = true
530 ; Singleton = false
531 ).
532prop_var(name(Name), Var) :-
533 ( nb_current('$variable_names', Bindings),
534 '$member'(Name0=Var0, Bindings),
535 Var0 == Var
536 -> Name = Name0
537 ).
538
539
540mark_vars_non_fresh([]) :- !.
541mark_vars_non_fresh([Var|Vars]) :-
542 ( get_attr(Var, '$var_info', Info)
543 -> ( get_dict(fresh, Info, false)
544 -> true
545 ; put_dict(fresh, Info, false, Info1),
546 put_attr(Var, '$var_info', Info1)
547 )
548 ; put_attr(Var, '$var_info', '$var_info'{fresh:false})
549 ),
550 mark_vars_non_fresh(Vars).
561remove_attributes(Term, Attr) :-
562 term_variables(Term, Vars),
563 remove_var_attr(Vars, Attr).
564
565remove_var_attr([], _):- !.
566remove_var_attr([Var|Vars], Attr):-
567 del_attr(Var, Attr),
568 remove_var_attr(Vars, Attr).
574'$var_info':attr_unify_hook(_, _).
575
576
577
587expand_goal(A, B) :-
588 expand_goal(A, _, B, _).
589
590expand_goal(A, P0, B, P) :-
591 '$def_modules'([goal_expansion/4, goal_expansion/2], MList),
592 ( expand_goal(A, P0, B, P, MList, _)
593 -> remove_attributes(B, '$var_info'), A \== B
594 ),
595 !.
596expand_goal(A, P, A, P).
605'$expand_closure'(G0, N, G) :-
606 '$expand_closure'(G0, _, N, G, _).
607
608'$expand_closure'(G0, P0, N, G, P) :-
609 length(Ex, N),
610 mark_vars_non_fresh(Ex),
611 extend_arg_pos(G0, P0, Ex, G1, P1),
612 expand_goal(G1, P1, G2, P2),
613 term_variables(G0, VL),
614 remove_arg_pos(G2, P2, [], VL, Ex, G, P).
615
616
617expand_goal(G0, P0, G, P, MList, Term) :-
618 '$current_source_module'(M),
619 expand_goal(G0, P0, G, P, M, MList, Term, []).
640
641expand_goal(G, P, G, P, _, _, _, _) :-
642 var(G),
643 !.
644expand_goal(M:G, P, M:G, P, _M, _MList, _Term, _) :-
645 var(M), var(G),
646 !.
647expand_goal(M:G, P0, M:EG, P, _M, _MList, Term, Done) :-
648 atom(M),
649 !,
650 f2_pos(P0, PA, PB0, P, PA, PB),
651 '$def_modules'(M:[goal_expansion/4,goal_expansion/2], MList),
652 setup_call_cleanup(
653 '$set_source_module'(Old, M),
654 '$expand':expand_goal(G, PB0, EG, PB, M, MList, Term, Done),
655 '$set_source_module'(Old)).
656expand_goal(G0, P0, G, P, M, MList, Term, Done) :-
657 ( already_expanded(G0, Done, Done1)
658 -> expand_control(G0, P0, G, P, M, MList, Term, Done1)
659 ; call_goal_expansion(MList, G0, P0, G1, P1)
660 -> expand_goal(G1, P1, G, P, M, MList, Term/G1, [G0|Done]) 661 ; expand_control(G0, P0, G, P, M, MList, Term, Done)
662 ).
663
664expand_control((A,B), P0, Conj, P, M, MList, Term, Done) :-
665 !,
666 f2_pos(P0, PA0, PB0, P1, PA, PB),
667 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
668 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
669 simplify((EA,EB), P1, Conj, P).
670expand_control((A;B), P0, Or, P, M, MList, Term, Done) :-
671 !,
672 f2_pos(P0, PA0, PB0, P1, PA1, PB),
673 term_variables(A, AVars),
674 term_variables(B, BVars),
675 var_intersection(AVars, BVars, SharedVars),
676 save_variable_info(SharedVars, SavedState),
677 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
678 save_variable_info(SharedVars, SavedState2),
679 restore_variable_info(SavedState),
680 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
681 merge_variable_info(SavedState2),
682 fixup_or_lhs(A, EA, PA, EA1, PA1),
683 simplify((EA1;EB), P1, Or, P).
684expand_control((A->B), P0, Goal, P, M, MList, Term, Done) :-
685 !,
686 f2_pos(P0, PA0, PB0, P1, PA, PB),
687 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
688 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
689 simplify((EA->EB), P1, Goal, P).
690expand_control((A*->B), P0, Goal, P, M, MList, Term, Done) :-
691 !,
692 f2_pos(P0, PA0, PB0, P1, PA, PB),
693 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
694 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
695 simplify((EA*->EB), P1, Goal, P).
696expand_control((\+A), P0, Goal, P, M, MList, Term, Done) :-
697 !,
698 f1_pos(P0, PA0, P1, PA),
699 term_variables(A, AVars),
700 save_variable_info(AVars, SavedState),
701 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
702 restore_variable_info(SavedState),
703 simplify(\+(EA), P1, Goal, P).
704expand_control(call(A), P0, call(EA), P, M, MList, Term, Done) :-
705 !,
706 f1_pos(P0, PA0, P, PA),
707 expand_goal(A, PA0, EA, PA, M, MList, Term, Done).
708expand_control($(A), P0, $(EA), P, M, MList, Term, Done) :-
709 !,
710 f1_pos(P0, PA0, P, PA),
711 expand_goal(A, PA0, EA, PA, M, MList, Term, Done).
712expand_control(G0, P0, G, P, M, MList, Term, Done) :-
713 is_meta_call(G0, M, Head),
714 !,
715 term_variables(G0, Vars),
716 mark_vars_non_fresh(Vars),
717 expand_meta(Head, G0, P0, G, P, M, MList, Term, Done).
718expand_control(G0, P0, G, P, M, MList, Term, _Done) :-
719 term_variables(G0, Vars),
720 mark_vars_non_fresh(Vars),
721 expand_functions(G0, P0, G, P, M, MList, Term).
725already_expanded(Goal, Done, Done1) :-
726 '$select'(G, Done, Done1),
727 G == Goal,
728 !.
737fixup_or_lhs(Old, New, PNew, Fix, PFixed) :-
738 nonvar(Old),
739 nonvar(New),
740 ( Old = (_ -> _)
741 -> New \= (_ -> _),
742 Fix = (New -> true)
743 ; New = (_ -> _),
744 Fix = (New, true)
745 ),
746 !,
747 lhs_pos(PNew, PFixed).
748fixup_or_lhs(_Old, New, P, New, P).
749
750lhs_pos(P0, _) :-
751 var(P0),
752 !.
753lhs_pos(P0, term_position(F,T,T,T,[P0,T-T])) :-
754 arg(1, P0, F),
755 arg(2, P0, T).
762is_meta_call(G0, M, Head) :-
763 compound(G0),
764 default_module(M, M2),
765 '$c_current_predicate'(_, M2:G0),
766 !,
767 '$get_predicate_attribute'(M2:G0, meta_predicate, Head),
768 has_meta_arg(Head).
773expand_meta(Spec, G0, P0, G, P, M, MList, Term, Done) :-
774 functor(Spec, _, Arity),
775 functor(G0, Name, Arity),
776 functor(G1, Name, Arity),
777 f_pos(P0, ArgPos0, P, ArgPos),
778 expand_meta(1, Arity, Spec,
779 G0, ArgPos0, Eval,
780 G1, ArgPos,
781 M, MList, Term, Done),
782 conj(Eval, G1, G).
783
784expand_meta(I, Arity, Spec, G0, ArgPos0, Eval, G, [P|PT], M, MList, Term, Done) :-
785 I =< Arity,
786 !,
787 arg_pos(ArgPos0, P0, PT0),
788 arg(I, Spec, Meta),
789 arg(I, G0, A0),
790 arg(I, G, A),
791 expand_meta_arg(Meta, A0, P0, EvalA, A, P, M, MList, Term, Done),
792 I2 is I + 1,
793 expand_meta(I2, Arity, Spec, G0, PT0, EvalB, G, PT, M, MList, Term, Done),
794 conj(EvalA, EvalB, Eval).
795expand_meta(_, _, _, _, _, true, _, [], _, _, _, _).
796
797arg_pos(List, _, _) :- var(List), !. 798arg_pos([H|T], H, T) :- !. 799arg_pos([], _, []). 800
801mapex([], _).
802mapex([E|L], E) :- mapex(L, E).
809extended_pos(Var, _, Var) :-
810 var(Var),
811 !.
812extended_pos(parentheses_term_position(O,C,Pos0),
813 N,
814 parentheses_term_position(O,C,Pos)) :-
815 !,
816 extended_pos(Pos0, N, Pos).
817extended_pos(term_position(F,T,FF,FT,Args),
818 _,
819 term_position(F,T,FF,FT,Args)) :-
820 var(Args),
821 !.
822extended_pos(term_position(F,T,FF,FT,Args0),
823 N,
824 term_position(F,T,FF,FT,Args)) :-
825 length(Ex, N),
826 mapex(Ex, T-T),
827 '$append'(Args0, Ex, Args),
828 !.
829extended_pos(F-T,
830 N,
831 term_position(F,T,F,T,Ex)) :-
832 !,
833 length(Ex, N),
834 mapex(Ex, T-T).
835extended_pos(Pos, N, Pos) :-
836 '$print_message'(warning, extended_pos(Pos, N)).
847expand_meta_arg(0, A0, PA0, true, A, PA, M, MList, Term, Done) :-
848 !,
849 expand_goal(A0, PA0, A1, PA, M, MList, Term, Done),
850 compile_meta_call(A1, A, M, Term).
851expand_meta_arg(N, A0, P0, true, A, P, M, MList, Term, Done) :-
852 integer(N), callable(A0),
853 replace_functions(A0, true, _, M),
854 !,
855 length(Ex, N),
856 mark_vars_non_fresh(Ex),
857 extend_arg_pos(A0, P0, Ex, A1, PA1),
858 expand_goal(A1, PA1, A2, PA2, M, MList, Term, Done),
859 compile_meta_call(A2, A3, M, Term),
860 term_variables(A0, VL),
861 remove_arg_pos(A3, PA2, M, VL, Ex, A, P).
862expand_meta_arg(^, A0, PA0, true, A, PA, M, MList, Term, Done) :-
863 !,
864 expand_setof_goal(A0, PA0, A, PA, M, MList, Term, Done).
865expand_meta_arg(S, A0, _PA0, Eval, A, _PA, M, _MList, _Term, _Done) :-
866 replace_functions(A0, Eval, A, M), 867 ( Eval == true
868 -> true
869 ; same_functor(A0, A)
870 -> true
871 ; meta_arg(S)
872 -> throw(error(context_error(function, meta_arg(S)), _))
873 ; true
874 ).
875
876same_functor(T1, T2) :-
877 compound(T1),
878 !,
879 compound(T2),
880 compound_name_arity(T1, N, A),
881 compound_name_arity(T2, N, A).
882same_functor(T1, T2) :-
883 atom(T1),
884 T1 == T2.
885
886variant_sha1_nat(Term, Hash) :-
887 copy_term_nat(Term, TNat),
888 variant_sha1(TNat, Hash).
889
890wrap_meta_arguments(A0, M, VL, Ex, A) :-
891 '$append'(VL, Ex, AV),
892 variant_sha1_nat(A0+AV, Hash),
893 atom_concat('__aux_wrapper_', Hash, AuxName),
894 H =.. [AuxName|AV],
895 compile_auxiliary_clause(M, (H :- A0)),
896 A =.. [AuxName|VL].
903extend_arg_pos(A, P, _, A, P) :-
904 var(A),
905 !.
906extend_arg_pos(M:A0, P0, Ex, M:A, P) :-
907 !,
908 f2_pos(P0, PM, PA0, P, PM, PA),
909 extend_arg_pos(A0, PA0, Ex, A, PA).
910extend_arg_pos(A0, P0, Ex, A, P) :-
911 callable(A0),
912 !,
913 extend_term(A0, Ex, A),
914 length(Ex, N),
915 extended_pos(P0, N, P).
916extend_arg_pos(A, P, _, A, P).
917
918extend_term(Atom, Extra, Term) :-
919 atom(Atom),
920 !,
921 Term =.. [Atom|Extra].
922extend_term(Term0, Extra, Term) :-
923 compound_name_arguments(Term0, Name, Args0),
924 '$append'(Args0, Extra, Args),
925 compound_name_arguments(Term, Name, Args).
936remove_arg_pos(A, P, _, _, _, A, P) :-
937 var(A),
938 !.
939remove_arg_pos(M:A0, P0, _, VL, Ex, M:A, P) :-
940 !,
941 f2_pos(P, PM, PA0, P0, PM, PA),
942 remove_arg_pos(A0, PA, M, VL, Ex, A, PA0).
943remove_arg_pos(A0, P0, M, VL, Ex0, A, P) :-
944 callable(A0),
945 !,
946 length(Ex0, N),
947 ( A0 =.. [F|Args],
948 length(Ex, N),
949 '$append'(Args0, Ex, Args),
950 Ex==Ex0
951 -> extended_pos(P, N, P0),
952 A =.. [F|Args0]
953 ; M \== [],
954 wrap_meta_arguments(A0, M, VL, Ex0, A),
955 wrap_meta_pos(P0, P)
956 ).
957remove_arg_pos(A, P, _, _, _, A, P).
958
959wrap_meta_pos(P0, P) :-
960 ( nonvar(P0)
961 -> P = term_position(F,T,_,_,_),
962 atomic_pos(P0, F-T)
963 ; true
964 ).
965
966has_meta_arg(Head) :-
967 arg(_, Head, Arg),
968 direct_call_meta_arg(Arg),
969 !.
970
971direct_call_meta_arg(I) :- integer(I).
972direct_call_meta_arg(^).
973
974meta_arg(:).
975meta_arg(//).
976meta_arg(I) :- integer(I).
977
978expand_setof_goal(Var, Pos, Var, Pos, _, _, _, _) :-
979 var(Var),
980 !.
981expand_setof_goal(V^G, P0, V^EG, P, M, MList, Term, Done) :-
982 !,
983 f2_pos(P0, PA0, PB, P, PA, PB),
984 expand_setof_goal(G, PA0, EG, PA, M, MList, Term, Done).
985expand_setof_goal(M0:G, P0, M0:EG, P, M, MList, Term, Done) :-
986 !,
987 f2_pos(P0, PA0, PB, P, PA, PB),
988 expand_setof_goal(G, PA0, EG, PA, M, MList, Term, Done).
989expand_setof_goal(G, P0, EG, P, M, MList, Term, Done) :-
990 !,
991 expand_goal(G, P0, EG0, P, M, MList, Term, Done),
992 compile_meta_call(EG0, EG1, M, Term),
993 ( extend_existential(G, EG1, V)
994 -> EG = V^EG1
995 ; EG = EG1
996 ).
1004extend_existential(G0, G1, V) :-
1005 term_variables(G0, GV0), sort(GV0, SV0),
1006 term_variables(G1, GV1), sort(GV1, SV1),
1007 ord_subtract(SV1, SV0, New),
1008 New \== [],
1009 V =.. [v|New].
1019call_goal_expansion(MList, G0, P0, G, P) :-
1020 current_prolog_flag(sandboxed_load, false),
1021 !,
1022 ( '$member'(M-Preds, MList),
1023 '$member'(Pred, Preds),
1024 ( Pred == goal_expansion/4
1025 -> M:goal_expansion(G0, P0, G, P)
1026 ; M:goal_expansion(G0, G),
1027 P = P0
1028 ),
1029 G0 \== G
1030 -> true
1031 ).
1032call_goal_expansion(MList, G0, P0, G, P) :-
1033 ( '$member'(M-Preds, MList),
1034 '$member'(Pred, Preds),
1035 ( Pred == goal_expansion/4
1036 -> Expand = M:goal_expansion(G0, P0, G, P)
1037 ; Expand = M:goal_expansion(G0, G)
1038 ),
1039 allowed_expansion(Expand),
1040 call(Expand),
1041 G0 \== G
1042 -> true
1043 ).
1053:- multifile
1054 prolog:sandbox_allowed_expansion/1. 1055
1056allowed_expansion(QGoal) :-
1057 strip_module(QGoal, M, Goal),
1058 E = error(Formal,_),
1059 catch(prolog:sandbox_allowed_expansion(M:Goal), E, true),
1060 ( var(Formal)
1061 -> fail
1062 ; !,
1063 print_message(error, E),
1064 fail
1065 ).
1066allowed_expansion(_).
1067
1068
1069
1080expand_functions(G0, P0, G, P, M, MList, Term) :-
1081 expand_functional_notation(G0, P0, G1, P1, M, MList, Term),
1082 ( expand_arithmetic(G1, P1, G, P, Term)
1083 -> true
1084 ; G = G1,
1085 P = P1
1086 ).
1093expand_functional_notation(G0, P0, G, P, M, _MList, _Term) :-
1094 contains_functions(G0),
1095 replace_functions(G0, P0, Eval, EvalPos, G1, G1Pos, M),
1096 Eval \== true,
1097 !,
1098 wrap_var(G1, G1Pos, G2, G2Pos),
1099 conj(Eval, EvalPos, G2, G2Pos, G, P).
1100expand_functional_notation(G, P, G, P, _, _, _).
1101
1102wrap_var(G, P, G, P) :-
1103 nonvar(G),
1104 !.
1105wrap_var(G, P0, call(G), P) :-
1106 ( nonvar(P0)
1107 -> P = term_position(F,T,F,T,[P0]),
1108 atomic_pos(P0, F-T)
1109 ; true
1110 ).
1116contains_functions(Term) :-
1117 \+ \+ ( '$factorize_term'(Term, Skeleton, Assignments),
1118 ( contains_functions2(Skeleton)
1119 ; contains_functions2(Assignments)
1120 )).
1121
1122contains_functions2(Term) :-
1123 compound(Term),
1124 ( function(Term, _)
1125 -> true
1126 ; arg(_, Term, Arg),
1127 contains_functions2(Arg)
1128 -> true
1129 ).
1138:- public
1139 replace_functions/4. 1140
1141replace_functions(GoalIn, Eval, GoalOut, Context) :-
1142 replace_functions(GoalIn, _, Eval, _, GoalOut, _, Context).
1143
1144replace_functions(Var, Pos, true, _, Var, Pos, _Ctx) :-
1145 var(Var),
1146 !.
1147replace_functions(F, FPos, Eval, EvalPos, Var, VarPos, Ctx) :-
1148 function(F, Ctx),
1149 !,
1150 compound_name_arity(F, Name, Arity),
1151 PredArity is Arity+1,
1152 compound_name_arity(G, Name, PredArity),
1153 arg(PredArity, G, Var),
1154 extend_1_pos(FPos, FArgPos, GPos, GArgPos, VarPos),
1155 map_functions(0, Arity, F, FArgPos, G, GArgPos, Eval0, EP0, Ctx),
1156 conj(Eval0, EP0, G, GPos, Eval, EvalPos).
1157replace_functions(Term0, Term0Pos, Eval, EvalPos, Term, TermPos, Ctx) :-
1158 compound(Term0),
1159 !,
1160 compound_name_arity(Term0, Name, Arity),
1161 compound_name_arity(Term, Name, Arity),
1162 f_pos(Term0Pos, Args0Pos, TermPos, ArgsPos),
1163 map_functions(0, Arity,
1164 Term0, Args0Pos, Term, ArgsPos, Eval, EvalPos, Ctx).
1165replace_functions(Term, Pos, true, _, Term, Pos, _).
1172map_functions(Arity, Arity, _, LPos0, _, LPos, true, _, _) :-
1173 !,
1174 pos_nil(LPos0, LPos).
1175map_functions(I0, Arity, Term0, LPos0, Term, LPos, Eval, EP, Ctx) :-
1176 pos_list(LPos0, AP0, APT0, LPos, AP, APT),
1177 I is I0+1,
1178 arg(I, Term0, Arg0),
1179 arg(I, Term, Arg),
1180 replace_functions(Arg0, AP0, Eval0, EP0, Arg, AP, Ctx),
1181 map_functions(I, Arity, Term0, APT0, Term, APT, Eval1, EP1, Ctx),
1182 conj(Eval0, EP0, Eval1, EP1, Eval, EP).
1183
1184conj(true, X, X) :- !.
1185conj(X, true, X) :- !.
1186conj(X, Y, (X,Y)).
1187
1188conj(true, _, X, P, X, P) :- !.
1189conj(X, P, true, _, X, P) :- !.
1190conj(X, PX, Y, PY, (X,Y), _) :-
1191 var(PX), var(PY),
1192 !.
1193conj(X, PX, Y, PY, (X,Y), P) :-
1194 P = term_position(F,T,FF,FT,[PX,PY]),
1195 atomic_pos(PX, F-FF),
1196 atomic_pos(PY, FT-T).
1203:- multifile
1204 function/2. 1205
1206function(.(_,_), _) :- \+ functor([_|_], ., _).
1207
1208
1209
1221expand_arithmetic(_G0, _P0, _G, _P, _Term) :- fail.
1222
1223
1224
1236f2_pos(Var, _, _, _, _, _) :-
1237 var(Var),
1238 !.
1239f2_pos(term_position(F,T,FF,FT,[A10,A20]), A10, A20,
1240 term_position(F,T,FF,FT,[A1, A2 ]), A1, A2) :- !.
1241f2_pos(parentheses_term_position(O,C,Pos0), A10, A20,
1242 parentheses_term_position(O,C,Pos), A1, A2) :-
1243 !,
1244 f2_pos(Pos0, A10, A20, Pos, A1, A2).
1245f2_pos(Pos, _, _, _, _, _) :-
1246 expected_layout(f2, Pos).
1247
1248f1_pos(Var, _, _, _) :-
1249 var(Var),
1250 !.
1251f1_pos(term_position(F,T,FF,FT,[A10]), A10,
1252 term_position(F,T,FF,FT,[A1 ]), A1) :- !.
1253f1_pos(parentheses_term_position(O,C,Pos0), A10,
1254 parentheses_term_position(O,C,Pos), A1) :-
1255 !,
1256 f1_pos(Pos0, A10, Pos, A1).
1257f1_pos(Pos, _, _, _) :-
1258 expected_layout(f1, Pos).
1259
1260f_pos(Var, _, _, _) :-
1261 var(Var),
1262 !.
1263f_pos(term_position(F,T,FF,FT,ArgPos0), ArgPos0,
1264 term_position(F,T,FF,FT,ArgPos), ArgPos) :- !.
1265f_pos(parentheses_term_position(O,C,Pos0), A10,
1266 parentheses_term_position(O,C,Pos), A1) :-
1267 !,
1268 f_pos(Pos0, A10, Pos, A1).
1269f_pos(Pos, _, _, _) :-
1270 expected_layout(compound, Pos).
1271
1272atomic_pos(Pos, _) :-
1273 var(Pos),
1274 !.
1275atomic_pos(Pos, F-T) :-
1276 arg(1, Pos, F),
1277 arg(2, Pos, T).
1284pos_nil(Var, _) :- var(Var), !.
1285pos_nil([], []) :- !.
1286pos_nil(Pos, _) :-
1287 expected_layout(nil, Pos).
1288
1289pos_list(Var, _, _, _, _, _) :- var(Var), !.
1290pos_list([H0|T0], H0, T0, [H|T], H, T) :- !.
1291pos_list(Pos, _, _, _, _, _) :-
1292 expected_layout(list, Pos).
1298extend_1_pos(Pos, _, _, _, _) :-
1299 var(Pos),
1300 !.
1301extend_1_pos(term_position(F,T,FF,FT,FArgPos), FArgPos,
1302 term_position(F,T,FF,FT,GArgPos), GArgPos0,
1303 FT-FT1) :-
1304 integer(FT),
1305 !,
1306 FT1 is FT+1,
1307 '$same_length'(FArgPos, GArgPos0),
1308 '$append'(GArgPos0, [FT-FT1], GArgPos).
1309extend_1_pos(F-T, [],
1310 term_position(F,T,F,T,[T-T1]), [],
1311 T-T1) :-
1312 integer(T),
1313 !,
1314 T1 is T+1.
1315extend_1_pos(Pos, _, _, _, _) :-
1316 expected_layout(callable, Pos).
1317
1318'$same_length'(List, List) :-
1319 var(List),
1320 !.
1321'$same_length'([], []).
1322'$same_length'([_|T0], [_|T]) :-
1323 '$same_length'(T0, T).
1333:- create_prolog_flag(debug_term_position, false, []). 1334
1335expected_layout(Expected, Pos) :-
1336 current_prolog_flag(debug_term_position, true),
1337 !,
1338 '$print_message'(warning, expected_layout(Expected, Pos)).
1339expected_layout(_, _).
1340
1341
1342
1353simplify(Control, P, Control, P) :-
1354 current_prolog_flag(optimise, false),
1355 !.
1356simplify(Control, P0, Simple, P) :-
1357 simple(Control, P0, Simple, P),
1358 !.
1359simplify(Control, P, Control, P).
1368simple((X,Y), P0, Conj, P) :-
1369 ( true(X)
1370 -> Conj = Y,
1371 f2_pos(P0, _, P, _, _, _)
1372 ; false(X)
1373 -> Conj = fail,
1374 f2_pos(P0, P1, _, _, _, _),
1375 atomic_pos(P1, P)
1376 ; true(Y)
1377 -> Conj = X,
1378 f2_pos(P0, P, _, _, _, _)
1379 ).
1380simple((I->T;E), P0, ITE, P) :- 1381 ( true(I) 1382 -> ITE = T, 1383 f2_pos(P0, P1, _, _, _, _),
1384 f2_pos(P1, _, P, _, _, _)
1385 ; false(I)
1386 -> ITE = E,
1387 f2_pos(P0, _, P, _, _, _)
1388 ).
1389simple((X;Y), P0, Or, P) :-
1390 false(X),
1391 Or = Y,
1392 f2_pos(P0, _, P, _, _, _).
1393
1394true(X) :-
1395 nonvar(X),
1396 eval_true(X).
1397
1398false(X) :-
1399 nonvar(X),
1400 eval_false(X).
1406eval_true(true).
1407eval_true(otherwise).
1408
1409eval_false(fail).
1410eval_false(false).
1411
1412
1413 1416
1417:- create_prolog_flag(compile_meta_arguments, false, [type(atom)]).
1423compile_meta_call(CallIn, CallIn, _, Term) :-
1424 var(Term),
1425 !. 1426compile_meta_call(CallIn, CallIn, _, _) :-
1427 var(CallIn),
1428 !.
1429compile_meta_call(CallIn, CallIn, _, _) :-
1430 ( current_prolog_flag(compile_meta_arguments, false)
1431 ; current_prolog_flag(xref, true)
1432 ),
1433 !.
1434compile_meta_call(CallIn, CallIn, _, _) :-
1435 strip_module(CallIn, _, Call),
1436 ( is_aux_meta(Call)
1437 ; \+ control(Call),
1438 ( '$c_current_predicate'(_, system:Call),
1439 \+ current_prolog_flag(compile_meta_arguments, always)
1440 ; current_prolog_flag(compile_meta_arguments, control)
1441 )
1442 ),
1443 !.
1444compile_meta_call(M:CallIn, CallOut, _, Term) :-
1445 !,
1446 ( atom(M), callable(CallIn)
1447 -> compile_meta_call(CallIn, CallOut, M, Term)
1448 ; CallOut = M:CallIn
1449 ).
1450compile_meta_call(CallIn, CallOut, Module, Term) :-
1451 compile_meta(CallIn, CallOut, Module, Term, Clause),
1452 compile_auxiliary_clause(Module, Clause).
1453
1454compile_auxiliary_clause(Module, Clause) :-
1455 Clause = (Head:-Body),
1456 '$current_source_module'(SM),
1457 ( predicate_property(SM:Head, defined)
1458 -> true
1459 ; SM == Module
1460 -> compile_aux_clauses([Clause])
1461 ; compile_aux_clauses([Head:-Module:Body])
1462 ).
1463
1464control((_,_)).
1465control((_;_)).
1466control((_->_)).
1467control((_*->_)).
1468control(\+(_)).
1469control($(_)).
1470
1471is_aux_meta(Term) :-
1472 callable(Term),
1473 functor(Term, Name, _),
1474 sub_atom(Name, 0, _, _, '__aux_meta_call_').
1475
1476compile_meta(CallIn, CallOut, M, Term, (CallOut :- Body)) :-
1477 replace_subterm(CallIn, true, Term, Term2),
1478 term_variables(Term2, AllVars),
1479 term_variables(CallIn, InVars),
1480 intersection_eq(InVars, AllVars, HeadVars),
1481 copy_term_nat(CallIn+HeadVars, NAT),
1482 variant_sha1(NAT, Hash),
1483 atom_concat('__aux_meta_call_', Hash, AuxName),
1484 expand_goal(CallIn, _Pos0, Body, _Pos, M, [], (CallOut:-CallIn), []),
1485 length(HeadVars, Arity),
1486 ( Arity > 256 1487 -> HeadArgs = [v(HeadVars)]
1488 ; HeadArgs = HeadVars
1489 ),
1490 CallOut =.. [AuxName|HeadArgs].
1496replace_subterm(From, To, TermIn, TermOut) :-
1497 From == TermIn,
1498 !,
1499 TermOut = To.
1500replace_subterm(From, To, TermIn, TermOut) :-
1501 compound(TermIn),
1502 compound_name_arity(TermIn, Name, Arity),
1503 Arity > 0,
1504 !,
1505 compound_name_arity(TermOut, Name, Arity),
1506 replace_subterm_compound(1, Arity, From, To, TermIn, TermOut).
1507replace_subterm(_, _, Term, Term).
1508
1509replace_subterm_compound(I, Arity, From, To, TermIn, TermOut) :-
1510 I =< Arity,
1511 !,
1512 arg(I, TermIn, A1),
1513 arg(I, TermOut, A2),
1514 replace_subterm(From, To, A1, A2),
1515 I2 is I+1,
1516 replace_subterm_compound(I2, Arity, From, To, TermIn, TermOut).
1517replace_subterm_compound(_I, _Arity, _From, _To, _TermIn, _TermOut).
1525intersection_eq([], _, []).
1526intersection_eq([H|T0], L, List) :-
1527 ( member_eq(H, L)
1528 -> List = [H|T],
1529 intersection_eq(T0, L, T)
1530 ; intersection_eq(T0, L, List)
1531 ).
1532
1533member_eq(E, [H|T]) :-
1534 ( E == H
1535 -> true
1536 ; member_eq(E, T)
1537 ).
1538
1539 1542
1543:- thread_local
1544 '$include_code'/3. 1545
1546'$including' :-
1547 '$include_code'(X, _, _),
1548 !,
1549 X == true.
1550'$including'.
1551
1552cond_compilation((:- if(G)), []) :-
1553 source_location(File, Line),
1554 ( '$including'
1555 -> ( catch('$eval_if'(G), E, (print_message(error, E), fail))
1556 -> asserta('$include_code'(true, File, Line))
1557 ; asserta('$include_code'(false, File, Line))
1558 )
1559 ; asserta('$include_code'(else_false, File, Line))
1560 ).
1561cond_compilation((:- elif(G)), []) :-
1562 source_location(File, Line),
1563 ( clause('$include_code'(Old, OF, _), _, Ref)
1564 -> same_source(File, OF, elif),
1565 erase(Ref),
1566 ( Old == true
1567 -> asserta('$include_code'(else_false, File, Line))
1568 ; Old == false,
1569 catch('$eval_if'(G), E, (print_message(error, E), fail))
1570 -> asserta('$include_code'(true, File, Line))
1571 ; asserta('$include_code'(Old, File, Line))
1572 )
1573 ; throw(error(conditional_compilation_error(no_if, elif), _))
1574 ).
1575cond_compilation((:- else), []) :-
1576 source_location(File, Line),
1577 ( clause('$include_code'(X, OF, _), _, Ref)
1578 -> same_source(File, OF, else),
1579 erase(Ref),
1580 ( X == true
1581 -> X2 = false
1582 ; X == false
1583 -> X2 = true
1584 ; X2 = X
1585 ),
1586 asserta('$include_code'(X2, File, Line))
1587 ; throw(error(conditional_compilation_error(no_if, else), _))
1588 ).
1589cond_compilation(end_of_file, end_of_file) :- 1590 !,
1591 source_location(File, _),
1592 ( clause('$include_code'(_, OF, OL), _)
1593 -> ( File == OF
1594 -> throw(error(conditional_compilation_error(
1595 unterminated,OF:OL), _))
1596 ; true
1597 )
1598 ; true
1599 ).
1600cond_compilation((:- endif), []) :-
1601 !,
1602 source_location(File, _),
1603 ( ( clause('$include_code'(_, OF, _), _, Ref)
1604 -> same_source(File, OF, endif),
1605 erase(Ref)
1606 )
1607 -> true
1608 ; throw(error(conditional_compilation_error(no_if, endif), _))
1609 ).
1610cond_compilation(_, []) :-
1611 \+ '$including'.
1612
1613same_source(File, File, _) :- !.
1614same_source(_, _, Op) :-
1615 throw(error(conditional_compilation_error(no_if, Op), _)).
1616
1617
1618'$eval_if'(G) :-
1619 expand_goal(G, G2),
1620 '$current_source_module'(Module),
1621 Module:G2
Prolog source-code transformation
This module specifies, together with
dcg.pl
, the transformation of terms as they are read from a file before they are processed by the compiler.The toplevel is expand_term/2. This uses three other translators:
Note that this ordering implies that conditional compilation directives cannot be generated by term_expansion/2 rules: they must literally appear in the source-code.
Term-expansion may choose to overrule DCG expansion. If the result of term-expansion is a DCG rule, the rule is subject to translation into a predicate.
Next, the result is passed to expand_bodies/2, which performs goal expansion. */