34
35:- module(interface,
36 [ bind_interface/2,
37 end_interface/4
38 ]). 39
40:- use_module(library(lists)). 41:- use_module(library(apply)). 42:- use_module(library(error)). 43:- reexport(library(compound_expand)). 44:- init_expansors. 45
46:- multifile
47 '$interface'/1,
48 '$interface'/2,
49 '$implementation'/2. 50
51direct_interface(M, F/A) :-
52 \+ ( current_predicate(M:F/A),
53 functor(H, F, A),
54 predicate_property(M:H, defined),
55 \+ predicate_property(M:H, imported_from(_))
56 ).
57
58end_interface(Interface, DIL) -->
59 [interface:'$interface'(Interface, DIL)],
60 findall((:- dynamic F/A),
61 member(F/A, DIL)).
62
63term_expansion_decl(implements(Alias), Clauses) :-
64 '$current_source_module'(Implementation),
65 Implementation:use_module(Alias, []), 66 absolute_file_name(Alias, File, [file_type(prolog), access(read)]),
67 module_property(Interface, file(File)),
68 term_expansion_decl(implements_mod(Interface), Clauses).
69term_expansion_decl(implements_mod(Interface), Clauses) :-
70 '$current_source_module'(Implementation),
71 '$interface'(Interface, PIL),
72 phrase(( [interface:'$implementation'(Implementation, Interface)],
73 findall((:- meta_predicate Implementation:Spec),
74 ( member(F/A, PIL),
75 functor(Pred, F, A),
76 predicate_property(Interface:Pred, meta_predicate(Spec))
77 )),
78 findall((:- export(PI)), member(PI, PIL))
79 ), Clauses).
80term_expansion_decl(interfaces(Alias), Clauses) :-
81 '$current_source_module'(Interface),
82 Interface:use_module(Alias, []),
83 absolute_file_name(Alias, File, [file_type(prolog), access(read)]),
84 module_property(Implementation, file(File)),
85 term_expansion_decl(interfaces_mod(Implementation), Clauses).
86term_expansion_decl(interfaces_mod(Implementation), Clauses) :-
87 '$current_source_module'(Interface),
88 phrase(interfaces_mod_clauses(Interface, Implementation), Clauses).
89term_expansion_decl(interface, interface:'$interface'(Interface)) :-
90 '$current_source_module'(Interface).
91
92interfaces_mod_clauses(Interface, Implementation) -->
93 {module_property(Implementation, exports(PIL))},
94 findall((:- export(PI)), member(PI, PIL)),
95 end_interface(Interface, PIL).
96
97term_expansion((:- Decl), Clauses) :-
98 term_expansion_decl(Decl, Clauses).
99term_expansion(end_of_file, Clauses) :-
100 '$current_source_module'(Interface),
101 '$interface'(Interface),
102 module_property(Interface, file(File)),
103 prolog_load_context(source, File),
104 module_property(Interface, exports(PIL)),
105 include(direct_interface(Interface), PIL, DIL),
106 phrase(end_interface(Interface, DIL), Clauses, [end_of_file]).
107
108prolog:called_by(Pred, Interface, Context, PredL) :-
109 '$interface'(Interface, DIL),
110 member(F/A, DIL),
111 functor(Pred, F, A),
112 findall(@(Implementation:Pred, Context),
113 interface:'$implementation'(Implementation, Interface),
114 PredL),
115 PredL \= [].
121bind_interface(Interface, Implementation) :-
122 ( '$interface'(Interface, DIL)
123 ->true
124 ; existence_error(interface, Interface)
125 ),
126 ( '$implementation'(Implementation, Interface)
127 ->true
128 ; ( '$implementation'(Implementation, _)
129 ->existence_error(implementation, Implementation)
130 ; existence_error(binding, Interface->Implementation)
131 )
132 ),
133 forall(( member(F/A, DIL),
134 functor(H, F, A)
135 ),
136 ( retractall(Interface:H),
137 Implementation:assertz((Interface:H :- H))))