2001-04-09 20:54:03 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* *
|
|
|
|
* YAP Prolog *
|
|
|
|
* *
|
|
|
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
|
|
|
* *
|
|
|
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
|
|
|
* *
|
|
|
|
**************************************************************************
|
|
|
|
* *
|
|
|
|
* File: attvar.c *
|
|
|
|
* Last rev: *
|
|
|
|
* mods: *
|
|
|
|
* comments: YAP support for attributed vars *
|
|
|
|
* *
|
|
|
|
*************************************************************************/
|
|
|
|
#ifdef SCCS
|
|
|
|
static char SccsId[]="%W% %G%";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Yap.h"
|
|
|
|
|
|
|
|
#include "Yatom.h"
|
|
|
|
#include "Heap.h"
|
|
|
|
#include "heapgc.h"
|
|
|
|
#include "attvar.h"
|
|
|
|
#ifndef NULL
|
|
|
|
#define NULL (void *)0
|
|
|
|
#endif
|
|
|
|
|
2004-06-23 18:24:20 +01:00
|
|
|
#ifdef COROUTINING
|
|
|
|
|
2001-07-04 17:48:54 +01:00
|
|
|
STATIC_PROTO(Term InitVarTime, (void));
|
2004-09-27 21:45:04 +01:00
|
|
|
STATIC_PROTO(void PutAtt, (attvar_record *,Int,Term));
|
2001-12-17 18:31:11 +00:00
|
|
|
STATIC_PROTO(Int BuildNewAttVar, (Term,Int,Term));
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
static CELL *
|
|
|
|
AddToQueue(attvar_record *attv)
|
|
|
|
{
|
|
|
|
Term t[2];
|
2004-06-05 04:37:01 +01:00
|
|
|
Term WGs, ng;
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
t[0] = (CELL)&(attv->Done);
|
|
|
|
t[1] = attv->Value;
|
|
|
|
/* follow the chain */
|
2004-06-05 04:37:01 +01:00
|
|
|
WGs = Yap_ReadTimedVar(WokenGoals);
|
|
|
|
ng = Yap_MkApplTerm(FunctorAttGoal, 2, t);
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2004-06-05 04:37:01 +01:00
|
|
|
Yap_UpdateTimedVar(WokenGoals, MkPairTerm(ng, WGs));
|
2001-04-09 20:54:03 +01:00
|
|
|
if ((Term)WGs == TermNil) {
|
|
|
|
/* from now on, we have to start waking up goals */
|
2004-01-23 02:23:51 +00:00
|
|
|
Yap_signal(YAP_WAKEUP_SIGNAL);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2004-06-05 04:37:01 +01:00
|
|
|
return(RepAppl(ng)+2);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
2004-06-05 04:37:01 +01:00
|
|
|
static void
|
2001-04-09 20:54:03 +01:00
|
|
|
AddFailToQueue(void)
|
|
|
|
{
|
2004-06-05 04:37:01 +01:00
|
|
|
Term WGs;
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
/* follow the chain */
|
2004-06-05 04:37:01 +01:00
|
|
|
WGs = Yap_ReadTimedVar(WokenGoals);
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2004-06-05 04:37:01 +01:00
|
|
|
Yap_UpdateTimedVar(WokenGoals, MkPairTerm(MkAtomTerm(AtomFail),WGs));
|
2001-04-09 20:54:03 +01:00
|
|
|
if ((Term)WGs == TermNil) {
|
|
|
|
/* from now on, we have to start waking up goals */
|
2004-01-23 02:23:51 +00:00
|
|
|
Yap_signal(YAP_WAKEUP_SIGNAL);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-12-11 03:34:03 +00:00
|
|
|
CopyAttVar(CELL *orig, CELL ***to_visit_ptr, CELL *res)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
|
|
|
register attvar_record *attv = (attvar_record *)orig;
|
|
|
|
register attvar_record *newv;
|
|
|
|
CELL **to_visit = *to_visit_ptr;
|
|
|
|
Term time = InitVarTime();
|
|
|
|
Int j;
|
|
|
|
|
|
|
|
/* add a new attributed variable */
|
2002-11-18 18:18:05 +00:00
|
|
|
newv = (attvar_record *)Yap_ReadTimedVar(DelayedVars);
|
2001-04-09 20:54:03 +01:00
|
|
|
if (H0 - (CELL *)newv < 1024+(2*NUM_OF_ATTS))
|
2004-09-09 21:00:59 +01:00
|
|
|
return FALSE;
|
2001-04-09 20:54:03 +01:00
|
|
|
RESET_VARIABLE(&(newv->Done));
|
|
|
|
newv->sus_id = attvars_ext;
|
|
|
|
RESET_VARIABLE(&(newv->Value));
|
2002-11-18 18:18:05 +00:00
|
|
|
newv->NS = Yap_UpdateTimedVar(AttsMutableList, (CELL)&(newv->Done));
|
2001-04-09 20:54:03 +01:00
|
|
|
for (j = 0; j < NUM_OF_ATTS; j++) {
|
2001-12-11 03:34:03 +00:00
|
|
|
Term t = Deref(attv->Atts[2*j+1]);
|
2001-06-06 20:10:51 +01:00
|
|
|
newv->Atts[2*j] = time;
|
2001-12-11 03:34:03 +00:00
|
|
|
|
|
|
|
if (IsVarTerm(t)) {
|
2004-04-20 23:08:57 +01:00
|
|
|
CELL *vt = VarOfTerm(t);
|
|
|
|
if (vt == attv->Atts+(2*j+1)) {
|
|
|
|
RESET_VARIABLE(newv->Atts+(2*j+1));
|
|
|
|
} else {
|
|
|
|
to_visit[0] = vt-1;
|
|
|
|
to_visit[1] = vt;
|
|
|
|
to_visit[2] = newv->Atts+2*j+1;
|
2004-09-18 15:03:42 +01:00
|
|
|
to_visit[3] = (CELL *)vt[-1];
|
2004-04-20 23:08:57 +01:00
|
|
|
to_visit += 4;
|
|
|
|
}
|
|
|
|
} else if (IsVarTerm(t) && IsAtomicTerm(t)) {
|
2001-12-11 03:34:03 +00:00
|
|
|
newv->Atts[2*j+1] = t;
|
|
|
|
} else {
|
|
|
|
to_visit[0] = attv->Atts+2*j;
|
|
|
|
to_visit[1] = attv->Atts+2*j+1;
|
|
|
|
to_visit[2] = newv->Atts+2*j+1;
|
|
|
|
to_visit[3] = (CELL *)(attv->Atts[2*j]);
|
|
|
|
to_visit += 4;
|
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
*to_visit_ptr = to_visit;
|
2001-12-11 03:34:03 +00:00
|
|
|
*res = (CELL)&(newv->Done);
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_UpdateTimedVar(DelayedVars, (CELL)(newv->Atts+2*j));
|
2001-04-09 20:54:03 +01:00
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
2001-12-17 18:31:11 +00:00
|
|
|
static Term
|
|
|
|
AttVarToTerm(CELL *orig)
|
|
|
|
{
|
|
|
|
register attvar_record *attv = (attvar_record *)orig;
|
|
|
|
Term list = TermNil;
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < NUM_OF_ATTS; j++) {
|
|
|
|
Term t = attv->Atts[2*(NUM_OF_ATTS-j-1)+1];
|
|
|
|
if (IsVarTerm(t))
|
|
|
|
list = MkPairTerm(MkVarTerm(),list);
|
|
|
|
else
|
|
|
|
list = MkPairTerm(t,list);
|
|
|
|
}
|
|
|
|
return(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
TermToAttVar(Term attvar, Term to)
|
|
|
|
{
|
2002-04-06 04:54:18 +01:00
|
|
|
return(BuildNewAttVar(to, -1, attvar));
|
2001-12-17 18:31:11 +00:00
|
|
|
}
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
static void
|
|
|
|
WakeAttVar(CELL* pt1, CELL reg2)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* if bound to someone else, follow until we find the last one */
|
|
|
|
attvar_record *attv = (attvar_record *)pt1;
|
|
|
|
CELL *myH = H;
|
|
|
|
CELL *bind_ptr;
|
|
|
|
|
|
|
|
if (IsVarTerm(reg2)) {
|
2004-09-10 21:18:01 +01:00
|
|
|
if (pt1 == VarOfTerm(reg2))
|
|
|
|
return;
|
2001-04-09 20:54:03 +01:00
|
|
|
if (IsAttachedTerm(reg2)) {
|
|
|
|
attvar_record *susp2 = (attvar_record *)VarOfTerm(reg2);
|
|
|
|
|
|
|
|
/* binding two suspended variables, be careful */
|
|
|
|
if (susp2->sus_id != attvars_ext) {
|
|
|
|
/* joining two different kinds of suspensions */
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(SYSTEM_ERROR, TermNil, "joining two different suspensions not implemented");
|
2001-04-09 20:54:03 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (susp2 >= attv) {
|
2004-09-18 15:03:42 +01:00
|
|
|
if (!IsVarTerm(susp2->Value) || !IsUnboundVar(&susp2->Value)) {
|
2001-04-09 20:54:03 +01:00
|
|
|
/* oops, our goal is on the queue to be woken */
|
2002-11-18 18:18:05 +00:00
|
|
|
if (!Yap_unify(susp2->Value, (CELL)pt1)) {
|
2001-04-09 20:54:03 +01:00
|
|
|
AddFailToQueue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind_Global(&(susp2->Value), (CELL)pt1);
|
|
|
|
AddToQueue(susp2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Bind(VarOfTerm(reg2), (CELL)pt1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2004-09-18 15:03:42 +01:00
|
|
|
if (!IsVarTerm(attv->Value) || !IsUnboundVar(&attv->Value)) {
|
2002-04-13 05:39:03 +01:00
|
|
|
/* oops, our goal is on the queue to be woken */
|
2002-11-18 18:18:05 +00:00
|
|
|
if (!Yap_unify(attv->Value, reg2)) {
|
2002-04-13 05:39:03 +01:00
|
|
|
AddFailToQueue();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
bind_ptr = AddToQueue(attv);
|
|
|
|
if (IsNonVarTerm(reg2)) {
|
|
|
|
if (IsPairTerm(reg2) && RepPair(reg2) == myH)
|
|
|
|
reg2 = AbsPair(H);
|
|
|
|
else if (IsApplTerm(reg2) && RepAppl(reg2) == myH)
|
|
|
|
reg2 = AbsAppl(H);
|
|
|
|
}
|
|
|
|
*bind_ptr = reg2;
|
|
|
|
Bind_Global(&(attv->Value), reg2);
|
|
|
|
}
|
|
|
|
|
2004-06-05 04:37:01 +01:00
|
|
|
void
|
|
|
|
Yap_WakeUp(CELL *pt0) {
|
|
|
|
CELL d0 = *pt0;
|
|
|
|
RESET_VARIABLE(pt0);
|
|
|
|
TR--;
|
|
|
|
WakeAttVar(pt0, d0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
static void
|
|
|
|
mark_attvar(CELL *orig)
|
|
|
|
{
|
|
|
|
register attvar_record *attv = (attvar_record *)orig;
|
|
|
|
Int i;
|
|
|
|
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_mark_external_reference(&(attv->Value));
|
|
|
|
Yap_mark_external_reference(&(attv->Done));
|
2001-04-09 20:54:03 +01:00
|
|
|
for (i = 0; i < NUM_OF_ATTS; i++) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_mark_external_reference(attv->Atts+2*i+1);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-04 17:48:54 +01:00
|
|
|
#if FROZEN_STACKS
|
|
|
|
static Term
|
|
|
|
CurrentTime(void) {
|
2002-11-18 18:18:05 +00:00
|
|
|
return(MkIntegerTerm(TR-(tr_fr_ptr)Yap_TrailBase));
|
2001-07-04 17:48:54 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static Term
|
2001-04-09 20:54:03 +01:00
|
|
|
InitVarTime(void) {
|
2001-07-04 17:48:54 +01:00
|
|
|
#if FROZEN_STACKS
|
|
|
|
if (B->cp_tr == TR) {
|
|
|
|
/* we run the risk of not making non-determinate bindings before
|
|
|
|
the end of the night */
|
|
|
|
/* so we just init a TR cell that will not harm anyone */
|
|
|
|
Bind((CELL *)(TR+1),AbsAppl(H-1));
|
|
|
|
}
|
2002-11-18 18:18:05 +00:00
|
|
|
return(MkIntegerTerm(B->cp_tr-(tr_fr_ptr)Yap_TrailBase));
|
2001-07-04 17:48:54 +01:00
|
|
|
#else
|
2001-06-06 20:10:51 +01:00
|
|
|
Term t = (CELL)H;
|
|
|
|
*H++ = TermFoundVar;
|
|
|
|
return(t);
|
2001-07-04 17:48:54 +01:00
|
|
|
#endif
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
2004-09-27 21:45:04 +01:00
|
|
|
static void
|
2001-04-09 20:54:03 +01:00
|
|
|
PutAtt(attvar_record *attv, Int i, Term tatt) {
|
|
|
|
Int pos = i*2;
|
2001-07-04 17:48:54 +01:00
|
|
|
#if FROZEN_STACKS
|
2002-11-18 18:18:05 +00:00
|
|
|
tr_fr_ptr timestmp = (tr_fr_ptr)Yap_TrailBase+IntegerOfTerm(attv->Atts[pos]);
|
2001-07-04 17:48:54 +01:00
|
|
|
if (B->cp_tr <= timestmp
|
|
|
|
&& timestmp <= TR) {
|
2001-04-09 20:54:03 +01:00
|
|
|
#if defined(SBA)
|
|
|
|
if (Unsigned((Int)(attv)-(Int)(H_FZ)) >
|
|
|
|
Unsigned((Int)(B_FZ)-(Int)(H_FZ))) {
|
|
|
|
CELL *ptr = STACK_TO_SBA(attv->Atts+pos+1);
|
|
|
|
*ptr = tatt;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
attv->Atts[pos+1] = tatt;
|
|
|
|
if (Unsigned((Int)(attv)-(Int)(HBREG)) >
|
2001-07-04 17:48:54 +01:00
|
|
|
Unsigned(BBREG)-(Int)(HBREG))
|
|
|
|
TrailVal(timestmp-1) = tatt;
|
|
|
|
} else {
|
|
|
|
Term tnewt;
|
|
|
|
MaBind(attv->Atts+pos+1, tatt);
|
|
|
|
tnewt = CurrentTime();
|
|
|
|
MaBind(attv->Atts+pos, tnewt);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
CELL *timestmp = (CELL *)(attv->Atts[pos]);
|
2003-02-14 10:52:00 +00:00
|
|
|
if (B->cp_h <= timestmp) {
|
|
|
|
attv->Atts[pos+1] = tatt;
|
2001-04-09 20:54:03 +01:00
|
|
|
} else {
|
|
|
|
Term tnewt;
|
|
|
|
MaBind(attv->Atts+pos+1, tatt);
|
2001-06-06 20:10:51 +01:00
|
|
|
tnewt = (Term)H;
|
|
|
|
*H++ = TermFoundVar;
|
2001-04-09 20:54:03 +01:00
|
|
|
MaBind(attv->Atts+pos, tnewt);
|
|
|
|
}
|
2001-07-04 17:48:54 +01:00
|
|
|
#endif
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
2004-06-05 04:37:01 +01:00
|
|
|
static Int
|
|
|
|
UpdateAtt(attvar_record *attv, Int i, Term tatt) {
|
|
|
|
Int pos = i*2;
|
2004-09-08 20:06:57 +01:00
|
|
|
Term tv = attv->Atts[pos+1];
|
2004-09-18 15:03:42 +01:00
|
|
|
if (!IsVarTerm(tv) || !IsUnboundVar(attv->Atts+pos+1)) {
|
2004-06-05 04:37:01 +01:00
|
|
|
tatt = MkPairTerm(tatt, attv->Atts[pos+1]);
|
|
|
|
} else {
|
|
|
|
tatt = MkPairTerm(tatt, TermNil);
|
|
|
|
}
|
2004-09-27 21:45:04 +01:00
|
|
|
PutAtt(attv, i, tatt);
|
|
|
|
return TRUE;
|
2004-06-05 04:37:01 +01:00
|
|
|
}
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
static Int
|
|
|
|
RmAtt(attvar_record *attv, Int i) {
|
|
|
|
Int pos = i *2;
|
|
|
|
if (!IsVarTerm(attv->Atts[pos+1])) {
|
2001-07-04 17:48:54 +01:00
|
|
|
#if FROZEN_STACKS
|
2002-11-18 18:18:05 +00:00
|
|
|
tr_fr_ptr timestmp = (tr_fr_ptr)Yap_TrailBase+IntegerOfTerm(attv->Atts[pos]);
|
2001-07-04 17:48:54 +01:00
|
|
|
if (B->cp_tr <= timestmp
|
|
|
|
&& timestmp <= TR) {
|
|
|
|
RESET_VARIABLE(attv->Atts+(pos+1));
|
|
|
|
if (Unsigned((Int)(attv)-(Int)(HBREG)) >
|
|
|
|
Unsigned(BBREG)-(Int)(HBREG))
|
|
|
|
TrailVal(timestmp-1) = attv->Atts[pos+1];
|
|
|
|
} else {
|
|
|
|
/* reset the variable */
|
|
|
|
Term tnewt;
|
|
|
|
#ifdef SBA
|
|
|
|
MaBind(attv->Atts+(pos+1), 0L);
|
|
|
|
#else
|
|
|
|
MaBind(attv->Atts+(pos+1), (CELL)(attv->Atts+(pos+1)));
|
2001-04-09 20:54:03 +01:00
|
|
|
#endif
|
2001-07-04 17:48:54 +01:00
|
|
|
tnewt = CurrentTime();
|
|
|
|
MaBind(attv->Atts+pos, tnewt);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
CELL *timestmp = (CELL *)(attv->Atts[pos]);
|
|
|
|
if (B->cp_h <= timestmp) {
|
2001-04-09 20:54:03 +01:00
|
|
|
RESET_VARIABLE(attv->Atts+(pos+1));
|
|
|
|
} else {
|
|
|
|
/* reset the variable */
|
|
|
|
Term tnewt;
|
|
|
|
#ifdef SBA
|
|
|
|
MaBind(attv->Atts+(pos+1), 0L);
|
|
|
|
#else
|
|
|
|
MaBind(attv->Atts+(pos+1), (CELL)(attv->Atts+(pos+1)));
|
|
|
|
#endif
|
2001-06-06 20:10:51 +01:00
|
|
|
tnewt = (Term)H;
|
|
|
|
*H++ = TermFoundVar;
|
|
|
|
MaBind(attv->Atts+pos, tnewt);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2001-07-04 17:48:54 +01:00
|
|
|
#endif
|
2003-02-14 10:52:00 +00:00
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
BuildNewAttVar(Term t, Int i, Term tatt)
|
|
|
|
{
|
|
|
|
/* allocate space in Heap */
|
2001-06-06 20:10:51 +01:00
|
|
|
Term time;
|
2001-04-09 20:54:03 +01:00
|
|
|
int j;
|
|
|
|
|
2002-11-18 18:18:05 +00:00
|
|
|
attvar_record *attv = (attvar_record *)Yap_ReadTimedVar(DelayedVars);
|
2001-04-09 20:54:03 +01:00
|
|
|
if (H0 - (CELL *)attv < 1024+(2*NUM_OF_ATTS)) {
|
2004-09-27 21:45:04 +01:00
|
|
|
return FALSE;
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2001-06-06 20:10:51 +01:00
|
|
|
time = InitVarTime();
|
2001-04-09 20:54:03 +01:00
|
|
|
RESET_VARIABLE(&(attv->Value));
|
|
|
|
RESET_VARIABLE(&(attv->Done));
|
|
|
|
attv->sus_id = attvars_ext;
|
|
|
|
for (j = 0; j < NUM_OF_ATTS; j++) {
|
2001-06-06 20:10:51 +01:00
|
|
|
attv->Atts[2*j] = time;
|
2004-04-20 23:08:57 +01:00
|
|
|
RESET_VARIABLE(attv->Atts+(2*j+1));
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2002-11-18 18:18:05 +00:00
|
|
|
attv->NS = Yap_UpdateTimedVar(AttsMutableList, (CELL)&(attv->Done));
|
2001-04-09 20:54:03 +01:00
|
|
|
Bind((CELL *)t,(CELL)attv);
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_UpdateTimedVar(DelayedVars,(CELL)(attv->Atts+2*j));
|
2004-09-07 21:20:12 +01:00
|
|
|
/* avoid trouble in gc */
|
2002-04-06 04:54:18 +01:00
|
|
|
/* if i < 0 then we have the list of arguments */
|
|
|
|
if (i < 0) {
|
|
|
|
Int j = 0;
|
|
|
|
while (IsPairTerm(tatt)) {
|
|
|
|
Term t = HeadOfTerm(tatt);
|
|
|
|
/* I need to do this because BuildNewAttVar may shift the stacks */
|
|
|
|
if (!IsVarTerm(t)) {
|
|
|
|
attv->Atts[2*j+1] = t;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
tatt = TailOfTerm(tatt);
|
|
|
|
}
|
2004-09-27 21:45:04 +01:00
|
|
|
return TRUE;
|
2002-04-06 04:54:18 +01:00
|
|
|
} else {
|
2004-09-27 21:45:04 +01:00
|
|
|
PutAtt(attv, i, tatt);
|
|
|
|
return TRUE;
|
2002-04-06 04:54:18 +01:00
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
GetAtt(attvar_record *attv, int i) {
|
|
|
|
Int pos = i *2;
|
|
|
|
#if SBA
|
2004-09-18 15:03:42 +01:00
|
|
|
if (IsVarTerm(attv->Atts[pos+1]) && IsUnboundVar(attv->Atts+pos+1))
|
2001-04-09 20:54:03 +01:00
|
|
|
return((CELL)&(attv->Atts[pos+1]));
|
|
|
|
#endif
|
|
|
|
return(attv->Atts[pos+1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
FreeAtt(attvar_record *attv, int i) {
|
|
|
|
Int pos = i *2;
|
|
|
|
return(IsVarTerm(attv->Atts[pos+1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
BindAttVar(attvar_record *attv) {
|
2004-09-18 15:03:42 +01:00
|
|
|
if (IsVarTerm(attv->Done) && IsUnboundVar(&attv->Done)) {
|
2003-02-14 10:52:00 +00:00
|
|
|
/* make sure we are not trying to bind a variable against itself */
|
|
|
|
if (!IsVarTerm(attv->Value)) {
|
|
|
|
Bind_Global(&(attv->Done), attv->Value);
|
|
|
|
} else if (IsVarTerm(attv->Value)) {
|
|
|
|
Term t = Deref(attv->Value);
|
|
|
|
if (IsVarTerm(t)) {
|
|
|
|
if (IsAttachedTerm(t)) {
|
|
|
|
attvar_record *attv2 = (attvar_record *)VarOfTerm(t);
|
|
|
|
if (attv2 < attv) {
|
|
|
|
Bind_Global(&(attv->Done), t);
|
|
|
|
} else {
|
|
|
|
Bind_Global(&(attv2->Done), (CELL)attv);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Yap_Error(SYSTEM_ERROR,(CELL)&(attv->Done),"attvar was bound when unset");
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Bind_Global(&(attv->Done), t);
|
|
|
|
}
|
|
|
|
}
|
2001-04-09 20:54:03 +01:00
|
|
|
return(TRUE);
|
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(SYSTEM_ERROR,(CELL)&(attv->Done),"attvar was bound when set");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Term
|
|
|
|
GetAllAtts(attvar_record *attv) {
|
|
|
|
Int i;
|
|
|
|
Term t = TermNil;
|
|
|
|
for (i = NUM_OF_ATTS-1; i >= 0; i --) {
|
|
|
|
if (!IsVarTerm(attv->Atts[2*i+1]))
|
|
|
|
t = MkPairTerm(MkPairTerm(MkIntegerTerm(i),attv->Atts[2*i+1]), t);
|
|
|
|
}
|
|
|
|
return(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Term
|
|
|
|
AllAttVars(Term t) {
|
|
|
|
if (t == TermNil) {
|
|
|
|
return(t);
|
|
|
|
} else {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(t);
|
2004-09-18 15:03:42 +01:00
|
|
|
if (!IsVarTerm(attv->Done) || !IsUnboundVar(&attv->Done))
|
2001-04-09 20:54:03 +01:00
|
|
|
return(AllAttVars(attv->NS));
|
|
|
|
else return(MkPairTerm(t,AllAttVars(attv->NS)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Term
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_CurrentAttVars(void) {
|
|
|
|
return(AllAttVars(Yap_ReadTimedVar(AttsMutableList)));
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_put_att(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
exts id = (exts)attv->sus_id;
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"put_attributes/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
2004-09-27 21:45:04 +01:00
|
|
|
PutAtt(attv, IntegerOfTerm(Deref(ARG2)), Deref(ARG3));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
while (!BuildNewAttVar(inp, IntegerOfTerm(Deref(ARG2)), Deref(ARG3))) {
|
|
|
|
if (!Yap_growglobal(NULL)) {
|
|
|
|
Yap_Error(OUT_OF_ATTVARS_ERROR, ARG1, Yap_ErrorMessage);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
inp = Deref(ARG1);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2004-09-27 21:45:04 +01:00
|
|
|
return TRUE;
|
2001-04-09 20:54:03 +01:00
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"put_attributes/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-05 04:37:01 +01:00
|
|
|
static Int
|
|
|
|
p_update_att(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
exts id = (exts)attv->sus_id;
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"put_attributes/2");
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
return(UpdateAtt(attv, IntegerOfTerm(Deref(ARG2)), Deref(ARG3)));
|
|
|
|
}
|
2004-09-27 21:45:04 +01:00
|
|
|
while (!BuildNewAttVar(inp, IntegerOfTerm(Deref(ARG2)), MkPairTerm(Deref(ARG3),TermNil))) {
|
|
|
|
if (!Yap_growglobal(NULL)) {
|
|
|
|
Yap_Error(OUT_OF_ATTVARS_ERROR, ARG1, Yap_ErrorMessage);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
inp = Deref(ARG1);
|
|
|
|
}
|
|
|
|
return TRUE;
|
2004-06-05 04:37:01 +01:00
|
|
|
} else {
|
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"put_attributes/2");
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
static Int
|
|
|
|
p_rm_att(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
exts id = (exts)attv->sus_id;
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"delete_attribute/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
return(RmAtt(attv, IntegerOfTerm(Deref(ARG2))));
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"delete_attribute/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_get_att(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
Term out;
|
|
|
|
exts id = (exts)attv->sus_id;
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
out = GetAtt(attv,IntegerOfTerm(Deref(ARG2)));
|
2002-11-18 18:18:05 +00:00
|
|
|
return(!IsVarTerm(out) && Yap_unify(ARG3,out));
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
2002-11-18 18:18:05 +00:00
|
|
|
/* Yap_Error(INSTANTIATION_ERROR,inp,"get_att/2");*/
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_free_att(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
exts id = (exts)attv->sus_id;
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
return(FreeAtt(attv,IntegerOfTerm(Deref(ARG2))));
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"free_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_bind_attvar(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
exts id = (exts)attv->sus_id;
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
return(BindAttVar(attv));
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"bind_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_get_all_atts(void) {
|
|
|
|
/* receive a variable in ARG1 */
|
|
|
|
Term inp = Deref(ARG1);
|
|
|
|
/* if this is unbound, ok */
|
|
|
|
if (IsVarTerm(inp)) {
|
|
|
|
if (IsAttachedTerm(inp)) {
|
|
|
|
attvar_record *attv = (attvar_record *)VarOfTerm(inp);
|
|
|
|
exts id = (exts)(attv->sus_id);
|
|
|
|
|
|
|
|
if (id != attvars_ext) {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
2002-11-18 18:18:05 +00:00
|
|
|
return(Yap_unify(ARG2,GetAllAtts(attv)));
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
} else {
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
2001-04-09 20:54:03 +01:00
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_inc_atts(void)
|
|
|
|
{
|
|
|
|
Term t = MkIntegerTerm(NUM_OF_ATTS);
|
|
|
|
NUM_OF_ATTS++;
|
2002-11-18 18:18:05 +00:00
|
|
|
return(Yap_unify(ARG1,t));
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_n_atts(void)
|
|
|
|
{
|
|
|
|
Term t = MkIntegerTerm(NUM_OF_ATTS);
|
2004-06-23 18:24:20 +01:00
|
|
|
return Yap_unify(ARG1,t);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_all_attvars(void)
|
|
|
|
{
|
2002-11-18 18:18:05 +00:00
|
|
|
Term t = Yap_ReadTimedVar(AttsMutableList);
|
2004-06-23 18:24:20 +01:00
|
|
|
return Yap_unify(ARG1,AllAttVars(t));
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_is_attvar(void)
|
|
|
|
{
|
|
|
|
Term t = Deref(ARG1);
|
|
|
|
return(IsVarTerm(t) &&
|
|
|
|
IsAttachedTerm(t) &&
|
|
|
|
((attvar_record *)VarOfTerm(t))->sus_id == attvars_ext);
|
|
|
|
}
|
|
|
|
|
2002-07-17 21:25:30 +01:00
|
|
|
/* check if we are not redoing effort */
|
|
|
|
static Int
|
|
|
|
p_attvar_bound(void)
|
|
|
|
{
|
|
|
|
Term t = Deref(ARG1);
|
|
|
|
return(IsVarTerm(t) &&
|
|
|
|
IsAttachedTerm(t) &&
|
|
|
|
((attvar_record *)VarOfTerm(t))->sus_id == attvars_ext &&
|
2004-09-18 15:03:42 +01:00
|
|
|
!IsUnboundVar(&((attvar_record *)VarOfTerm(t))->Done));
|
2002-07-17 21:25:30 +01:00
|
|
|
}
|
|
|
|
|
2004-06-23 18:24:20 +01:00
|
|
|
#else
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_all_attvars(void)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_is_attvar(void)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Int
|
|
|
|
p_attvar_bound(void)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* COROUTINING */
|
|
|
|
|
2002-11-18 18:18:05 +00:00
|
|
|
void Yap_InitAttVarPreds(void)
|
2001-04-09 20:54:03 +01:00
|
|
|
{
|
2004-05-13 21:54:58 +01:00
|
|
|
Term OldCurrentModule = CurrentModule;
|
2004-06-23 18:24:20 +01:00
|
|
|
CurrentModule = ATTRIBUTES_MODULE;
|
|
|
|
#ifdef COROUTINING
|
2001-04-09 20:54:03 +01:00
|
|
|
attas[attvars_ext].bind_op = WakeAttVar;
|
|
|
|
attas[attvars_ext].copy_term_op = CopyAttVar;
|
2001-12-17 18:31:11 +00:00
|
|
|
attas[attvars_ext].to_term_op = AttVarToTerm;
|
|
|
|
attas[attvars_ext].term_to_op = TermToAttVar;
|
2001-04-09 20:54:03 +01:00
|
|
|
attas[attvars_ext].mark_op = mark_attvar;
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_InitCPred("get_att", 3, p_get_att, SafePredFlag);
|
|
|
|
Yap_InitCPred("get_all_atts", 2, p_get_all_atts, SafePredFlag);
|
|
|
|
Yap_InitCPred("free_att", 2, p_free_att, SafePredFlag);
|
|
|
|
Yap_InitCPred("put_att", 3, p_put_att, 0);
|
2004-06-05 04:37:01 +01:00
|
|
|
Yap_InitCPred("update_att", 3, p_update_att, 0);
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_InitCPred("rm_att", 2, p_rm_att, SafePredFlag);
|
|
|
|
Yap_InitCPred("inc_n_of_atts", 1, p_inc_atts, SafePredFlag);
|
|
|
|
Yap_InitCPred("n_of_atts", 1, p_n_atts, SafePredFlag);
|
|
|
|
Yap_InitCPred("bind_attvar", 1, p_bind_attvar, SafePredFlag);
|
2004-06-23 18:24:20 +01:00
|
|
|
#endif /* COROUTINING */
|
2002-11-18 18:18:05 +00:00
|
|
|
Yap_InitCPred("all_attvars", 1, p_all_attvars, SafePredFlag);
|
2004-05-13 21:54:58 +01:00
|
|
|
CurrentModule = OldCurrentModule;
|
2004-09-10 21:18:01 +01:00
|
|
|
Yap_InitCPred("attvar", 1, p_is_attvar, SafePredFlag|TestPredFlag);
|
2004-11-18 22:32:40 +00:00
|
|
|
Yap_InitCPred("$att_bound", 1, p_attvar_bound, SafePredFlag|TestPredFlag|HiddenPredFlag);
|
2001-04-09 20:54:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|