2012-12-17 20:23:03 +00:00
|
|
|
#include <stdio.h>
|
2012-12-28 17:46:11 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <Judy.h>
|
2009-02-12 16:39:20 +00:00
|
|
|
#include "Yap.h"
|
2012-12-17 20:23:03 +00:00
|
|
|
#include "YapInterface.h"
|
2009-02-12 16:39:20 +00:00
|
|
|
#include "clause.h"
|
2012-12-18 18:26:59 +00:00
|
|
|
#include "clause_list.h"
|
2012-12-27 12:11:14 +00:00
|
|
|
#include "udi_private.h"
|
2012-12-17 20:23:03 +00:00
|
|
|
|
|
|
|
/* to keep a vector of udi indexers */
|
|
|
|
UT_icd udicb_icd = {sizeof(UdiControlBlock), NULL, NULL, NULL};
|
|
|
|
UT_array *indexing_structures;
|
2009-02-12 16:39:20 +00:00
|
|
|
|
2012-12-17 20:23:03 +00:00
|
|
|
/*
|
2012-12-27 12:11:14 +00:00
|
|
|
* New user indexed predicate (used by the public udi interface)
|
2012-12-17 20:23:03 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
Yap_UdiRegister(UdiControlBlock cb){
|
|
|
|
/*TODO: check structure integrity and duplicates */
|
|
|
|
utarray_push_back(indexing_structures, &cb);
|
|
|
|
}
|
2009-02-20 15:52:17 +00:00
|
|
|
|
2012-12-17 20:23:03 +00:00
|
|
|
/*
|
|
|
|
* New user indexed predicate:
|
|
|
|
* the first argument is the term.
|
|
|
|
*/
|
2012-12-27 12:11:14 +00:00
|
|
|
static YAP_Int
|
2011-03-07 16:02:55 +00:00
|
|
|
p_new_udi( USES_REGS1 )
|
2009-02-12 16:39:20 +00:00
|
|
|
{
|
2012-12-17 20:23:03 +00:00
|
|
|
Term spec = Deref(ARG1);
|
|
|
|
|
2009-02-12 16:39:20 +00:00
|
|
|
PredEntry *p;
|
2012-12-17 20:23:03 +00:00
|
|
|
UdiInfo blk;
|
|
|
|
int info;
|
|
|
|
|
2012-12-18 18:26:59 +00:00
|
|
|
//fprintf(stderr,"new pred\n");
|
2009-02-12 16:39:20 +00:00
|
|
|
|
2009-02-12 21:45:41 +00:00
|
|
|
/* get the predicate from the spec, copied from cdmgr.c */
|
2009-02-12 16:39:20 +00:00
|
|
|
if (IsVarTerm(spec)) {
|
2012-12-17 20:23:03 +00:00
|
|
|
Yap_Error(INSTANTIATION_ERROR,spec,"new user index/1");
|
|
|
|
return FALSE;
|
2009-02-12 16:39:20 +00:00
|
|
|
} else if (!IsApplTerm(spec)) {
|
2012-12-17 20:23:03 +00:00
|
|
|
Yap_Error(TYPE_ERROR_COMPOUND,spec,"new user index/1");
|
|
|
|
return FALSE;
|
2009-02-12 16:39:20 +00:00
|
|
|
} else {
|
2012-12-17 20:23:03 +00:00
|
|
|
Functor fun = FunctorOfTerm(spec);
|
|
|
|
Term tmod = CurrentModule;
|
|
|
|
|
|
|
|
while (fun == FunctorModule) {
|
|
|
|
tmod = ArgOfTerm(1,spec);
|
|
|
|
if (IsVarTerm(tmod) ) {
|
|
|
|
Yap_Error(INSTANTIATION_ERROR, spec, "new user index/1");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!IsAtomTerm(tmod) ) {
|
|
|
|
Yap_Error(TYPE_ERROR_ATOM, spec, "new user index/1");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
spec = ArgOfTerm(2, spec);
|
|
|
|
fun = FunctorOfTerm(spec);
|
|
|
|
}
|
|
|
|
p = RepPredProp(PredPropByFunc(fun, tmod));
|
2009-02-12 16:39:20 +00:00
|
|
|
}
|
2009-02-20 11:42:48 +00:00
|
|
|
if (!p)
|
2012-12-17 20:23:03 +00:00
|
|
|
return FALSE;
|
2009-02-12 21:45:41 +00:00
|
|
|
/* boring, boring, boring! */
|
2012-12-17 20:23:03 +00:00
|
|
|
if ((p->PredFlags
|
|
|
|
& (DynamicPredFlag|LogUpdatePredFlag|UserCPredFlag|CArgsPredFlag|NumberDBPredFlag|AtomDBPredFlag|TestPredFlag|AsmPredFlag|CPredFlag|BinaryPredFlag))
|
|
|
|
|| (p->ModuleOfPred == PROLOG_MODULE)) {
|
|
|
|
Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE, spec, "udi/2");
|
|
|
|
return FALSE;
|
2009-02-12 16:39:20 +00:00
|
|
|
}
|
|
|
|
if (p->PredFlags & (DynamicPredFlag|LogUpdatePredFlag|TabledPredFlag)) {
|
2012-12-17 20:23:03 +00:00
|
|
|
Yap_Error(PERMISSION_ERROR_ACCESS_PRIVATE_PROCEDURE, spec, "udi/2");
|
|
|
|
return FALSE;
|
2009-02-12 16:39:20 +00:00
|
|
|
}
|
2012-12-17 20:23:03 +00:00
|
|
|
/* TODO: remove AtomRTree from atom list */
|
|
|
|
|
2009-02-12 21:45:41 +00:00
|
|
|
/* this is the real work */
|
2012-12-17 20:23:03 +00:00
|
|
|
blk = (UdiInfo) Yap_AllocCodeSpace(sizeof(struct udi_info));
|
2012-12-18 18:26:59 +00:00
|
|
|
memset((void *) blk,0, sizeof(struct udi_info));
|
|
|
|
|
2012-12-17 20:23:03 +00:00
|
|
|
if (!blk) {
|
|
|
|
Yap_Error(OUT_OF_HEAP_ERROR, spec, "new user index/1");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-12-28 17:46:11 +00:00
|
|
|
utarray_new(blk->clauselist, &cl_icd);
|
2012-12-27 12:11:14 +00:00
|
|
|
utarray_new(blk->args, &arg_icd);
|
2012-12-17 20:23:03 +00:00
|
|
|
blk->p = p;
|
2012-12-27 12:11:14 +00:00
|
|
|
HASH_ADD_UdiInfo(UdiControlBlocks, p, blk);
|
2012-12-18 18:26:59 +00:00
|
|
|
//fprintf(stderr,"PRED %p\n",p);
|
2012-12-17 20:23:03 +00:00
|
|
|
|
|
|
|
info = Yap_udi_args_init(spec, p->ArityOfPE, blk);
|
2012-12-27 12:11:14 +00:00
|
|
|
if (!info) /*TODO: clear blk here*/
|
2009-02-12 16:39:20 +00:00
|
|
|
return FALSE;
|
2012-12-17 20:23:03 +00:00
|
|
|
|
2009-02-12 16:39:20 +00:00
|
|
|
p->PredFlags |= UDIPredFlag;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-12-17 20:23:03 +00:00
|
|
|
/*
|
|
|
|
* Here we initialize the arguments indexing
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
Yap_udi_args_init(Term spec, int arity, UdiInfo blk)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Term arg;
|
|
|
|
Atom idxtype;
|
|
|
|
UdiControlBlock *p;
|
2012-12-27 12:11:14 +00:00
|
|
|
struct udi_p_args p_arg;
|
2012-12-17 20:23:03 +00:00
|
|
|
|
2012-12-18 18:26:59 +00:00
|
|
|
//fprintf(stderr,"udi init\n");
|
|
|
|
|
2012-12-27 12:11:14 +00:00
|
|
|
for (i = 1; i <= arity; i++) {
|
2012-12-17 20:23:03 +00:00
|
|
|
arg = ArgOfTerm(i,spec);
|
|
|
|
if (IsAtomTerm(arg)) {
|
|
|
|
idxtype = AtomOfTerm(arg);
|
2012-12-18 18:26:59 +00:00
|
|
|
// fprintf(stderr,"%p-%s %p-%s\n",idxtype, YAP_AtomName(idxtype),
|
|
|
|
// AtomMinus, YAP_AtomName(AtomMinus));
|
2012-12-17 20:23:03 +00:00
|
|
|
if (idxtype == AtomMinus)
|
|
|
|
continue;
|
2012-12-27 12:11:14 +00:00
|
|
|
p_arg.control = NULL;
|
2012-12-17 20:23:03 +00:00
|
|
|
p = NULL;
|
|
|
|
while ((p = (UdiControlBlock *) utarray_next(indexing_structures, p))) {
|
2012-12-18 18:26:59 +00:00
|
|
|
//fprintf(stderr,"cb: %p %p-%s\n", *p, (*p)->decl, YAP_AtomName((*p)->decl));
|
2012-12-17 20:23:03 +00:00
|
|
|
if (idxtype == (*p)->decl){
|
2012-12-27 12:11:14 +00:00
|
|
|
p_arg.arg = i;
|
|
|
|
p_arg.control = *p;
|
|
|
|
p_arg.idxstr = (*p)->init(spec, i, arity);
|
|
|
|
utarray_push_back(blk->args, &p_arg);
|
2012-12-17 20:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
2012-12-27 12:11:14 +00:00
|
|
|
if (p_arg.control == NULL){ /* not "-" and not found*/
|
2012-12-17 20:23:03 +00:00
|
|
|
fprintf(stderr, "Invalid Spec (%s)\n", AtomName(idxtype));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-02-12 21:45:41 +00:00
|
|
|
/* just pass info to user, called from cdmgr.c */
|
2009-02-12 16:39:20 +00:00
|
|
|
int
|
|
|
|
Yap_new_udi_clause(PredEntry *p, yamop *cl, Term t)
|
|
|
|
{
|
2012-12-18 18:26:59 +00:00
|
|
|
int i;
|
2012-12-27 12:11:14 +00:00
|
|
|
UdiPArg parg;
|
|
|
|
UdiInfo info;
|
2012-12-28 17:46:11 +00:00
|
|
|
int index;
|
|
|
|
// yamop **x;
|
2012-12-18 18:26:59 +00:00
|
|
|
|
2012-12-27 12:11:14 +00:00
|
|
|
/* try to find our structure*/
|
|
|
|
HASH_FIND_UdiInfo(UdiControlBlocks,p,info);
|
2012-12-17 20:23:03 +00:00
|
|
|
if (!info)
|
|
|
|
return FALSE;
|
|
|
|
|
2012-12-27 12:11:14 +00:00
|
|
|
/*insert into clauselist will be used latter*/
|
2012-12-28 17:46:11 +00:00
|
|
|
utarray_push_back(info->clauselist, &cl);
|
2012-12-18 18:26:59 +00:00
|
|
|
|
2012-12-27 12:11:14 +00:00
|
|
|
for (i = 0; i < utarray_len(info->args) ; i++) {
|
|
|
|
parg = (UdiPArg) utarray_eltptr(info->args,i);
|
2012-12-28 17:46:11 +00:00
|
|
|
index = utarray_len(info->clauselist);
|
|
|
|
// x = (yamop **) utarray_eltptr(info->clauselist, index);
|
|
|
|
// fprintf(stderr,"Insert (%p %p %d) %d - %p %p %p\n",
|
|
|
|
// info->clauselist,info->clauselist->d,info->clauselist->icd.sz,
|
|
|
|
// index,
|
|
|
|
// cl, *x, *((yamop **) utarray_eltptr(info->clauselist, index)));
|
|
|
|
parg->idxstr = parg->control->insert(parg->idxstr, t,
|
|
|
|
parg->arg,
|
|
|
|
(void *) index);
|
2012-12-27 12:11:14 +00:00
|
|
|
//info->cb = info->functions->insert(t, info->cb, (void *)cl);
|
2012-12-18 18:26:59 +00:00
|
|
|
}
|
2012-12-17 20:23:03 +00:00
|
|
|
return TRUE;
|
2009-02-12 16:39:20 +00:00
|
|
|
}
|
|
|
|
|
2012-12-28 17:46:11 +00:00
|
|
|
static inline int callback(void *key, void *data, void *arg)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
Pvoid_t *array = (Pvoid_t *) arg;
|
|
|
|
// fprintf(stderr,"Found %p %d",data, (int) data);
|
|
|
|
J1S(r, *array, (int) data);
|
|
|
|
if (r == JERR)
|
|
|
|
return FALSE;
|
|
|
|
J1C(r, *array, 0 , -1);
|
|
|
|
// fprintf(stderr," (%d)\n",r);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-02-12 21:45:41 +00:00
|
|
|
/* index, called from absmi.c */
|
2009-02-12 16:39:20 +00:00
|
|
|
yamop *
|
|
|
|
Yap_udi_search(PredEntry *p)
|
|
|
|
{
|
2012-12-28 17:46:11 +00:00
|
|
|
int i, r;
|
2012-12-18 18:26:59 +00:00
|
|
|
struct ClauseList clauselist;
|
2012-12-28 17:46:11 +00:00
|
|
|
// struct CallbackM cm;
|
|
|
|
// callback_m_t c;
|
2012-12-27 12:11:14 +00:00
|
|
|
UdiPArg parg;
|
|
|
|
UdiInfo info;
|
2012-12-28 17:46:11 +00:00
|
|
|
Pvoid_t tmp, result;
|
|
|
|
Word_t count;
|
|
|
|
Word_t idx_r = 0L;
|
|
|
|
yamop **x;
|
2012-12-18 18:26:59 +00:00
|
|
|
|
|
|
|
/* find our structure*/
|
2012-12-27 12:11:14 +00:00
|
|
|
HASH_FIND_UdiInfo(UdiControlBlocks,p,info);
|
2012-12-17 20:23:03 +00:00
|
|
|
if (!info)
|
|
|
|
return NULL;
|
2012-12-18 18:26:59 +00:00
|
|
|
|
2012-12-28 17:46:11 +00:00
|
|
|
// /*TODO: handle intersection*/
|
|
|
|
// c = &cm;
|
|
|
|
// c->cl = Yap_ClauseListInit(&clauselist);
|
|
|
|
// c->pred = p;
|
2012-12-27 12:11:14 +00:00
|
|
|
|
2012-12-28 17:46:11 +00:00
|
|
|
/*
|
|
|
|
* I will start with the simplest case
|
|
|
|
* for each index create a set and intersect it with the
|
|
|
|
* next
|
|
|
|
*/
|
|
|
|
result = (Pvoid_t) NULL;
|
|
|
|
tmp = (Pvoid_t) NULL;
|
|
|
|
r = -1;
|
2012-12-27 12:11:14 +00:00
|
|
|
for (i = 0; i < utarray_len(info->args) ; i++) {
|
2012-12-28 17:46:11 +00:00
|
|
|
// fprintf(stderr,"Start Search\n");
|
2012-12-27 12:11:14 +00:00
|
|
|
parg = (UdiPArg) utarray_eltptr(info->args,i);
|
2012-12-28 17:46:11 +00:00
|
|
|
r = parg->control->search(parg->idxstr, parg->arg, callback, &tmp);
|
|
|
|
|
|
|
|
if (r == -1) /*this arg does not prune search*/
|
|
|
|
continue;
|
|
|
|
|
|
|
|
J1C(count, result, 0, -1);
|
2012-12-18 18:26:59 +00:00
|
|
|
|
2012-12-28 17:46:11 +00:00
|
|
|
if (r == 0)
|
2012-12-18 18:26:59 +00:00
|
|
|
{
|
2012-12-28 17:46:11 +00:00
|
|
|
if (count > 0) // clear previous result if it exists
|
|
|
|
J1FA(count, result);
|
|
|
|
fprintf(stderr,"Search Failed");
|
2012-12-18 18:26:59 +00:00
|
|
|
return Yap_FAILCODE();
|
|
|
|
}
|
|
|
|
|
2012-12-28 17:46:11 +00:00
|
|
|
if (r > 0 && count == 0) // first result_set
|
2012-12-18 18:26:59 +00:00
|
|
|
{
|
2012-12-28 17:46:11 +00:00
|
|
|
result = tmp;
|
|
|
|
tmp = (Pvoid_t) NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{/*intersection*/
|
|
|
|
Word_t idx_tmp = 0L;
|
|
|
|
|
|
|
|
idx_r = 0L;
|
|
|
|
J1F(count, result, idx_r);//succeeds one time at least
|
|
|
|
J1F(count, tmp, idx_tmp); //succeeds one time at least
|
|
|
|
while (count)
|
|
|
|
{
|
|
|
|
while (idx_r < idx_tmp)
|
|
|
|
{
|
|
|
|
J1U(count, result, idx_r); //does not belong
|
|
|
|
J1N(count, result, idx_r); //next
|
|
|
|
if (! count) break; //end result set
|
|
|
|
}
|
|
|
|
if(idx_r == idx_tmp)
|
|
|
|
{
|
|
|
|
J1N(count, result, idx_r); //next
|
|
|
|
if (! count) break; //end result set
|
|
|
|
J1N(count, tmp, idx_tmp); //next tmp
|
|
|
|
//if (! count) break; //end tmp set
|
|
|
|
}
|
|
|
|
else // (idx_r > idx_tmp)
|
|
|
|
{
|
|
|
|
idx_tmp = idx_r; // fast forward
|
|
|
|
J1F(count, tmp, idx_tmp); // first starting in idx_r
|
|
|
|
if (! count) break; //end tmp set
|
|
|
|
}
|
|
|
|
}
|
|
|
|
J1F(count, result, idx_r); // first starting in idx_r
|
|
|
|
//clear up the rest
|
|
|
|
while (idx_r > idx_tmp && count) //result has more setted values
|
|
|
|
{
|
|
|
|
J1U(count, result, idx_r); //does not belong
|
|
|
|
J1N(count, result, idx_r); //next
|
|
|
|
}
|
|
|
|
J1FA(count, tmp);
|
2012-12-18 18:26:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-12-28 17:46:11 +00:00
|
|
|
|
|
|
|
Yap_ClauseListInit(&clauselist);
|
|
|
|
idx_r = 0L;
|
|
|
|
J1F(count, result, idx_r);
|
|
|
|
while (count)
|
|
|
|
{
|
|
|
|
x = (yamop **) utarray_eltptr(info->clauselist, idx_r - 1);
|
|
|
|
// fprintf(stderr,"Clausule %d of %d: %p\n",
|
|
|
|
// idx_r, utarray_len(info->clauselist),
|
|
|
|
// *x);
|
|
|
|
Yap_ClauseListExtend(
|
|
|
|
&clauselist,
|
|
|
|
*x,
|
|
|
|
info->p);
|
|
|
|
J1N(count, result, idx_r);
|
|
|
|
}
|
|
|
|
J1FA(count,result);
|
|
|
|
// fprintf(stderr,"J1 used space %d bytes for %d clausules\n",
|
|
|
|
// count, Yap_ClauseListCount(&clauselist));
|
|
|
|
Yap_ClauseListClose(&clauselist);
|
|
|
|
|
|
|
|
if (Yap_ClauseListCount(&clauselist) == 0)
|
|
|
|
{
|
|
|
|
Yap_ClauseListDestroy(&clauselist);
|
|
|
|
// fprintf(stderr,"Search Not needed\n");
|
|
|
|
return NULL; /*FAIL CODE handled before*/
|
|
|
|
}
|
|
|
|
if (Yap_ClauseListCount(&clauselist) == 1)
|
|
|
|
{
|
|
|
|
// fprintf(stderr,"Returning 1 value\n");
|
|
|
|
return Yap_ClauseListToClause(&clauselist);
|
|
|
|
}
|
|
|
|
// fprintf(stderr,"Returning Multiple values (%d)\n", Yap_ClauseListCount(&clauselist));
|
|
|
|
return Yap_ClauseListCode(&clauselist);
|
2009-02-12 16:39:20 +00:00
|
|
|
}
|
|
|
|
|
2012-06-21 16:47:19 +01:00
|
|
|
/* index, called from absmi.c */
|
|
|
|
void
|
|
|
|
Yap_udi_abolish(PredEntry *p)
|
|
|
|
{
|
2012-12-17 20:23:03 +00:00
|
|
|
/* tell the predicate destroy */
|
2012-06-21 16:47:19 +01:00
|
|
|
}
|
|
|
|
|
2012-12-27 12:11:14 +00:00
|
|
|
/*
|
|
|
|
* Init Yap udi interface
|
|
|
|
*/
|
2009-02-12 16:39:20 +00:00
|
|
|
void
|
|
|
|
Yap_udi_init(void)
|
|
|
|
{
|
|
|
|
UdiControlBlocks = NULL;
|
2012-12-17 20:23:03 +00:00
|
|
|
|
|
|
|
/*init indexing structures array*/
|
|
|
|
utarray_new(indexing_structures, &udicb_icd);
|
|
|
|
|
|
|
|
Yap_InitCPred("$udi_init", 1, p_new_udi, 0);
|
2012-12-27 12:11:14 +00:00
|
|
|
/* TODO: decide if udi.yap should be loaded automaticaly in init.yap */
|
2009-02-12 16:39:20 +00:00
|
|
|
}
|