YAP 7.1.0
udi.c
1#include <stdio.h>
2#include <assert.h>
3#include "Yap.h"
4#include "YapInterface.h"
5#include "clause.h"
6#include "udi_private.h"
7
8/* to keep an array with the registered udi indexers */
9UT_icd udicb_icd = {sizeof(UdiControlBlock), NULL, NULL, NULL};
10UT_array *indexing_structures;
11
12/*
13 * Register a new user indexer
14 */
15void
16Yap_UdiRegister(UdiControlBlock cb){
17 /*TODO: check structure integrity and duplicates */
18 utarray_push_back(indexing_structures, &cb);
19}
20
21/*
22 * New user indexed predicate:
23 * the first argument is the term.
24 */
25static YAP_Int
26p_new_udi( USES_REGS1 )
27{
28 Term spec = Deref(ARG1);
29
30 PredEntry *p;
31 UdiInfo blk;
32 int info;
33
34 /* get the predicate from the spec, copied from cdmgr.c */
35 if (IsVarTerm(spec)) {
36 Yap_Error(INSTANTIATION_ERROR,spec,"new user index/1");
37 return FALSE;
38 } else if (!IsApplTerm(spec)) {
39 Yap_Error(TYPE_ERROR_COMPOUND,spec,"new user index/1");
40 return FALSE;
41 } else {
42 Functor fun = FunctorOfTerm(spec);
43 Term tmod = CurrentModule;
44
45 while (fun == FunctorModule) {
46 tmod = ArgOfTerm(1,spec);
47 if (IsVarTerm(tmod) ) {
48 Yap_Error(INSTANTIATION_ERROR, spec, "new user index/1");
49 return FALSE;
50 }
51 if (!IsAtomTerm(tmod) ) {
52 Yap_Error(TYPE_ERROR_ATOM, spec, "new user index/1");
53 return FALSE;
54 }
55 spec = ArgOfTerm(2, spec);
56 fun = FunctorOfTerm(spec);
57 }
58 p = RepPredProp(PredPropByFunc(fun, tmod));
59 }
60 if (!p)
61 return FALSE;
62 /* boring, boring, boring! */
63 if ((p->PredFlags
64 & (DynamicPredFlag|LogUpdatePredFlag|UserCPredFlag|CArgsPredFlag|NumberDBPredFlag|AtomDBPredFlag|TestPredFlag|AsmPredFlag|CPredFlag|BinaryPredFlag))
65 || (p->ModuleOfPred == PROLOG_MODULE)) {
66 Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE, spec, "udi/2");
67 return FALSE;
68 }
69 if (p->PredFlags & (DynamicPredFlag|LogUpdatePredFlag|TabledPredFlag)) {
70 Yap_Error(PERMISSION_ERROR_ACCESS_PRIVATE_PROCEDURE, spec, "udi/2");
71 return FALSE;
72 }
73 /* TODO: remove AtomRTree from atom list */
74
75 /* this is the real work */
76 blk = (UdiInfo) Yap_AllocCodeSpace(sizeof(struct udi_info));
77 memset((void *) blk,0, sizeof(struct udi_info));
78 if (!blk) {
79 Yap_Error(RESOURCE_ERROR_HEAP, spec, "new user index/1");
80 return FALSE;
81 }
82
83 /*Init UdiInfo */
84 utarray_new(blk->args, &arg_icd);
85 utarray_new(blk->clauselist, &cl_icd);
86 blk->p = p;
87
88 /*Now Init args list*/
89 info = p_udi_args_init(spec, p->ArityOfPE, blk);
90 if (!info)
91 {
92 utarray_free(blk->args);
93 utarray_free(blk->clauselist);
94 Yap_FreeCodeSpace((char *) blk);
95 return FALSE;
96 }
97
98 /*Push into the hash*/
99 HASH_ADD_UdiInfo(UdiControlBlocks, p, blk);
100
101 p->PredFlags |= UDIPredFlag;
102
103 return TRUE;
104}
105
106/*
107 * Here we initialize the arguments indexing
108 */
109YAP_Int
110p_udi_args_init(Term spec, int arity, UdiInfo blk)
111{
112 int i;
113 Term arg;
114 Atom idxtype;
115 UdiControlBlock *cb;
116 struct udi_p_args p_arg;
117
118 for (i = 1; i <= arity; i++) {
119 arg = ArgOfTerm(i,spec);
120 if (IsAtomTerm(arg)) {
121 idxtype = AtomOfTerm(arg);
122 if (idxtype == AtomMinus) //skip this argument
123 continue;
124 p_arg.control = NULL;
125 cb = NULL;
126 while ((cb = (UdiControlBlock *) utarray_next(indexing_structures, cb))) {
127 if (idxtype == (*cb)->decl){
128 p_arg.arg = i;
129 p_arg.control = *cb;
130 p_arg.idxstr = (*cb)->init(spec, i, arity);
131 utarray_push_back(blk->args, &p_arg);
132 }
133 }
134 if (p_arg.control == NULL){ /* not "-" and not found */
135 fprintf(stderr, "Invalid Spec (%s)\n", AtomName(idxtype));
136 return FALSE;
137 }
138 }
139 }
140 return TRUE;
141}
142
143/*
144 * From now on this is called in several places of yap
145 * when the predicate has the UDIPredFlag
146 * and is what actually triggers the insert/search/abolish of indexing structures
147 */
148
149/*
150 * Init Yap udi interface
151 */
152void
153Yap_udi_init(void)
154{
155 UdiControlBlocks = NULL;
156
157 /*init indexing structures array*/
158 utarray_new(indexing_structures, &udicb_icd);
159
160 Yap_InitCPred("$udi_init", 1, p_new_udi, 0);
161 /* TODO: decide if udi.yap should be loaded automaticaly in init.yap */
162}
163
164/* called from cdmgr.c
165 *
166 * for each assert of a udipredicate
167 * to pass info to user structure
168 */
169int
170Yap_new_udi_clause(PredEntry *p, yamop *cl, Term t)
171{
172 int i;
173 UdiPArg parg;
174 UdiInfo info;
175 YAP_Int index;
176
177 /* try to find our structure */
178 HASH_FIND_UdiInfo(UdiControlBlocks,p,info);
179 if (!info)
180 return FALSE;
181
182 /* insert into clauselist */
183 utarray_push_back(info->clauselist, &cl);
184
185 for (i = 0; i < utarray_len(info->args) ; i++) {
186 parg = (UdiPArg) utarray_eltptr(info->args,i);
187 index = (YAP_Int) utarray_len(info->clauselist);
188 parg->idxstr = parg->control->insert(parg->idxstr, t,
189 parg->arg,
190 (void *) index);
191 }
192 return TRUE;
193}
194
195/* index, called from absmi.c
196 *
197 * Returns:
198 * NULL (yap fallback) No usable indexing available
199 *
200 * Yap_FAILCODE() (fail) No result found
201 * Yap_CauseListToClause(cl) 1 solution found
202 * Yap_ClauseListCode(cl) 2+ solutions found
203 */
204yamop *
205Yap_udi_search(PredEntry *p)
206{
207 int r;
208 struct ClauseList clauselist;
209 UdiPArg parg;
210 UdiInfo info;
211
212 /* find our structure*/
213 HASH_FIND_UdiInfo(UdiControlBlocks,p,info);
214 if (!info || utarray_len(info->args) == 0)
215 return NULL;
216
217 if (utarray_len(info->args) == 1){ //simple case no intersection needed
218 struct si_callback_h c;
219
220 c.cl = Yap_ClauseListInit(&clauselist);
221 c.clauselist = info->clauselist;
222 c.pred = info->p;
223 if (!c.cl)
224 return NULL;
225
226 parg = (UdiPArg) utarray_eltptr(info->args,0);
227 r = parg->control->search(parg->idxstr, parg->arg, si_callback, (void *) &c);
228 Yap_ClauseListClose(c.cl);
229
230 if (r == -1) {
231 Yap_ClauseListDestroy(c.cl);
232 return NULL;
233 }
234
235 if (Yap_ClauseListCount(c.cl) == 0) {
236 Yap_ClauseListDestroy(c.cl);
237 return Yap_FAILCODE();
238 }
239#if 0
240 } else {//intersection needed using Judy
241 Yap_udi_join( &clauselist, parg, info );
242#endif
243 }
244
245 if (Yap_ClauseListCount(&clauselist) == 1)
246 return Yap_ClauseListToClause(&clauselist);
247 return Yap_ClauseListCode(&clauselist);
248}
249
250/* index, called from absmi.c */
251void
252Yap_udi_abolish(PredEntry *p)
253{
254 /* tell the predicate destroy */
255}
Main definitions.
@ index
index
Definition: YapGFlagInfo.h:354
Definition: utarray.h:47
Definition: Yatom.h:544
Definition: amidefs.h:264