33
34:- module(tabling,
35 [ (table)/1, 36
37 current_table/2, 38 abolish_all_tables/0,
39 abolish_table_subgoals/1, 40
41 start_tabling/2, 42
43 op(1150, fx, table)
44 ]).
45:- use_module(library(error)).
46:- set_prolog_flag(generate_debug_info, false).
47
48:- meta_predicate
49 start_tabling(+, 0),
50 current_table(:, -),
51 abolish_table_subgoals(:).
52
62
72
73table(PIList) :-
74 throw(error(context_error(nodirective, table(PIList)), _)).
75
85
86start_tabling(Wrapper,Worker) :-
87 '$tbl_variant_table'(Wrapper, Trie, Status),
88 ( Status == complete
89 -> trie_gen(Trie, Wrapper, _)
90 ; ( '$tbl_scheduling_component'(false, true)
91 -> catch(run_leader(Wrapper, Worker, Trie), E, true),
92 ( var(E)
93 -> trie_gen(Trie, Wrapper, _)
94 ; '$tbl_table_discard_all',
95 throw(E)
96 )
97 ; run_follower(Status, Wrapper, Worker, Trie)
98 )
99 ).
100
101run_follower(fresh, Wrapper, Worker, Trie) :-
102 !,
103 activate(Wrapper, Worker, Trie, Worklist),
104 shift(call_info(Wrapper, Worklist)).
105run_follower(Worklist, Wrapper, _Worker, _Trie) :-
106 shift(call_info(Wrapper, Worklist)).
107
108run_leader(Wrapper, Worker, Trie) :-
109 activate(Wrapper, Worker, Trie, _Worklist),
110 completion,
111 '$tbl_scheduling_component'(_, false).
112
113activate(Wrapper, Worker, Trie, WorkList) :-
114 '$tbl_new_worklist'(WorkList, Trie),
115 ( delim(Wrapper, Worker, WorkList),
116 fail
117 ; true
118 ).
119
120delim(Wrapper, Worker, WorkList) :-
121 reset(Worker,SourceCall,Continuation),
122 ( Continuation == 0
123 -> '$tbl_wkl_add_answer'(WorkList, Wrapper)
124 ; SourceCall = call_info(SrcWrapper, SourceWL),
125 TargetCall = call_info(Wrapper, WorkList),
126 Dependency = dependency(SrcWrapper,Continuation,TargetCall),
127 '$tbl_wkl_add_suspension'(SourceWL, Dependency)
128 ).
129
130completion :-
131 '$tbl_pop_worklist'(WorkList),
132 !,
133 completion_step(WorkList),
134 completion.
135completion :-
136 '$tbl_table_complete_all'.
137
138completion_step(SourceTable) :-
139 ( '$tbl_wkl_work'(SourceTable, Answer, Dependency),
140 dep(Answer, Dependency, Wrapper,Continuation,TargetTable),
141 delim(Wrapper,Continuation,TargetTable),
142 fail
143 ; true
144 ).
145
146dep(Answer, dependency(Answer, Continuation, call_info(Wrapper, TargetTable)),
147 Wrapper, Continuation,TargetTable).
148
149
150 153
162
163abolish_all_tables :-
164 '$tbl_abolish_all_tables'.
165
169
170abolish_table_subgoals(M:SubGoal) :-
171 '$tbl_variant_table'(VariantTrie),
172 current_module(M),
173 forall(trie_gen(VariantTrie, M:SubGoal, Trie),
174 '$tbl_destroy_table'(Trie)).
175
176
177 180
184
185current_table(M:Variant, Trie) :-
186 '$tbl_variant_table'(VariantTrie),
187 ( (var(Variant) ; var(M))
188 -> trie_gen(VariantTrie, M:Variant, Trie)
189 ; trie_lookup(VariantTrie, M:Variant, Trie)
190 ).
191
192
193 196
197:- multifile
198 system:term_expansion/2,
199 prolog:rename_predicate/2,
200 tabled/2.
201:- dynamic
202 system:term_expansion/2.
203
204wrappers(Var) -->
205 { var(Var),
206 !,
207 instantiation_error(Var)
208 }.
209wrappers((A,B)) -->
210 !,
211 wrappers(A),
212 wrappers(B).
213wrappers(Name//Arity) -->
214 { atom(Name), integer(Arity), Arity >= 0,
215 !,
216 Arity1 is Arity+2
217 },
218 wrappers(Name/Arity1).
219wrappers(Name/Arity) -->
220 { atom(Name), integer(Arity), Arity >= 0,
221 !,
222 functor(Head, Name, Arity),
223 atom_concat(Name, ' tabled', WrapName),
224 Head =.. [Name|Args],
225 WrappedHead =.. [WrapName|Args],
226 prolog_load_context(module, Module)
227 },
228 [ '$tabled'(Head),
229 ( Head :-
230 start_tabling(Module:Head, WrappedHead)
231 )
232 ].
233
238
239prolog:rename_predicate(M:Head0, M:Head) :-
240 '$flushed_predicate'(M:'$tabled'(_)),
241 call(M:'$tabled'(Head0)),
242 !,
243 rename_term(Head0, Head).
244
245rename_term(Compound0, Compound) :-
246 compound(Compound0),
247 !,
248 compound_name_arguments(Compound0, Name, Args),
249 atom_concat(Name, ' tabled', WrapName),
250 compound_name_arguments(Compound, WrapName, Args).
251rename_term(Name, WrapName) :-
252 atom_concat(Name, ' tabled', WrapName).
253
254
255system:term_expansion((:- table(Preds)),
256 [ (:- discontiguous('$tabled'/1))
257 | Clauses
258 ]) :-
259 phrase(wrappers(Preds), Clauses).
260
261
262 265
266:- multifile
267 sandbox:safe_directive/1,
268 sandbox:safe_primitive/1,
269 sandbox:safe_meta/2.
270
274
275sandbox:safe_directive(Dir) :-
276 ground(Dir),
277 local_tabling_dir(Dir).
278
279local_tabling_dir(table(Preds)) :-
280 local_preds(Preds).
281
282local_preds((A,B)) :-
283 !,
284 local_preds(A),
285 local_preds(B).
286
287local_preds(Name/Arity) :-
288 atom(Name), integer(Arity).
289local_preds(Name//Arity) :-
290 atom(Name), integer(Arity).
291
292sandbox:safe_meta_predicate(tabling:start_tabling/2).
293
294sandbox:safe_primitive(tabling:abolish_all_tables).
295sandbox:safe_meta(tabling:abolish_table_subgoals(V), []) :-
296 \+ qualified(V).
297sandbox:safe_meta(tabling:current_table(V, _), []) :-
298 \+ qualified(V).
299
300qualified(V) :-
301 nonvar(V),
302 V = _:_.