34
35:- module(goalstub, [register_stub/1,
36 stub_term_expansion/5]). 37
38:- use_module(library(lists)). 39:- use_module(library(sequence_list)). 40
41:- dynamic
42 stub/2,
43 requires_stub/4. 44
45:- multifile
46 stub/2,
47 requires_stub/4. 48
49:- meta_predicate register_stub(:). 50register_stub(M:Stub) :-
51 52 compile_aux_clauses(goalstub:stub(M, Stub)).
53
54stub_term_expansion((:- Decl), _, EM, CL, _) :-
55 Decl =.. [Stub, S],
56 stub(EM, Stub), !,
57 sequence_list(S, L, []),
58 '$current_source_module'(M),
59 findall(goalstub:requires_stub(F, A, M, Stub), member(F/A, L), CL).
60
61stub_term_expansion(end_of_file, P, _, CL, P) :- !,
62 '$current_source_module'(M),
63 module_property(M, file(File)),
64 prolog_load_context(file, File),
65 findall((H :- G),
66 ( findall(F/A, requires_stub(F, A, M, _), PIU),
67 sort(PIU, PIL), 68 member(F/A, PIL),
69 functor(H, F, A),
70 stub_head(H, HS),
71 findall(S, requires_stub(F, A, M, S), StubL),
72 concat_stubs(StubL, H, G, HS)
73 ), CL, [end_of_file]).
74stub_term_expansion(Term1, P, _, Term, P) :-
75 '$current_source_module'(M),
76 requires_stub_rename_head(Term1, Term, M).
77
78concat_stubs([], _, G, G).
79concat_stubs([S|L], H, G1, G) :-
80 G1 =.. [S, H, G2],
81 concat_stubs(L, H, G2, G).
82
83stub_head(Head1, Head) :-
84 Head1 =.. [F1|Args],
85 atom_concat(F1, '$stub', F),
86 Head =.. [F |Args].
87
88requires_stub_rename_head(M:Term1, Term, _) :- !,
89 requires_stub_rename_head(Term1, Term, M).
90requires_stub_rename_head((Head1 :- Body),
91 (Head :- Body),
92 M) :- !,
93 requires_stub_rename_head_(Head1, Head, 0, M).
94requires_stub_rename_head((Head1 --> Body),
95 (Head --> Body),
96 M) :-
97 requires_stub_rename_head_(Head1, Head, 2, M).
98
99
100requires_stub_rename_head_(M:Head1, Head, N, _) :- !,
101 requires_stub_rename_head_(Head1, Head, N, M).
102
103requires_stub_rename_head_(Head1, Head, N, M) :-
104 functor(Head1, F, A1),
105 A is A1 + N,
106 requires_stub(F, A, M, _), !,
107 stub_head(Head1, Head)