2005-09-08 23:36:16 +01:00
|
|
|
|
/*************************************************************************
|
|
|
|
|
* *
|
|
|
|
|
* BEAM -> Basic Extended Andorra Model *
|
|
|
|
|
* BEAM extends the YAP Prolog system to support the EAM *
|
|
|
|
|
* *
|
|
|
|
|
* Copyright: Ricardo Lopes and NCC - University of Porto, Portugal *
|
|
|
|
|
* *
|
|
|
|
|
**************************************************************************
|
|
|
|
|
* comments: split related functions *
|
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
|
|
void do_forking_andbox(struct AND_BOX *a);
|
|
|
|
|
Cell copy_structures(Cell c);
|
|
|
|
|
void replicate_local_variables(struct AND_BOX *a);
|
|
|
|
|
struct OR_BOX *copy_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call);
|
|
|
|
|
struct AND_BOX *copy_andbox(struct AND_BOX *a,struct OR_BOX *parent);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void do_forking_andbox(struct AND_BOX *a)
|
|
|
|
|
{
|
|
|
|
|
struct OR_BOX *op,*opp, *new_orbox;
|
|
|
|
|
struct AND_BOX *ap, *new_andbox;
|
|
|
|
|
int nr_all_alternatives, nr_all_calls;
|
|
|
|
|
struct status_and *nr_call,*new_call;
|
|
|
|
|
struct status_or *nr_alternative, *alternatives, *new_alternatives;
|
|
|
|
|
|
|
|
|
|
nr_call_forking++;
|
|
|
|
|
op=a->parent; /* or box parent */
|
|
|
|
|
ap=op->parent; /* and box parent */
|
|
|
|
|
opp=ap->parent; /* or box parent parent */
|
|
|
|
|
if (opp==NULL) {
|
|
|
|
|
abort_eam("Forking with orbox parent parent NULL, maybe I'm on top ?????");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
alternatives=opp->alternatives;
|
|
|
|
|
nr_all_alternatives=opp->nr_all_alternatives;
|
|
|
|
|
nr_alternative=ap->nr_alternative;
|
|
|
|
|
nr_all_calls=ap->nr_all_calls;
|
|
|
|
|
nr_call=op->nr_call;
|
|
|
|
|
|
|
|
|
|
new_andbox=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
|
|
|
|
|
new_orbox=(struct OR_BOX *) request_memory(ORBOX_SIZE);
|
|
|
|
|
new_andbox->parent=opp;
|
|
|
|
|
// new_andbox->nr_alternative=nr_alternative; /* seted after creating a new status_or */
|
|
|
|
|
new_andbox->nr_all_calls=nr_all_calls;
|
|
|
|
|
new_andbox->level=ap->level;
|
|
|
|
|
new_andbox->perms=ap->perms;
|
|
|
|
|
new_andbox->suspended=NULL;
|
|
|
|
|
if (ap->suspended) new_andbox->suspended=addto_suspensions_list(new_andbox,ap->suspended->reason);
|
|
|
|
|
new_andbox->side_effects=ap->side_effects;
|
|
|
|
|
|
|
|
|
|
if (ap->externals) {
|
|
|
|
|
struct EXTERNAL_VAR *old_externals, *list=NULL;
|
|
|
|
|
old_externals=ap->externals;
|
|
|
|
|
while (old_externals) {
|
|
|
|
|
struct EXTERNAL_VAR *e;
|
|
|
|
|
struct SUSPENSIONS_VAR *s;
|
|
|
|
|
|
|
|
|
|
e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE);
|
|
|
|
|
e->value=old_externals->value;
|
|
|
|
|
e->var=(struct PERM_VAR *) old_externals->var;
|
|
|
|
|
e->next=list;
|
|
|
|
|
list=e;
|
|
|
|
|
|
|
|
|
|
if (isvar(e->var)) {
|
|
|
|
|
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); /* Add and_box to suspension list of var*/
|
|
|
|
|
s->and_box=new_andbox;
|
|
|
|
|
s->next=e->var->suspensions;
|
|
|
|
|
e->var->suspensions=s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
old_externals=old_externals->next;
|
|
|
|
|
}
|
|
|
|
|
new_andbox->externals=list;
|
|
|
|
|
} else new_andbox->externals=NULL;
|
|
|
|
|
|
|
|
|
|
new_call=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
|
|
|
|
new_call->call=new_orbox;
|
|
|
|
|
new_call->locals=nr_call->locals;
|
|
|
|
|
new_call->code=nr_call->code;
|
|
|
|
|
new_call->state=WAKE;
|
|
|
|
|
nr_call->state=WAKE; /* NEW PARA TORNAR A CALL NUM WAKE STATE */
|
|
|
|
|
|
|
|
|
|
new_orbox->parent=new_andbox;
|
|
|
|
|
new_orbox->nr_call=new_call;
|
|
|
|
|
new_orbox->nr_all_alternatives=1;
|
|
|
|
|
new_alternatives=a->nr_alternative;
|
|
|
|
|
new_orbox->alternatives=new_alternatives;
|
|
|
|
|
|
|
|
|
|
/* remove andbox from op */
|
|
|
|
|
op->nr_all_alternatives-=1;
|
|
|
|
|
if (new_alternatives->previous==NULL) op->alternatives=new_alternatives->next;
|
|
|
|
|
else new_alternatives->previous->next=new_alternatives->next;
|
|
|
|
|
if (new_alternatives->next!=NULL) new_alternatives->next->previous=new_alternatives->previous;
|
|
|
|
|
new_alternatives->next=NULL;
|
|
|
|
|
new_alternatives->previous=NULL;
|
|
|
|
|
|
|
|
|
|
a->parent=new_orbox;
|
|
|
|
|
|
|
|
|
|
/* increase the nr_alternatives by 1 in opp or_box parent parent and conect new_andbox*/
|
|
|
|
|
new_alternatives=(struct status_or *) request_memory(STATUS_OR_SIZE);
|
|
|
|
|
new_andbox->nr_alternative=new_alternatives;
|
|
|
|
|
|
|
|
|
|
new_alternatives->next=nr_alternative;
|
|
|
|
|
new_alternatives->previous=nr_alternative->previous;
|
|
|
|
|
if (nr_alternative->previous==NULL) opp->alternatives=new_alternatives;
|
|
|
|
|
else nr_alternative->previous->next=new_alternatives;
|
|
|
|
|
nr_alternative->previous=new_alternatives;
|
|
|
|
|
|
|
|
|
|
new_alternatives->args=nr_alternative->args;
|
|
|
|
|
new_alternatives->code=nr_alternative->code;
|
|
|
|
|
new_alternatives->state=nr_alternative->state;
|
|
|
|
|
new_alternatives->alternative=new_andbox;
|
|
|
|
|
|
|
|
|
|
opp->nr_all_alternatives=nr_all_alternatives+1;
|
|
|
|
|
|
|
|
|
|
/* copy and_box ap to new_and-box */
|
|
|
|
|
{ struct status_and *first=NULL, *last=NULL,*calls,*calls_new;
|
|
|
|
|
calls=ap->calls;
|
|
|
|
|
while(calls!=NULL) {
|
|
|
|
|
if (calls==nr_call) {
|
|
|
|
|
calls_new=new_call;
|
|
|
|
|
} else {
|
|
|
|
|
calls_new=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
|
|
|
|
calls_new->code=calls->code;
|
|
|
|
|
calls_new->locals=calls->locals;
|
|
|
|
|
calls_new->state=calls->state;
|
|
|
|
|
calls_new->call=copy_orbox(calls->call,new_andbox,calls_new); /* Do a exact copy of the tree*/
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (first==NULL) first=calls_new;
|
|
|
|
|
else last->next=calls_new;
|
|
|
|
|
calls_new->previous=last;
|
|
|
|
|
calls_new->next=NULL;
|
|
|
|
|
last=calls_new;
|
|
|
|
|
calls=calls->next;
|
|
|
|
|
}
|
|
|
|
|
new_andbox->calls=first;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* remove and_box a from suspension list on vars */
|
|
|
|
|
if (a->externals) {
|
|
|
|
|
struct EXTERNAL_VAR *e;
|
|
|
|
|
e=a->externals;
|
|
|
|
|
while(e) {
|
|
|
|
|
if (e->var->home->level>=a->parent->parent->level)
|
|
|
|
|
remove_from_perm_var_suspensions(e->var,a);
|
|
|
|
|
e=e->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now we have to create new local vars and refresh the external vars to point to those */
|
|
|
|
|
|
|
|
|
|
if (MEM_Going==1) {
|
|
|
|
|
VAR_TRAIL=((Cell *) START_ADDR_BOXES)-1;
|
|
|
|
|
} else VAR_TRAIL=(Cell *) START_ADDR_HEAP;
|
|
|
|
|
VAR_TRAIL_NR=0;
|
|
|
|
|
replicate_local_variables(new_andbox);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct OR_BOX *copy_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call)
|
|
|
|
|
{
|
|
|
|
|
struct OR_BOX *new_orbox;
|
|
|
|
|
struct status_or *old,*new,*first=NULL,*last=NULL;
|
|
|
|
|
|
|
|
|
|
if (o==NULL) return(NULL);
|
|
|
|
|
|
|
|
|
|
new_orbox=(struct OR_BOX *) request_memory(ORBOX_SIZE);
|
|
|
|
|
new_orbox->parent=parent;
|
|
|
|
|
new_orbox->nr_call=nr_call;
|
|
|
|
|
new_orbox->nr_all_alternatives=o->nr_all_alternatives;
|
|
|
|
|
old=o->alternatives;
|
|
|
|
|
while(old!=NULL) {
|
|
|
|
|
new=(struct status_or *) request_memory(STATUS_OR_SIZE);
|
|
|
|
|
new->args=old->args;
|
|
|
|
|
new->code=old->code;
|
|
|
|
|
new->state=old->state;
|
|
|
|
|
new->alternative=copy_andbox(old->alternative,new_orbox);
|
|
|
|
|
if (new->alternative!=NULL) new->alternative->nr_alternative=new;
|
|
|
|
|
|
|
|
|
|
if (first==NULL) first=new;
|
|
|
|
|
else last->next=new;
|
|
|
|
|
new->previous=last;
|
|
|
|
|
new->next=NULL;
|
|
|
|
|
last=new;
|
|
|
|
|
old=old->next;
|
|
|
|
|
}
|
|
|
|
|
new_orbox->alternatives=first;
|
|
|
|
|
|
|
|
|
|
return(new_orbox);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct AND_BOX *copy_andbox(struct AND_BOX *a,struct OR_BOX *parent)
|
|
|
|
|
{
|
|
|
|
|
struct AND_BOX *new_andbox;
|
|
|
|
|
|
|
|
|
|
if (a==NULL) return(NULL);
|
|
|
|
|
|
|
|
|
|
new_andbox=(struct AND_BOX *) request_memory(ANDBOX_SIZE);
|
|
|
|
|
new_andbox->parent=parent;
|
|
|
|
|
// new_andbox->nr_alternative=a->nr_alternative; /* this is seted in the copy_orbox, after calling copy_andbox */
|
|
|
|
|
new_andbox->nr_all_calls=a->nr_all_calls;
|
|
|
|
|
new_andbox->level=a->level;
|
|
|
|
|
new_andbox->perms=a->perms;
|
|
|
|
|
new_andbox->externals=a->externals;
|
|
|
|
|
new_andbox->side_effects=a->side_effects;
|
|
|
|
|
new_andbox->suspended=NULL;
|
|
|
|
|
if (a->suspended) {
|
|
|
|
|
new_andbox->suspended=addto_suspensions_list(new_andbox,a->suspended->reason);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{ struct status_and *first=NULL, *last=NULL,*calls,*calls_new;
|
|
|
|
|
calls=a->calls;
|
|
|
|
|
while(calls!=NULL) {
|
|
|
|
|
calls_new=(struct status_and *) request_memory(STATUS_AND_SIZE);
|
|
|
|
|
calls_new->code=calls->code;
|
|
|
|
|
calls_new->locals=calls->locals;
|
|
|
|
|
calls_new->state=calls->state;
|
|
|
|
|
calls_new->call=copy_orbox(calls->call,new_andbox,calls_new); /* Do a exact copy of the tree*/
|
|
|
|
|
|
|
|
|
|
if (first==NULL) first=calls_new;
|
|
|
|
|
else last->next=calls_new;
|
|
|
|
|
calls_new->previous=last;
|
|
|
|
|
calls_new->next=NULL;
|
|
|
|
|
last=calls_new;
|
|
|
|
|
calls=calls->next;
|
|
|
|
|
}
|
|
|
|
|
new_andbox->calls=first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return(new_andbox);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void replicate_local_variables(struct AND_BOX *a) /* used by fork -ABX is set*/
|
|
|
|
|
{
|
|
|
|
|
struct PERM_VAR *l,*new_list;
|
|
|
|
|
int i,OLD_VAR_TRAIL_NR;
|
|
|
|
|
struct EXTERNAL_VAR *old_externals,*externals;
|
|
|
|
|
|
|
|
|
|
if (a==NULL) return;
|
|
|
|
|
|
|
|
|
|
OLD_VAR_TRAIL_NR=VAR_TRAIL_NR;
|
|
|
|
|
l=a->perms;
|
|
|
|
|
new_list=NULL;
|
|
|
|
|
while(l) {
|
|
|
|
|
struct PERM_VAR *new;
|
|
|
|
|
Cell *c;
|
|
|
|
|
|
|
|
|
|
new=request_permVar(a);
|
|
|
|
|
new->yapvar=l->yapvar;
|
|
|
|
|
new->next=new_list;
|
|
|
|
|
new_list=new;
|
|
|
|
|
|
|
|
|
|
c=&l->value;
|
|
|
|
|
VAR_TRAIL[VAR_TRAIL_NR]=(Cell) c;
|
|
|
|
|
VAR_TRAIL_NR-=MEM_Going;
|
|
|
|
|
VAR_TRAIL[VAR_TRAIL_NR]=(Cell) *c;
|
|
|
|
|
VAR_TRAIL_NR-=MEM_Going;
|
|
|
|
|
|
|
|
|
|
if ((Cell *)*c==c) {
|
|
|
|
|
new->value=(Cell) &new->value;
|
|
|
|
|
*c=new->value;
|
|
|
|
|
} else {
|
|
|
|
|
new->value= (Cell) *c;
|
|
|
|
|
*c=(Cell) &new->value;
|
|
|
|
|
}
|
|
|
|
|
l=l->next;
|
|
|
|
|
}
|
|
|
|
|
a->perms=new_list;
|
|
|
|
|
l=new_list;
|
|
|
|
|
while(l) {
|
|
|
|
|
l->value=copy_structures(l->value);
|
|
|
|
|
l=l->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* At this point all old local vars are pointing to the new local vars */
|
|
|
|
|
|
|
|
|
|
if (a==ABX) { /* Nao preciso de criar um novo vector das externals */
|
|
|
|
|
old_externals=a->externals;
|
|
|
|
|
while(old_externals) {
|
|
|
|
|
if (old_externals->var->home->level>=ABX->parent->parent->level) {
|
|
|
|
|
old_externals->value=copy_structures((Cell ) old_externals->value);
|
|
|
|
|
old_externals->var=(struct PERM_VAR *) old_externals->var->value;
|
|
|
|
|
if (isvar(old_externals->var)) {
|
|
|
|
|
struct SUSPENSIONS_VAR *s;
|
|
|
|
|
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); /* Add and_box to suspension list of var*/
|
|
|
|
|
s->and_box=a;
|
|
|
|
|
s->next=old_externals->var->suspensions;
|
|
|
|
|
old_externals->var->suspensions=s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
old_externals=old_externals->next;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
old_externals=a->externals;
|
|
|
|
|
externals=NULL;
|
|
|
|
|
a->externals=NULL;
|
|
|
|
|
|
|
|
|
|
while(old_externals) {
|
|
|
|
|
struct EXTERNAL_VAR *e;
|
|
|
|
|
struct SUSPENSIONS_VAR *s;
|
|
|
|
|
|
|
|
|
|
e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE);
|
|
|
|
|
e->next=externals;
|
|
|
|
|
externals=e;
|
|
|
|
|
|
|
|
|
|
if (old_externals->var->home->level>=ABX->parent->parent->level) {
|
|
|
|
|
e->value=copy_structures((Cell ) old_externals->value);
|
|
|
|
|
e->var=(struct PERM_VAR *) old_externals->var->value;
|
|
|
|
|
} else {
|
|
|
|
|
e->value=old_externals->value;
|
|
|
|
|
e->var=(struct PERM_VAR *) old_externals->var->value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isvar(e->var)) {
|
|
|
|
|
s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); /* Add and_box to suspension list of var*/
|
|
|
|
|
s->and_box=a;
|
|
|
|
|
s->next=e->var->suspensions;
|
|
|
|
|
e->var->suspensions=s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
old_externals=old_externals->next;
|
|
|
|
|
}
|
|
|
|
|
a->externals=externals;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* CUIDADO: Preciso agora de duplicar os vectores das variaveis locais */
|
|
|
|
|
{ struct status_and *calls;
|
|
|
|
|
#if !Fast_go
|
|
|
|
|
Cell **backup=NULL; int i, counted=0,max=1000;
|
|
|
|
|
backup=(Cell **) malloc(max);
|
|
|
|
|
#else
|
|
|
|
|
Cell *backup[1000]; int i, counted=0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
calls=a->calls;
|
|
|
|
|
while(calls!=NULL) {
|
|
|
|
|
if (calls->locals!=NULL) {
|
|
|
|
|
/* primeiro vou ver se j<> foi copiado */
|
|
|
|
|
for(i=0;i<counted;i+=2) {
|
|
|
|
|
if (backup[i]==calls->locals) {
|
|
|
|
|
calls->locals=backup[i+1];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (i==counted) { /* afinal ainda nao foi copiado: fazer copia em duas fases*/
|
|
|
|
|
Cell *c, *newvars, *oldvars; int nr;
|
|
|
|
|
|
|
|
|
|
oldvars=calls->locals;
|
|
|
|
|
nr=oldvars[-1];
|
2005-10-09 22:13:57 +01:00
|
|
|
|
newvars=request_memory_locals_noinit(nr);
|
2005-09-08 23:36:16 +01:00
|
|
|
|
calls->locals=newvars;
|
|
|
|
|
/* primeiro actualizo as variaveis */
|
|
|
|
|
for(i=0;i<nr;i++) {
|
|
|
|
|
c=&oldvars[i];
|
|
|
|
|
VAR_TRAIL[VAR_TRAIL_NR]=(Cell) c;
|
|
|
|
|
VAR_TRAIL_NR-=MEM_Going;
|
|
|
|
|
VAR_TRAIL[VAR_TRAIL_NR]=(Cell) *c;
|
|
|
|
|
VAR_TRAIL_NR-=MEM_Going;
|
|
|
|
|
|
|
|
|
|
if ((Cell *)*c==c) {
|
|
|
|
|
newvars[i]=(Cell) &newvars[i];
|
|
|
|
|
*c=newvars[i];
|
|
|
|
|
} else {
|
|
|
|
|
newvars[i]= (Cell) *c;
|
|
|
|
|
*c=(Cell) &newvars[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* depois copio as estruturas */
|
|
|
|
|
for(i=0;i<nr;i++) {
|
|
|
|
|
newvars[i]=copy_structures(oldvars[i]);
|
|
|
|
|
}
|
|
|
|
|
#if !Fast_go
|
|
|
|
|
if (max<counted+2) {
|
|
|
|
|
max+=200;
|
|
|
|
|
backup=realloc(backup,max);
|
|
|
|
|
if (backup==NULL) abort_eam("No more memory... realloc in gc \n");
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (counted>=998) abort_eam("No more memory... realloc in gc \n");
|
|
|
|
|
#endif
|
|
|
|
|
backup[counted]=oldvars;
|
|
|
|
|
backup[counted+1]=newvars;
|
|
|
|
|
counted+=2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
calls=calls->next;
|
|
|
|
|
}
|
|
|
|
|
#if !Fast_go
|
|
|
|
|
free(backup);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* redo the process to the inner boxes */
|
|
|
|
|
{ struct status_and *calls;
|
|
|
|
|
|
|
|
|
|
calls=a->calls;
|
|
|
|
|
while(calls!=NULL) {
|
|
|
|
|
|
|
|
|
|
if (calls->call!=NULL) {
|
|
|
|
|
register struct OR_BOX *o;
|
|
|
|
|
register struct status_or *nr;
|
|
|
|
|
|
|
|
|
|
o=calls->call;
|
|
|
|
|
nr=o->alternatives;
|
|
|
|
|
while(nr!=NULL) {
|
|
|
|
|
replicate_local_variables(nr->alternative);
|
|
|
|
|
nr=nr->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
calls=calls->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (MEM_Going==1) {
|
|
|
|
|
for(i=OLD_VAR_TRAIL_NR;i>VAR_TRAIL_NR;i-=2) {
|
|
|
|
|
Cell *c;
|
|
|
|
|
c=(Cell *) VAR_TRAIL[i];
|
|
|
|
|
*c=(Cell) VAR_TRAIL[i-1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for(i=OLD_VAR_TRAIL_NR;i<VAR_TRAIL_NR;i+=2) {
|
|
|
|
|
Cell *c;
|
|
|
|
|
c=(Cell *) VAR_TRAIL[i];
|
|
|
|
|
*c=(Cell) VAR_TRAIL[i+1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VAR_TRAIL_NR=OLD_VAR_TRAIL_NR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cell copy_structures(Cell c)
|
|
|
|
|
{
|
|
|
|
|
Cell *NewC, *NewH;
|
|
|
|
|
Cell OldC,OldH;
|
|
|
|
|
|
|
|
|
|
OldC=deref((Cell) c);
|
|
|
|
|
|
|
|
|
|
if (isvar(OldC)) {
|
|
|
|
|
return(OldC);
|
|
|
|
|
}
|
|
|
|
|
if (isatom(OldC)) {
|
|
|
|
|
return(OldC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OldH=(Cell) _H;
|
|
|
|
|
NewH=_H;
|
|
|
|
|
if (isappl(OldC)) {
|
|
|
|
|
int i,arity;
|
|
|
|
|
|
|
|
|
|
NewC=(Cell *) repappl(OldC);
|
|
|
|
|
arity = ((int) ArityOfFunctor((Functor) *NewC));
|
|
|
|
|
*NewH++=*NewC++;
|
|
|
|
|
_H+=arity+1;
|
|
|
|
|
for(i=0;i<arity ;i++) {
|
|
|
|
|
*NewH=copy_structures((Cell) NewC);
|
|
|
|
|
NewH++;
|
|
|
|
|
NewC++;
|
|
|
|
|
}
|
|
|
|
|
return(absappl(OldH));
|
|
|
|
|
}
|
|
|
|
|
/* else if (ispair(c)) { */
|
|
|
|
|
NewC=(Cell *) reppair(OldC);
|
|
|
|
|
_H+=2;
|
|
|
|
|
*NewH=copy_structures((Cell) NewC);
|
|
|
|
|
NewC++;
|
|
|
|
|
NewH++;
|
|
|
|
|
*NewH=copy_structures((Cell) NewC);
|
|
|
|
|
return(abspair(OldH));
|
|
|
|
|
}
|