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:- '$notransact'((system:term_expansion/2,
91 system:goal_expansion/2,
92 user:term_expansion/2,
93 user:goal_expansion/2,
94 system:term_expansion/4,
95 system:goal_expansion/4,
96 user:term_expansion/4,
97 user:goal_expansion/4)). 98
99:- meta_predicate
100 expand_terms(4, +, ?, -, -).
108expand_term(Term0, Term) :-
109 expand_term(Term0, _, Term, _).
110
111expand_term(Var, Pos, Expanded, Pos) :-
112 var(Var),
113 !,
114 Expanded = Var.
115expand_term(Term, Pos0, [], Pos) :-
116 cond_compilation(Term, X),
117 X == [],
118 !,
119 atomic_pos(Pos0, Pos).
120expand_term(Term, Pos0, Expanded, Pos) :-
121 setup_call_cleanup(
122 '$push_input_context'(expand_term),
123 expand_term_keep_source_loc(Term, Pos0, Expanded, Pos),
124 '$pop_input_context').
125
126expand_term_keep_source_loc(Term, Pos0, Expanded, Pos) :-
127 b_setval('$term', Term),
128 prepare_directive(Term),
129 '$def_modules'([term_expansion/4,term_expansion/2], MList),
130 call_term_expansion(MList, Term, Pos0, Term1, Pos1),
131 expand_terms(expand_term_2, Term1, Pos1, Expanded, Pos),
132 b_setval('$term', []).
141prepare_directive((:- Directive)) :-
142 '$current_source_module'(M),
143 prepare_directive(Directive, M),
144 !.
145prepare_directive(_).
146
147prepare_directive(Goal, _) :-
148 \+ callable(Goal),
149 !.
150prepare_directive((A,B), Module) :-
151 !,
152 prepare_directive(A, Module),
153 prepare_directive(B, Module).
154prepare_directive(module(_,_), _) :- !.
155prepare_directive(Goal, Module) :-
156 '$get_predicate_attribute'(Module:Goal, defined, 1),
157 !.
158prepare_directive(Goal, Module) :-
159 \+ current_prolog_flag(autoload, false),
160 ( compound(Goal)
161 -> compound_name_arity(Goal, Name, Arity)
162 ; Name = Goal, Arity = 0
163 ),
164 '$autoload'(Module:Name/Arity),
165 !.
166prepare_directive(_, _).
167
168
169call_term_expansion([], Term, Pos, Term, Pos).
170call_term_expansion([M-Preds|T], Term0, Pos0, Term, Pos) :-
171 current_prolog_flag(sandboxed_load, false),
172 !,
173 ( '$member'(Pred, Preds),
174 ( Pred == term_expansion/2
175 -> M:term_expansion(Term0, Term1),
176 Pos1 = Pos0
177 ; M:term_expansion(Term0, Pos0, Term1, Pos1)
178 )
179 -> expand_terms(call_term_expansion(T), Term1, Pos1, Term, Pos)
180 ; call_term_expansion(T, Term0, Pos0, Term, Pos)
181 ).
182call_term_expansion([M-Preds|T], Term0, Pos0, Term, Pos) :-
183 ( '$member'(Pred, Preds),
184 ( Pred == term_expansion/2
185 -> allowed_expansion(M:term_expansion(Term0, Term1)),
186 call(M:term_expansion(Term0, Term1)),
187 Pos1 = Pos
188 ; allowed_expansion(M:term_expansion(Term0, Pos0, Term1, Pos1)),
189 call(M:term_expansion(Term0, Pos0, Term1, Pos1))
190 )
191 -> expand_terms(call_term_expansion(T), Term1, Pos1, Term, Pos)
192 ; call_term_expansion(T, Term0, Pos0, Term, Pos)
193 ).
194
195expand_term_2((Head --> Body), Pos0, Expanded, Pos) :-
196 dcg_translate_rule((Head --> Body), Pos0, Expanded0, Pos1),
197 !,
198 expand_bodies(Expanded0, Pos1, Expanded1, Pos),
199 non_terminal_decl(Expanded1, Expanded).
200expand_term_2(Term0, Pos0, Term, Pos) :-
201 nonvar(Term0),
202 !,
203 expand_bodies(Term0, Pos0, Term, Pos).
204expand_term_2(Term, Pos, Term, Pos).
205
206non_terminal_decl(Clause, Decl) :-
207 \+ current_prolog_flag(xref, true),
208 clause_head(Clause, Head),
209 '$current_source_module'(M),
210 ( '$get_predicate_attribute'(M:Head, non_terminal, NT)
211 -> NT == 0
212 ; true
213 ),
214 !,
215 '$pi_head'(PI, Head),
216 Decl = [:-(non_terminal(M:PI)), Clause].
217non_terminal_decl(Clause, Clause).
218
219clause_head(Head:-_, Head) :- !.
220clause_head(Head, Head).
231expand_bodies(Terms, Pos0, Out, Pos) :-
232 '$def_modules'([goal_expansion/4,goal_expansion/2], MList),
233 expand_terms(expand_body(MList), Terms, Pos0, Out, Pos),
234 remove_attributes(Out, '$var_info').
235
236expand_body(MList, Clause0, Pos0, Clause, Pos) :-
237 clause_head_body(Clause0, Left0, Neck, Body0),
238 !,
239 clause_head_body(Clause, Left, Neck, Body),
240 f2_pos(Pos0, LPos0, BPos0, Pos, LPos, BPos),
241 ( head_guard(Left0, Neck, Head0, Guard0)
242 -> f2_pos(LPos0, HPos, GPos0, LPos, HPos, GPos),
243 mark_head_variables(Head0),
244 expand_goal(Guard0, GPos0, Guard, GPos, MList, Clause0),
245 Left = (Head,Guard)
246 ; LPos = LPos0,
247 Head0 = Left0,
248 Left = Head,
249 mark_head_variables(Head0)
250 ),
251 expand_goal(Body0, BPos0, Body1, BPos, MList, Clause0),
252 expand_head_functions(Head0, Head, Body1, Body).
253expand_body(MList, (:- Body), Pos0, (:- ExpandedBody), Pos) :-
254 !,
255 f1_pos(Pos0, BPos0, Pos, BPos),
256 expand_goal(Body, BPos0, ExpandedBody, BPos, MList, (:- Body)).
257
258clause_head_body((Head :- Body), Head, :-, Body).
259clause_head_body((Head => Body), Head, =>, Body).
260clause_head_body(?=>(Head, Body), Head, ?=>, Body).
261
262head_guard(Left, Neck, Head, Guard) :-
263 nonvar(Left),
264 Left = (Head,Guard),
265 ( Neck == (=>)
266 -> true
267 ; Neck == (?=>)
268 ).
269
270mark_head_variables(Head) :-
271 term_variables(Head, HVars),
272 mark_vars_non_fresh(HVars).
273
274expand_head_functions(Head0, Head, Body0, Body) :-
275 compound(Head0),
276 '$current_source_module'(M),
277 replace_functions(Head0, Eval, Head, M),
278 Eval \== true,
279 !,
280 Body = (Eval,Body0).
281expand_head_functions(Head, Head, Body, Body).
282
283expand_body(_MList, Head0, Pos, Clause, Pos) :- 284 compound(Head0),
285 '$current_source_module'(M),
286 replace_functions(Head0, Eval, Head, M),
287 Eval \== true,
288 !,
289 Clause = (Head :- Eval).
290expand_body(_, Head, Pos, Head, Pos).
300expand_terms(_, X, P, X, P) :-
301 var(X),
302 !.
303expand_terms(C, List0, Pos0, List, Pos) :-
304 nonvar(List0),
305 List0 = [_|_],
306 !,
307 ( is_list(List0)
308 -> list_pos(Pos0, Elems0, Pos, Elems),
309 expand_term_list(C, List0, Elems0, List, Elems)
310 ; '$type_error'(list, List0)
311 ).
312expand_terms(C, '$source_location'(File, Line):Clause0, Pos0, Clause, Pos) :-
313 !,
314 expand_terms(C, Clause0, Pos0, Clause1, Pos),
315 add_source_location(Clause1, '$source_location'(File, Line), Clause).
316expand_terms(C, Term0, Pos0, Term, Pos) :-
317 call(C, Term0, Pos0, Term, Pos).
324add_source_location(Clauses0, SrcLoc, Clauses) :-
325 ( is_list(Clauses0)
326 -> add_source_location_list(Clauses0, SrcLoc, Clauses)
327 ; Clauses = SrcLoc:Clauses0
328 ).
329
330add_source_location_list([], _, []).
331add_source_location_list([Clause|Clauses0], SrcLoc, [SrcLoc:Clause|Clauses]) :-
332 add_source_location_list(Clauses0, SrcLoc, Clauses).
336expand_term_list(_, [], _, [], []) :- !.
337expand_term_list(C, [H0|T0], [PH0], Terms, PosL) :-
338 !,
339 expand_terms(C, H0, PH0, H, PH),
340 add_term(H, PH, Terms, TT, PosL, PT),
341 expand_term_list(C, T0, [PH0], TT, PT).
342expand_term_list(C, [H0|T0], [PH0|PT0], Terms, PosL) :-
343 !,
344 expand_terms(C, H0, PH0, H, PH),
345 add_term(H, PH, Terms, TT, PosL, PT),
346 expand_term_list(C, T0, PT0, TT, PT).
347expand_term_list(C, [H0|T0], PH0, Terms, PosL) :-
348 expected_layout(list, PH0),
349 expand_terms(C, H0, PH0, H, PH),
350 add_term(H, PH, Terms, TT, PosL, PT),
351 expand_term_list(C, T0, [PH0], TT, PT).
355add_term(List, Pos, Terms, TermT, PosL, PosT) :-
356 nonvar(List), List = [_|_],
357 !,
358 ( is_list(List)
359 -> append_tp(List, Terms, TermT, Pos, PosL, PosT)
360 ; '$type_error'(list, List)
361 ).
362add_term(Term, Pos, [Term|Terms], Terms, [Pos|PosT], PosT).
363
364append_tp([], Terms, Terms, _, PosL, PosL).
365append_tp([H|T0], [H|T1], Terms, [HP], [HP|TP1], PosL) :-
366 !,
367 append_tp(T0, T1, Terms, [HP], TP1, PosL).
368append_tp([H|T0], [H|T1], Terms, [HP0|TP0], [HP0|TP1], PosL) :-
369 !,
370 append_tp(T0, T1, Terms, TP0, TP1, PosL).
371append_tp([H|T0], [H|T1], Terms, Pos, [Pos|TP1], PosL) :-
372 expected_layout(list, Pos),
373 append_tp(T0, T1, Terms, [Pos], TP1, PosL).
374
375
376list_pos(Var, _, _, _) :-
377 var(Var),
378 !.
379list_pos(list_position(F,T,Elems0,none), Elems0,
380 list_position(F,T,Elems,none), Elems).
381list_pos(Pos, [Pos], Elems, Elems).
382
383
384
392var_intersection(List1, List2, Intersection) :-
393 sort(List1, Set1),
394 sort(List2, Set2),
395 ord_intersection(Set1, Set2, Intersection).
401ord_intersection([], _Int, []).
402ord_intersection([H1|T1], L2, Int) :-
403 isect2(L2, H1, T1, Int).
404
405isect2([], _H1, _T1, []).
406isect2([H2|T2], H1, T1, Int) :-
407 compare(Order, H1, H2),
408 isect3(Order, H1, T1, H2, T2, Int).
409
410isect3(<, _H1, T1, H2, T2, Int) :-
411 isect2(T1, H2, T2, Int).
412isect3(=, H1, T1, _H2, T2, [H1|Int]) :-
413 ord_intersection(T1, T2, Int).
414isect3(>, H1, T1, _H2, T2, Int) :-
415 isect2(T2, H1, T1, Int).
419ord_subtract([], _Not, []).
420ord_subtract(S1, S2, Diff) :-
421 S1 == S2,
422 !,
423 Diff = [].
424ord_subtract([H1|T1], L2, Diff) :-
425 diff21(L2, H1, T1, Diff).
426
427diff21([], H1, T1, [H1|T1]).
428diff21([H2|T2], H1, T1, Diff) :-
429 compare(Order, H1, H2),
430 diff3(Order, H1, T1, H2, T2, Diff).
431
432diff12([], _H2, _T2, []).
433diff12([H1|T1], H2, T2, Diff) :-
434 compare(Order, H1, H2),
435 diff3(Order, H1, T1, H2, T2, Diff).
436
437diff3(<, H1, T1, H2, T2, [H1|Diff]) :-
438 diff12(T1, H2, T2, Diff).
439diff3(=, _H1, T1, _H2, T2, Diff) :-
440 ord_subtract(T1, T2, Diff).
441diff3(>, H1, T1, _H2, T2, Diff) :-
442 diff21(T2, H1, T1, Diff).
452merge_variable_info(State) :-
453 catch(merge_variable_info_(State),
454 error(uninstantiation_error(Term),_),
455 throw(error(goal_expansion_error(bound, Term), _))).
456
457merge_variable_info_([]).
458merge_variable_info_([Var=State|States]) :-
459 ( get_attr(Var, '$var_info', CurrentState)
460 -> true
461 ; CurrentState = (-)
462 ),
463 merge_states(Var, State, CurrentState),
464 merge_variable_info_(States).
465
466merge_states(_Var, State, State) :- !.
467merge_states(_Var, -, _) :- !.
468merge_states(Var, State, -) :-
469 !,
470 put_attr(Var, '$var_info', State).
471merge_states(Var, Left, Right) :-
472 ( get_dict(fresh, Left, false)
473 -> put_dict(fresh, Right, false)
474 ; get_dict(fresh, Right, false)
475 -> put_dict(fresh, Left, false)
476 ),
477 !,
478 ( Left >:< Right
479 -> put_dict(Left, Right, State),
480 put_attr(Var, '$var_info', State)
481 ; print_message(warning,
482 inconsistent_variable_properties(Left, Right)),
483 put_dict(Left, Right, State),
484 put_attr(Var, '$var_info', State)
485 ).
486
487
488save_variable_info([], []).
489save_variable_info([Var|Vars], [Var=State|States]):-
490 ( get_attr(Var, '$var_info', State)
491 -> true
492 ; State = (-)
493 ),
494 save_variable_info(Vars, States).
495
496restore_variable_info(State) :-
497 catch(restore_variable_info_(State),
498 error(uninstantiation_error(Term),_),
499 throw(error(goal_expansion_error(bound, Term), _))).
500
501restore_variable_info_([]).
502restore_variable_info_([Var=State|States]) :-
503 ( State == (-)
504 -> del_attr(Var, '$var_info')
505 ; put_attr(Var, '$var_info', State)
506 ),
507 restore_variable_info_(States).
523var_property(Var, Property) :-
524 prop_var(Property, Var).
525
526prop_var(fresh(Fresh), Var) :-
527 ( get_attr(Var, '$var_info', Info),
528 get_dict(fresh, Info, Fresh0)
529 -> Fresh = Fresh0
530 ; Fresh = true
531 ).
532prop_var(singleton(Singleton), Var) :-
533 nb_current('$term', Term),
534 term_singletons(Term, Singletons),
535 ( '$member'(V, Singletons),
536 V == Var
537 -> Singleton = true
538 ; Singleton = false
539 ).
540prop_var(name(Name), Var) :-
541 ( nb_current('$variable_names', Bindings),
542 '$member'(Name0=Var0, Bindings),
543 Var0 == Var
544 -> Name = Name0
545 ).
546
547
548mark_vars_non_fresh([]) :- !.
549mark_vars_non_fresh([Var|Vars]) :-
550 ( get_attr(Var, '$var_info', Info)
551 -> ( get_dict(fresh, Info, false)
552 -> true
553 ; put_dict(fresh, Info, false, Info1),
554 put_attr(Var, '$var_info', Info1)
555 )
556 ; put_attr(Var, '$var_info', '$var_info'{fresh:false})
557 ),
558 mark_vars_non_fresh(Vars).
569remove_attributes(Term, Attr) :-
570 term_variables(Term, Vars),
571 remove_var_attr(Vars, Attr).
572
573remove_var_attr([], _):- !.
574remove_var_attr([Var|Vars], Attr):-
575 del_attr(Var, Attr),
576 remove_var_attr(Vars, Attr).
582'$var_info':attr_unify_hook(_, _).
583
584
585
595expand_goal(A, B) :-
596 expand_goal(A, _, B, _).
597
598expand_goal(A, P0, B, P) :-
599 '$def_modules'([goal_expansion/4, goal_expansion/2], MList),
600 ( expand_goal(A, P0, B, P, MList, _)
601 -> remove_attributes(B, '$var_info'), A \== B
602 ),
603 !.
604expand_goal(A, P, A, P).
613'$expand_closure'(G0, N, G) :-
614 '$expand_closure'(G0, _, N, G, _).
615
616'$expand_closure'(G0, P0, N, G, P) :-
617 length(Ex, N),
618 mark_vars_non_fresh(Ex),
619 extend_arg_pos(G0, P0, Ex, G1, P1),
620 expand_goal(G1, P1, G2, P2),
621 term_variables(G0, VL),
622 remove_arg_pos(G2, P2, [], VL, Ex, G, P).
623
624
625expand_goal(G0, P0, G, P, MList, Term) :-
626 '$current_source_module'(M),
627 expand_goal(G0, P0, G, P, M, MList, Term, []).
648
649expand_goal(G, P, G, P, _, _, _, _) :-
650 var(G),
651 !.
652expand_goal(M:G, P, M:G, P, _M, _MList, _Term, _) :-
653 var(M), var(G),
654 !.
655expand_goal(M:G, P0, M:EG, P, _M, _MList, Term, Done) :-
656 atom(M),
657 !,
658 f2_pos(P0, PA, PB0, P, PA, PB),
659 '$def_modules'(M:[goal_expansion/4,goal_expansion/2], MList),
660 setup_call_cleanup(
661 '$set_source_module'(Old, M),
662 '$expand':expand_goal(G, PB0, EG, PB, M, MList, Term, Done),
663 '$set_source_module'(Old)).
664expand_goal(G0, P0, G, P, M, MList, Term, Done) :-
665 ( already_expanded(G0, Done, Done1)
666 -> expand_control(G0, P0, G, P, M, MList, Term, Done1)
667 ; call_goal_expansion(MList, G0, P0, G1, P1)
668 -> expand_goal(G1, P1, G, P, M, MList, Term/G1, [G0|Done]) 669 ; expand_control(G0, P0, G, P, M, MList, Term, Done)
670 ).
671
672expand_control((A,B), P0, Conj, P, M, MList, Term, Done) :-
673 !,
674 f2_pos(P0, PA0, PB0, P1, PA, PB),
675 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
676 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
677 simplify((EA,EB), P1, Conj, P).
678expand_control((A;B), P0, Or, P, M, MList, Term, Done) :-
679 !,
680 f2_pos(P0, PA0, PB0, P1, PA1, PB),
681 term_variables(A, AVars),
682 term_variables(B, BVars),
683 var_intersection(AVars, BVars, SharedVars),
684 save_variable_info(SharedVars, SavedState),
685 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
686 save_variable_info(SharedVars, SavedState2),
687 restore_variable_info(SavedState),
688 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
689 merge_variable_info(SavedState2),
690 fixup_or_lhs(A, EA, PA, EA1, PA1),
691 simplify((EA1;EB), P1, Or, P).
692expand_control((A->B), P0, Goal, P, M, MList, Term, Done) :-
693 !,
694 f2_pos(P0, PA0, PB0, P1, PA, PB),
695 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
696 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
697 simplify((EA->EB), P1, Goal, P).
698expand_control((A*->B), P0, Goal, P, M, MList, Term, Done) :-
699 !,
700 f2_pos(P0, PA0, PB0, P1, PA, PB),
701 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
702 expand_goal(B, PB0, EB, PB, M, MList, Term, Done),
703 simplify((EA*->EB), P1, Goal, P).
704expand_control((\+A), P0, Goal, P, M, MList, Term, Done) :-
705 !,
706 f1_pos(P0, PA0, P1, PA),
707 term_variables(A, AVars),
708 save_variable_info(AVars, SavedState),
709 expand_goal(A, PA0, EA, PA, M, MList, Term, Done),
710 restore_variable_info(SavedState),
711 simplify(\+(EA), P1, Goal, P).
712expand_control(call(A), P0, call(EA), P, M, MList, Term, Done) :-
713 !,
714 f1_pos(P0, PA0, P, PA),
715 expand_goal(A, PA0, EA, PA, M, MList, Term, Done).
716expand_control($(A), P0, $(EA), P, M, MList, Term, Done) :-
717 !,
718 f1_pos(P0, PA0, P, PA),
719 expand_goal(A, PA0, EA, PA, M, MList, Term, Done).
720expand_control(G0, P0, G, P, M, MList, Term, Done) :-
721 is_meta_call(G0, M, Head),
722 !,
723 term_variables(G0, Vars),
724 mark_vars_non_fresh(Vars),
725 expand_meta(Head, G0, P0, G, P, M, MList, Term, Done).
726expand_control(G0, P0, G, P, M, MList, Term, _Done) :-
727 term_variables(G0, Vars),
728 mark_vars_non_fresh(Vars),
729 expand_functions(G0, P0, G, P, M, MList, Term).
733already_expanded(Goal, Done, Done1) :-
734 '$select'(G, Done, Done1),
735 G == Goal,
736 !.
745fixup_or_lhs(Old, New, PNew, Fix, PFixed) :-
746 nonvar(Old),
747 nonvar(New),
748 ( Old = (_ -> _)
749 -> New \= (_ -> _),
750 Fix = (New -> true)
751 ; New = (_ -> _),
752 Fix = (New, true)
753 ),
754 !,
755 lhs_pos(PNew, PFixed).
756fixup_or_lhs(_Old, New, P, New, P).
757
758lhs_pos(P0, _) :-
759 var(P0),
760 !.
761lhs_pos(P0, term_position(F,T,T,T,[P0,T-T])) :-
762 arg(1, P0, F),
763 arg(2, P0, T).
770is_meta_call(G0, M, Head) :-
771 compound(G0),
772 default_module(M, M2),
773 '$c_current_predicate'(_, M2:G0),
774 !,
775 '$get_predicate_attribute'(M2:G0, meta_predicate, Head),
776 has_meta_arg(Head).
781expand_meta(Spec, G0, P0, G, P, M, MList, Term, Done) :-
782 functor(Spec, _, Arity),
783 functor(G0, Name, Arity),
784 functor(G1, Name, Arity),
785 f_pos(P0, ArgPos0, G1P, ArgPos),
786 expand_meta(1, Arity, Spec,
787 G0, ArgPos0, Eval, EvalPos,
788 G1, ArgPos,
789 M, MList, Term, Done),
790 conj(Eval, EvalPos, G1, G1P, G, P).
791
792expand_meta(I, Arity, Spec, G0, ArgPos0, Eval, EvalPos, G, [P|PT],
793 M, MList, Term, Done) :-
794 I =< Arity,
795 !,
796 arg_pos(ArgPos0, P0, PT0),
797 arg(I, Spec, Meta),
798 arg(I, G0, A0),
799 arg(I, G, A),
800 expand_meta_arg(Meta, A0, P0, EvalA, EPA, A, P, M, MList, Term, Done),
801 I2 is I + 1,
802 expand_meta(I2, Arity, Spec, G0, PT0, EvalB,EPB, G, PT, M, MList, Term, Done),
803 conj(EvalA, EPA, EvalB, EPB, Eval, EvalPos).
804expand_meta(_, _, _, _, _, true, _, _, [], _, _, _, _).
805
806arg_pos(List, _, _) :- var(List), !. 807arg_pos([H|T], H, T) :- !. 808arg_pos([], _, []). 809
810mapex([], _).
811mapex([E|L], E) :- mapex(L, E).
818extended_pos(Var, _, Var) :-
819 var(Var),
820 !.
821extended_pos(parentheses_term_position(O,C,Pos0),
822 N,
823 parentheses_term_position(O,C,Pos)) :-
824 !,
825 extended_pos(Pos0, N, Pos).
826extended_pos(term_position(F,T,FF,FT,Args),
827 _,
828 term_position(F,T,FF,FT,Args)) :-
829 var(Args),
830 !.
831extended_pos(term_position(F,T,FF,FT,Args0),
832 N,
833 term_position(F,T,FF,FT,Args)) :-
834 length(Ex, N),
835 mapex(Ex, T-T),
836 '$append'(Args0, Ex, Args),
837 !.
838extended_pos(F-T,
839 N,
840 term_position(F,T,F,T,Ex)) :-
841 !,
842 length(Ex, N),
843 mapex(Ex, T-T).
844extended_pos(Pos, N, Pos) :-
845 '$print_message'(warning, extended_pos(Pos, N)).
856expand_meta_arg(0, A0, PA0, true, _, A, PA, M, MList, Term, Done) :-
857 !,
858 expand_goal(A0, PA0, A1, PA, M, MList, Term, Done),
859 compile_meta_call(A1, A, M, Term).
860expand_meta_arg(N, A0, P0, true, _, A, P, M, MList, Term, Done) :-
861 integer(N), callable(A0),
862 replace_functions(A0, true, _, M),
863 !,
864 length(Ex, N),
865 mark_vars_non_fresh(Ex),
866 extend_arg_pos(A0, P0, Ex, A1, PA1),
867 expand_goal(A1, PA1, A2, PA2, M, MList, Term, Done),
868 compile_meta_call(A2, A3, M, Term),
869 term_variables(A0, VL),
870 remove_arg_pos(A3, PA2, M, VL, Ex, A, P).
871expand_meta_arg(^, A0, PA0, true, _, A, PA, M, MList, Term, Done) :-
872 !,
873 expand_setof_goal(A0, PA0, A, PA, M, MList, Term, Done).
874expand_meta_arg(S, A0, PA0, Eval, EPA, A, PA, M, _MList, _Term, _Done) :-
875 replace_functions(A0, PA0, Eval, EPA, A, PA, M),
876 ( Eval == true
877 -> true
878 ; same_functor(A0, A)
879 -> true
880 ; meta_arg(S)
881 -> throw(error(context_error(function, meta_arg(S)), _))
882 ; true
883 ).
884
885same_functor(T1, T2) :-
886 compound(T1),
887 !,
888 compound(T2),
889 compound_name_arity(T1, N, A),
890 compound_name_arity(T2, N, A).
891same_functor(T1, T2) :-
892 atom(T1),
893 T1 == T2.
894
895variant_sha1_nat(Term, Hash) :-
896 copy_term_nat(Term, TNat),
897 variant_sha1(TNat, Hash).
898
899wrap_meta_arguments(A0, M, VL, Ex, A) :-
900 '$append'(VL, Ex, AV),
901 variant_sha1_nat(A0+AV, Hash),
902 atom_concat('__aux_wrapper_', Hash, AuxName),
903 H =.. [AuxName|AV],
904 compile_auxiliary_clause(M, (H :- A0)),
905 A =.. [AuxName|VL].
912extend_arg_pos(A, P, _, A, P) :-
913 var(A),
914 !.
915extend_arg_pos(M:A0, P0, Ex, M:A, P) :-
916 !,
917 f2_pos(P0, PM, PA0, P, PM, PA),
918 extend_arg_pos(A0, PA0, Ex, A, PA).
919extend_arg_pos(A0, P0, Ex, A, P) :-
920 callable(A0),
921 !,
922 extend_term(A0, Ex, A),
923 length(Ex, N),
924 extended_pos(P0, N, P).
925extend_arg_pos(A, P, _, A, P).
926
927extend_term(Atom, Extra, Term) :-
928 atom(Atom),
929 !,
930 Term =.. [Atom|Extra].
931extend_term(Term0, Extra, Term) :-
932 compound_name_arguments(Term0, Name, Args0),
933 '$append'(Args0, Extra, Args),
934 compound_name_arguments(Term, Name, Args).
945remove_arg_pos(A, P, _, _, _, A, P) :-
946 var(A),
947 !.
948remove_arg_pos(M:A0, P0, _, VL, Ex, M:A, P) :-
949 !,
950 f2_pos(P, PM, PA0, P0, PM, PA),
951 remove_arg_pos(A0, PA, M, VL, Ex, A, PA0).
952remove_arg_pos(A0, P0, M, VL, Ex0, A, P) :-
953 callable(A0),
954 !,
955 length(Ex0, N),
956 ( A0 =.. [F|Args],
957 length(Ex, N),
958 '$append'(Args0, Ex, Args),
959 Ex==Ex0
960 -> extended_pos(P, N, P0),
961 A =.. [F|Args0]
962 ; M \== [],
963 wrap_meta_arguments(A0, M, VL, Ex0, A),
964 wrap_meta_pos(P0, P)
965 ).
966remove_arg_pos(A, P, _, _, _, A, P).
967
968wrap_meta_pos(P0, P) :-
969 ( nonvar(P0)
970 -> P = term_position(F,T,_,_,_),
971 atomic_pos(P0, F-T)
972 ; true
973 ).
974
975has_meta_arg(Head) :-
976 arg(_, Head, Arg),
977 direct_call_meta_arg(Arg),
978 !.
979
980direct_call_meta_arg(I) :- integer(I).
981direct_call_meta_arg(^).
982
983meta_arg(:).
984meta_arg(//).
985meta_arg(I) :- integer(I).
986
987expand_setof_goal(Var, Pos, Var, Pos, _, _, _, _) :-
988 var(Var),
989 !.
990expand_setof_goal(V^G, P0, V^EG, P, M, MList, Term, Done) :-
991 !,
992 f2_pos(P0, PA0, PB, P, PA, PB),
993 expand_setof_goal(G, PA0, EG, PA, M, MList, Term, Done).
994expand_setof_goal(M0:G, P0, M0:EG, P, M, MList, Term, Done) :-
995 !,
996 f2_pos(P0, PA0, PB, P, PA, PB),
997 expand_setof_goal(G, PA0, EG, PA, M, MList, Term, Done).
998expand_setof_goal(G, P0, EG, P, M, MList, Term, Done) :-
999 !,
1000 expand_goal(G, P0, EG0, P, M, MList, Term, Done),
1001 compile_meta_call(EG0, EG1, M, Term),
1002 ( extend_existential(G, EG1, V)
1003 -> EG = V^EG1
1004 ; EG = EG1
1005 ).
1013extend_existential(G0, G1, V) :-
1014 term_variables(G0, GV0), sort(GV0, SV0),
1015 term_variables(G1, GV1), sort(GV1, SV1),
1016 ord_subtract(SV1, SV0, New),
1017 New \== [],
1018 V =.. [v|New].
1028call_goal_expansion(MList, G0, P0, G, P) :-
1029 current_prolog_flag(sandboxed_load, false),
1030 !,
1031 ( '$member'(M-Preds, MList),
1032 '$member'(Pred, Preds),
1033 ( Pred == goal_expansion/4
1034 -> M:goal_expansion(G0, P0, G, P)
1035 ; M:goal_expansion(G0, G),
1036 P = P0
1037 ),
1038 G0 \== G
1039 -> true
1040 ).
1041call_goal_expansion(MList, G0, P0, G, P) :-
1042 ( '$member'(M-Preds, MList),
1043 '$member'(Pred, Preds),
1044 ( Pred == goal_expansion/4
1045 -> Expand = M:goal_expansion(G0, P0, G, P)
1046 ; Expand = M:goal_expansion(G0, G)
1047 ),
1048 allowed_expansion(Expand),
1049 call(Expand),
1050 G0 \== G
1051 -> true
1052 ).
1062:- multifile
1063 prolog:sandbox_allowed_expansion/1. 1064
1065allowed_expansion(QGoal) :-
1066 strip_module(QGoal, M, Goal),
1067 E = error(Formal,_),
1068 catch(prolog:sandbox_allowed_expansion(M:Goal), E, true),
1069 ( var(Formal)
1070 -> fail
1071 ; !,
1072 print_message(error, E),
1073 fail
1074 ).
1075allowed_expansion(_).
1076
1077
1078
1089expand_functions(G0, P0, G, P, M, MList, Term) :-
1090 expand_functional_notation(G0, P0, G1, P1, M, MList, Term),
1091 ( expand_arithmetic(G1, P1, G, P, Term)
1092 -> true
1093 ; G = G1,
1094 P = P1
1095 ).
1102expand_functional_notation(G0, P0, G, P, M, _MList, _Term) :-
1103 contains_functions(G0),
1104 replace_functions(G0, P0, Eval, EvalPos, G1, G1Pos, M),
1105 Eval \== true,
1106 !,
1107 wrap_var(G1, G1Pos, G2, G2Pos),
1108 conj(Eval, EvalPos, G2, G2Pos, G, P).
1109expand_functional_notation(G, P, G, P, _, _, _).
1110
1111wrap_var(G, P, G, P) :-
1112 nonvar(G),
1113 !.
1114wrap_var(G, P0, call(G), P) :-
1115 ( nonvar(P0)
1116 -> P = term_position(F,T,F,T,[P0]),
1117 atomic_pos(P0, F-T)
1118 ; true
1119 ).
1125contains_functions(Term) :-
1126 \+ \+ ( '$factorize_term'(Term, Skeleton, Assignments),
1127 ( contains_functions2(Skeleton)
1128 ; contains_functions2(Assignments)
1129 )).
1130
1131contains_functions2(Term) :-
1132 compound(Term),
1133 ( function(Term, _)
1134 -> true
1135 ; arg(_, Term, Arg),
1136 contains_functions2(Arg)
1137 -> true
1138 ).
1147:- public
1148 replace_functions/4. 1149
1150replace_functions(GoalIn, Eval, GoalOut, Context) :-
1151 replace_functions(GoalIn, _, Eval, _, GoalOut, _, Context).
1152
1153replace_functions(Var, Pos, true, _, Var, Pos, _Ctx) :-
1154 var(Var),
1155 !.
1156replace_functions(F, FPos, Eval, EvalPos, Var, VarPos, Ctx) :-
1157 function(F, Ctx),
1158 !,
1159 compound_name_arity(F, Name, Arity),
1160 PredArity is Arity+1,
1161 compound_name_arity(G, Name, PredArity),
1162 arg(PredArity, G, Var),
1163 extend_1_pos(FPos, FArgPos, GPos, GArgPos, VarPos),
1164 map_functions(0, Arity, F, FArgPos, G, GArgPos, Eval0, EP0, Ctx),
1165 conj(Eval0, EP0, G, GPos, Eval, EvalPos).
1166replace_functions(Term0, Term0Pos, Eval, EvalPos, Term, TermPos, Ctx) :-
1167 compound(Term0),
1168 !,
1169 compound_name_arity(Term0, Name, Arity),
1170 compound_name_arity(Term, Name, Arity),
1171 f_pos(Term0Pos, Args0Pos, TermPos, ArgsPos),
1172 map_functions(0, Arity,
1173 Term0, Args0Pos, Term, ArgsPos, Eval, EvalPos, Ctx).
1174replace_functions(Term, Pos, true, _, Term, Pos, _).
1181map_functions(Arity, Arity, _, LPos0, _, LPos, true, _, _) :-
1182 !,
1183 pos_nil(LPos0, LPos).
1184map_functions(I0, Arity, Term0, LPos0, Term, LPos, Eval, EP, Ctx) :-
1185 pos_list(LPos0, AP0, APT0, LPos, AP, APT),
1186 I is I0+1,
1187 arg(I, Term0, Arg0),
1188 arg(I, Term, Arg),
1189 replace_functions(Arg0, AP0, Eval0, EP0, Arg, AP, Ctx),
1190 map_functions(I, Arity, Term0, APT0, Term, APT, Eval1, EP1, Ctx),
1191 conj(Eval0, EP0, Eval1, EP1, Eval, EP).
1195conj(true, _, X, P, X, P) :- !.
1196conj(X, P, true, _, X, P) :- !.
1197conj(X, PX, Y, PY, (X,Y), _) :-
1198 var(PX), var(PY),
1199 !.
1200conj(X, PX, Y, PY, (X,Y), P) :-
1201 P = term_position(F,T,FF,FT,[PX,PY]),
1202 atomic_pos(PX, F-FF),
1203 atomic_pos(PY, FT-T).
1210:- multifile
1211 function/2. 1212
1213function(.(_,_), _) :- \+ functor([_|_], ., _).
1214
1215
1216
1228expand_arithmetic(_G0, _P0, _G, _P, _Term) :- fail.
1229
1230
1231
1243f2_pos(Var, _, _, _, _, _) :-
1244 var(Var),
1245 !.
1246f2_pos(term_position(F,T,FF,FT,[A10,A20]), A10, A20,
1247 term_position(F,T,FF,FT,[A1, A2 ]), A1, A2) :- !.
1248f2_pos(parentheses_term_position(O,C,Pos0), A10, A20,
1249 parentheses_term_position(O,C,Pos), A1, A2) :-
1250 !,
1251 f2_pos(Pos0, A10, A20, Pos, A1, A2).
1252f2_pos(Pos, _, _, _, _, _) :-
1253 expected_layout(f2, Pos).
1254
1255f1_pos(Var, _, _, _) :-
1256 var(Var),
1257 !.
1258f1_pos(term_position(F,T,FF,FT,[A10]), A10,
1259 term_position(F,T,FF,FT,[A1 ]), A1) :- !.
1260f1_pos(parentheses_term_position(O,C,Pos0), A10,
1261 parentheses_term_position(O,C,Pos), A1) :-
1262 !,
1263 f1_pos(Pos0, A10, Pos, A1).
1264f1_pos(Pos, _, _, _) :-
1265 expected_layout(f1, Pos).
1266
1267f_pos(Var, _, _, _) :-
1268 var(Var),
1269 !.
1270f_pos(term_position(F,T,FF,FT,ArgPos0), ArgPos0,
1271 term_position(F,T,FF,FT,ArgPos), ArgPos) :- !.
1272f_pos(parentheses_term_position(O,C,Pos0), A10,
1273 parentheses_term_position(O,C,Pos), A1) :-
1274 !,
1275 f_pos(Pos0, A10, Pos, A1).
1276f_pos(Pos, _, _, _) :-
1277 expected_layout(compound, Pos).
1278
1279atomic_pos(Pos, _) :-
1280 var(Pos),
1281 !.
1282atomic_pos(Pos, F-T) :-
1283 arg(1, Pos, F),
1284 arg(2, Pos, T).
1291pos_nil(Var, _) :- var(Var), !.
1292pos_nil([], []) :- !.
1293pos_nil(Pos, _) :-
1294 expected_layout(nil, Pos).
1295
1296pos_list(Var, _, _, _, _, _) :- var(Var), !.
1297pos_list([H0|T0], H0, T0, [H|T], H, T) :- !.
1298pos_list(Pos, _, _, _, _, _) :-
1299 expected_layout(list, Pos).
1305extend_1_pos(Pos, _, _, _, _) :-
1306 var(Pos),
1307 !.
1308extend_1_pos(term_position(F,T,FF,FT,FArgPos), FArgPos,
1309 term_position(F,T,FF,FT,GArgPos), GArgPos0,
1310 FT-FT1) :-
1311 integer(FT),
1312 !,
1313 FT1 is FT+1,
1314 '$same_length'(FArgPos, GArgPos0),
1315 '$append'(GArgPos0, [FT-FT1], GArgPos).
1316extend_1_pos(F-T, [],
1317 term_position(F,T,F,T,[T-T1]), [],
1318 T-T1) :-
1319 integer(T),
1320 !,
1321 T1 is T+1.
1322extend_1_pos(Pos, _, _, _, _) :-
1323 expected_layout(callable, Pos).
1324
1325'$same_length'(List, List) :-
1326 var(List),
1327 !.
1328'$same_length'([], []).
1329'$same_length'([_|T0], [_|T]) :-
1330 '$same_length'(T0, T).
1340:- create_prolog_flag(debug_term_position, false, []). 1341
1342expected_layout(Expected, Pos) :-
1343 current_prolog_flag(debug_term_position, true),
1344 !,
1345 '$print_message'(warning, expected_layout(Expected, Pos)).
1346expected_layout(_, _).
1347
1348
1349
1360simplify(Control, P, Control, P) :-
1361 current_prolog_flag(optimise, false),
1362 !.
1363simplify(Control, P0, Simple, P) :-
1364 simple(Control, P0, Simple, P),
1365 !.
1366simplify(Control, P, Control, P).
1375simple((X,Y), P0, Conj, P) :-
1376 ( true(X)
1377 -> Conj = Y,
1378 f2_pos(P0, _, P, _, _, _)
1379 ; false(X)
1380 -> Conj = fail,
1381 f2_pos(P0, P1, _, _, _, _),
1382 atomic_pos(P1, P)
1383 ; true(Y)
1384 -> Conj = X,
1385 f2_pos(P0, P, _, _, _, _)
1386 ).
1387simple((I->T;E), P0, ITE, P) :- 1388 ( true(I) 1389 -> ITE = T, 1390 f2_pos(P0, P1, _, _, _, _),
1391 f2_pos(P1, _, P, _, _, _)
1392 ; false(I)
1393 -> ITE = E,
1394 f2_pos(P0, _, P, _, _, _)
1395 ).
1396simple((X;Y), P0, Or, P) :-
1397 false(X),
1398 Or = Y,
1399 f2_pos(P0, _, P, _, _, _).
1400
1401true(X) :-
1402 nonvar(X),
1403 eval_true(X).
1404
1405false(X) :-
1406 nonvar(X),
1407 eval_false(X).
1413eval_true(true).
1414eval_true(otherwise).
1415
1416eval_false(fail).
1417eval_false(false).
1418
1419
1420 1423
1424:- create_prolog_flag(compile_meta_arguments, false, [type(atom)]).
1430compile_meta_call(CallIn, CallIn, _, Term) :-
1431 var(Term),
1432 !. 1433compile_meta_call(CallIn, CallIn, _, _) :-
1434 var(CallIn),
1435 !.
1436compile_meta_call(CallIn, CallIn, _, _) :-
1437 ( current_prolog_flag(compile_meta_arguments, false)
1438 ; current_prolog_flag(xref, true)
1439 ),
1440 !.
1441compile_meta_call(CallIn, CallIn, _, _) :-
1442 strip_module(CallIn, _, Call),
1443 ( is_aux_meta(Call)
1444 ; \+ control(Call),
1445 ( '$c_current_predicate'(_, system:Call),
1446 \+ current_prolog_flag(compile_meta_arguments, always)
1447 ; current_prolog_flag(compile_meta_arguments, control)
1448 )
1449 ),
1450 !.
1451compile_meta_call(M:CallIn, CallOut, _, Term) :-
1452 !,
1453 ( atom(M), callable(CallIn)
1454 -> compile_meta_call(CallIn, CallOut, M, Term)
1455 ; CallOut = M:CallIn
1456 ).
1457compile_meta_call(CallIn, CallOut, Module, Term) :-
1458 compile_meta(CallIn, CallOut, Module, Term, Clause),
1459 compile_auxiliary_clause(Module, Clause).
1460
1461compile_auxiliary_clause(Module, Clause) :-
1462 Clause = (Head:-Body),
1463 '$current_source_module'(SM),
1464 ( predicate_property(SM:Head, defined)
1465 -> true
1466 ; SM == Module
1467 -> compile_aux_clauses([Clause])
1468 ; compile_aux_clauses([Head:-Module:Body])
1469 ).
1470
1471control((_,_)).
1472control((_;_)).
1473control((_->_)).
1474control((_*->_)).
1475control(\+(_)).
1476control($(_)).
1477
1478is_aux_meta(Term) :-
1479 callable(Term),
1480 functor(Term, Name, _),
1481 sub_atom(Name, 0, _, _, '__aux_meta_call_').
1482
1483compile_meta(CallIn, CallOut, M, Term, (CallOut :- Body)) :-
1484 replace_subterm(CallIn, true, Term, Term2),
1485 term_variables(Term2, AllVars),
1486 term_variables(CallIn, InVars),
1487 intersection_eq(InVars, AllVars, HeadVars),
1488 copy_term_nat(CallIn+HeadVars, NAT),
1489 variant_sha1(NAT, Hash),
1490 atom_concat('__aux_meta_call_', Hash, AuxName),
1491 expand_goal(CallIn, _Pos0, Body, _Pos, M, [], (CallOut:-CallIn), []),
1492 length(HeadVars, Arity),
1493 ( Arity > 256 1494 -> HeadArgs = [v(HeadVars)]
1495 ; HeadArgs = HeadVars
1496 ),
1497 CallOut =.. [AuxName|HeadArgs].
1503replace_subterm(From, To, TermIn, TermOut) :-
1504 From == TermIn,
1505 !,
1506 TermOut = To.
1507replace_subterm(From, To, TermIn, TermOut) :-
1508 compound(TermIn),
1509 compound_name_arity(TermIn, Name, Arity),
1510 Arity > 0,
1511 !,
1512 compound_name_arity(TermOut, Name, Arity),
1513 replace_subterm_compound(1, Arity, From, To, TermIn, TermOut).
1514replace_subterm(_, _, Term, Term).
1515
1516replace_subterm_compound(I, Arity, From, To, TermIn, TermOut) :-
1517 I =< Arity,
1518 !,
1519 arg(I, TermIn, A1),
1520 arg(I, TermOut, A2),
1521 replace_subterm(From, To, A1, A2),
1522 I2 is I+1,
1523 replace_subterm_compound(I2, Arity, From, To, TermIn, TermOut).
1524replace_subterm_compound(_I, _Arity, _From, _To, _TermIn, _TermOut).
1532intersection_eq([], _, []).
1533intersection_eq([H|T0], L, List) :-
1534 ( member_eq(H, L)
1535 -> List = [H|T],
1536 intersection_eq(T0, L, T)
1537 ; intersection_eq(T0, L, List)
1538 ).
1539
1540member_eq(E, [H|T]) :-
1541 ( E == H
1542 -> true
1543 ; member_eq(E, T)
1544 ).
1545
1546 1549
1550:- thread_local
1551 '$include_code'/3. 1552
1553'$including' :-
1554 '$include_code'(X, _, _),
1555 !,
1556 X == true.
1557'$including'.
1558
1559cond_compilation((:- if(G)), []) :-
1560 source_location(File, Line),
1561 ( '$including'
1562 -> ( catch('$eval_if'(G), E, (print_message(error, E), fail))
1563 -> asserta('$include_code'(true, File, Line))
1564 ; asserta('$include_code'(false, File, Line))
1565 )
1566 ; asserta('$include_code'(else_false, File, Line))
1567 ).
1568cond_compilation((:- elif(G)), []) :-
1569 source_location(File, Line),
1570 ( clause('$include_code'(Old, File, _), _, Ref)
1571 -> erase(Ref),
1572 ( Old == true
1573 -> asserta('$include_code'(else_false, File, Line))
1574 ; Old == false,
1575 catch('$eval_if'(G), E, (print_message(error, E), fail))
1576 -> asserta('$include_code'(true, File, Line))
1577 ; asserta('$include_code'(Old, File, Line))
1578 )
1579 ; throw(error(conditional_compilation_error(no_if, elif), _))
1580 ).
1581cond_compilation((:- else), []) :-
1582 source_location(File, Line),
1583 ( clause('$include_code'(X, File, _), _, Ref)
1584 -> erase(Ref),
1585 ( X == true
1586 -> X2 = false
1587 ; X == false
1588 -> X2 = true
1589 ; X2 = X
1590 ),
1591 asserta('$include_code'(X2, File, Line))
1592 ; throw(error(conditional_compilation_error(no_if, else), _))
1593 ).
1594cond_compilation(end_of_file, end_of_file) :- 1595 !,
1596 source_location(File, _),
1597 ( clause('$include_code'(_, OF, OL), _)
1598 -> ( File == OF
1599 -> throw(error(conditional_compilation_error(
1600 unterminated,OF:OL), _))
1601 ; true
1602 )
1603 ; true
1604 ).
1605cond_compilation((:- endif), []) :-
1606 !,
1607 source_location(File, _),
1608 ( ( clause('$include_code'(_, File, _), _, Ref)
1609 -> erase(Ref)
1610 )
1611 -> true
1612 ; throw(error(conditional_compilation_error(no_if, endif), _))
1613 ).
1614cond_compilation(_, []) :-
1615 \+ '$including'.
1616
1617'$eval_if'(G) :-
1618 expand_goal(G, G2),
1619 '$current_source_module'(Module),
1620 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. */